From 33fe7afc58e55290b9677e4ff858724c580b4dd0 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 11:54:35 +0100 Subject: [PATCH 01/42] keep copy of configurations for modalities in experiment --- src/supramolsim/experiments.py | 4 +++- src/supramolsim/utils/data_format/configuration_format.py | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/supramolsim/experiments.py b/src/supramolsim/experiments.py index cb956f01..d9de9c2c 100644 --- a/src/supramolsim/experiments.py +++ b/src/supramolsim/experiments.py @@ -67,12 +67,14 @@ def __post_init__(self): modalities_dir = os.path.join(local_dir, "modalities") modalities_names_list = [] modality_parameters = {} + self.config_modalities = dict() for mods in os.listdir(modalities_dir): if os.path.splitext(mods)[-1] == ".yaml" and "_template" not in mods: modalities_names_list.append(os.path.splitext(mods)[0]) for mod in modalities_names_list: - mod_info = configuration_format.compile_modality_parameters(mod, local_dir) + mod_info, mod_configuration = configuration_format.compile_modality_parameters(mod, local_dir) modality_parameters[mod] = mod_info + self.config_modalities[mod] = mod_configuration self.local_modalities_names = modalities_names_list self.local_modalities_parameters = modality_parameters probes_dir = os.path.join(local_dir, "probes") diff --git a/src/supramolsim/utils/data_format/configuration_format.py b/src/supramolsim/utils/data_format/configuration_format.py index b4f85b3d..1d4db6f4 100644 --- a/src/supramolsim/utils/data_format/configuration_format.py +++ b/src/supramolsim/utils/data_format/configuration_format.py @@ -66,7 +66,7 @@ def compile_modality_parameters( emission=emission_behaviour, # blinking or constant modality=modality_name, ) - return modality_params + return modality_params, mod_pars else: if ( "filters" not in mod_pars.keys() @@ -99,7 +99,7 @@ def compile_modality_parameters( emission=emission_behaviour, # blinking or constant modality=modality_name, ) - return modality_params + return modality_params, mod_pars def define_emission_behaviour(mod_emission, fluo_emissions): From cb0697ed22c90c8c75ea84feb08ada8488c0f867 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 12:33:50 +0100 Subject: [PATCH 02/42] use half of psf depth when using integrating convolved volume from the focus --- src/supramolsim/utils/transform/image_convolution.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/supramolsim/utils/transform/image_convolution.py b/src/supramolsim/utils/transform/image_convolution.py index 4f96b672..6576445e 100644 --- a/src/supramolsim/utils/transform/image_convolution.py +++ b/src/supramolsim/utils/transform/image_convolution.py @@ -76,7 +76,7 @@ def frame_by_volume_convolution( bin_size, kernel3D, zfocus_slice, - projection_depth=1, + projection_depth=2, asframe=True ): """ @@ -89,6 +89,7 @@ def frame_by_volume_convolution( IMPORTANT: All units are in the same scale, except image dimensions """ + projection_depth_half = int(projection_depth / 2) intensity_voxel = voxelize_active_fluorophores_withrange( coordinates, photon_vector, ranges, bin_pixelsize=bin_size ) @@ -98,14 +99,14 @@ def frame_by_volume_convolution( # there's no need to calculate the convolution if there are no photons convolved_intensity = intensity_voxel subset_of_frames = ( - zfocus_slice - projection_depth, - zfocus_slice + projection_depth, + zfocus_slice - projection_depth_half, + zfocus_slice + projection_depth_half, ) if asframe: frame = np.sum( np.array( convolved_intensity[ - :, :, zfocus_slice - projection_depth : zfocus_slice + projection_depth + :, :, zfocus_slice - projection_depth_half : zfocus_slice + projection_depth_half ] ), axis=2, From 7c7e7b16eaf49d25059afddd3d860322c0a9f854 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 12:34:07 +0100 Subject: [PATCH 03/42] update modality with depth of field --- src/supramolsim/experiments.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/supramolsim/experiments.py b/src/supramolsim/experiments.py index d9de9c2c..e6077066 100644 --- a/src/supramolsim/experiments.py +++ b/src/supramolsim/experiments.py @@ -216,6 +216,7 @@ def update_modality( lateral_resolution_nm: int = None, axial_resolution_nm: int = None, psf_voxel_nm: int = None, + depth_of_field_nm: int = None, remove=False, ): """ @@ -279,6 +280,12 @@ def update_modality( psf_voxel_nm, ] changes = True + if depth_of_field_nm is not None: + depth_in_slices = None + voxel_size = self.local_modalities_parameters[modality_name]["psf_params"]["voxelsize"][2] + depth=int(depth_of_field_nm / voxel_size) + self.imaging_modalities[modality_name]["psf_params"]["depth"] = depth + changes = True if changes: self.imager.set_imaging_modality( **self.imaging_modalities[modality_name] From f86beb97ab1b3cdefb292b32062496a9ccdb4f46 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 17:01:45 +0100 Subject: [PATCH 04/42] update tests --- tests/test_image_generation.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/test_image_generation.py b/tests/test_image_generation.py index be220bba..c3f84610 100644 --- a/tests/test_image_generation.py +++ b/tests/test_image_generation.py @@ -27,10 +27,8 @@ def test_image_from_field(configuration_directory, gt_structural_model_field): selected_mods = [ "STED", ] - imaging_system, modality_parameters = workflows.create_imaging_system( - gt_structural_model_field, selected_mods, configuration_path - ) - assert imaging_system.get_absoulte_reference_point().shape == (1, 3) + imgs, experiment_test = experiments.image_vsample(vsample=gt_structural_model_field, run_simulation=False, modalities=selected_mods, configuration_path=configuration_path) + assert experiment_test.imager.get_absoulte_reference_point().shape == (1, 3) def test_imager_optional_methods(experiment_7r5k_base): From 4daf0842f48e3c19462fd4d8224d032f72cd4570 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 18:00:02 +0100 Subject: [PATCH 05/42] make preview optional with button --- .../jupyter_widgets/_experiment_parameters.py | 65 ++++++++++++------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 6e721e6b..88d8d7fa 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -654,8 +654,8 @@ def remove_modality(b): def select_modalities(b): experiment.build(modules=["imager"]) - modality_gui["add_modality"].disabled = True - modality_gui["remove_modality"].disabled = True + b1.disabled = True + b2.disabled = True modality_gui["select_modalities"].disabled = True def update_plot(change): @@ -670,11 +670,11 @@ def update_plot(change): half_xy - int(half_xy * xy_zoom_in) : half_xy + int(half_xy * xy_zoom_in), :] dimension_plane = modality_gui["dimension_slice"].value - if dimension_plane == "YZ plane": + if dimension_plane == "YZ": dimension = 0 - elif dimension_plane == "XZ plane": + elif dimension_plane == "XZ": dimension = 1 - elif dimension_plane == "XY plane": + elif dimension_plane == "XY": dimension = 2 # mod info pixelsize = experiment.local_modalities_parameters[mod_name]["detector"]["pixelsize"] @@ -692,8 +692,7 @@ def update_plot(change): s3 = "Depth of field (nm): " + str(psf_depth) s4 = "PSF preview (on a 1x1 µm field of view)" modality_gui["modality_info"].value = ( - "Modality: " + mod_name + "
" - + "" + s1 + "
" + "" + s1 + "
" + "" + s2 + "
" + "" + s3 + "
" + "" + s4 + "
" @@ -711,21 +710,32 @@ def update_plot(change): options=modalities_default, on_change=update_plot, ) - modality_gui.add_button( - "add_modality", - description="Add modality", - disabled=False - ) - modality_gui.add_button( - "remove_modality", - description="Remove modality", - disabled=False + b1 = widgets.Button( + description="Add Modality", + button_style="success", + layout=widgets.Layout(width="50%") + ) + b2 = widgets.Button( + description="Remove Modality", + button_style="danger", + layout=widgets.Layout(width="50%") + ) + modality_gui.add_custom_widget( + "add_remove", + widgets.HBox, + children=[ + b1, + b2 + ] ) modality_gui.add_button( "select_modalities", description="Select list and update virtual modalities", ) - modality_gui.add_label("Modality information") + modality_gui.add_button( + "toggle_advanced_parameters", + description="Show/Hide modality info and PSF preview", + ) modality_gui.add_HTML( "modality_info", "" @@ -733,8 +743,8 @@ def update_plot(change): modality_gui.add_custom_widget( "dimension_slice", widgets.ToggleButtons, - options=["XY plane", "XZ plane", "YZ plane"], - value="XY plane", + options=["XY", "XZ", "YZ"], + value="XY", on_change=update_plot, style={"description_width": "initial"}, description="Plane of view: ", @@ -744,11 +754,22 @@ def update_plot(change): description="Preview of selected modality", style={"description_width": "initial"}, ) - + def toggle_advanced_parameters(b): + widgets_visibility["modality_info"] = not widgets_visibility["modality_info"] + widgets_visibility["dimension_slice"] = not widgets_visibility["dimension_slice"] + widgets_visibility["preview_modality"] = not widgets_visibility["preview_modality"] + update_widgets_visibility(modality_gui, widgets_visibility) - modality_gui["add_modality"].on_click(add_modality) - modality_gui["remove_modality"].on_click(remove_modality) + widgets_visibility = {} + for wgt in modality_gui.elements.keys(): + widgets_visibility[wgt] = True + modality_gui.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex") + modality_gui["dimension_slice"].style = dict(description_width="initial") + b1.on_click(add_modality) + b2.on_click(remove_modality) modality_gui["select_modalities"].on_click(select_modalities) + modality_gui["toggle_advanced_parameters"].on_click(toggle_advanced_parameters) + toggle_advanced_parameters(True) # Initialize with default visibility update_message() update_plot(True) return modality_gui From dc4af6402ac553fd5c89f6eea6eb80b5f5a6987e Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 18:03:29 +0100 Subject: [PATCH 06/42] minor update --- src/supramolsim/jupyter_widgets/_experiment_parameters.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 88d8d7fa..c46a2e3a 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -733,7 +733,7 @@ def update_plot(change): description="Select list and update virtual modalities", ) modality_gui.add_button( - "toggle_advanced_parameters", + "toggle_preview", description="Show/Hide modality info and PSF preview", ) modality_gui.add_HTML( @@ -754,7 +754,7 @@ def update_plot(change): description="Preview of selected modality", style={"description_width": "initial"}, ) - def toggle_advanced_parameters(b): + def toggle_preview(b): widgets_visibility["modality_info"] = not widgets_visibility["modality_info"] widgets_visibility["dimension_slice"] = not widgets_visibility["dimension_slice"] widgets_visibility["preview_modality"] = not widgets_visibility["preview_modality"] @@ -768,8 +768,8 @@ def toggle_advanced_parameters(b): b1.on_click(add_modality) b2.on_click(remove_modality) modality_gui["select_modalities"].on_click(select_modalities) - modality_gui["toggle_advanced_parameters"].on_click(toggle_advanced_parameters) - toggle_advanced_parameters(True) # Initialize with default visibility + modality_gui["toggle_preview"].on_click(toggle_preview) + toggle_preview(True) # Initialize with default visibility update_message() update_plot(True) return modality_gui From c889b239f9e69c6d02e48264a3f61806fd98afd6 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 18:51:12 +0100 Subject: [PATCH 07/42] update modality from widgets --- .../jupyter_widgets/_experiment_parameters.py | 63 ++++++++++++++++--- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index c46a2e3a..1cfde3ef 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -635,6 +635,16 @@ def add_modality(b): ) update_message() + def update_modality_params(b): + selected_modality = modality_gui["modality"].value + if selected_modality != "All": + experiment.update_modality( + modality_name=selected_modality, + depth_of_field_nm=modality_gui["psf_depth"].value, + ) + update_message() + update_plot(None) + def remove_modality(b): selected_modality = modality_gui["modality"].value if selected_modality == "All": @@ -660,7 +670,12 @@ def select_modalities(b): def update_plot(change): mod_name = modality_gui["modality"].value + if mod_name != "All": + if mod_name not in experiment.imaging_modalities: + info = experiment.local_modalities_parameters[mod_name] + else: + info = experiment.imaging_modalities[mod_name] psf_stack = preview_experiment.imager.get_modality_psf_stack(mod_name) psf_shape = psf_stack.shape half_xy = int(psf_shape[0] / 2) @@ -677,15 +692,15 @@ def update_plot(change): elif dimension_plane == "XY": dimension = 2 # mod info - pixelsize = experiment.local_modalities_parameters[mod_name]["detector"]["pixelsize"] + pixelsize = info["detector"]["pixelsize"] pixelsize_nm = pixelsize * 1000 psf_voxel = np.array( - experiment.local_modalities_parameters[mod_name]["psf_params"]["voxelsize"] + info["psf_params"]["voxelsize"] ) psf_sd = np.array( - experiment.local_modalities_parameters[mod_name]["psf_params"]["std_devs"] + info["psf_params"]["std_devs"] ) - psf_depth = experiment.local_modalities_parameters[mod_name]["psf_params"]["depth"] + psf_depth = info["psf_params"]["depth"]*psf_voxel[0] s1 = "Detector pixelsize (nm): " + str(pixelsize_nm) psf_sd_metric = np.multiply(psf_voxel, psf_sd) s2 = "PSF sd (nm): " + str(psf_sd_metric) @@ -712,13 +727,18 @@ def update_plot(change): ) b1 = widgets.Button( description="Add Modality", - button_style="success", + style={"button_color": "#4daf4ac7"}, layout=widgets.Layout(width="50%") ) b2 = widgets.Button( description="Remove Modality", - button_style="danger", + style={"button_color": "#ff8000da"}, layout=widgets.Layout(width="50%") + ) + b3 = widgets.Button( + description="Update modality parameters", + style={"button_color": "#4985b7d9"}, + layout=widgets.Layout(width="100%") ) modality_gui.add_custom_widget( "add_remove", @@ -732,9 +752,30 @@ def update_plot(change): "select_modalities", description="Select list and update virtual modalities", ) + modality_gui.add_button( + "toggle_advanced_parameters", + description="Toggle advanced parameters", + ) + modality_gui.add_int_slider( + "psf_depth", + description="PSF depth (nm)", + min=10, + max=1000, + step=10, + value=100, + continuous_update=False, + style={"description_width": "initial"}, + ) + modality_gui.add_custom_widget( + "update_modality_params", + widgets.HBox, + children=[ + b3, + ] + ) modality_gui.add_button( "toggle_preview", - description="Show/Hide modality info and PSF preview", + description="Toggle modality info and PSF preview", ) modality_gui.add_HTML( "modality_info", @@ -760,6 +801,11 @@ def toggle_preview(b): widgets_visibility["preview_modality"] = not widgets_visibility["preview_modality"] update_widgets_visibility(modality_gui, widgets_visibility) + def toggle_advanced_parameters(b): + widgets_visibility["psf_depth"] = not widgets_visibility["psf_depth"] + widgets_visibility["update_modality_params"] = not widgets_visibility["update_modality_params"] + update_widgets_visibility(modality_gui, widgets_visibility) + widgets_visibility = {} for wgt in modality_gui.elements.keys(): widgets_visibility[wgt] = True @@ -768,8 +814,11 @@ def toggle_preview(b): b1.on_click(add_modality) b2.on_click(remove_modality) modality_gui["select_modalities"].on_click(select_modalities) + modality_gui["toggle_advanced_parameters"].on_click(toggle_advanced_parameters) + b3.on_click(update_modality_params) modality_gui["toggle_preview"].on_click(toggle_preview) toggle_preview(True) # Initialize with default visibility + toggle_advanced_parameters(True) # Initialize with default visibility update_message() update_plot(True) return modality_gui From d6af71ea9e64c42a6bee83b39440481e025e4cd2 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 18:57:17 +0100 Subject: [PATCH 08/42] icon update button --- src/supramolsim/jupyter_widgets/_experiment_parameters.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 1cfde3ef..9ee2c1d2 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -738,7 +738,8 @@ def update_plot(change): b3 = widgets.Button( description="Update modality parameters", style={"button_color": "#4985b7d9"}, - layout=widgets.Layout(width="100%") + layout=widgets.Layout(width="100%"), + icon="fa-wrench" ) modality_gui.add_custom_widget( "add_remove", From 54681abb2bea0c79f031b93907689888f902c736 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 19:19:10 +0100 Subject: [PATCH 09/42] updates on icons --- .../jupyter_widgets/_experiment_parameters.py | 53 ++++++++++++++----- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 9ee2c1d2..12cc3e70 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -727,13 +727,13 @@ def update_plot(change): ) b1 = widgets.Button( description="Add Modality", - style={"button_color": "#4daf4ac7"}, - layout=widgets.Layout(width="50%") + layout=widgets.Layout(width="50%"), + icon="fa-plus" ) b2 = widgets.Button( description="Remove Modality", - style={"button_color": "#ff8000da"}, - layout=widgets.Layout(width="50%") + layout=widgets.Layout(width="50%"), + icon="fa-minus" ) b3 = widgets.Button( description="Update modality parameters", @@ -749,13 +749,30 @@ def update_plot(change): b2 ] ) - modality_gui.add_button( + select_modalities_button = widgets.Button( + description="Select modalities", + style={"button_color": "#4daf4ac7"}, + layout=widgets.Layout(width="100%"), + icon="fa-check" + ) + modality_gui.add_custom_widget( "select_modalities", - description="Select list and update virtual modalities", + widgets.HBox, + children=[ + select_modalities_button + ] ) - modality_gui.add_button( + button_toggle_advanced_parameters = widgets.Button( + description="Toggle advanced parameters", + layout=widgets.Layout(width="100%"), + icon="eye-slash", + ) + modality_gui.add_custom_widget( "toggle_advanced_parameters", - description="Toggle advanced parameters", + widgets.HBox, + children=[ + button_toggle_advanced_parameters + ] ) modality_gui.add_int_slider( "psf_depth", @@ -774,9 +791,17 @@ def update_plot(change): b3, ] ) - modality_gui.add_button( + button_toggle_preview = widgets.Button( + description="Toggle modality info and PSF preview", + layout=widgets.Layout(width="100%"), + icon="eye-slash", + ) + modality_gui.add_custom_widget( "toggle_preview", - description="Toggle modality info and PSF preview", + widgets.HBox, + children=[ + button_toggle_preview + ] ) modality_gui.add_HTML( "modality_info", @@ -810,14 +835,14 @@ def toggle_advanced_parameters(b): widgets_visibility = {} for wgt in modality_gui.elements.keys(): widgets_visibility[wgt] = True - modality_gui.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex") + modality_gui.elements[wgt].layout = widgets.Layout(width="50%") modality_gui["dimension_slice"].style = dict(description_width="initial") b1.on_click(add_modality) b2.on_click(remove_modality) - modality_gui["select_modalities"].on_click(select_modalities) - modality_gui["toggle_advanced_parameters"].on_click(toggle_advanced_parameters) + select_modalities_button.on_click(select_modalities) + button_toggle_advanced_parameters.on_click(toggle_advanced_parameters) b3.on_click(update_modality_params) - modality_gui["toggle_preview"].on_click(toggle_preview) + button_toggle_preview.on_click(toggle_preview) toggle_preview(True) # Initialize with default visibility toggle_advanced_parameters(True) # Initialize with default visibility update_message() From ca845532a412bb298e5a3168e0f5c501cef1703c Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 19:58:36 +0100 Subject: [PATCH 10/42] update icon in select structure --- src/supramolsim/jupyter_widgets/_experiment_parameters.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 12cc3e70..28061fc3 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -43,6 +43,10 @@ import numpy as np import tifffile as tif +select_colour = "#4daf4ac7" +remove_colour = "#ff8000da" +update_colour = "#00bfffda" + def ui_select_structure(experiment): """ Create a widget for selecting the experiment structure. @@ -60,6 +64,7 @@ def ui_select_structure(experiment): gui = EZInput("Select_structure") def select_structure(elements): elements["label_1"].value = "Current structure selected: Loading..." + elements["select_structure"].icon= "fa-spinner fa-spin" #elements["select_structure"].disabled = True for wgt in elements.keys(): elements[wgt].disabled = True @@ -67,6 +72,7 @@ def select_structure(elements): experiment.build(modules="structure") update_structure_list() #elements["select_structure"].disabled = False + elements["select_structure"].icon= "fa-check" for wgt in elements.keys(): elements[wgt].disabled = False @@ -87,6 +93,8 @@ def update_structure_list(): select_structure, gui.elements, description="Select structure", + icon="fa-check", + style={"button_color": select_colour}, ) return gui From 5e0bd7605cb2dd0431538c42f0216849a3e838fc Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 20:17:39 +0100 Subject: [PATCH 11/42] justify content center --- src/supramolsim/jupyter_widgets/_experiment_visualisation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py index aec1d6e7..b4a403b1 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py +++ b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py @@ -112,6 +112,7 @@ def show_structure(widget_elements): show_structure, gui.elements, description="Show structure", + icon="eye", ) def update_plot(value): @@ -151,6 +152,7 @@ def enable_view_widgets(b): for wgt in gui.elements.keys(): widgets_visibility[wgt] = True gui.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex") + gui["button"].layout = widgets.Layout(width='50%', align_items='center', justify_content='center') widgets_visibility["n_atoms"] = False widgets_visibility["hview"] = False widgets_visibility["vview"] = False From 10703808d92e868903ee1b2220d53874e7df638b Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 20:20:43 +0100 Subject: [PATCH 12/42] minor update --- src/supramolsim/jupyter_widgets/_experiment_parameters.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 28061fc3..860a6027 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -272,7 +272,7 @@ def type_dropdown_change(change): options=probe_options) probes_gui.add_HTML("probe_info", "") probes_gui["select_probe_template"].observe(show_probe_info, names="value") - probes_gui.add_button("toggle_advanced_parameters", description="Toggle advanced parameters") + probes_gui.add_button("toggle_advanced_parameters", description="Toggle advanced parameters", icon="eye-slash") # advanced parameters probes_gui.add_HTML("advanced_param_header", "Advanced parameters", style=dict(font_size='15px')) probes_gui.add_text(tag="probe_name", value=probes_gui["select_probe_template"].value, description="Probe name") @@ -388,6 +388,8 @@ def toggle_advanced_parameters(b): select_probe, probes_gui.elements, description="Select probe (with defaults)", + icon="fa-check", + style={"button_color": select_colour}, ) probes_gui.add_button("create_particle", description="Create labelled structure", @@ -396,7 +398,7 @@ def toggle_advanced_parameters(b): probe_widgets_visibility = {} for wgt in probes_gui.elements.keys(): probe_widgets_visibility[wgt] = True - probes_gui.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex") + probes_gui.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex", align_items="center", justify_content="center") show_probe_info(True) probes_gui["create_particle"].on_click(create_particle) From 9c6c50e8d71b2b07bd534932ee8c4fbcc15a485d Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 20:38:56 +0100 Subject: [PATCH 13/42] defaults on colors and icons --- src/supramolsim/jupyter_widgets/_experiment_parameters.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 860a6027..a926282c 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -47,6 +47,13 @@ remove_colour = "#ff8000da" update_colour = "#00bfffda" +select_icon = "fa-check" +add_icon = "fa-plus" +remove_icon = "fa-minus" +loding_icon = "fa-spinner fa-spin" +update_icon = "fa-wrench" # create +toggle_icon = "fa-eye-slash" + def ui_select_structure(experiment): """ Create a widget for selecting the experiment structure. From da3a43e6a2cc6db95556f277834aaa60d70e0600 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 20:40:00 +0100 Subject: [PATCH 14/42] use defaults --- .../jupyter_widgets/_experiment_parameters.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index a926282c..628b9956 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -71,7 +71,7 @@ def ui_select_structure(experiment): gui = EZInput("Select_structure") def select_structure(elements): elements["label_1"].value = "Current structure selected: Loading..." - elements["select_structure"].icon= "fa-spinner fa-spin" + elements["select_structure"].icon= loding_icon #elements["select_structure"].disabled = True for wgt in elements.keys(): elements[wgt].disabled = True @@ -79,7 +79,7 @@ def select_structure(elements): experiment.build(modules="structure") update_structure_list() #elements["select_structure"].disabled = False - elements["select_structure"].icon= "fa-check" + elements["select_structure"].icon= select_icon for wgt in elements.keys(): elements[wgt].disabled = False @@ -100,7 +100,7 @@ def update_structure_list(): select_structure, gui.elements, description="Select structure", - icon="fa-check", + icon=select_icon, style={"button_color": select_colour}, ) @@ -279,7 +279,7 @@ def type_dropdown_change(change): options=probe_options) probes_gui.add_HTML("probe_info", "") probes_gui["select_probe_template"].observe(show_probe_info, names="value") - probes_gui.add_button("toggle_advanced_parameters", description="Toggle advanced parameters", icon="eye-slash") + probes_gui.add_button("toggle_advanced_parameters", description="Toggle advanced parameters", icon=toggle_icon) # advanced parameters probes_gui.add_HTML("advanced_param_header", "Advanced parameters", style=dict(font_size='15px')) probes_gui.add_text(tag="probe_name", value=probes_gui["select_probe_template"].value, description="Probe name") @@ -372,7 +372,10 @@ def type_dropdown_change(change): ) probes_gui.add_button("add_custom_probe", description="Select probe with custom parameters", - disabled=False) + disabled=False, + icon=select_icon, + style={"button_color": select_colour} + ) probes_gui["mock_type"].observe(type_dropdown_change, names="value") # def toggle_advanced_parameters(b): From e0929fcb11684f8bdaeb61cffb267dd5397f925b Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 20:41:21 +0100 Subject: [PATCH 15/42] unstyle widgets --- .../jupyter_widgets/_experiment_parameters.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 628b9956..38296413 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -125,7 +125,15 @@ def update_widgets_visibility(ezwidget, visibility_dictionary): if visibility_dictionary[widgetname]: ezwidget[widgetname].layout.display = "inline-flex" else: - ezwidget[widgetname].layout.display = "None" + ezwidget[widgetname].layout.display = "None" + +def _unstyle_widgets(ezwidget, visibility_dictionary): + for wgt in ezwidget.elements.keys(): + visibility_dictionary[wgt] = True + if isinstance(ezwidget[wgt], widgets.Button): + ezwidget.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex", align_items="center", justify_content="center") + else: + ezwidget.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex") def ui_select_probe(experiment, **kwargs): """ @@ -403,13 +411,12 @@ def toggle_advanced_parameters(b): ) probes_gui.add_button("create_particle", description="Create labelled structure", + style={"button_color": update_colour}, + icon=update_icon, disabled=True) probes_gui.add_HTML("message2", "No labelled structure created yet.", style = dict(font_weight='bold', font_size='15px')) probe_widgets_visibility = {} - for wgt in probes_gui.elements.keys(): - probe_widgets_visibility[wgt] = True - probes_gui.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex", align_items="center", justify_content="center") - + _unstyle_widgets(probes_gui, probe_widgets_visibility) show_probe_info(True) probes_gui["create_particle"].on_click(create_particle) probes_gui["toggle_advanced_parameters"].on_click(toggle_advanced_parameters) From 433ee5f2901dd8aab90c876138750f4a66dd8936 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 20:45:01 +0100 Subject: [PATCH 16/42] minor updates --- src/supramolsim/jupyter_widgets/_experiment_parameters.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 38296413..2eb19bce 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -605,9 +605,7 @@ def toggle_advanced_parameters(b): widgets_visibility["random"] = not widgets_visibility["random"] update_widgets_visibility(sample_gui, widgets_visibility) widgets_visibility = {} - for wgt in sample_gui.elements.keys(): - widgets_visibility[wgt] = True - sample_gui.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex") + _unstyle_widgets(sample_gui, widgets_visibility) widgets_visibility["upload_and_set"] = False widgets_visibility["File"] = False widgets_visibility["pixel_size"] = False @@ -860,9 +858,7 @@ def toggle_advanced_parameters(b): update_widgets_visibility(modality_gui, widgets_visibility) widgets_visibility = {} - for wgt in modality_gui.elements.keys(): - widgets_visibility[wgt] = True - modality_gui.elements[wgt].layout = widgets.Layout(width="50%") + _unstyle_widgets(modality_gui, widgets_visibility) modality_gui["dimension_slice"].style = dict(description_width="initial") b1.on_click(add_modality) b2.on_click(remove_modality) From 3826bc3772ddc3a44fbb66fbcfc5150cbe8e63e2 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 20:45:52 +0100 Subject: [PATCH 17/42] unstyle in visualisations --- .../jupyter_widgets/_experiment_visualisation.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py index b4a403b1..ea2d30f1 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py +++ b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py @@ -65,6 +65,14 @@ def update_widgets_visibility(ezwidget, visibility_dictionary): ezwidget[widgetname].layout.display = "inline-flex" else: ezwidget[widgetname].layout.display = "None" + +def _unstyle_widgets(ezwidget, visibility_dictionary): + for wgt in ezwidget.elements.keys(): + visibility_dictionary[wgt] = True + if isinstance(ezwidget[wgt], widgets.Button): + ezwidget.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex", align_items="center", justify_content="center") + else: + ezwidget.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex") def ui_show_structure(experiment): """ From dc0ce5778aea346d53c902e7161b6e9023e7a2e7 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 20:48:26 +0100 Subject: [PATCH 18/42] update styles visualisations --- .../_experiment_visualisation.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py index ea2d30f1..0f7b096a 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py +++ b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py @@ -65,7 +65,7 @@ def update_widgets_visibility(ezwidget, visibility_dictionary): ezwidget[widgetname].layout.display = "inline-flex" else: ezwidget[widgetname].layout.display = "None" - + def _unstyle_widgets(ezwidget, visibility_dictionary): for wgt in ezwidget.elements.keys(): visibility_dictionary[wgt] = True @@ -157,9 +157,7 @@ def enable_view_widgets(b): #gui.add_button("show_structure", description="Show structure") gui.add_output("preview_structure") widgets_visibility = {} - for wgt in gui.elements.keys(): - widgets_visibility[wgt] = True - gui.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex") + _unstyle_widgets(gui, widgets_visibility) gui["button"].layout = widgets.Layout(width='50%', align_items='center', justify_content='center') widgets_visibility["n_atoms"] = False widgets_visibility["hview"] = False @@ -278,9 +276,7 @@ def enable_view_widgets(b): gui["show_labelled_structure"].on_click(show_labelled_structure) gui.add_output("preview_labelled_structure") widgets_visibility = {} - for wgt in gui.elements.keys(): - widgets_visibility[wgt] = True - gui.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex") + _unstyle_widgets(gui, widgets_visibility) widgets_visibility["emitter_plotsize"] = False widgets_visibility["source_plotsize"] = False widgets_visibility["hview"] = False @@ -345,7 +341,8 @@ def update_plot(change): on_change=update_plot, disabled=True, ) - + widgets_visibility = {} + _unstyle_widgets(gui, widgets_visibility) gui["show_virtual_sample"].on_click(update_plot) gui.add_output("preview_virtual_sample") return gui @@ -665,11 +662,7 @@ def _mods_text_update(mods_text_base, mod_acq_params, keys_to_use = ["exp_time", acquisition_gui.add_output("image_output") acq_widgets = {} - for wgt in acquisition_gui.elements.keys(): - acq_widgets[wgt] = False - acquisition_gui.elements[wgt].layout = widgets.Layout( - width="50%", display="None" - ) + _unstyle_widgets(acquisition_gui, acq_widgets) acquisition_gui.show() acq_widgets["Frames"] = True acq_widgets["Set"] = True From 7e3348fd9af6c0453a38c4d8e08ff9ded3040064 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 21:08:08 +0100 Subject: [PATCH 19/42] icons updates --- .../jupyter_widgets/_experiment_parameters.py | 35 ++++++++-------- .../_experiment_visualisation.py | 40 +++++++++++++++---- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 2eb19bce..1a080d69 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -53,6 +53,7 @@ loding_icon = "fa-spinner fa-spin" update_icon = "fa-wrench" # create toggle_icon = "fa-eye-slash" +upload_icon = "fa-upload" def ui_select_structure(experiment): """ @@ -379,10 +380,9 @@ def type_dropdown_change(change): description="Wobble cone range (degrees)", ) probes_gui.add_button("add_custom_probe", - description="Select probe with custom parameters", + description="Add probe with custom parameters", disabled=False, - icon=select_icon, - style={"button_color": select_colour} + icon=add_icon, ) probes_gui["mock_type"].observe(type_dropdown_change, names="value") # @@ -405,14 +405,13 @@ def toggle_advanced_parameters(b): "add_probe", select_probe, probes_gui.elements, - description="Select probe (with defaults)", - icon="fa-check", - style={"button_color": select_colour}, + description="Add probe (with defaults)", + icon=add_icon, ) probes_gui.add_button("create_particle", description="Create labelled structure", - style={"button_color": update_colour}, - icon=update_icon, + style={"button_color": select_colour}, + icon=select_icon, disabled=True) probes_gui.add_HTML("message2", "No labelled structure created yet.", style = dict(font_weight='bold', font_size='15px')) probe_widgets_visibility = {} @@ -489,10 +488,11 @@ def update_message(): sample_gui.add_button( "advanced_parameters", description="Toggle advanced parameters", + icon=toggle_icon, ) #### advanced parameters #### sample_gui.add_file_upload( - "File", description="Select from file", accept="*.tif", save_settings=False + "File", description="Select from file", accept="*.tif", save_settings=False, ) sample_gui.add_bounded_int_text("pixel_size", description="Pixel size (nm)", @@ -541,9 +541,12 @@ def update_message(): sample_gui.add_button( "select_sample_parameters", description="Select sample parameters", - disabled=False + disabled=False, + icon=select_icon, + style={"button_color": select_colour}, ) - sample_gui.add_button("upload_and_set", description="Load image and select parameters", disabled=False) + sample_gui.add_button("upload_and_set", description="Load image and select parameters", disabled=False, + icon=upload_icon, style={"button_color": select_colour}) sample_gui.add_HTML("advanced_params_feedback", "", style=dict(font_weight='bold')) def select_virtual_sample_parameters(b): if sample_gui["use_min_from_particle"].value: @@ -606,19 +609,13 @@ def toggle_advanced_parameters(b): update_widgets_visibility(sample_gui, widgets_visibility) widgets_visibility = {} _unstyle_widgets(sample_gui, widgets_visibility) - widgets_visibility["upload_and_set"] = False - widgets_visibility["File"] = False - widgets_visibility["pixel_size"] = False - widgets_visibility["background_intensity"] = False - widgets_visibility["blur_sigma"] = False - widgets_visibility["intensity_threshold"] = False - widgets_visibility["detection_method"] = False - widgets_visibility["random"] = False update_widgets_visibility(sample_gui, widgets_visibility) sample_gui["select_sample_parameters"].on_click(select_virtual_sample_parameters) sample_gui["advanced_parameters"].on_click(toggle_advanced_parameters) sample_gui["upload_and_set"].on_click(upload_and_set) + widgets_visibility["select_sample_parameters"] = False select_virtual_sample_parameters(True) # Initialize with default parameters + toggle_advanced_parameters(True) # Initialize with advanced parameters hidden return sample_gui def ui_select_modality(experiment): diff --git a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py index 0f7b096a..34b0ecb7 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py +++ b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py @@ -45,6 +45,20 @@ from IPython.utils import io from ..utils.visualisation.matplotlib_plots import plot_projection + +select_colour = "#4daf4ac7" +remove_colour = "#ff8000da" +update_colour = "#00bfffda" + +select_icon = "fa-check" +add_icon = "fa-plus" +show_icon = "fa-eye" +remove_icon = "fa-minus" +loding_icon = "fa-spinner fa-spin" +update_icon = "fa-wrench" # create +toggle_icon = "fa-eye-slash" +upload_icon = "fa-upload" +reset_icon = "fa-undo" def update_widgets_visibility(ezwidget, visibility_dictionary): """ Show or hide widgets in an EZInput widget based on a visibility dictionary. @@ -120,7 +134,7 @@ def show_structure(widget_elements): show_structure, gui.elements, description="Show structure", - icon="eye", + icon=show_icon, ) def update_plot(value): @@ -218,7 +232,11 @@ def show_labelled_structure(change): hview=gui["hview"].value, vview=gui["vview"].value )) - + gui.add_button( + "show_labelled_structure", + description="Show labelled structure", + icon=show_icon, + ) gui.add_int_slider( "emitter_plotsize", description="Emitter size", @@ -263,10 +281,7 @@ def show_labelled_structure(change): on_change=show_labelled_structure, disabled=True ) - gui.add_button( - "show_labelled_structure", - description="Show labelled structure", - ) + def enable_view_widgets(b): widgets_visibility["emitter_plotsize"] = True widgets_visibility["source_plotsize"] = True @@ -304,6 +319,9 @@ def update_plot(change): gui["preview_virtual_sample"].clear_output() with gui["preview_virtual_sample"]: if experiment.generators_status("coordinate_field"): + widgets_visibility["horizontal_view"] = True + widgets_visibility["vertical_view"] = True + update_widgets_visibility(gui, widgets_visibility) gui["horizontal_view"].disabled = False gui["vertical_view"].disabled = False hview = gui["horizontal_view"].value @@ -318,6 +336,7 @@ def update_plot(change): gui.add_button( "show_virtual_sample", description="Show virtual sample", + icon=show_icon, ) gui.add_int_slider( "horizontal_view", @@ -343,6 +362,9 @@ def update_plot(change): ) widgets_visibility = {} _unstyle_widgets(gui, widgets_visibility) + widgets_visibility["horizontal_view"] = False + widgets_visibility["vertical_view"] = False + update_widgets_visibility(gui, widgets_visibility) gui["show_virtual_sample"].on_click(update_plot) gui.add_output("preview_virtual_sample") return gui @@ -639,8 +661,10 @@ def _mods_text_update(mods_text_base, mod_acq_params, keys_to_use = ["exp_time", ) acquisition_gui["Noise"].observe(preview_params_chage, names="value") acquisition_gui["Exposure"].observe(preview_params_chage, names="value") - acquisition_gui.add_button("Set", description="Update acquisition parameters") - acquisition_gui.add_button("Clear", description="Reset params") + acquisition_gui.add_button("Set", description="Update acquisition parameters", + icon=update_icon, style={"button_color": update_colour}) + acquisition_gui.add_button("Clear", description="Reset params", + icon=reset_icon) acquisition_gui["Set"].on_click(set_params) acquisition_gui["Clear"].on_click(clear) acquisition_gui.add_checkbox( From cae685a559e3e39dc49d164bcc05d72645a79329 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 21:12:28 +0100 Subject: [PATCH 20/42] minor update --- .../jupyter_widgets/_experiment_visualisation.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py index 34b0ecb7..3d0f65c4 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py +++ b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py @@ -661,6 +661,14 @@ def _mods_text_update(mods_text_base, mod_acq_params, keys_to_use = ["exp_time", ) acquisition_gui["Noise"].observe(preview_params_chage, names="value") acquisition_gui["Exposure"].observe(preview_params_chage, names="value") + acquisition_gui.add_HTML( + "current_parameters", + _mods_text_update( + mods_text_base="Current acquisition parameters for modalities: ", + mod_acq_params=experiment.selected_mods, + keys_to_use=["exp_time", "noise", "nframes"], + ), + ) acquisition_gui.add_button("Set", description="Update acquisition parameters", icon=update_icon, style={"button_color": update_colour}) acquisition_gui.add_button("Clear", description="Reset params", @@ -698,14 +706,6 @@ def _mods_text_update(mods_text_base, mod_acq_params, keys_to_use = ["exp_time", acq_widgets["Clear"] = True acq_widgets["show_preview"] = True acq_widgets["show_as_volume"] = True - acquisition_gui.add_HTML( - "current_parameters", - _mods_text_update( - mods_text_base="Current acquisition parameters for modalities: ", - mod_acq_params=experiment.selected_mods, - keys_to_use=["exp_time", "noise", "nframes"], - ), - ) update_widgets_visibility(acquisition_gui, acq_widgets) return acquisition_gui From 5ff90805f8bb404511d965fcda3a4588d11462a6 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 22:58:04 +0100 Subject: [PATCH 21/42] update sample widget --- .../jupyter_widgets/_experiment_parameters.py | 53 ++++++++++++------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 1a080d69..b32fce56 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -451,9 +451,9 @@ def update_message(): sample_gui["message"].value = "No sample parameters selected yet." else: text = "" - for key, value in experiment.virtualsample_params.items(): - if key in ["number_of_particles", "random_orientations", "minimal_distance"]: - text += f"{key}: {value}
" + for param in ["number_of_particles", "random_orientations", "minimal_distance"]: + value = experiment.virtualsample_params[param] + text += f"{param}: {value}
" sample_gui["message"].value = text @@ -471,6 +471,13 @@ def update_message(): description="Randomise orientations", value=True ) + + sample_gui.add_button( + "advanced_parameters", + description="Toggle advanced parameters", + icon=toggle_icon, + ) + #### advanced parameters #### sample_gui.add_checkbox( "use_min_from_particle", value=True, @@ -484,13 +491,6 @@ def update_message(): step=1, style={"description_width": "initial"}, ) - - sample_gui.add_button( - "advanced_parameters", - description="Toggle advanced parameters", - icon=toggle_icon, - ) - #### advanced parameters #### sample_gui.add_file_upload( "File", description="Select from file", accept="*.tif", save_settings=False, ) @@ -538,9 +538,15 @@ def update_message(): description="Randomise positions (enforced when there is more than one particle)", style={"description_width": "initial"}, ) + sample_gui.add_button( + "update_sample_parameters", + description="Update sample parameters", + icon=update_icon, + style={"button_color": update_colour}, + ) sample_gui.add_button( "select_sample_parameters", - description="Select sample parameters", + description="Select parameters and build virtual sample", disabled=False, icon=select_icon, style={"button_color": select_colour}, @@ -548,16 +554,23 @@ def update_message(): sample_gui.add_button("upload_and_set", description="Load image and select parameters", disabled=False, icon=upload_icon, style={"button_color": select_colour}) sample_gui.add_HTML("advanced_params_feedback", "", style=dict(font_weight='bold')) - def select_virtual_sample_parameters(b): + + def update_parameters(b): if sample_gui["use_min_from_particle"].value: - min_distance = None + experiment.set_virtualsample_params( + number_of_particles=sample_gui["number_of_particles"].value, + random_orientations=sample_gui["random_orientations"].value, + ) else: min_distance = sample_gui["minimal_distance_nm"].value - experiment.set_virtualsample_params( - number_of_particles=sample_gui["number_of_particles"].value, - random_orientations=sample_gui["random_orientations"].value, - minimal_distance=min_distance - ) + experiment.set_virtualsample_params( + number_of_particles=sample_gui["number_of_particles"].value, + random_orientations=sample_gui["random_orientations"].value, + minimal_distance=min_distance + ) + update_message() + + def select_virtual_sample_parameters(b): experiment.build(modules=["coordinate_field"]) if experiment.objects_created["imager"]: experiment.build(modules=["imager"]) @@ -597,6 +610,8 @@ def upload_and_set(b): update_message() def toggle_advanced_parameters(b): + widgets_visibility["minimal_distance_nm"] = not widgets_visibility["minimal_distance_nm"] + widgets_visibility["use_min_from_particle"] = not widgets_visibility["use_min_from_particle"] widgets_visibility["select_sample_parameters"] = not widgets_visibility["select_sample_parameters"] widgets_visibility["upload_and_set"] = not widgets_visibility["upload_and_set"] widgets_visibility["File"] = not widgets_visibility["File"] @@ -613,7 +628,9 @@ def toggle_advanced_parameters(b): sample_gui["select_sample_parameters"].on_click(select_virtual_sample_parameters) sample_gui["advanced_parameters"].on_click(toggle_advanced_parameters) sample_gui["upload_and_set"].on_click(upload_and_set) + sample_gui["update_sample_parameters"].on_click(update_parameters) widgets_visibility["select_sample_parameters"] = False + update_parameters(True) select_virtual_sample_parameters(True) # Initialize with default parameters toggle_advanced_parameters(True) # Initialize with advanced parameters hidden return sample_gui From 8e70939e2b07c2090a37e5f76b373ca1f0fe4f41 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 22:58:44 +0100 Subject: [PATCH 22/42] update method to set virtualsample parameters --- src/supramolsim/experiments.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/supramolsim/experiments.py b/src/supramolsim/experiments.py index e6077066..4ed05b3f 100644 --- a/src/supramolsim/experiments.py +++ b/src/supramolsim/experiments.py @@ -1001,6 +1001,10 @@ def set_virtualsample_params( None """ # load default configuration for virtual sample + try: + particle_minimal_distance = self.coordinate_field.molecules_params["minimal_distance"] + except: + particle_minimal_distance = None virtual_sample_template = os.path.join( self.configuration_path, "virtualsample", @@ -1017,7 +1021,10 @@ def set_virtualsample_params( vsample_configuration["random_orientations"] = random_orientations if random_placing is not None: vsample_configuration["random_placing"] = random_placing - vsample_configuration["minimal_distance"] = minimal_distance + if minimal_distance is not None: + vsample_configuration["minimal_distance"] = minimal_distance + else: + vsample_configuration["minimal_distance"] = particle_minimal_distance self.virtualsample_params = vsample_configuration def use_image_for_positioning( From cfa90eb44e4d807df77ca890a01b5f095d6ad5f6 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 23:06:10 +0100 Subject: [PATCH 23/42] minor updates --- src/supramolsim/jupyter_widgets/_experiment_parameters.py | 2 +- src/supramolsim/jupyter_widgets/_experiment_visualisation.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index b32fce56..1aa3e199 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -789,7 +789,7 @@ def update_plot(change): ] ) select_modalities_button = widgets.Button( - description="Select modalities", + description="Select modalities and update virtual microscope", style={"button_color": "#4daf4ac7"}, layout=widgets.Layout(width="100%"), icon="fa-check" diff --git a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py index 3d0f65c4..763e4bc3 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py +++ b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py @@ -624,7 +624,7 @@ def preview_params_chage(change): def _mods_text_update(mods_text_base, mod_acq_params, keys_to_use = ["exp_time", "noise"]): - mods_text = mods_text_base + "
" + mods_text = ""+mods_text_base+"" + "
" for modality_name, acq_params in mod_acq_params.items(): if acq_params is None: acq_params = "Default" From 983cc857c1a6c02c825a68cbbc12b0fa39be0bd3 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 22 Jul 2025 23:17:24 +0100 Subject: [PATCH 24/42] minor update --- src/supramolsim/jupyter_widgets/_experiment_visualisation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py index 763e4bc3..b251c526 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py +++ b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py @@ -577,10 +577,10 @@ def get_volume(Modality, Exposure, Noise): ) acquisition_gui["image_output"].clear_output() slider = widgets.IntSlider( - value=45, + value=0, min=0, max=180, - step=1, + step=20, description='Angle:', continuous_update=False, ) From 95ac9e53274b549c2185aa4403543585583e6f77 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 23 Jul 2025 11:21:51 +0100 Subject: [PATCH 25/42] update experiment default path --- src/supramolsim/experiments.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/supramolsim/experiments.py b/src/supramolsim/experiments.py index 4ed05b3f..f699c463 100644 --- a/src/supramolsim/experiments.py +++ b/src/supramolsim/experiments.py @@ -20,8 +20,14 @@ from supramolsim.utils.io import yaml_functions from IPython.utils import io from pathlib import Path +import sys + +IN_COLAB = 'google.colab' in sys.modules +if IN_COLAB: + output_path = "/content/vlab4mic_outputs" +else: + output_path = Path.home() / "vlab4mic_outputs" -output_path = Path.home() / "vlab4mic_outputs" if not os.path.exists(output_path): os.makedirs(output_path) From 1292f3c013b7f772c5fb4decb5f20aac2410617e Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 23 Jul 2025 11:24:06 +0100 Subject: [PATCH 26/42] capture outputs --- .../jupyter_widgets/_experiment_parameters.py | 23 ++++++++++++------- .../_experiment_visualisation.py | 4 +++- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 1aa3e199..a2c2e920 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -42,6 +42,7 @@ from supramolsim.utils.visualisation.matplotlib_plots import slider_normalised import numpy as np import tifffile as tif +from IPython.utils import io select_colour = "#4daf4ac7" remove_colour = "#ff8000da" @@ -55,6 +56,7 @@ toggle_icon = "fa-eye-slash" upload_icon = "fa-upload" + def ui_select_structure(experiment): """ Create a widget for selecting the experiment structure. @@ -77,7 +79,8 @@ def select_structure(elements): for wgt in elements.keys(): elements[wgt].disabled = True experiment.structure_id = experiment.structures_info_list[elements["structures"].value] - experiment.build(modules="structure") + with io.outoutput.capture() as captured: + experiment.build(modules="structure") update_structure_list() #elements["select_structure"].disabled = False elements["select_structure"].icon= select_icon @@ -241,7 +244,8 @@ def update_probe_list(): def create_particle(b): probes_gui["message2"].value = "Creating labelled structure..." - experiment.build(modules=["particle"]) + with io.outoutput.capture() as captured: + experiment.build(modules=["particle"]) probes_gui["add_probe"].disabled = True probes_gui["create_particle"].disabled = True if experiment.generators_status("particle"): @@ -571,10 +575,11 @@ def update_parameters(b): update_message() def select_virtual_sample_parameters(b): - experiment.build(modules=["coordinate_field"]) - if experiment.objects_created["imager"]: - experiment.build(modules=["imager"]) - update_message() + with io.outoutput.capture() as captured: + experiment.build(modules=["coordinate_field"]) + if experiment.objects_created["imager"]: + experiment.build(modules=["imager"]) + update_message() def upload_and_set(b): filepath = sample_gui["File"].selected @@ -702,7 +707,8 @@ def remove_modality(b): update_message() def select_modalities(b): - experiment.build(modules=["imager"]) + with io.outoutput.capture() as captured: + experiment.build(modules=["imager"]) b1.disabled = True b2.disabled = True modality_gui["select_modalities"].disabled = True @@ -911,7 +917,8 @@ def run_simulation(b): experiment.output_directory = sav_dir save = True experiment.experiment_id = run_gui["experiment_name"].value - output = experiment.run_simulation(save=save) + with io.outoutput.capture() as captured: + output = experiment.run_simulation(save=save) run_gui.save_settings() if output is None: run_gui["message"].value = "Simulation failed. Make sure all parameters are set correctly." diff --git a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py index b251c526..5e49a07f 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py +++ b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py @@ -59,6 +59,7 @@ toggle_icon = "fa-eye-slash" upload_icon = "fa-upload" reset_icon = "fa-undo" + def update_widgets_visibility(ezwidget, visibility_dictionary): """ Show or hide widgets in an EZInput widget based on a visibility dictionary. @@ -603,7 +604,8 @@ def get_volume(Modality, Exposure, Noise): def clear(b): print("Acquisition parameters cleared") - experiment.reset_to_defaults(module="acquisitions", save=True) + with io.capture_output() as captured: + experiment.reset_to_defaults(module="acquisitions", save=True) acquisition_gui["current_parameters"].value = _mods_text_update( mods_text_base="Current acquisition parameters for modalities: ", mod_acq_params=experiment.selected_mods, From 194fd4658db048ba54ce0eb9ec8b044d0e2b5673 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 23 Jul 2025 11:33:11 +0100 Subject: [PATCH 27/42] fix mehtod names --- .../jupyter_widgets/_experiment_parameters.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index a2c2e920..aa0c4098 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -79,7 +79,7 @@ def select_structure(elements): for wgt in elements.keys(): elements[wgt].disabled = True experiment.structure_id = experiment.structures_info_list[elements["structures"].value] - with io.outoutput.capture() as captured: + with io.capture_output() as captured: experiment.build(modules="structure") update_structure_list() #elements["select_structure"].disabled = False @@ -244,7 +244,7 @@ def update_probe_list(): def create_particle(b): probes_gui["message2"].value = "Creating labelled structure..." - with io.outoutput.capture() as captured: + with io.capture_output() as captured: experiment.build(modules=["particle"]) probes_gui["add_probe"].disabled = True probes_gui["create_particle"].disabled = True @@ -575,7 +575,7 @@ def update_parameters(b): update_message() def select_virtual_sample_parameters(b): - with io.outoutput.capture() as captured: + with io.capture_output() as captured: experiment.build(modules=["coordinate_field"]) if experiment.objects_created["imager"]: experiment.build(modules=["imager"]) @@ -707,7 +707,7 @@ def remove_modality(b): update_message() def select_modalities(b): - with io.outoutput.capture() as captured: + with io.capture_output() as captured: experiment.build(modules=["imager"]) b1.disabled = True b2.disabled = True @@ -917,7 +917,7 @@ def run_simulation(b): experiment.output_directory = sav_dir save = True experiment.experiment_id = run_gui["experiment_name"].value - with io.outoutput.capture() as captured: + with io.capture_output() as captured: output = experiment.run_simulation(save=save) run_gui.save_settings() if output is None: From e00e37ea41df6dea1240ca82733c8d976ee0fe97 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 23 Jul 2025 11:35:02 +0100 Subject: [PATCH 28/42] update run experiment wigets icons --- src/supramolsim/jupyter_widgets/_experiment_parameters.py | 2 +- src/supramolsim/jupyter_widgets/_experiment_visualisation.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index aa0c4098..9e93f1e6 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -947,6 +947,6 @@ def run_simulation(b): "", style=dict(font_weight='bold') ) - run_gui.add_button("Acquire", description="Run Simulation") + run_gui.add_button("Acquire", description="Run Simulation", icon=select_icon, style={"button_color": select_colour}) run_gui["Acquire"].on_click(run_simulation) return run_gui \ No newline at end of file diff --git a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py index 5e49a07f..8350cce0 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py +++ b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py @@ -755,6 +755,7 @@ def show_results(b): gui.add_button( "show_results", description="Show Results", + icon=show_icon, ) def update_plot(change): From ad374fa4a9afb22b02deb9bf7afc7687723d8429 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 23 Jul 2025 12:07:48 +0100 Subject: [PATCH 29/42] return image along with its corresponding parameters in sweep --- .../sweep_parameters_widgets.py | 67 ++++++++++++++----- src/supramolsim/sweep_generator.py | 2 +- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/sweep_parameters_widgets.py b/src/supramolsim/jupyter_widgets/sweep_parameters_widgets.py index e63a9676..3e10f88c 100644 --- a/src/supramolsim/jupyter_widgets/sweep_parameters_widgets.py +++ b/src/supramolsim/jupyter_widgets/sweep_parameters_widgets.py @@ -38,6 +38,22 @@ import matplotlib.pyplot as plt import numpy as np from ._widget_generator import widgen +import pprint + + +select_colour = "#4daf4ac7" +remove_colour = "#ff8000da" +update_colour = "#00bfffda" + +select_icon = "fa-check" +add_icon = "fa-plus" +remove_icon = "fa-minus" +loding_icon = "fa-spinner fa-spin" +update_icon = "fa-wrench" # create +toggle_icon = "fa-eye-slash" +upload_icon = "fa-upload" +view_icon = "fa-eye" +save_icon = "fa-save" def update_widgets_visibility(ezwidget, visibility_dictionary): @@ -61,6 +77,14 @@ def update_widgets_visibility(ezwidget, visibility_dictionary): else: ezwidget[widgetname].layout.display = "None" +def _unstyle_widgets(ezwidget, visibility_dictionary): + for wgt in ezwidget.elements.keys(): + visibility_dictionary[wgt] = True + if isinstance(ezwidget[wgt], widgets.Button): + ezwidget.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex", align_items="center", justify_content="center") + else: + ezwidget.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex") + def select_structure(sweep_gen): """ @@ -78,7 +102,7 @@ def select_structure(sweep_gen): """ ez_sweep_structure = EZInput(title="structure") ez_sweep_structure.add_dropdown("structures", options=sweep_gen.structures_info_list.keys()) - ez_sweep_structure.add_button("Select", description="Select") + ez_sweep_structure.add_button("Select", description="Select", icon=select_icon, style={"button_color": select_colour}) def select(b): sweep_gen.structures = [sweep_gen.structures_info_list[ @@ -136,7 +160,7 @@ def select_str(b): for name in tab_name: widget_modules[name].disabled = True - ez_sweep.add_button("Select", description="Select") + ez_sweep.add_button("Select", description="Select", icon=select_icon, style={"button_color": select_colour}) ez_sweep["Select"].on_click(select_str) return ez_sweep @@ -169,9 +193,11 @@ def add_parameters_values(sweep_gen): sweep_parameter_gui.add_label() sweep_parameter_gui.add_button("select_parameters", - "Select parameters for sweep") + "Select parameters for sweep", + icon=select_icon, style={"button_color": select_colour}) sweep_parameter_gui.add_button("clear_parameters", "Clear all parameters", + icon=remove_icon, style={"button_color": remove_colour} ) sweep_parameter_gui.add_HTML( tag="message", @@ -276,6 +302,7 @@ def show_reference(b): reference.add_button( "advanced_parameters", description="Toggle advanced parameters", + icon=toggle_icon ) # advanced parameters reference.add_HTML( @@ -294,7 +321,8 @@ def show_reference(b): step=0.1, style={"description_width": "initial"}, ) - reference.add_button("upload_and_set", description="Upload image reference", disabled=False) + reference.add_button("upload_and_set", description="Upload image reference", disabled=False, + icon=upload_icon) def toggle_advanced_parameters(b): ref_widgets_visibility["Upload_ref_message"] = not ref_widgets_visibility["Upload_ref_message"] @@ -312,10 +340,12 @@ def upload_and_set(b): reference["preview"].disabled = False # reference.add_button( - "set", description="Generate image reference" + "set", description="Generate image reference", + icon=select_colour, style={"button_color": select_colour} ) reference.add_button( - "preview", description="Preview reference", disabled = True + "preview", description="Preview reference", disabled = True, + icon=view_icon ) reference.elements["feedback"] = widgets.HTML("", style = dict(font_size= "15px", font_weight='bold')) reference.add_output( @@ -324,9 +354,7 @@ def upload_and_set(b): # visibility and layout ref_widgets_visibility = {} - for wgt in reference.elements.keys(): - ref_widgets_visibility[wgt] = True - reference.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex") + _unstyle_widgets(reference, ref_widgets_visibility) reference["set"].on_click(gen_ref) reference["preview"].on_click(show_reference) @@ -434,7 +462,7 @@ def save_results(b): ) analysis_widget.add_checkbox("plots", description="Generate plots", value=True) analysis_widget.add_button( - "analyse", description="Run analysis" + "analyse", description="Run analysis", icon=select_colour, style={"button_color": select_colour} ) analysis_widget.elements["feedback"] = widgets.HTML("", style = dict(font_size= "15px", font_weight='bold')) analysis_widget.elements["outputs"] = widgets.Output() @@ -460,7 +488,7 @@ def update_plot(change): acquisition_parameters = analysis_widget["acquisition_parameters"].value replica_number = analysis_widget["replica_number"].value - image = sweep_gen.preview_image_output_by_ID( + image, parameters = sweep_gen.preview_image_output_by_ID( modality_template=modality_template, probe_template=probe_template, probe_parameters=probe_parameters, @@ -477,6 +505,13 @@ def update_plot(change): plt.close() analysis_widget["preview_results"].clear_output() with analysis_widget["preview_results"]: + print(f"Structure: {parameters[0]}") + print(f"Modality: {parameters[5]}") + print(f"Probe: {parameters[1]}") + print(f"Probe Parameters: {parameters[2]}") + print(f"Defect Parameters: {parameters[3]}") + print(f"Virtual Sample Parameters: {parameters[4]}") + print(f"Acquisition Parameters: {parameters[6]}") display(figure) def toggle_preview(b): @@ -495,7 +530,8 @@ def toggle_preview(b): # preview widgets analysis_widget.add_button( - "preview", description="Preview results", disabled=True + "preview", description="Preview results", disabled=True, + icon=view_icon ) analysis_widget.add_int_slider( "modality_template", @@ -552,12 +588,11 @@ def toggle_preview(b): # save analysis_widget.add_checkbox("save_images", description="Save images", value=False) analysis_widget.add_button( - "save", description="save analysis", disabled=True + "save", description="save analysis", disabled=True, + icon=save_icon ) widgets_visibility = {} - for wgt in analysis_widget.elements.keys(): - widgets_visibility[wgt] = True - analysis_widget.elements[wgt].layout = widgets.Layout(width="50%", display="inline-flex") + _unstyle_widgets(analysis_widget, widgets_visibility) widgets_visibility["preview_results"] = False widgets_visibility["modality_template"] = False widgets_visibility["probe_template"] = False diff --git a/src/supramolsim/sweep_generator.py b/src/supramolsim/sweep_generator.py index a77419ec..0bd932df 100644 --- a/src/supramolsim/sweep_generator.py +++ b/src/supramolsim/sweep_generator.py @@ -276,7 +276,7 @@ def preview_image_output_by_ID( else: image = self.acquisition_outputs[parameter_id][replica_number] if return_image: - return image + return image, self.acquisition_outputs_parameters[parameter_id] else: plt.imshow(image) print(self.acquisition_outputs_parameters[parameter_id]) From a68acc49299dcd90048cc8ecbfb42a5aaa0cd7cf Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 23 Jul 2025 13:30:29 +0100 Subject: [PATCH 30/42] minor update --- src/supramolsim/generate/molecular_structure.py | 8 ++++++-- .../jupyter_widgets/_experiment_visualisation.py | 13 +++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/supramolsim/generate/molecular_structure.py b/src/supramolsim/generate/molecular_structure.py index 9776b6a2..e9fe3f14 100644 --- a/src/supramolsim/generate/molecular_structure.py +++ b/src/supramolsim/generate/molecular_structure.py @@ -853,7 +853,7 @@ def show_target_labels( fig.show def show_assembly_atoms( - self, assembly_fraction=0.01, view_init=[0, 0, 0], axesoff=True + self, assembly_fraction=0.01, view_init=[0, 0, 0], axesoff=True,return_plot=False ): """ Visualize a fraction of the assembly atoms. @@ -888,7 +888,11 @@ def show_assembly_atoms( ) if axesoff: ax.set_axis_off() - return fig + if return_plot: + plt.close() + return fig + else: + fig.show() def create_instance_builder(self, write=False, savingdir=None): """ diff --git a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py index 8350cce0..a68578ac 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py +++ b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py @@ -117,13 +117,14 @@ def show_structure(widget_elements): fraction = atoms_number/total else: fraction = 1.0 - with widget_elements["preview_structure"]: - display( - experiment.structure.show_assembly_atoms( - assembly_fraction=fraction, - view_init=[vview, hview, 0] - ) + with io.capture_output() as captured: + fig = experiment.structure.show_assembly_atoms( + assembly_fraction=fraction, + view_init=[vview, hview, 0], + return_plot=True ) + with widget_elements["preview_structure"]: + display(fig) plt.close() else: widget_elements["preview_structure"].clear_output() From 705fbb736453ec455d5ad70c1927b52dad6a95d7 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 23 Jul 2025 15:08:50 +0100 Subject: [PATCH 31/42] bugfix distance to epitope --- src/supramolsim/generate/labels.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/supramolsim/generate/labels.py b/src/supramolsim/generate/labels.py index 0ffad43f..5cdc2ff3 100644 --- a/src/supramolsim/generate/labels.py +++ b/src/supramolsim/generate/labels.py @@ -230,8 +230,10 @@ def construct_label( # keynames reserved for parameters that can be iteratet over if "model_ID" in kwargs.keys(): label_params["model"]["ID"] = kwargs["model_ID"] - if "distance_to_epitope" in kwargs.keys(): - label_params["binding"]["distance"]["to_target"] = kwargs["distance_to_epitope"] + if "distance_to_epitope" in label_params.keys(): + label_params["binding"]["distance"]["to_target"] = label_params["distance_to_epitope"] + else: + print("No distance to epitope provided, using default value.") if "distance_between_epitope" in kwargs.keys(): label_params["binding"]["distance"]["between_targets"] = kwargs["distance_between_epitope"] if "paratope" in kwargs.keys(): From 17f3cd766d1f1efe0b7373f3536a530c384e6798 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 23 Jul 2025 15:09:01 +0100 Subject: [PATCH 32/42] minor updates --- .../jupyter_widgets/_experiment_parameters.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 9e93f1e6..652b5052 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -51,6 +51,7 @@ select_icon = "fa-check" add_icon = "fa-plus" remove_icon = "fa-minus" +clear_icon = "fa-trash" loding_icon = "fa-spinner fa-spin" update_icon = "fa-wrench" # create toggle_icon = "fa-eye-slash" @@ -283,9 +284,16 @@ def type_dropdown_change(change): probes_gui["mock_type_options2"].options = options_per_type2[change.new] probes_gui["mock_type_options2"].value = options_per_type2[change.new][0] + def clear_probes(b): + experiment.remove_probes() + probes_gui["message1"].value = "No probes selected yet." + probes_gui["message2"].value = "No labelled structure created yet." + probes_gui["add_probe"].disabled = False + probes_gui["create_particle"].disabled = True + update_probe_list() # widgets - probes_gui.add_label("Seleced probes:") + probes_gui.add_HTML(tag="Header_message", value="Selected probes:") probes_gui.add_HTML("message1", "No probes selected yet.", style = dict(font_weight='bold', font_size='15px')) probes_gui.add_dropdown("select_probe_template", description="Choose a probe:", @@ -412,8 +420,9 @@ def toggle_advanced_parameters(b): description="Add probe (with defaults)", icon=add_icon, ) + probes_gui.add_button("clear_probes", description="Clear all probes", icon=clear_icon, style={"button_color": remove_colour}) probes_gui.add_button("create_particle", - description="Create labelled structure", + description="Select probes and create labelled structure", style={"button_color": select_colour}, icon=select_icon, disabled=True) @@ -422,6 +431,7 @@ def toggle_advanced_parameters(b): _unstyle_widgets(probes_gui, probe_widgets_visibility) show_probe_info(True) probes_gui["create_particle"].on_click(create_particle) + probes_gui["clear_probes"].on_click(clear_probes) probes_gui["toggle_advanced_parameters"].on_click(toggle_advanced_parameters) probes_gui["add_custom_probe"].on_click(select_custom_probe) toggle_advanced_parameters(True) # Initialize with default visibility From 8c7957ed04b97d91c2afc7b434be005aeaa5ac22 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 23 Jul 2025 15:23:59 +0100 Subject: [PATCH 33/42] update wobble theta parameter --- src/supramolsim/experiments.py | 7 ++++--- src/supramolsim/generate/labels.py | 7 ++----- .../jupyter_widgets/_experiment_parameters.py | 15 +++++++-------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/supramolsim/experiments.py b/src/supramolsim/experiments.py index f699c463..ace99eb5 100644 --- a/src/supramolsim/experiments.py +++ b/src/supramolsim/experiments.py @@ -837,7 +837,7 @@ def add_probe( probe_conjugation_target_info=None, probe_conjugation_efficiency: float = None, probe_seconday_epitope=None, - probe_wobbling=False, + probe_wobble_theta: float = None, labelling_efficiency: float = 1.0, as_primary=False, peptide_motif: dict = None, @@ -946,8 +946,9 @@ def add_probe( probe_configuration["conjugation_efficiency"] = probe_conjugation_efficiency if probe_seconday_epitope is not None: probe_configuration["epitope_target_info"] = probe_seconday_epitope - if probe_wobbling: - probe_configuration["enable_wobble"] = probe_wobbling + if probe_wobble_theta is not None: + probe_configuration["enable_wobble"] = True + probe_configuration["wobble_theta"] = probe_wobble_theta if as_primary: print("Adding probe as primary linker") probe_configuration["as_linker"] = True diff --git a/src/supramolsim/generate/labels.py b/src/supramolsim/generate/labels.py index 5cdc2ff3..db704442 100644 --- a/src/supramolsim/generate/labels.py +++ b/src/supramolsim/generate/labels.py @@ -209,8 +209,6 @@ def construct_label( fluorophore_id: str = "AF647", lab_eff: float = None, target_info=None, - enable_wobble=False, - wobble_theta=None, **kwargs, ): """ @@ -244,9 +242,8 @@ def construct_label( label_params["conjugation_sites"]["efficiency"] = kwargs["conjugation_efficiency"] if "epitope_target_info" in kwargs.keys(): label_params["epitope"]["target"] = kwargs["epitope_target_info"] - if enable_wobble: - if label_params["binding"]["wobble_range"]["theta"] is None: - label_params["binding"]["wobble_range"]["theta"] = wobble_theta + if "wobble_theta" in label_params.keys(): + label_params["binding"]["wobble_range"]["theta"] = label_params["wobble_theta"] else: label_params["binding"]["wobble_range"]["theta"] = None ######## information about target diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 652b5052..b95c81bd 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -186,8 +186,10 @@ def select_custom_probe(b): probe_target_value = probes_gui["mock_type_options1"].value probe_target_value2 = probes_gui["mock_type_options2"].value as_linker = probes_gui["as_linker"].value - wobble = probes_gui["wobble"].value - wobble_theta = probes_gui["wobble_theta"].value + if probes_gui["wobble"].value: + probe_wobble_theta = probes_gui["wobble_theta"].value + else: + probe_wobble_theta = None if as_linker: options_per_type1["Primary_Probe"] = [ probe_name, @@ -204,8 +206,7 @@ def select_custom_probe(b): labelling_efficiency=labelling_efficiency, probe_distance_to_epitope=probe_distance_to_epitope, as_primary=as_linker, - wobble=wobble, - wobble_theta=wobble_theta, + probe_wobble_theta=probe_wobble_theta, ) elif probe_target_type == "Atom_residue": residue = probes_gui["mock_type_options1"].value @@ -218,8 +219,7 @@ def select_custom_probe(b): labelling_efficiency=labelling_efficiency, probe_distance_to_epitope=probe_distance_to_epitope, as_primary=as_linker, - wobble=wobble, - wobble_theta=wobble_theta, + probe_wobble_theta=probe_wobble_theta, ) elif probe_target_type == "Primary": experiment.add_probe( @@ -230,8 +230,7 @@ def select_custom_probe(b): labelling_efficiency=labelling_efficiency, probe_distance_to_epitope=probe_distance_to_epitope, as_primary=as_linker, - wobble=wobble, - wobble_theta=wobble_theta, + probe_wobble_theta=probe_wobble_theta, ) probes_gui["create_particle"].disabled = False update_probe_list() From a89f07420ead749e4f8b570db9ba65181d520bc8 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 23 Jul 2025 16:14:33 +0100 Subject: [PATCH 34/42] update sequential labelling notebook --- notebooks/Example_outputs/Indirect_labelling.ipynb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/notebooks/Example_outputs/Indirect_labelling.ipynb b/notebooks/Example_outputs/Indirect_labelling.ipynb index 0490ee70..17048d43 100644 --- a/notebooks/Example_outputs/Indirect_labelling.ipynb +++ b/notebooks/Example_outputs/Indirect_labelling.ipynb @@ -71,17 +71,17 @@ "source": [ "experiment.remove_probes()\n", "experiment.add_probe(\n", - "probe_name = \"Antibody\",\n", + "probe_template = \"Antibody\",\n", "probe_target_type = \"Sequence\",\n", "probe_target_value = \"ELAVGSL\",\n", "as_primary=True,\n", ")\n", "experiment.add_probe(\n", - "probe_name = \"Nanobody\",\n", + "probe_template = \"Nanobody\",\n", "probe_target_type = \"Primary\",\n", "probe_target_value = \"Antibody\"\n", ")\n", - "experiment.build()" + "experiment.build(modules=[\"particle\", \"coordinate_field\"])" ] }, { From 520ee396430acd7c8f31de2b152cf004c0df9c41 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 23 Jul 2025 16:30:34 +0100 Subject: [PATCH 35/42] get modalities previews from new experiment instead of copying existing --- src/supramolsim/jupyter_widgets/_experiment_parameters.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/supramolsim/jupyter_widgets/_experiment_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index b95c81bd..9a462cfe 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -43,6 +43,7 @@ import numpy as np import tifffile as tif from IPython.utils import io +from ..experiments import build_virtual_microscope select_colour = "#4daf4ac7" remove_colour = "#ff8000da" @@ -664,7 +665,7 @@ def ui_select_modality(experiment): Widget for modality selection and preview. """ modalities_default = ["Widefield", "Confocal", "STED", "SMLM", "All"] - preview_experiment = copy.deepcopy(experiment) + imager, preview_experiment = build_virtual_microscope(multimodal=modalities_default) xy_zoom_in = 0.5 for mod_names in modalities_default[0:len(modalities_default)-1]: preview_experiment.add_modality(modality_name=mod_names, save=True) From ef3cfe528771d5c3e4a672e5092d4591eab963b8 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 23 Jul 2025 17:22:13 +0100 Subject: [PATCH 36/42] update config parameter settings --- src/supramolsim/configs/parameter_settings.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/supramolsim/configs/parameter_settings.yaml b/src/supramolsim/configs/parameter_settings.yaml index db9f0296..aa03fef8 100644 --- a/src/supramolsim/configs/parameter_settings.yaml +++ b/src/supramolsim/configs/parameter_settings.yaml @@ -22,5 +22,5 @@ acquisition: exp_time: ptype: numeric wtype: float_slider - range: [0, 1, 0.001] + range: [0, 0.01, 0.0001] nintervals: 2 \ No newline at end of file From 642672c40ed0d84e420970a7ecb361c620776bbb Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 23 Jul 2025 17:32:36 +0100 Subject: [PATCH 37/42] sweep_gen: default probe parameter set to none --- src/supramolsim/analysis/sweep.py | 2 +- src/supramolsim/sweep_generator.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/supramolsim/analysis/sweep.py b/src/supramolsim/analysis/sweep.py index ebe5d77c..f3691cdf 100644 --- a/src/supramolsim/analysis/sweep.py +++ b/src/supramolsim/analysis/sweep.py @@ -71,7 +71,7 @@ def sweep_vasmples( probe_filepath = os.path.join(local_dir, "probes", default_probe + ".yaml") default_params = load_yaml(probe_filepath) probe_parameters = dict() - probe_parameters[0] = default_params + probe_parameters[0] = None if particle_defects is None: particle_defects = dict() particle_defects[0] = {"use_defects": False} diff --git a/src/supramolsim/sweep_generator.py b/src/supramolsim/sweep_generator.py index 0bd932df..89f8d5c7 100644 --- a/src/supramolsim/sweep_generator.py +++ b/src/supramolsim/sweep_generator.py @@ -583,8 +583,6 @@ def generate_analysis_plots( if plot_type not in self.analysis["plots"].keys(): self.analysis["plots"][plot_type] = {} plot_params = self.plot_parameters[plot_type] - print(plot_type) - print(plot_params) if plot_type == "heatmaps": metric_plot = self._gen_heatmaps( metric_name=metric_name, @@ -640,7 +638,7 @@ def _gen_heatmaps( if category is None: category = "modality_name" if param1 is None: - param1 = "labelling_efficiency" + param1 = self.parameters_with_set_values[0] if param2 is None: param2 = "probe_n" analysis_resut_df = self.get_analysis_output(keyname="dataframes") From 88ff02ba30598a5311e42ac292ce5f798d126f73 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Thu, 24 Jul 2025 12:55:58 +0100 Subject: [PATCH 38/42] bugfix cases where depth exceeds volume --- src/supramolsim/utils/transform/image_convolution.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/supramolsim/utils/transform/image_convolution.py b/src/supramolsim/utils/transform/image_convolution.py index 6576445e..9c60e0de 100644 --- a/src/supramolsim/utils/transform/image_convolution.py +++ b/src/supramolsim/utils/transform/image_convolution.py @@ -102,6 +102,8 @@ def frame_by_volume_convolution( zfocus_slice - projection_depth_half, zfocus_slice + projection_depth_half, ) + if projection_depth_half > int(convolved_intensity.shape[2] / 2): + projection_depth_half = int(convolved_intensity.shape[2] / 2) if asframe: frame = np.sum( np.array( From ac2ce36f0703494487dee894710550565b777f5d Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Fri, 25 Jul 2025 11:02:21 +0100 Subject: [PATCH 39/42] minor update --- src/supramolsim/jupyter_widgets/sweep_parameters_widgets.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/supramolsim/jupyter_widgets/sweep_parameters_widgets.py b/src/supramolsim/jupyter_widgets/sweep_parameters_widgets.py index 3e10f88c..d52b252b 100644 --- a/src/supramolsim/jupyter_widgets/sweep_parameters_widgets.py +++ b/src/supramolsim/jupyter_widgets/sweep_parameters_widgets.py @@ -102,6 +102,7 @@ def select_structure(sweep_gen): """ ez_sweep_structure = EZInput(title="structure") ez_sweep_structure.add_dropdown("structures", options=sweep_gen.structures_info_list.keys()) + ez_sweep_structure.add_HTML("message", value="Note: parsing of the structure will be done when running the sweep", style={'font_size': '15px'}) ez_sweep_structure.add_button("Select", description="Select", icon=select_icon, style={"button_color": select_colour}) def select(b): From 2371ebbc1bb7f6b9ccd2621ef3452c4a10568c1e Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 29 Jul 2025 14:39:28 +0100 Subject: [PATCH 40/42] bugfix: use exeriment attribute for vsample generation --- src/supramolsim/sweep_generator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/supramolsim/sweep_generator.py b/src/supramolsim/sweep_generator.py index 89f8d5c7..d3a4b014 100644 --- a/src/supramolsim/sweep_generator.py +++ b/src/supramolsim/sweep_generator.py @@ -118,6 +118,7 @@ def generate_virtual_samples(self): self.create_parameters_iterables() self.experiment, self.virtual_samples, self.virtual_samples_parameters = ( sweep.sweep_vasmples( + experiment=self.experiment, structures=self.structures, probes=self.probes, probe_parameters=self.probe_parameters, From f64927d0d93747e2d23d91e93e03fc0b9296ad78 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 29 Jul 2025 15:02:32 +0100 Subject: [PATCH 41/42] save image parameters yml --- src/supramolsim/sweep_generator.py | 4 +++- src/supramolsim/utils/io/yaml_functions.py | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/supramolsim/sweep_generator.py b/src/supramolsim/sweep_generator.py index d3a4b014..e9dad252 100644 --- a/src/supramolsim/sweep_generator.py +++ b/src/supramolsim/sweep_generator.py @@ -4,7 +4,7 @@ from IPython.utils import io import os from pathlib import Path -from .utils.io.yaml_functions import load_yaml +from .utils.io.yaml_functions import load_yaml, save_yaml from .analysis import _plots import numpy as np from datetime import datetime @@ -822,7 +822,9 @@ def save_images(self, output_name=None, output_directory=None): image = np.concatenate((image, replicates[i])) name = output_directory + param_combination_id + ".tiff" tiff.imwrite(name, image) + save_yaml(data=self.acquisition_outputs_parameters, name="acquisition_parameters", output_directory=output_directory) if self.reference_image is not None: # save reference image name_ref = output_directory + "reference.tiff" tiff.imwrite(name_ref, self.reference_image) + diff --git a/src/supramolsim/utils/io/yaml_functions.py b/src/supramolsim/utils/io/yaml_functions.py index 200c900a..da6a1fcc 100644 --- a/src/supramolsim/utils/io/yaml_functions.py +++ b/src/supramolsim/utils/io/yaml_functions.py @@ -1,4 +1,5 @@ import yaml +import os def load_yaml(yaml_file: str): @@ -8,3 +9,14 @@ def load_yaml(yaml_file: str): with open(yaml_file, "r") as f: config_dictionary = yaml.safe_load(f) return config_dictionary + + +def save_yaml(data=None, name="NONAME", output_directory=None): + """ + Saves a dictionary to a yaml file + """ + file_name = name + ".yml" + file_path = os.path.join(output_directory, file_name) + #yaml.Dumper.ignore_aliases = lambda self, data: True + with open(file_path, "w") as f: + yaml.safe_dump(data, f, default_flow_style=False) \ No newline at end of file From 6e513ec9969fd46ab8a3e8bb7950726519d6ee60 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 30 Jul 2025 11:39:13 +0100 Subject: [PATCH 42/42] updated metrics --- src/supramolsim/analysis/metrics.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/supramolsim/analysis/metrics.py b/src/supramolsim/analysis/metrics.py index 9b822fc5..8fb659ab 100644 --- a/src/supramolsim/analysis/metrics.py +++ b/src/supramolsim/analysis/metrics.py @@ -298,17 +298,20 @@ def get_circles(img, cirlce_params : dict Parameters used for circle detection. """ - if blur_px: - gray_blurred = cv2.blur(img, (blur_px, blur_px), 0) - else: - gray_blurred = img + gray_blurred = img if gray_blurred.min() < 0: gray_blurred += -gray_blurred.min() if gray_blurred.dtype != np.uint8: if gray_blurred.dtype in [np.float32, np.float64]: - gray_blurred = np.uint8(gray_blurred * 255) + #gray_blurred = np.uint8(gray_blurred * 255) + gray_blurred = np.uint8(gray_blurred/gray_blurred.max() * 255) else: - gray_blurred = gray_blurred.astype(np.uint8) + #gray_blurred = gray_blurred.astype(np.uint8) + gray_blurred = (gray_blurred/256).astype('uint8') + if blur_px: + gray_blurred = cv2.blur(gray_blurred, (blur_px, blur_px), 0) + else: + gray_blurred = gray_blurred circles = cv2.HoughCircles( gray_blurred, cv2.HOUGH_GRADIENT,