From 19bbfe7e342a0467580bfed56fa839c970266dcf Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Thu, 8 Jan 2026 13:42:34 +0000 Subject: [PATCH 1/8] fix typos --- src/vlab4mic/analysis/sweep.py | 2 +- src/vlab4mic/generate/imaging.py | 26 +++++++++---------- src/vlab4mic/generate/molecular_structure.py | 2 +- src/vlab4mic/sweep_generator.py | 2 +- .../utils/data_format/configuration_format.py | 6 ++--- src/vlab4mic/utils/transform/defects.py | 4 +-- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/vlab4mic/analysis/sweep.py b/src/vlab4mic/analysis/sweep.py index 4c21d5fc..1b12459b 100644 --- a/src/vlab4mic/analysis/sweep.py +++ b/src/vlab4mic/analysis/sweep.py @@ -840,7 +840,7 @@ def pivot_dataframes_byCategory( ) .reset_index() ) - # get mean and std accross parameter combinations of axes_param_names + # get mean and std across parameter combinations of axes_param_names condition_mean_pivot = summarised_group.pivot( index=param1, columns=param2, values="Mean_Value" ).round(4) diff --git a/src/vlab4mic/generate/imaging.py b/src/vlab4mic/generate/imaging.py index 8e276836..dbfb68b8 100644 --- a/src/vlab4mic/generate/imaging.py +++ b/src/vlab4mic/generate/imaging.py @@ -38,7 +38,7 @@ def __init__(self): self.field["reference_point"] = None self.fluorophore_params = ( dict() - ) # contiain its photophysical parameters such as excitation and emission + ) # contain its photophysical parameters such as excitation and emission self.emitters_by_fluorophore = dict() self.emitters_by_channel = dict() self.writing_dir = "" @@ -101,7 +101,7 @@ def _calculate_roi_ranges(self): ] self.roi_params["ranges"] = [xrange, yrange, zrange] - def get_absoulte_reference_point(self): + def get_absolute_reference_point(self): """ Get the absolute reference point in 3D (including focus plane). @@ -403,11 +403,11 @@ def _set_modality_channels(self, modality, fluorophores_in_channel, prints=False if prints: print(fluoname) channel_name = "ch" + str(ch) - fluorophores_in_chanel = [] - fluorophores_in_chanel.append( + fluorophores_in_channel = [] + fluorophores_in_channel.append( fluoname ) # this is because a channel can have several fluorophores - filter_dictionary[channel_name] = fluorophores_in_chanel + filter_dictionary[channel_name] = fluorophores_in_channel ch += 1 self.modalities[modality]["filters"] = filter_dictionary else: @@ -441,7 +441,7 @@ def _set_modality_psf( if "depth" not in self.modalities[modality]["psf"]: depth_default = int((psf_stack.shape)[2] / 2) if prints: - print("No depth parameter found for psf, asigning default") + print("No depth parameter found for psf, assigning default") self.modalities[modality]["psf"]["depth"] = depth_default def _set_modality_emission(self, modality, emission): @@ -450,7 +450,7 @@ def _set_modality_emission(self, modality, emission): def _set_modality_detector( self, modality, - image_size=[], # decpreciated, image size will only be taken from ROI + image_size=[], # deprecated, image size will only be taken from ROI pixelsize=None, bits_pixel=None, noise_model=None, @@ -480,7 +480,7 @@ def _set_modality_detector( def _calculate_imsize_from_ROIranges( self, mod_pixelsize - ): # THere should be specified the scale of the pixelsize of modality + ): # There should be specified the scale of the pixelsize of modality roi_scale = self.get_roi_params("scale") xrange = self.get_roi_params("ranges")[0] yrange = self.get_roi_params("ranges")[1] @@ -585,7 +585,7 @@ def generate_imaging( **kwargs, ): """ - Master funciton that generates image sequences depending on the modality + Master function that generates image sequences depending on the modality This function is responsible for Preparing the coordinates according to ROI (DONE!) Creating the Photons per frame matrix @@ -609,7 +609,7 @@ def generate_imaging( ) else: fluonames = list(self.modalities[modality]["filters"][ch]) - # prepare a dictionary that conaints the emitters per channel defined + # prepare a dictionary that contains the emitters per channel defined output_per_fluoname = dict() writing_notes = self.identifier + "_" + str(modality) + "_" + str(ch) + "_" for fluo in fluonames: # a channel could capture multiple fluorophores @@ -869,8 +869,8 @@ def add_detector_noise(self, modality, stack): def _adjust_to_pixel_depth(self, modality, stack): bits = self.modalities[modality]["detector"]["bits_pixel"] - saturaton = (2**bits) - 1 - stack[stack > saturaton] == saturaton + saturation = (2**bits) - 1 + stack[stack > saturation] == saturation return stack def _save_timeseries_with_beads(self, timeseries_stack, beads_stack, notes): @@ -1212,7 +1212,7 @@ def show_field( ax.plot_surface(xx, yy, zz, alpha=0.2) # show ROI reference point if reference_pt: - ref_pt = self.get_absoulte_reference_point() * factor + ref_pt = self.get_absolute_reference_point() * factor add_ax_scatter(ax, format_coordinates(ref_pt)) # EMITTERS PER FLUOROPHORE SPECIES if self.emitters_by_fluorophore is not None: diff --git a/src/vlab4mic/generate/molecular_structure.py b/src/vlab4mic/generate/molecular_structure.py index 0d497bfc..eea7991f 100644 --- a/src/vlab4mic/generate/molecular_structure.py +++ b/src/vlab4mic/generate/molecular_structure.py @@ -597,7 +597,7 @@ def gen_targets_by_sequence(self, target_name, sequence, **kwargs): **kwargs Additional keyword arguments (e.g., fluorophore, labeling_efficiency, method). """ - # only the first appearance of the epitope in every chain is retreived + # only the first appearance of the epitope in every chain is retrieved # if a chain has more than one epitope, only the first one is returned target_seq = sequence method = "average" diff --git a/src/vlab4mic/sweep_generator.py b/src/vlab4mic/sweep_generator.py index 3f1f566b..7a9157be 100644 --- a/src/vlab4mic/sweep_generator.py +++ b/src/vlab4mic/sweep_generator.py @@ -1369,7 +1369,7 @@ def run_parameter_sweep( sweep_gen.select_modalities(modalities=modalities) sweep_gen.set_output_directory(output_directory=output_directory) sweep_gen.set_number_of_repetitions(sweep_repetitions) - # number of particles accross sweep + # number of particles across sweep if particle_positions is not None: # set those positions sweep_gen.experiment.set_virtualsample_params( diff --git a/src/vlab4mic/utils/data_format/configuration_format.py b/src/vlab4mic/utils/data_format/configuration_format.py index 1d4db6f4..6cdb939d 100644 --- a/src/vlab4mic/utils/data_format/configuration_format.py +++ b/src/vlab4mic/utils/data_format/configuration_format.py @@ -79,11 +79,11 @@ def compile_modality_parameters( if prints: print(fluoname) channel_name = "ch" + str(ch) - fluorophores_in_chanel = [] - fluorophores_in_chanel.append( + fluorophores_in_channel = [] + fluorophores_in_channel.append( fluoname ) # this is because a channel can have several fluorophores - filter_dictionary[channel_name] = fluorophores_in_chanel + filter_dictionary[channel_name] = fluorophores_in_channel ch += 1 else: filter_dictionary = mod_pars["filters"] diff --git a/src/vlab4mic/utils/transform/defects.py b/src/vlab4mic/utils/transform/defects.py index ed3e170e..1d51996e 100644 --- a/src/vlab4mic/utils/transform/defects.py +++ b/src/vlab4mic/utils/transform/defects.py @@ -197,11 +197,11 @@ def xmersubset_byclustering( else: return np.array([]) # ids_validated are the ids of the center of each xmer that we want to preserve - # we only need to then retreive the appropiate indices of the epitopes themselves + # we only need to then retrieve the appropriate indices of the epitopes themselves # that correspond to these labels epitopes_ids = notin_logical_list( label_p_epitope, ids_validated - ) # this function retreives false + ) # this function retrieves false # for each time a value ids_validated appears in label_p_epitope final_epitopes_ids = epitopes_ids subset = epitopes_coords[final_epitopes_ids,] From 6a624c6056725969de60fa9973556d065ca80e7b Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Thu, 8 Jan 2026 13:44:02 +0000 Subject: [PATCH 2/8] fix typos in tests --- tests/test_image_generation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_image_generation.py b/tests/test_image_generation.py index c8a1dd69..6dfa6318 100644 --- a/tests/test_image_generation.py +++ b/tests/test_image_generation.py @@ -6,7 +6,7 @@ def test_simple_imaging_system(): imager, _ = experiments.build_virtual_microscope() - assert imager.get_absoulte_reference_point().shape == (1, 3) + assert imager.get_absolute_reference_point().shape == (1, 3) def test_get_raw_volume(experiment_7r5k_base): @@ -21,7 +21,7 @@ def test_multi_imaging_system(): imager, _ = experiments.build_virtual_microscope( multimodal=["STED", "Confocal"] ) - assert imager.get_absoulte_reference_point().shape == (1, 3) + assert imager.get_absolute_reference_point().shape == (1, 3) def test_image_from_field(configuration_directory, gt_structural_model_field): @@ -35,7 +35,7 @@ def test_image_from_field(configuration_directory, gt_structural_model_field): save=True, multimodal=selected_mods, ) - assert experiment_test.imager.get_absoulte_reference_point().shape == ( + assert experiment_test.imager.get_absolute_reference_point().shape == ( 1, 3, ) From a56f2a6e7cc30b6b034831ec6a66d6eec0f028f7 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Thu, 8 Jan 2026 14:30:03 +0000 Subject: [PATCH 3/8] Add missing space character in matplotlib plot --- src/vlab4mic/sweep_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vlab4mic/sweep_generator.py b/src/vlab4mic/sweep_generator.py index 7a9157be..10d505b7 100644 --- a/src/vlab4mic/sweep_generator.py +++ b/src/vlab4mic/sweep_generator.py @@ -1095,7 +1095,7 @@ def _gen_lineplots( axes.xaxis.set_major_formatter(FormatStrFormatter(decimals)) title = estimator + " " + metric_name + " for " + x_param if style is not None: - title = title + "per " + style + title = title + " per " + style plt.title(title) plt.close() return fig From 292171c160aece13418df88b74a22cb4eba297c1 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Thu, 8 Jan 2026 14:37:23 +0000 Subject: [PATCH 4/8] solve warning message due to previous call to np.diff with no explicit index to retrieve --- src/vlab4mic/utils/transform/image_convolution.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vlab4mic/utils/transform/image_convolution.py b/src/vlab4mic/utils/transform/image_convolution.py index cbc6fa10..f063bd19 100644 --- a/src/vlab4mic/utils/transform/image_convolution.py +++ b/src/vlab4mic/utils/transform/image_convolution.py @@ -35,9 +35,9 @@ def voxelate_points_withrange(coordinates, bin_pixelsize, ranges): binrange = [ranges[0], ranges[1], ranges[2]] nbins = [ - int(np.diff(ranges[0]) / bin_pixelsize), - int(np.diff(ranges[1]) / bin_pixelsize), - int(np.diff(ranges[2]) / bin_pixelsize), + int(np.diff(ranges[0])[0] / bin_pixelsize), + int(np.diff(ranges[1])[0] / bin_pixelsize), + int(np.diff(ranges[2])[0] / bin_pixelsize), ] hist3D, edges = np.histogramdd(coordinates, bins=nbins, range=binrange) return hist3D From 15b4aede016665a453946ae1148122cf5c8f8898 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Thu, 8 Jan 2026 15:56:57 +0000 Subject: [PATCH 5/8] add incresing number on filenames --- src/vlab4mic/sweep_generator.py | 59 ++++++++++++++++++++++++++++++--- src/vlab4mic/utils/io/text.py | 24 +++++++++++++- src/vlab4mic/utils/io/tiff.py | 23 +++++++++++++ 3 files changed, 100 insertions(+), 6 deletions(-) diff --git a/src/vlab4mic/sweep_generator.py b/src/vlab4mic/sweep_generator.py index 10d505b7..d26c7f7d 100644 --- a/src/vlab4mic/sweep_generator.py +++ b/src/vlab4mic/sweep_generator.py @@ -1140,6 +1140,17 @@ def save_analysis( if keyname == "dataframes": df = self.get_analysis_output(keyname) df_name = output_name + "_dataframe.csv" + files_indir = os.listdir(output_directory) + if df_name in files_indir: + count = 1 + df_name = ( + output_name + "_dataframe_" + str(count) + ".csv" + ) + while df_name in files_indir: + count += 1 + df_name = ( + output_name + "_dataframe_" + str(count) + ".csv" + ) df.to_csv(os.path.join(output_directory, df_name), index=False) elif keyname == "plots": plots_dictionary = self.get_analysis_output(keyname) @@ -1153,6 +1164,31 @@ def save_analysis( + plot_type + ".png" ) + current_files = os.listdir(output_directory) + if figure_name in current_files: + count = 1 + figure_name = ( + output_name + + "_" + + metric + + "_" + + plot_type + + "_" + + str(count) + + ".png" + ) + while figure_name in current_files: + dt_string = dt_string + "_1" + figure_name = ( + output_name + + "_" + + metric + + "_" + + plot_type + + "_" + + str(count) + + ".png" + ) plot.savefig( os.path.join(output_directory, figure_name) ) @@ -1182,11 +1218,21 @@ def save_images(self, output_name=None, output_directory=None, floats_as=float): - If `self.reference_image` is present, saves it as "reference.tiff" in the output directory. - Saves acquisition parameters as a YAML file in the output directory. """ + now = datetime.now() # dd/mm/YY H:M:S + dt_string = now.strftime("%Y%m%d") if output_name is None: output_name = "vLab4mic_images_" if output_directory is None: + foldername = "simulated_images_" + dt_string + filesindir = os.listdir(self.output_directory) + if foldername in filesindir: + count = 1 + foldername = "simulated_images_" + dt_string + "_" + str(count) + while foldername in filesindir: + count+=1 + foldername = "simulated_images_" + dt_string + "_" + str(count) output_directory = os.path.join( - self.output_directory, "simulated_images", "" + self.output_directory, foldername ) if not os.path.exists(output_directory): os.makedirs(output_directory) @@ -1198,8 +1244,9 @@ def save_images(self, output_name=None, output_directory=None, floats_as=float): image = replicates[0] for i in range(1, nreps): image = np.concatenate((image, replicates[i])) - name = output_directory + param_combination_id + ".tiff" - tiff.imwrite(name, image) + name = param_combination_id + ".tiff" + dir_name = os.path.join(output_directory, name) + tiff.imwrite(dir_name, image) if floats_as is not None and callable(floats_as): copy_of_params = copy.deepcopy(self.acquisition_outputs_parameters) for combination_id, list_of_parameters in copy_of_params.items(): @@ -1221,8 +1268,10 @@ def save_images(self, output_name=None, output_directory=None, floats_as=float): ) if self.reference_image is not None: # save reference image - name_ref = output_directory + "reference.tiff" - tiff.imwrite(name_ref, self.reference_image) + name_ref = param_combination_id + ".tiff" + dir_name_ref = os.path.join(output_directory, name_ref) + #name_ref = output_directory + "reference.tiff" + tiff.imwrite(dir_name_ref, self.reference_image) def run_parameter_sweep( diff --git a/src/vlab4mic/utils/io/text.py b/src/vlab4mic/utils/io/text.py index 2b692859..5cbea797 100644 --- a/src/vlab4mic/utils/io/text.py +++ b/src/vlab4mic/utils/io/text.py @@ -1,11 +1,33 @@ from datetime import datetime import numpy as np - +import os def write_txt(list_of_lines: list, dirname: str, notes: str): now = datetime.now() # dd/mm/YY H:M:S sim_dt_string = now.strftime("%Y%m%d") + "_" filename = dirname + sim_dt_string + notes + ".csv" + current_files = os.listdir(dirname) + if filename.split("/")[-1] in current_files: + count = 1 + new_filename = ( + dirname + + sim_dt_string + + notes + + "_" + + str(count) + + ".csv" + ) + while new_filename.split("/")[-1] in current_files: + count += 1 + new_filename = ( + dirname + + sim_dt_string + + notes + + "_" + + str(count) + + ".csv" + ) + filename = new_filename text_file = open(filename, "w") for li in range(len(list_of_lines)): text_file.write(list_of_lines[li]) diff --git a/src/vlab4mic/utils/io/tiff.py b/src/vlab4mic/utils/io/tiff.py index 984dc541..11080a28 100644 --- a/src/vlab4mic/utils/io/tiff.py +++ b/src/vlab4mic/utils/io/tiff.py @@ -1,6 +1,7 @@ import tifffile as tif from datetime import datetime import numpy as np +import os def write_tif(image_stack: np.ndarray, dirname: str, notes: str): @@ -12,5 +13,27 @@ def write_tif(image_stack: np.ndarray, dirname: str, notes: str): else: image_stack = image_stack.astype(np.uint32) filename = dirname + dt_string + notes + ".tif" + current_files = os.listdir(dirname) + if filename.split("/")[-1] in current_files: + count = 1 + new_filename = ( + dirname + + dt_string + + notes + + "_" + + str(count) + + ".tif" + ) + while new_filename.split("/")[-1] in current_files: + count += 1 + new_filename = ( + dirname + + dt_string + + notes + + "_" + + str(count) + + ".tif" + ) + filename = new_filename print(f"image saved in {filename}") tif.imwrite(filename, image_stack, bigtiff=True) From 34bc000b83cba6a23afa32e9356b7a4bae712c87 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Thu, 8 Jan 2026 16:31:38 +0000 Subject: [PATCH 6/8] ParameterSweep: add option to use Nan values to zero when plotting. Does not affect dataframe output. --- src/vlab4mic/analysis/_plots.py | 4 ++-- src/vlab4mic/sweep_generator.py | 13 ++++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/vlab4mic/analysis/_plots.py b/src/vlab4mic/analysis/_plots.py index 1b8c60e7..9ef65da6 100644 --- a/src/vlab4mic/analysis/_plots.py +++ b/src/vlab4mic/analysis/_plots.py @@ -14,7 +14,7 @@ def sns_heatmap_pivots( return_figure=False, metric_name=None, decimals="%.4f", - fillna = True, + na_as_zero = True, **kwargs, ): conditions = list(df_pivots.keys()) @@ -37,7 +37,7 @@ def sns_heatmap_pivots( else: metric_n = "Metric" for n, cond in enumerate(conditions): - if fillna: + if na_as_zero: mask = df_pivots[cond][0].isna() df_pivots[cond][0][mask] = 0.0 mask2 = df_pivots[cond][1].isna() diff --git a/src/vlab4mic/sweep_generator.py b/src/vlab4mic/sweep_generator.py index d26c7f7d..c66270df 100644 --- a/src/vlab4mic/sweep_generator.py +++ b/src/vlab4mic/sweep_generator.py @@ -876,6 +876,7 @@ def generate_analysis_plots( decimals: int = None, return_figure=True, filter_dictionary=None, + na_as_zero = True, **kwargs, ): """ @@ -918,6 +919,7 @@ def generate_analysis_plots( return_figure=return_figure, decimals=decimals, filter_dictionary=filter_dictionary, + na_as_zero = na_as_zero, **plot_params, **kwargs ) @@ -929,6 +931,7 @@ def generate_analysis_plots( decimals=decimals, return_figure=return_figure, filter_dictionary=filter_dictionary, + na_as_zero = na_as_zero, **plot_params, **kwargs ) @@ -945,6 +948,7 @@ def _gen_heatmaps( filter_dictionary=None, annotations=False, palette=None, + na_as_zero = False, **kwargs, ): """ @@ -1016,6 +1020,7 @@ def _gen_heatmaps( metric_name=metric_name, conditions_cmaps=[cmap_palette]*nconditions, decimals=decimals, + na_as_zero = na_as_zero, **kwargs ) return plot @@ -1034,6 +1039,7 @@ def _gen_lineplots( decimals="%.4f", return_figure=True, filter_dictionary=None, + na_as_zero = False, **kwargs, ): """ @@ -1079,8 +1085,13 @@ def _gen_lineplots( if style is None and len(self.parameters_with_set_values) > 1: style = self.parameters_with_set_values[1] fig, axes = plt.subplots(figsize=figsize) + if na_as_zero: + data_to_plot = data.copy(deep=True) + data_to_plot.fillna(0, inplace=True) + else: + data_to_plot = data sns.lineplot( - data=data, + data=data_to_plot, x=x_param, y=metric_name, hue=hue, From 9f56aff909a3aca873b6fe8f10ab3005eab5fb50 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Thu, 8 Jan 2026 16:58:46 +0000 Subject: [PATCH 7/8] update high level function of parameter sweep with na_as_zero for plots --- src/vlab4mic/sweep_generator.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/vlab4mic/sweep_generator.py b/src/vlab4mic/sweep_generator.py index c66270df..52f4398c 100644 --- a/src/vlab4mic/sweep_generator.py +++ b/src/vlab4mic/sweep_generator.py @@ -95,6 +95,8 @@ def __init__(self): self.plot_parameters["lineplots"]["style"] = None self.plot_parameters["lineplots"]["estimator"] = "mean" self.plot_parameters["lineplots"]["errorbar"] = "ci" + self.plot_parameters["general"] = {} + self.plot_parameters["general"]["na_as_zero"] = True self.structures_info_list = self.experiment.structures_info_list # Use the directly loaded parameter_settings instead of experiment.param_settings # to ensure all parameter groups (including particle_defect) are available @@ -753,6 +755,22 @@ def set_plot_parameters(self, plot_type, **kwargs): for key, val in kwargs.items(): self.plot_parameters[plot_type][key] = val + def set_na_as_zero_in_plots(self, na_as_zero: bool = True): + """ + Set whether to treat NaN values as zero in plots. + + Parameters + ---------- + :param na_as_zero: bool, optional + If True, NaN values will be treated as zero in plots. Defaults to True. + This does not affect the underlying data, only the visualization. + + Returns + ------- + None + """ + self.plot_parameters["general"]["na_as_zero"] = na_as_zero + def run_analysis( self, save=True, @@ -818,6 +836,7 @@ def run_analysis( return_figure=True, metric_name=metric_name, filter_dictionary=None, + na_as_zero=self.plot_parameters["general"]["na_as_zero"], ) if save: self.save_analysis( @@ -1331,6 +1350,8 @@ def run_parameter_sweep( psf_voxel_nm = None, depth_of_field_nm = None, exp_time = None, + # for plot generation + na_as_zero = True, # Add more as needed for your sweep ): """ @@ -1476,6 +1497,7 @@ def run_parameter_sweep( reference_structure=reference_structure, reference_probe=reference_probe, **reference_parameters) + sweep_gen.set_na_as_zero_in_plots(na_as_zero=na_as_zero) if run_analysis: sweep_gen.run_analysis( save=save_analysis_results, From a7c8d3ba898742f3604cf7022e4f32216a80dd11 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Thu, 8 Jan 2026 17:25:56 +0000 Subject: [PATCH 8/8] ParameterSweep: create matplotlib subplots with squeeze option to False to avoid index mismatches --- src/vlab4mic/analysis/_plots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vlab4mic/analysis/_plots.py b/src/vlab4mic/analysis/_plots.py index 9ef65da6..9a30a7e0 100644 --- a/src/vlab4mic/analysis/_plots.py +++ b/src/vlab4mic/analysis/_plots.py @@ -23,7 +23,7 @@ def sns_heatmap_pivots( annot_kws = {"size": 10, "rotation": 45} else: annot_kws = kwargs["annot_kws"] - f, axes = plt.subplots(nconditions, 2, figsize=figsize) + f, axes = plt.subplots(nconditions, 2, figsize=figsize, squeeze = False) plot_num = 0 if cmaps_range == "same": # min and max here correspond to SSIM