Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding basic functionality to filter results #156

Merged
merged 6 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions callbacks/control_bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ def update_selected_class_style(selected_class, all_annotation_classes):
Input("pan-and-zoom", "n_clicks"),
Input("keybind-event-listener", "event"),
State("annotation-store", "data"),
State("image-viewer-loading", "zIndex"),
State("generate-annotation-class-modal", "opened"),
State({"type": "edit-annotation-class-modal", "index": ALL}, "opened"),
prevent_initial_call=True,
Expand All @@ -173,7 +172,6 @@ def annotation_mode(
pan_and_zoom,
keybind_event_listener,
annotation_store,
figure_overlay_z_index,
generate_modal_opened,
edit_modal_opened,
):
Expand Down
75 changes: 65 additions & 10 deletions callbacks/image_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
from plotly.subplots import make_subplots

from constants import ANNOT_ICONS, ANNOT_NOTIFICATION_MSGS, KEYBINDS
from utils.data_utils import get_data_sequence_by_name, get_data_shape_by_name
from utils.data_utils import (
get_annotated_segmented_results,
get_data_sequence_by_name,
get_data_shape_by_name,
)
from utils.plot_utils import (
create_viewfinder,
downscale_view,
Expand All @@ -45,8 +49,8 @@
)
def hide_show_segmentation_overlay(toggle_seg_result, opacity):
"""
This callback is responsible for hiding or showing the segmentation results overaly
by making the opacity 0 (given that this iamge has already been rendered in the render_image callback).
This callback is responsible for hiding or showing the segmentation results overlay
by making the opacity 0 (given that this image has already been rendered in the render_image callback).
This callback also adjusts the opactiy of the results based on the opacity slider.
"""
fig = Patch()
Expand All @@ -64,6 +68,7 @@ def hide_show_segmentation_overlay(toggle_seg_result, opacity):
Output("annotated-slices-selector", "value"),
Output("image-selection-slider", "value", allow_duplicate=True),
Output("notifications-container", "children", allow_duplicate=True),
Output("image-viewer-loading", "className"),
Input("image-selection-slider", "value"),
Input("show-result-overlay-toggle", "checked"),
Input("annotated-slices-selector", "value"),
Expand Down Expand Up @@ -98,8 +103,9 @@ def render_image(
if ctx.triggered_id == "annotated-slices-selector":
reset_slice_selection = None
if image_idx == slice_selection:
ret_values = [dash.no_update] * 7
ret_values = [dash.no_update] * 8
ret_values[4] = reset_slice_selection
ret_values[7] = "hidden"
return ret_values
image_idx = slice_selection
update_slider_value = slice_selection
Expand All @@ -119,12 +125,15 @@ def render_image(
len(fig["data"]) == 2
and ctx.triggered_id == "show-result-overlay-toggle"
):
raise PreventUpdate
result = get_data_sequence_by_name(seg_result_selection)[image_idx]
return [dash.no_update] * 7 + ["hidden"]
if str(image_idx + 1) in get_annotated_segmented_results():
result = get_data_sequence_by_name(seg_result_selection)[image_idx]
else:
result = None
else:
tf = np.zeros((500, 500))
fig = px.imshow(tf, binary_string=True)
if toggle_seg_result:
if toggle_seg_result and result is not None:
unique_segmentation_values = np.unique(result)
normalized_range = np.linspace(
0, 1, len(unique_segmentation_values)
Expand Down Expand Up @@ -209,6 +218,7 @@ def render_image(
reset_slice_selection,
update_slider_value,
notification,
"hidden",
)


Expand Down Expand Up @@ -325,14 +335,59 @@ def update_viewfinder(relayout_data, annotation_store):

clientside_callback(
"""
function EnableImageLoadingOverlay(zIndexSlider,zIndexToggle,zIndexSliceSelector) {
return 9999;
function EnableImageLoadingOverlay(a) {
const ctx = window.dash_clientside.callback_context;
console.log(ctx)
if (a == null){return "hidden"}
return "visible";
}
""",
Output("image-viewer-loading", "zIndex"),
Output("image-viewer-loading", "className", allow_duplicate=True),
Input("image-selection-slider", "value"),
prevent_initial_call=True,
)
clientside_callback(
"""
function EnableImageLoadingOverlay(a) {
if (a == null){return "hidden"}
return "visible";
}
""",
Output("image-viewer-loading", "className", allow_duplicate=True),
Input("show-result-overlay-toggle", "checked"),
prevent_initial_call=True,
)
clientside_callback(
"""
function EnableImageLoadingOverlay(a) {
if (a == null){return "hidden"}
return "visible";
}
""",
Output("image-viewer-loading", "className", allow_duplicate=True),
Input("annotated-slices-selector", "value"),
prevent_initial_call=True,
)
clientside_callback(
"""
function EnableImageLoadingOverlay(a) {
if (a == null){return "hidden"}
return "visible";
}
""",
Output("image-viewer-loading", "className", allow_duplicate=True),
Input("project-name-src", "value"),
prevent_initial_call=True,
)
clientside_callback(
"""
function DisableImageLoadingOverlay(fig) {
return "hidden";
}
""",
Output("image-viewer-loading", "className", allow_duplicate=True),
Input("image-viewer", "figure"),
prevent_initial_call=True,
)


Expand Down
10 changes: 9 additions & 1 deletion components/control_bar.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import dash_bootstrap_components as dbc

Check failure on line 1 in components/control_bar.py

View workflow job for this annotation

GitHub Actions / test-and-lint

Imports are incorrectly sorted and/or formatted.
import dash_mantine_components as dmc
from dash import dcc, html
from dash_extensions import EventListener
from dash_iconify import DashIconify

import dash_core_components as dcc
from components.annotation_class import annotation_class_item
from constants import ANNOT_ICONS, KEYBINDS
from utils import data_utils
Expand Down Expand Up @@ -164,6 +164,14 @@
),
),
dmc.Space(h=10),
dmc.Center(
dmc.Loader(
id="image-viewer-loading",
style={"height": "20px", "width": "90px"},
className="hidden",
),
pt=20,
),
],
),
_accordion_item(
Expand Down
28 changes: 9 additions & 19 deletions components/image_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,15 @@ def layout():
dcc.Store("image-metadata", data={"name": None}),
dcc.Store("screen-size"),
dcc.Location("url"),
dmc.LoadingOverlay(
id="image-viewer-loading",
overlayOpacity=0,
loaderProps=dict(
color=dmc.theme.DEFAULT_COLORS["blue"][6], variant="bars"
),
children=[
dcc.Graph(
id="image-viewer",
config=FIGURE_CONFIG,
figure=blank_fig(),
style={
"width": "100vw",
"height": "100vh",
"position": "fixed",
},
),
],
style={"height": "100vh", "width": "100vw"},
dcc.Graph(
id="image-viewer",
config=FIGURE_CONFIG,
figure=blank_fig(),
style={
"width": "100vw",
"height": "100vh",
"position": "fixed",
},
),
dcc.Graph(
id="image-viewfinder",
Expand Down
1 change: 1 addition & 0 deletions exported_annotation_data.json

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions utils/data_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,14 @@ def get_data_shape_by_name(project_name):
if project_container:
return project_container.shape
return None


def get_annotated_segmented_results(json_file_path="exported_annotation_data.json"):
annotated_slices = []
with open(json_file_path, "r") as f:
for line in f:
if line.strip():
json_data = json.loads(line)
json_data["data"] = json.loads(json_data["data"])
annotated_slices = list(json_data["data"][0]["annotations"].keys())
return annotated_slices
Loading