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\"])" ] }, { 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, 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/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 diff --git a/src/supramolsim/experiments.py b/src/supramolsim/experiments.py index cb956f01..ace99eb5 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) @@ -67,12 +73,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") @@ -214,6 +222,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, ): """ @@ -277,6 +286,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] @@ -822,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, @@ -931,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 @@ -992,6 +1008,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", @@ -1008,7 +1028,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( diff --git a/src/supramolsim/generate/labels.py b/src/supramolsim/generate/labels.py index 0ffad43f..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, ): """ @@ -230,8 +228,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(): @@ -242,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/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_parameters.py b/src/supramolsim/jupyter_widgets/_experiment_parameters.py index 6e721e6b..9a462cfe 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_parameters.py +++ b/src/supramolsim/jupyter_widgets/_experiment_parameters.py @@ -42,6 +42,22 @@ from supramolsim.utils.visualisation.matplotlib_plots import slider_normalised 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" +update_colour = "#00bfffda" + +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" +upload_icon = "fa-upload" + def ui_select_structure(experiment): """ @@ -60,13 +76,16 @@ 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= loding_icon #elements["select_structure"].disabled = True 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.capture_output() as captured: + experiment.build(modules="structure") update_structure_list() #elements["select_structure"].disabled = False + elements["select_structure"].icon= select_icon for wgt in elements.keys(): elements[wgt].disabled = False @@ -87,6 +106,8 @@ def update_structure_list(): select_structure, gui.elements, description="Select structure", + icon=select_icon, + style={"button_color": select_colour}, ) return gui @@ -110,7 +131,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): """ @@ -158,8 +187,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, @@ -176,8 +207,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 @@ -190,8 +220,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( @@ -202,8 +231,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() @@ -217,7 +245,8 @@ def update_probe_list(): def create_particle(b): probes_gui["message2"].value = "Creating labelled structure..." - experiment.build(modules=["particle"]) + with io.capture_output() as captured: + experiment.build(modules=["particle"]) probes_gui["add_probe"].disabled = True probes_gui["create_particle"].disabled = True if experiment.generators_status("particle"): @@ -255,16 +284,23 @@ 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:", 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=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") @@ -356,8 +392,10 @@ def type_dropdown_change(change): description="Wobble cone range (degrees)", ) probes_gui.add_button("add_custom_probe", - description="Select probe with custom parameters", - disabled=False) + description="Add probe with custom parameters", + disabled=False, + icon=add_icon, + ) probes_gui["mock_type"].observe(type_dropdown_change, names="value") # def toggle_advanced_parameters(b): @@ -379,19 +417,21 @@ def toggle_advanced_parameters(b): "add_probe", select_probe, probes_gui.elements, - description="Select probe (with defaults)", + 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) 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") - + _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 @@ -425,9 +465,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 @@ -445,6 +485,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, @@ -458,14 +505,8 @@ def update_message(): step=1, style={"description_width": "initial"}, ) - - sample_gui.add_button( - "advanced_parameters", - description="Toggle advanced parameters", - ) - #### 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)", @@ -511,28 +552,45 @@ 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", - disabled=False + description="Select parameters and build virtual sample", + 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): + + 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.build(modules=["coordinate_field"]) - if experiment.objects_created["imager"]: - experiment.build(modules=["imager"]) + 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): + with io.capture_output() 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 img = tif.imread(filepath) @@ -567,6 +625,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"] @@ -578,22 +638,16 @@ 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") - 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 + _unstyle_widgets(sample_gui, widgets_visibility) 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) + 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 def ui_select_modality(experiment): @@ -611,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) @@ -635,6 +689,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": @@ -653,14 +717,20 @@ def remove_modality(b): update_message() def select_modalities(b): - experiment.build(modules=["imager"]) - modality_gui["add_modality"].disabled = True - modality_gui["remove_modality"].disabled = True + with io.capture_output() as captured: + experiment.build(modules=["imager"]) + b1.disabled = True + b2.disabled = True modality_gui["select_modalities"].disabled = True 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) @@ -670,30 +740,29 @@ 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"] + 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) 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 +780,84 @@ def update_plot(change): options=modalities_default, on_change=update_plot, ) - modality_gui.add_button( - "add_modality", - description="Add modality", - disabled=False + b1 = widgets.Button( + description="Add Modality", + layout=widgets.Layout(width="50%"), + icon="fa-plus" + ) + b2 = widgets.Button( + description="Remove Modality", + layout=widgets.Layout(width="50%"), + icon="fa-minus" + ) + b3 = widgets.Button( + description="Update modality parameters", + style={"button_color": "#4985b7d9"}, + layout=widgets.Layout(width="100%"), + icon="fa-wrench" + ) + modality_gui.add_custom_widget( + "add_remove", + widgets.HBox, + children=[ + b1, + b2 + ] ) - modality_gui.add_button( - "remove_modality", - description="Remove modality", - disabled=False + select_modalities_button = widgets.Button( + description="Select modalities and update virtual microscope", + style={"button_color": "#4daf4ac7"}, + layout=widgets.Layout(width="100%"), + icon="fa-check" ) - modality_gui.add_button( + modality_gui.add_custom_widget( "select_modalities", - description="Select list and update virtual modalities", + widgets.HBox, + children=[ + select_modalities_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", + widgets.HBox, + children=[ + button_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, + ] + ) + 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", + widgets.HBox, + children=[ + button_toggle_preview + ] ) - modality_gui.add_label("Modality information") modality_gui.add_HTML( "modality_info", "" @@ -733,8 +865,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 +876,28 @@ def update_plot(change): description="Preview of selected modality", style={"description_width": "initial"}, ) - + 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"] + update_widgets_visibility(modality_gui, widgets_visibility) - modality_gui["add_modality"].on_click(add_modality) - modality_gui["remove_modality"].on_click(remove_modality) - modality_gui["select_modalities"].on_click(select_modalities) + 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 = {} + _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) + select_modalities_button.on_click(select_modalities) + button_toggle_advanced_parameters.on_click(toggle_advanced_parameters) + b3.on_click(update_modality_params) + button_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 @@ -778,7 +927,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.capture_output() 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." @@ -807,6 +957,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 aec1d6e7..a68578ac 100644 --- a/src/supramolsim/jupyter_widgets/_experiment_visualisation.py +++ b/src/supramolsim/jupyter_widgets/_experiment_visualisation.py @@ -45,6 +45,21 @@ 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. @@ -66,6 +81,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 ui_show_structure(experiment): """ Create a widget for visualising the experiment structure. @@ -94,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() @@ -112,6 +136,7 @@ def show_structure(widget_elements): show_structure, gui.elements, description="Show structure", + icon=show_icon, ) def update_plot(value): @@ -148,9 +173,8 @@ 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 widgets_visibility["vview"] = False @@ -210,7 +234,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", @@ -255,10 +283,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 @@ -268,9 +293,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 @@ -298,6 +321,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 @@ -312,6 +338,7 @@ def update_plot(change): gui.add_button( "show_virtual_sample", description="Show virtual sample", + icon=show_icon, ) gui.add_int_slider( "horizontal_view", @@ -335,7 +362,11 @@ def update_plot(change): on_change=update_plot, disabled=True, ) - + 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 @@ -548,10 +579,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, ) @@ -574,7 +605,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, @@ -595,7 +627,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" @@ -632,8 +664,18 @@ 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_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", + icon=reset_icon) acquisition_gui["Set"].on_click(set_params) acquisition_gui["Clear"].on_click(clear) acquisition_gui.add_checkbox( @@ -655,11 +697,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 @@ -671,14 +709,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 @@ -726,6 +756,7 @@ def show_results(b): gui.add_button( "show_results", description="Show Results", + icon=show_icon, ) def update_plot(change): diff --git a/src/supramolsim/jupyter_widgets/sweep_parameters_widgets.py b/src/supramolsim/jupyter_widgets/sweep_parameters_widgets.py index e63a9676..d52b252b 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,8 @@ 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_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): sweep_gen.structures = [sweep_gen.structures_info_list[ @@ -136,7 +161,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 +194,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 +303,7 @@ def show_reference(b): reference.add_button( "advanced_parameters", description="Toggle advanced parameters", + icon=toggle_icon ) # advanced parameters reference.add_HTML( @@ -294,7 +322,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 +341,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 +355,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 +463,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 +489,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 +506,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 +531,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 +589,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..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 @@ -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, @@ -276,7 +277,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]) @@ -583,8 +584,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 +639,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") @@ -823,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/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): 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 diff --git a/src/supramolsim/utils/transform/image_convolution.py b/src/supramolsim/utils/transform/image_convolution.py index 4f96b672..9c60e0de 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,16 @@ 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 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( convolved_intensity[ - :, :, zfocus_slice - projection_depth : zfocus_slice + projection_depth + :, :, zfocus_slice - projection_depth_half : zfocus_slice + projection_depth_half ] ), axis=2, 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):