From 9d8f3646f0a62eb2d14d9e3c3f220ed4c46c6ac7 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Fri, 17 Apr 2026 15:03:02 +0100 Subject: [PATCH 01/17] create method to simulate localisation table of emitters --- .../utils/transform/points_transforms.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/vlab4mic/utils/transform/points_transforms.py b/src/vlab4mic/utils/transform/points_transforms.py index cfc6e17..49e7793 100644 --- a/src/vlab4mic/utils/transform/points_transforms.py +++ b/src/vlab4mic/utils/transform/points_transforms.py @@ -205,4 +205,20 @@ def apply_euler_rotation(vector, phi=0, theta=0, psi=0, order = "zyx", reset_ori """ combined_R = R.from_euler(order, [phi,theta, psi], degrees=True) new_vector = combined_R.apply(vector) - return new_vector \ No newline at end of file + return new_vector + + +def generate_localisations_with_noise(array3d, loc_precision_nm, av_loc_per_emitter=1, z_pos=0): + locs_i_x_list = [] + locs_i_y_list = [] + for emitter in range(array3d.shape[0]): + n_locs = np.random.poisson(lam=av_loc_per_emitter) + locs_i_x = np.random.normal(loc=array3d[emitter][0], scale=loc_precision_nm, size=n_locs) + locs_i_y = np.random.normal(loc=array3d[emitter][1], scale=loc_precision_nm, size=n_locs) + locs_i_x_list.extend(locs_i_x.tolist()) + locs_i_y_list.extend(locs_i_y.tolist()) + noisy_locs = np.zeros(shape=(len(locs_i_x_list), 3)) + noisy_locs[:,0] = locs_i_x_list + noisy_locs[:,1] = locs_i_y_list + noisy_locs[:,2] = np.repeat(z_pos, len(locs_i_x_list)) + return noisy_locs \ No newline at end of file From 92d5e882a43a842a5bc07b3738f6461f62d533ed Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Fri, 17 Apr 2026 17:47:20 +0100 Subject: [PATCH 02/17] include emitter parameter for modality config file --- src/vlab4mic/configs/modalities/SMLM.yaml | 4 +++- src/vlab4mic/utils/data_format/configuration_format.py | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/vlab4mic/configs/modalities/SMLM.yaml b/src/vlab4mic/configs/modalities/SMLM.yaml index 36a512a..621d848 100644 --- a/src/vlab4mic/configs/modalities/SMLM.yaml +++ b/src/vlab4mic/configs/modalities/SMLM.yaml @@ -23,7 +23,9 @@ detector: mean: 0 standard_dev: 0 ADU: 1 - +emitters: + precision: 5 + nlocalisations: 5 # no value is only poisson noise. Expected order of values # p (binomial), mean, standard deviation (gaussian), gain (gamma), mean, standard deviation (abaselevel), adu (conversion factor) \ No newline at end of file diff --git a/src/vlab4mic/utils/data_format/configuration_format.py b/src/vlab4mic/utils/data_format/configuration_format.py index 6cdb939..f2eb7be 100644 --- a/src/vlab4mic/utils/data_format/configuration_format.py +++ b/src/vlab4mic/utils/data_format/configuration_format.py @@ -54,6 +54,10 @@ def compile_modality_parameters( noise_order=["binomial", "gamma", "baselevel", "gaussian", "conversion"], bits_pixel=32, ) + if "emitters" in mod_pars.keys(): + emitters = mod_pars["emitters"] + else: + emitters = None # get filters default should be one per channel if fluo_emissions is None: filter_dictionary = None @@ -65,6 +69,7 @@ def compile_modality_parameters( detector=detector_params, emission=emission_behaviour, # blinking or constant modality=modality_name, + emitters=emitters ) return modality_params, mod_pars else: @@ -98,6 +103,7 @@ def compile_modality_parameters( detector=detector_params, emission=emission_behaviour, # blinking or constant modality=modality_name, + emitters=emitters ) return modality_params, mod_pars From ee2dbad8f557e0625a6c5fbafe5e39dd754cd985 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Fri, 17 Apr 2026 17:53:19 +0100 Subject: [PATCH 03/17] add emitter params when creating modality in imager --- src/vlab4mic/generate/imaging.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/vlab4mic/generate/imaging.py b/src/vlab4mic/generate/imaging.py index dbfb68b..d1d3f23 100644 --- a/src/vlab4mic/generate/imaging.py +++ b/src/vlab4mic/generate/imaging.py @@ -359,6 +359,7 @@ def set_imaging_modality( detector: dict, emission="blinking", modality: str = "modality1", + emitters: dict = None, prints=False, **kwargs, ): @@ -387,10 +388,25 @@ def set_imaging_modality( self._set_modality_emission(modality, emission) self._set_modality_psf(modality, **psf_params, prints=prints) self._set_modality_detector(modality, **detector) + if emitters is not None: + self._set_emitter_params(modality, **emitters) + else: + self._set_emitter_params(modality) + + def _set_emitter_params(self, modality:str, precision = None, nlocalisations = None): + self.modalities[modality]["emitters"] = dict() + if precision is not None: + self.modalities[modality]["emitters"]["precision"] = precision + else: + self.modalities[modality]["emitters"]["precision"] = None + if nlocalisations is not None: + self.modalities[modality]["emitters"]["nlocalisations"] = nlocalisations + else: + self.modalities[modality]["emitters"]["nlocalisations"] = None def _create_modality(self, modality: str): self.modalities[modality] = dict( - filters=None, detector=None, psf=None, emission=None + filters=None, detector=None, psf=None, emission=None, emitters=None ) def _set_modality_channels(self, modality, fluorophores_in_channel, prints=False): From 41eac19764456abed89fcc5577e263fe0f1faf06 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Fri, 17 Apr 2026 17:54:35 +0100 Subject: [PATCH 04/17] render emitter positions as localisation sampled from the ground truth position --- src/vlab4mic/generate/imaging.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/vlab4mic/generate/imaging.py b/src/vlab4mic/generate/imaging.py index d1d3f23..7490c9e 100644 --- a/src/vlab4mic/generate/imaging.py +++ b/src/vlab4mic/generate/imaging.py @@ -17,6 +17,7 @@ from ..utils.data_format.visualisation import format_coordinates from ..utils.visualisation.matplotlib_plots import add_ax_scatter from ..utils.transform.noise import add_image_noise +from ..utils.transform import points_transforms class Imager: @@ -662,6 +663,22 @@ def generate_imaging( field_data, psf_data = self._homogenise_scales4convolution_modality( modality, emitters, photons_frames ) + # check for parameters for localisaiton generation + loc_precision_nm = self.modalities[modality]["emitters"]["precision"] + av_loc_per_emitter = self.modalities[modality]["emitters"]["nlocalisations"] + if loc_precision_nm is not None and av_loc_per_emitter is not None: + localisations = points_transforms.generate_localisations_with_noise( + array3d=field_data["field_coordinates"], + loc_precision_nm=loc_precision_nm, + av_loc_per_emitter=av_loc_per_emitter, + z_pos=0 + ) + n_emitters = localisations.shape[0] + photons_frames, emission_notes = self.calculate_photons_per_frame( + modality, fluo, n_emitters, nframes, exp_time, equal=100 + ) + field_data["field_coordinates"] = localisations + field_data["photons_frames"] = photons_frames # write emitter positions after being placed in the FOV gt_notes = writing_notes_fluo + "_usedForImaging" emitters_to_export = field_data["field_coordinates"] @@ -994,7 +1011,7 @@ def get_emitters_in_ROI(self, fluoname: str, masks=False): return copy.copy(emitters_in_ROI) def calculate_photons_per_frame( - self, modality, fluo, n_emitters, nframes, exp_time=1, **kwargs + self, modality, fluo, n_emitters, nframes, exp_time=1, equal=None, **kwargs ): """ Calculate the number of photons per frame for emitters. @@ -1035,7 +1052,11 @@ def calculate_photons_per_frame( ) emission_notes = dictionary2string(kinetics) else: #if emission == "constant": - photons_per_second = self.fluorophore_params[fluo]["photons_per_second"] + if equal is not None: + photons_per_second = equal, + exp_time = 1 + else: + photons_per_second = self.fluorophore_params[fluo]["photons_per_second"] photons_per_frame = exp_time * photons_per_second print(f"Average number of photons per frame: {photons_per_frame}") photon_frames = self._generate_constant_emission_modality( From b11459ca4561b9081767931d63c75485e6f89637 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Fri, 17 Apr 2026 18:21:04 +0100 Subject: [PATCH 05/17] include option to set locs params form update modality method --- src/vlab4mic/experiments.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/vlab4mic/experiments.py b/src/vlab4mic/experiments.py index bf88278..080f3e0 100644 --- a/src/vlab4mic/experiments.py +++ b/src/vlab4mic/experiments.py @@ -280,6 +280,9 @@ def update_modality( psf_voxel_nm: int = None, depth_of_field_nm: int = None, remove=False, + loc_precision = None, + nlocalisations = None, + simulate_localistations = False, **kwargs, ): """ @@ -355,6 +358,17 @@ def update_modality( "depth" ] = depth changes = True + if simulate_localistations: + if loc_precision is not None: + self.imaging_modalities[modality_name]["emitters"]["precision"] = loc_precision + changes = True + if nlocalisations is not None: + self.imaging_modalities[modality_name]["emitters"]["nlocalisations"] = nlocalisations + changes = True + else: + self.imaging_modalities[modality_name]["emitters"]["precision"] = None + self.imaging_modalities[modality_name]["emitters"]["nlocalisations"] = None + changes = True if changes: self.imager.set_imaging_modality( **self.imaging_modalities[modality_name] From 78e67d794875933a38ac3881a95901e4e1027774 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Mon, 20 Apr 2026 14:24:37 +0100 Subject: [PATCH 06/17] incude zpos when simulating locs --- src/vlab4mic/generate/imaging.py | 1 - src/vlab4mic/utils/transform/points_transforms.py | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vlab4mic/generate/imaging.py b/src/vlab4mic/generate/imaging.py index 7490c9e..16dc77f 100644 --- a/src/vlab4mic/generate/imaging.py +++ b/src/vlab4mic/generate/imaging.py @@ -671,7 +671,6 @@ def generate_imaging( array3d=field_data["field_coordinates"], loc_precision_nm=loc_precision_nm, av_loc_per_emitter=av_loc_per_emitter, - z_pos=0 ) n_emitters = localisations.shape[0] photons_frames, emission_notes = self.calculate_photons_per_frame( diff --git a/src/vlab4mic/utils/transform/points_transforms.py b/src/vlab4mic/utils/transform/points_transforms.py index 49e7793..4f73802 100644 --- a/src/vlab4mic/utils/transform/points_transforms.py +++ b/src/vlab4mic/utils/transform/points_transforms.py @@ -211,14 +211,17 @@ def apply_euler_rotation(vector, phi=0, theta=0, psi=0, order = "zyx", reset_ori def generate_localisations_with_noise(array3d, loc_precision_nm, av_loc_per_emitter=1, z_pos=0): locs_i_x_list = [] locs_i_y_list = [] + locs_i_z_list = [] for emitter in range(array3d.shape[0]): n_locs = np.random.poisson(lam=av_loc_per_emitter) locs_i_x = np.random.normal(loc=array3d[emitter][0], scale=loc_precision_nm, size=n_locs) locs_i_y = np.random.normal(loc=array3d[emitter][1], scale=loc_precision_nm, size=n_locs) + locs_i_z = np.random.normal(loc=array3d[emitter][2], scale=loc_precision_nm, size=n_locs) locs_i_x_list.extend(locs_i_x.tolist()) locs_i_y_list.extend(locs_i_y.tolist()) + locs_i_z_list.extend(locs_i_z.tolist()) noisy_locs = np.zeros(shape=(len(locs_i_x_list), 3)) noisy_locs[:,0] = locs_i_x_list noisy_locs[:,1] = locs_i_y_list - noisy_locs[:,2] = np.repeat(z_pos, len(locs_i_x_list)) + noisy_locs[:,2] = locs_i_z_list return noisy_locs \ No newline at end of file From bfdad15c4c64e1d4a37d18170f3077698ee9c00c Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Mon, 20 Apr 2026 17:07:37 +0100 Subject: [PATCH 07/17] Update method to generate localisation --- src/vlab4mic/configs/modalities/SMLM.yaml | 3 ++- src/vlab4mic/experiments.py | 13 ++++++++---- src/vlab4mic/generate/imaging.py | 20 ++++++++++++------- .../utils/transform/points_transforms.py | 8 ++++---- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/vlab4mic/configs/modalities/SMLM.yaml b/src/vlab4mic/configs/modalities/SMLM.yaml index 621d848..d19f37b 100644 --- a/src/vlab4mic/configs/modalities/SMLM.yaml +++ b/src/vlab4mic/configs/modalities/SMLM.yaml @@ -24,7 +24,8 @@ detector: standard_dev: 0 ADU: 1 emitters: - precision: 5 + lateral_precision: 5 + axial_precision: 5 nlocalisations: 5 # no value is only poisson noise. Expected order of values diff --git a/src/vlab4mic/experiments.py b/src/vlab4mic/experiments.py index 080f3e0..38d8f8d 100644 --- a/src/vlab4mic/experiments.py +++ b/src/vlab4mic/experiments.py @@ -280,7 +280,8 @@ def update_modality( psf_voxel_nm: int = None, depth_of_field_nm: int = None, remove=False, - loc_precision = None, + lateral_precision = None, + axial_precision = None, nlocalisations = None, simulate_localistations = False, **kwargs, @@ -359,14 +360,18 @@ def update_modality( ] = depth changes = True if simulate_localistations: - if loc_precision is not None: - self.imaging_modalities[modality_name]["emitters"]["precision"] = loc_precision + if lateral_precision is not None: + self.imaging_modalities[modality_name]["emitters"]["lateral_precision"] = lateral_precision + changes = True + if axial_precision is not None: + self.imaging_modalities[modality_name]["emitters"]["axial_precision"] = axial_precision changes = True if nlocalisations is not None: self.imaging_modalities[modality_name]["emitters"]["nlocalisations"] = nlocalisations changes = True else: - self.imaging_modalities[modality_name]["emitters"]["precision"] = None + self.imaging_modalities[modality_name]["emitters"]["lateral_precision"] = None + self.imaging_modalities[modality_name]["emitters"]["axial_precision"] = None self.imaging_modalities[modality_name]["emitters"]["nlocalisations"] = None changes = True if changes: diff --git a/src/vlab4mic/generate/imaging.py b/src/vlab4mic/generate/imaging.py index 16dc77f..4836ed4 100644 --- a/src/vlab4mic/generate/imaging.py +++ b/src/vlab4mic/generate/imaging.py @@ -394,12 +394,16 @@ def set_imaging_modality( else: self._set_emitter_params(modality) - def _set_emitter_params(self, modality:str, precision = None, nlocalisations = None): + def _set_emitter_params(self, modality:str, lateral_precision = None, axial_precision = None, nlocalisations = None): self.modalities[modality]["emitters"] = dict() - if precision is not None: - self.modalities[modality]["emitters"]["precision"] = precision + if lateral_precision is not None: + self.modalities[modality]["emitters"]["lateral_precision"] = lateral_precision else: - self.modalities[modality]["emitters"]["precision"] = None + self.modalities[modality]["emitters"]["lateral_precision"] = None + if axial_precision is not None: + self.modalities[modality]["emitters"]["axial_precision"] = axial_precision + else: + self.modalities[modality]["emitters"]["axial_precision"] = None if nlocalisations is not None: self.modalities[modality]["emitters"]["nlocalisations"] = nlocalisations else: @@ -664,12 +668,14 @@ def generate_imaging( modality, emitters, photons_frames ) # check for parameters for localisaiton generation - loc_precision_nm = self.modalities[modality]["emitters"]["precision"] + loc_precision_xy_nm = self.modalities[modality]["emitters"]["lateral_precision"] + loc_precision_z_nm = self.modalities[modality]["emitters"]["axial_precision"] av_loc_per_emitter = self.modalities[modality]["emitters"]["nlocalisations"] - if loc_precision_nm is not None and av_loc_per_emitter is not None: + if loc_precision_xy_nm is not None and av_loc_per_emitter is not None: localisations = points_transforms.generate_localisations_with_noise( array3d=field_data["field_coordinates"], - loc_precision_nm=loc_precision_nm, + loc_precision_xy_nm=loc_precision_xy_nm, + loc_precision_z_nm=loc_precision_z_nm, av_loc_per_emitter=av_loc_per_emitter, ) n_emitters = localisations.shape[0] diff --git a/src/vlab4mic/utils/transform/points_transforms.py b/src/vlab4mic/utils/transform/points_transforms.py index 4f73802..991d4d6 100644 --- a/src/vlab4mic/utils/transform/points_transforms.py +++ b/src/vlab4mic/utils/transform/points_transforms.py @@ -208,15 +208,15 @@ def apply_euler_rotation(vector, phi=0, theta=0, psi=0, order = "zyx", reset_ori return new_vector -def generate_localisations_with_noise(array3d, loc_precision_nm, av_loc_per_emitter=1, z_pos=0): +def generate_localisations_with_noise(array3d, loc_precision_xy_nm, loc_precision_z_nm, av_loc_per_emitter=1, z_pos=0): locs_i_x_list = [] locs_i_y_list = [] locs_i_z_list = [] for emitter in range(array3d.shape[0]): n_locs = np.random.poisson(lam=av_loc_per_emitter) - locs_i_x = np.random.normal(loc=array3d[emitter][0], scale=loc_precision_nm, size=n_locs) - locs_i_y = np.random.normal(loc=array3d[emitter][1], scale=loc_precision_nm, size=n_locs) - locs_i_z = np.random.normal(loc=array3d[emitter][2], scale=loc_precision_nm, size=n_locs) + locs_i_x = np.random.normal(loc=array3d[emitter][0], scale=loc_precision_xy_nm, size=n_locs) + locs_i_y = np.random.normal(loc=array3d[emitter][1], scale=loc_precision_xy_nm, size=n_locs) + locs_i_z = np.random.normal(loc=array3d[emitter][2], scale=loc_precision_z_nm, size=n_locs) locs_i_x_list.extend(locs_i_x.tolist()) locs_i_y_list.extend(locs_i_y.tolist()) locs_i_z_list.extend(locs_i_z.tolist()) From 1ca9588d1d066f6e00e8f524d1727d16a0e746cd Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 21 Apr 2026 11:07:07 +0100 Subject: [PATCH 08/17] remove outdated notebooks --- .../FitCircles_experimental2simulation.ipynb | 341 ------------------ .../Example_outputs/Indirect_labelling.ipynb | 172 --------- .../Example_outputs/NPC_multimomodal.ipynb | 153 -------- notebooks/Example_outputs/script_HIV.ipynb | 117 ------ notebooks/Example_outputs/script_NPC.ipynb | 117 ------ 5 files changed, 900 deletions(-) delete mode 100644 notebooks/Example_outputs/FitCircles_experimental2simulation.ipynb delete mode 100644 notebooks/Example_outputs/Indirect_labelling.ipynb delete mode 100644 notebooks/Example_outputs/NPC_multimomodal.ipynb delete mode 100644 notebooks/Example_outputs/script_HIV.ipynb delete mode 100644 notebooks/Example_outputs/script_NPC.ipynb diff --git a/notebooks/Example_outputs/FitCircles_experimental2simulation.ipynb b/notebooks/Example_outputs/FitCircles_experimental2simulation.ipynb deleted file mode 100644 index 9ab32a8..0000000 --- a/notebooks/Example_outputs/FitCircles_experimental2simulation.ipynb +++ /dev/null @@ -1,341 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "383b20e2", - "metadata": {}, - "outputs": [], - "source": [ - "from vlab4mic.generate import coordinates_field\n", - "from vlab4mic import experiments \n", - "from vlab4mic.analysis import metrics\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import cv2" - ] - }, - { - "cell_type": "markdown", - "id": "03ef0df5", - "metadata": {}, - "source": [ - "# Load image" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0eea1785", - "metadata": {}, - "outputs": [], - "source": [ - "experimental_example = \"PATH/TO/image.tif\"\n", - "img_tif = tif.imread(experimental_example)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4baca9b5", - "metadata": {}, - "outputs": [], - "source": [ - "plt.imshow(img_tif)\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "id": "ccd4fd14", - "metadata": {}, - "source": [ - "# Approximate particle positions" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "95a69ed3", - "metadata": {}, - "outputs": [], - "source": [ - "# offset in image\n", - "background = 0\n", - "# pixelsize of image in nanometers\n", - "pixelsize = 10\n", - "# kernel size for blurring image\n", - "sigma = 5\n", - "# in pixels, minimal distance expected between centers\n", - "min_distance = 10\n", - "# pixel value thershold for accepting local maxima\n", - "threshold = 0.01" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3b1df5ca", - "metadata": {}, - "outputs": [], - "source": [ - "xyz_relative, image_physical_size = coordinates_field.gen_positions_from_image(\n", - " img_tif,\n", - " mode=\"localmaxima\",\n", - " sigma=sigma,\n", - " background=background,\n", - " threshold=threshold,\n", - " pixelsize=pixelsize,\n", - " min_distance=min_distance)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "50d1fcbd", - "metadata": {}, - "outputs": [], - "source": [ - "plt.imshow(img_tif, cmap=\"grey\")\n", - "for rel in xyz_relative:\n", - " rel2 = (rel[0:2] * image_physical_size)\n", - " plt.plot(rel2[1]/pixelsize, rel2[0]/pixelsize, \"o\", c=\"r\", markersize=2)" - ] - }, - { - "cell_type": "markdown", - "id": "aaea4a28", - "metadata": {}, - "source": [ - "# Simulate particles at positions estimated from your image" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "02899787", - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "structure = \"7R5K\"\n", - "probe_name = \"NPC_Nup96_Cterminal_direct\"\n", - "fluorophore_id = \"AF647\"\n", - "virtual_sample = \"square1x1um_randomised\" \n", - "modalities = [\"STED\", ]\n", - "_1, experiment = experiments.image_vsample(\n", - " structure=structure,\n", - " probe_template=probe_name,\n", - " fluorophore_id=fluorophore_id,\n", - " multimodal=modalities,\n", - " run_simulation=False,\n", - ")\n", - "experiment.use_image_for_positioning(\n", - " img=experimental_example,\n", - " mode=\"localmaxima\",\n", - " sigma=sigma,\n", - " background=background,\n", - " threshold=threshold,\n", - " pixelsize=pixelsize,\n", - " min_distance=min_distance)\n", - "# adjust modality to match your image pixelsize\n", - "experiment.update_modality(\"STED\", pixelsize_nm=pixelsize)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c29ef34e", - "metadata": {}, - "outputs": [], - "source": [ - "experiment.set_modality_acq(\"STED\", exp_time=0.001, nframes=1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a2835ae2", - "metadata": {}, - "outputs": [], - "source": [ - "images = experiment.run_simulation()" - ] - }, - { - "cell_type": "markdown", - "id": "86c5327c", - "metadata": {}, - "source": [ - "# Circle Fittings on image" - ] - }, - { - "cell_type": "markdown", - "id": "ca9e767b", - "metadata": {}, - "source": [ - "### Define the expected dimensions for circle-like objects in the FOV" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9830d56e", - "metadata": {}, - "outputs": [], - "source": [ - "# expected parameters of objects\n", - "expected_min_radius = 40 # in nanometers\n", - "expected_MAX_radius = 70 # in nanometers\n", - "min_radius_px = expected_min_radius / pixelsize\n", - "MAX_radius_px = expected_MAX_radius / pixelsize\n", - "minRadius_round = np.ceil(min_radius_px).astype('int64')\n", - "maxRadius_round = np.ceil(MAX_radius_px).astype('int64')\n", - "minDist = minRadius_round" - ] - }, - { - "cell_type": "markdown", - "id": "b41cb633", - "metadata": {}, - "source": [ - "### Parameters for fitting multiple circles in image" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ca6390f0", - "metadata": {}, - "outputs": [], - "source": [ - "# dp, param1 and param2 are user-defined pararmeters\n", - "HCparams = dict(dp=1, minDist=maxRadius_round, \n", - " param1=1, param2=7, minRadius=minRadius_round, maxRadius=maxRadius_round)" - ] - }, - { - "cell_type": "markdown", - "id": "1ec479c1", - "metadata": {}, - "source": [ - "## Fit circles on simulated data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9a9c9c0c", - "metadata": {}, - "outputs": [], - "source": [ - "circles_sim, img_blurred_sim, c_params_sim = metrics.get_circles(images[\"STED\"][0], **HCparams)\n", - "radii_simulated= []\n", - "for (x, y, r) in circles_sim[0]:\n", - " radii_simulated.append((r*pixelsize))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a37de2a8", - "metadata": {}, - "outputs": [], - "source": [ - "plt.imshow(img_blurred_sim, cmap=\"grey\")\n", - "plt.rcParams['figure.figsize'] = [10,10]\n", - "if circles_sim is not None:\n", - " ncircles = circles_sim.shape[1]\n", - " for (x, y, r) in circles_sim[0]:\n", - " circle = plt.Circle((x, y), r, color=\"r\", fill=False, linewidth=2, alpha=0.5)\n", - " plt.gca().add_patch(circle)\n", - " plt.title(\"Fitted circles. STED simulation\")" - ] - }, - { - "cell_type": "markdown", - "id": "8012181d", - "metadata": {}, - "source": [ - "## Fit circles on experimental data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d8528c6c", - "metadata": {}, - "outputs": [], - "source": [ - "circles_exp, img_blurred_exp, c_params_exp = metrics.get_circles(img_tif, **HCparams)\n", - "radii_experimental = []\n", - "for (x, y, r) in circles_exp[0]:\n", - " radii_experimental.append((r*pixelsize))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "11ee450b", - "metadata": {}, - "outputs": [], - "source": [ - "plt.imshow(img_blurred_exp, cmap=\"grey\")\n", - "plt.rcParams['figure.figsize'] = [10,10]\n", - "if circles_exp is not None:\n", - " ncircles = circles_exp.shape[1]\n", - " for (x, y, r) in circles_exp[0]:\n", - " circle = plt.Circle((x, y), r, color=\"r\", fill=False, linewidth=2, alpha=0.5)\n", - " plt.gca().add_patch(circle)\n", - " plt.title(\"Fitted circles. STED experimental\")" - ] - }, - { - "cell_type": "markdown", - "id": "7fe3d81b", - "metadata": {}, - "source": [ - "## Plot histograms" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "105d8d99", - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "plt.rcParams['figure.figsize'] = [4,4]\n", - "df = pd.DataFrame({\n", - " 'value': np.concatenate([radii_experimental, radii_simulated]),\n", - " 'Condition': ['Experimental'] * len(radii_experimental) + ['Simulated'] * len(radii_simulated)\n", - "})\n", - "sns.histplot(data=df, x=\"value\", hue=\"Condition\", binrange=[40,70], bins=20, kde=True)\n", - "plt.xlabel(\"Radius (nm)\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "vlab-dev", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.13" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/notebooks/Example_outputs/Indirect_labelling.ipynb b/notebooks/Example_outputs/Indirect_labelling.ipynb deleted file mode 100644 index 867bbb9..0000000 --- a/notebooks/Example_outputs/Indirect_labelling.ipynb +++ /dev/null @@ -1,172 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "d14bbd9d", - "metadata": {}, - "source": [ - "# Model indirect labelling" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "25e125a2", - "metadata": {}, - "outputs": [], - "source": [ - "import vlab4mic\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from vlab4mic import experiments" - ] - }, - { - "cell_type": "markdown", - "id": "ee470801", - "metadata": {}, - "source": [ - "# Initialise an experiment.\n", - "Here we use a Nuclear Pore complex model.
\n", - "By default, \"generate_virtual_sample\" method primes any structure with a NHS ester.
\n", - "We set \"clear_probes\" parameter as true, to override this step to avoid using that probe. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b09e27df", - "metadata": {}, - "outputs": [], - "source": [ - "sample, experiment = experiments.generate_virtual_sample(structure=\"7R5K\", clear_probes=True)" - ] - }, - { - "cell_type": "markdown", - "id": "186d38e0", - "metadata": {}, - "source": [ - "# Use the method \"add_probe\" to define each probe.\n", - "For this example, our primary probe is an antibody that will recognise a sequence \"ELAVGSL\" in the structure.
\n", - "As such we only need to specify the probe_name for the linker \"Mock_antibody\".
\n", - "Since we aim to target an aminoacid motif the \"probe_target_type\" is set to \"Sequence\".
\n", - "Its value then correspond to the actual sequence.\n", - "
\n", - "
\n", - "Our second probe will then target the first one. This secondary will be modelled by a nanobody mock.
\n", - "The target type then needs to reflect that it will targets a primary probe. So that \"probe_target_type\" is set to \"Primary\".
\n", - "Its value then correspond to the name of the primary probe \"Mock_antibody\"." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "03422bc6", - "metadata": {}, - "outputs": [], - "source": [ - "experiment.remove_probes()\n", - "experiment.add_probe(\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_template = \"Nanobody\",\n", - "probe_target_type = \"Primary\",\n", - "probe_target_value = \"Antibody\"\n", - ")\n", - "experiment.build(modules=[\"particle\", \"coordinate_field\"])" - ] - }, - { - "cell_type": "markdown", - "id": "1177b977", - "metadata": {}, - "source": [ - "# Explore the model created from priamry and secondary probes" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "25cd1a32", - "metadata": {}, - "outputs": [], - "source": [ - "experiment.particle.show_instance(with_sources=True, show_axis=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2004014d", - "metadata": {}, - "outputs": [], - "source": [ - "experiment.coordinate_field.show_field()" - ] - }, - { - "cell_type": "markdown", - "id": "b67b0cba", - "metadata": {}, - "source": [ - "# Image virtual sample generated" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1405f00b", - "metadata": {}, - "outputs": [], - "source": [ - "modalities = [\"STED\", \"SMLM\"]\n", - "vsample = experiment.exported_coordinate_field\n", - "outputs, experiment2 = experiments.image_vsample(vsample=vsample, multimodal=modalities)" - ] - }, - { - "cell_type": "markdown", - "id": "596ebcc8", - "metadata": {}, - "source": [ - "# View output images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "20159c7c", - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "plt.rcParams['figure.figsize'] = [20, 10]\n", - "nmods = len(modalities)\n", - "\n", - "fig, axs = plt.subplots(1, nmods)\n", - "nframe = 0\n", - "for i, mod in enumerate(modalities):\n", - " axs[i].imshow(outputs[mod][nframe], cmap=\"gray\")\n", - "#experiment2.imager.show_field()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "vlab-dev", - "language": "python", - "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.11.13" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/notebooks/Example_outputs/NPC_multimomodal.ipynb b/notebooks/Example_outputs/NPC_multimomodal.ipynb deleted file mode 100644 index 6b6a988..0000000 --- a/notebooks/Example_outputs/NPC_multimomodal.ipynb +++ /dev/null @@ -1,153 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "1fcb201f", - "metadata": {}, - "source": [ - "# Image a Nuclear pore complex (7R5K) across modalities" - ] - }, - { - "cell_type": "markdown", - "id": "a8c96a2d", - "metadata": {}, - "source": [ - "## Import dependencies" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6554c4ea", - "metadata": {}, - "outputs": [], - "source": [ - "import vlab4mic\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from vlab4mic import experiments" - ] - }, - { - "cell_type": "markdown", - "id": "e06deddc", - "metadata": {}, - "source": [ - "# Set simulation parameters: Structure model, probe, virtual sample, and imaging modalities to use" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "19582461", - "metadata": {}, - "outputs": [], - "source": [ - "structure = \"7R5K\"\n", - "probe_name = \"NPC_Nup96_Cterminal_direct\"\n", - "fluorophore_id = \"AF647\"\n", - "virtual_sample = \"square1x1um_randomised\" \n", - "modalities = [\"Widefield_Thev2016\", \"Confocal_Thev2016\", \"AiryScan_Thev2016\", \"STED_Thev2016\", \"STORM_Thev2016\"]" - ] - }, - { - "cell_type": "markdown", - "id": "40ccff79", - "metadata": {}, - "source": [ - "# Use the Experiments module to image a sample.\n", - "### By default, the image simulation will be triggered.
Here, we set the \"run_simulation\" to False in order to further explore the experiment, the virtual sample and update simualation parameters.
(This verification step can also be done after image generation)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a9c72529", - "metadata": {}, - "outputs": [], - "source": [ - "images_ , experiment = experiments.image_vsample(\n", - " structure=structure,\n", - " probe_template=probe_name,\n", - " fluorophore_id=fluorophore_id,\n", - " virtual_sample=virtual_sample,\n", - " multimodal=modalities,\n", - " number_of_particles = 10,\n", - " run_simulation=False\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "995e8b5f", - "metadata": {}, - "source": [ - "### The experiment module allows you to update parameters on modules, for example, modality acquisition, such as the exposure time (seconds).
This parameter represents the fraction of the average photons emitted per second of a given fluorophore." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b87803bd", - "metadata": {}, - "outputs": [], - "source": [ - "experiment.set_modality_acq(\"Widefield_Thev2016\", exp_time=0.07)\n", - "experiment.set_modality_acq(\"AiryScan_Thev2016\", exp_time=0.07)\n", - "experiment.set_modality_acq(\"Confocal_Thev2016\", exp_time=0.005)\n", - "experiment.set_modality_acq(\"STED_Thev2016\", exp_time=0.0008)" - ] - }, - { - "cell_type": "markdown", - "id": "62a432c7", - "metadata": {}, - "source": [ - "# Use the experiment mehtod \"run_simulation\" to simulate image acquisition of your virtual sample." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "69287ee3", - "metadata": {}, - "outputs": [], - "source": [ - "images = experiment.run_simulation()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c1c921b4", - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "plt.rcParams['figure.figsize'] = [20, 10]\n", - "nmods = len(modalities)\n", - "\n", - "fig, axs = plt.subplots(1, nmods)\n", - "nframe = 0\n", - "for i, mod in enumerate(modalities):\n", - " vmin = images[mod][nframe].min()\n", - " vmax = images[mod][nframe].max()\n", - " axs[i].imshow(images[mod][nframe], cmap=\"magma\", vmin=vmin, vmax=vmax)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "vlab-dev", - "language": "python", - "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.11.13" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/notebooks/Example_outputs/script_HIV.ipynb b/notebooks/Example_outputs/script_HIV.ipynb deleted file mode 100644 index b102a0e..0000000 --- a/notebooks/Example_outputs/script_HIV.ipynb +++ /dev/null @@ -1,117 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Import dependencies and prepare default directory" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import vlab4mic\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from vlab4mic import experiments" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Define structure and modalities to use" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "structure = \"3J3Y\"\n", - "modalities = [\"STED\", \"SMLM\"]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "labelling_efficiency = 0.01\n", - "random_orientations = False\n", - "number_of_particles = 10" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "outputs, experiment = experiments.image_vsample(\n", - " structure = structure, \n", - " multimodal = modalities, \n", - " labelling_efficiency = labelling_efficiency, \n", - " random_orientations = random_orientations, \n", - " number_of_particles = number_of_particles)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# View output images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "plt.rcParams['figure.figsize'] = [20, 10]\n", - "nmods = len(modalities)\n", - "\n", - "fig, axs = plt.subplots(1, nmods)\n", - "nframe = 0\n", - "for i, mod in enumerate(modalities):\n", - " axs[i].imshow(outputs[mod][nframe], cmap=\"gray\")\n", - "experiment.imager.show_field()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "vlab-dev", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.13" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/notebooks/Example_outputs/script_NPC.ipynb b/notebooks/Example_outputs/script_NPC.ipynb deleted file mode 100644 index ecb0ff0..0000000 --- a/notebooks/Example_outputs/script_NPC.ipynb +++ /dev/null @@ -1,117 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Import dependencies and prepare default directory" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import vlab4mic\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from vlab4mic import experiments" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Define structure and modalities to use" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "structure = \"7R5K\"\n", - "modalities = [\"STED\", \"SMLM\"]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "labelling_efficiency = 0.01\n", - "random_orientations = False\n", - "number_of_particles = 10" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "outputs, experiment = experiments.image_vsample(\n", - " structure = structure, \n", - " multimodal = modalities, \n", - " labelling_efficiency = labelling_efficiency, \n", - " random_orientations = random_orientations, \n", - " number_of_particles = number_of_particles)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# View output images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "plt.rcParams['figure.figsize'] = [20, 10]\n", - "nmods = len(modalities)\n", - "\n", - "fig, axs = plt.subplots(1, nmods)\n", - "nframe = 0\n", - "for i, mod in enumerate(modalities):\n", - " axs[i].imshow(outputs[mod][nframe], cmap=\"gray\")\n", - "experiment.imager.show_field()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "vlab-dev", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.13" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From 494e09d2bde28fa9679548b732a405a6e892de25 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 21 Apr 2026 11:33:50 +0100 Subject: [PATCH 09/17] update example scripts and save current date in experiment --- examples/article_figures/fig2_EF.py | 42 ++++++++++++++++++----------- src/vlab4mic/experiments.py | 3 +++ 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/examples/article_figures/fig2_EF.py b/examples/article_figures/fig2_EF.py index 0014883..49769cb 100644 --- a/examples/article_figures/fig2_EF.py +++ b/examples/article_figures/fig2_EF.py @@ -5,9 +5,9 @@ import os import numpy as np from vlab4mic.analysis.metrics import zoom_img -from mpl_toolkits.axes_grid1.anchored_artists import AnchoredSizeBar -np.random.seed(44) +from mpl_toolkits.axes_grid1.anchored_artists import AnchoredSizeBar +random_seed = 24 modalities = ["STED", "SMLM",] target_colour="#01579D" @@ -18,8 +18,10 @@ probe_template = "GFP_w_nanobody", probe_target_type = "Sequence", probe_target_value = "ELAVGSL", + probe_DoL = 2, multimodal=modalities, - clear_experiment=True + clear_experiment=True, + random_seed=random_seed ) ############ T4 capsid head image_outputs2, image_outputs_noiseless2, experiment2 = image_vsample( @@ -29,14 +31,19 @@ multimodal=modalities, random_orientations=True, yz_orientations=[90,], - clear_experiment=True + clear_experiment=True, + random_seed=random_seed ) ############ HIV-capsid image_outputs3, image_outputs_noiseless3, experiment3 = image_vsample( structure = "3J3Y", - probe_template = "anti-p24_primary_antibody_HIV", + probe_template = "Antibody", + probe_target_type = "Sequence", + probe_target_value = "SPRTLNA", + probe_DoL = 6, multimodal=modalities, - clear_experiment=True + clear_experiment=True, + random_seed=random_seed ) ############ Clathrin coated pit, primary and secodnary labelling @@ -50,7 +57,8 @@ probe_template = "Antibody", probe_name="Secondary-clathrin", probe_target_type = "Primary", - probe_target_value = "Primary-clathrin" + probe_target_value = "Primary-clathrin", + probe_DoL = 1.5 ) image_outputs4, image_outputs_noiseless4, experiment4 = image_vsample( structure = "1XI5", @@ -58,7 +66,8 @@ secondary_probe = secondary, multimodal=modalities, clear_experiment=True, - run_simulation=True + run_simulation=True, + random_seed=random_seed ) @@ -71,17 +80,17 @@ #ax_general = fig.add_subplot(111, projection="3d") hide_axes=True experiment1.particle.transform_translate(np.array([0,0,0])) -experiment1.particle.gen_axis_plot(axesoff=hide_axes, with_sources=True, axis_object=ax_general,target_colour=target_colour, source_plotsize=5, emitter_plotsize=5) +experiment1.particle.gen_axis_plot(axesoff=hide_axes, with_sources=True, axis_object=ax_general,target_colour=target_colour, source_plotsize=5, emitter_plotsize=5, source_plotmarker="o") experiment4.particle.transform_translate(np.array([0,1400,0])) -experiment4.particle.gen_axis_plot(axesoff=hide_axes,with_sources=True, axis_object=ax_general,target_colour=target_colour, source_plotsize=2, emitter_plotsize=0.5, source_plotalpha=1) +experiment4.particle.gen_axis_plot(axesoff=hide_axes,with_sources=True, axis_object=ax_general,target_colour=target_colour, source_plotsize=2, emitter_plotsize=0.5, source_plotalpha=1, source_plotmarker="o") experiment2.particle.transform_translate(np.array([0,2600,0])) -experiment2.particle.gen_axis_plot(axesoff=hide_axes, with_sources=True, axis_object=ax_general,target_colour=target_colour, source_plotsize=0.5, emitter_plotsize=10, source_plotalpha=0.05) +experiment2.particle.gen_axis_plot(axesoff=hide_axes, with_sources=True, axis_object=ax_general,target_colour=target_colour, source_plotsize=0.5, emitter_plotsize=10, source_plotalpha=0.05, source_plotmarker="o") experiment3.particle.transform_translate(np.array([0,3800,0])) -experiment3.particle.gen_axis_plot(axesoff=hide_axes, with_sources=True, axis_object=ax_general,target_colour=target_colour, source_plotsize=1, emitter_plotsize=0.5, source_plotalpha=1) +experiment3.particle.gen_axis_plot(axesoff=hide_axes, with_sources=True, axis_object=ax_general,target_colour=target_colour, source_plotsize=1, emitter_plotsize=0.5, source_plotalpha=1, source_plotmarker="o") ax_general.set_zlim3d(bottom=-300, top=1000) ax_general.set_ylim3d(bottom=-500, top=4500) ax_general.set_xlim3d(left=0, right=1000) @@ -98,10 +107,10 @@ y0,y1 = figy*0.64, figy*0.82 bbox = Bbox([[x0,y0],[x1,y1]]) -filename1 = os.path.join(experiment1.output_directory, 'vlab4mic_fig2_E.png') - -#bbox = bbox.transformed(ax_general.transData).transformed(fig.dpi_scale_trans.inverted()) +filename_ = experiment1.date_as_string + 'vlab4mic_fig2_E.png' +filename1 = os.path.join(experiment1.output_directory, filename_) fig.savefig(filename1, dpi=300, bbox_inches=bbox) + fig = plt.figure(figsize=[figy,figx]) ax = fig.add_subplot(141) img_zoom = 0.6 @@ -142,5 +151,6 @@ y0,y1 = figy*0.6, figy*0.89 bbox = Bbox([[x0,y0],[x1,y1]]) -filename2 = os.path.join(experiment1.output_directory, 'vlab4mic_fig2_F.png') +filename = experiment1.date_as_string + 'vlab4mic_fig2_F.png' +filename2 = os.path.join(experiment1.output_directory, filename) fig.savefig(filename2,dpi=300, bbox_inches=bbox) \ No newline at end of file diff --git a/src/vlab4mic/experiments.py b/src/vlab4mic/experiments.py index 38d8f8d..2bb26d7 100644 --- a/src/vlab4mic/experiments.py +++ b/src/vlab4mic/experiments.py @@ -22,6 +22,7 @@ from IPython.utils import io from pathlib import Path import sys +from datetime import datetime IN_COLAB = "google.colab" in sys.modules if IN_COLAB: @@ -180,6 +181,8 @@ def __post_init__(self): self.modality_noise_images = dict() if self.random_seed is not None: np.random.seed(self.random_seed) + self.now = datetime.now() # dd/mm/YY H:M:S + self.date_as_string = self.now.strftime("%Y%m%d") + "_" def select_structure(self, structure_id="1XI5", build=True, structure_path:str = None): """ From 70b309905f30f4942663ef83c5e808bda11f9e57 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 21 Apr 2026 12:05:13 +0100 Subject: [PATCH 10/17] fix missing key in modality params --- src/vlab4mic/experiments.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vlab4mic/experiments.py b/src/vlab4mic/experiments.py index 2bb26d7..e1daf4f 100644 --- a/src/vlab4mic/experiments.py +++ b/src/vlab4mic/experiments.py @@ -273,6 +273,12 @@ def add_modality(self, modality_name, save=False, modality_template=None, **kwar self.local_modalities_parameters[modality_name] = copy.deepcopy( self.imaging_modalities[modality_name] ) + keys = list(self.imaging_modalities[modality_name].keys()) + if "emitters" not in keys or self.imaging_modalities[modality_name]["emitters"] is None: + self.imaging_modalities[modality_name]["emitters"] = dict() + self.imaging_modalities[modality_name]["emitters"]["lateral_precision"] = None + self.imaging_modalities[modality_name]["emitters"]["axial_precision"] = None + self.imaging_modalities[modality_name]["emitters"]["nlocalisations"] = None def update_modality( self, From 10e81bcfb16f1d1a96b67956a437ac00f3fe66b3 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 21 Apr 2026 12:05:25 +0100 Subject: [PATCH 11/17] update example script --- examples/article_figures/fig3F.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/article_figures/fig3F.py b/examples/article_figures/fig3F.py index f0864bb..3dca964 100644 --- a/examples/article_figures/fig3F.py +++ b/examples/article_figures/fig3F.py @@ -316,7 +316,7 @@ def render_from_localisations(localisations, crop_size_nm = 3000, centerx = None axs[0,0].set_ylabel("Thevathasan, et al. 2019", fontsize=24) axs[1,0].set_ylabel("VLab4Mic simulation", fontsize=24) plt.tight_layout(h_pad=0, w_pad=3) - -filename = os.path.join(my_experiment.output_directory, 'vlab4mic_fig3F_url.png') +name = my_experiment.date_as_string + 'vlab4mic_fig3F_url.png' +filename = os.path.join(my_experiment.output_directory, name) fig.savefig(filename, dpi=300, bbox_inches='tight') plt.close() \ No newline at end of file From 008216feb76f4575fc5b6c8c4ec493e1c249930e Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 21 Apr 2026 14:07:06 +0100 Subject: [PATCH 12/17] fix test and update smlm config modality --- src/vlab4mic/configs/modalities/SMLM.yaml | 4 ++-- tests/test_image_generation.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vlab4mic/configs/modalities/SMLM.yaml b/src/vlab4mic/configs/modalities/SMLM.yaml index d19f37b..98042e7 100644 --- a/src/vlab4mic/configs/modalities/SMLM.yaml +++ b/src/vlab4mic/configs/modalities/SMLM.yaml @@ -6,13 +6,13 @@ PSF: X: 8 Y: 8 Z: 8 - voxelsize: 5 + voxelsize: 2 depth: 100 # in nanometers detector: FOV_size: # in nanometers. Default unless changed X: 1000 Y: 1000 - pixelsize: 5 # in nanometers + pixelsize: 2 # in nanometers noise: binomial: 1 gaussian: diff --git a/tests/test_image_generation.py b/tests/test_image_generation.py index 7936883..5ca1e85 100644 --- a/tests/test_image_generation.py +++ b/tests/test_image_generation.py @@ -16,7 +16,7 @@ def test_get_raw_volume(): images_volumes, beads, img_noiseless, b_noiseless = testexperiment.imager.generate_imaging( modality="SMLM", convolution_type="raw_volume", exp_time=0.001 ) - assert images_volumes["raw_volume"][0].shape == (200, 200, 150) + assert images_volumes["raw_volume"][0].shape == (500, 500, 150) def test_multi_imaging_system(): From 9fe6315517856903dfb39d9d4fa2ef673708c931 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 21 Apr 2026 14:22:18 +0100 Subject: [PATCH 13/17] fix case for primary to have dol as none --- src/vlab4mic/configs/probes/Antibody.yaml | 2 +- src/vlab4mic/experiments.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vlab4mic/configs/probes/Antibody.yaml b/src/vlab4mic/configs/probes/Antibody.yaml index e331adf..d80037f 100644 --- a/src/vlab4mic/configs/probes/Antibody.yaml +++ b/src/vlab4mic/configs/probes/Antibody.yaml @@ -26,7 +26,7 @@ conjugation_sites: - CA residues: - LYS - DoL: + DoL: 6 epitope: # for secondary target: type: Sequence diff --git a/src/vlab4mic/experiments.py b/src/vlab4mic/experiments.py index e1daf4f..81cd087 100644 --- a/src/vlab4mic/experiments.py +++ b/src/vlab4mic/experiments.py @@ -1113,6 +1113,7 @@ def add_probe( if as_primary: print("Adding probe as primary linker") probe_configuration["as_linker"] = True + probe_configuration["conjugation_sites"]["DoL"] = None else: probe_configuration["as_linker"] = False if probe_steric_hindrance is not None: From bda350ac6c1c50ac908fb22568e36f773e1c66ab Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Tue, 21 Apr 2026 15:02:21 +0100 Subject: [PATCH 14/17] change default for locs parameter --- src/vlab4mic/experiments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vlab4mic/experiments.py b/src/vlab4mic/experiments.py index 81cd087..6ed9505 100644 --- a/src/vlab4mic/experiments.py +++ b/src/vlab4mic/experiments.py @@ -292,7 +292,7 @@ def update_modality( lateral_precision = None, axial_precision = None, nlocalisations = None, - simulate_localistations = False, + simulate_localistations = True, **kwargs, ): """ From b472f83ec306b6b925a3eb0c2e6bb9be5665b687 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 22 Apr 2026 14:32:26 +0100 Subject: [PATCH 15/17] include test for for smlm locs --- tests/test_image_generation.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/test_image_generation.py b/tests/test_image_generation.py index 5ca1e85..84c1eec 100644 --- a/tests/test_image_generation.py +++ b/tests/test_image_generation.py @@ -52,3 +52,17 @@ def test_imager_optional_methods(): testexperiment.imager.set_roi_position(x=0.1, y=0.2) testexperiment.imager.set_roi_sizes(x=2, y=2) testexperiment.imager.recenter_roi() + + +def test_smlm_with_locs(): + images, noisless, testexperiment = experiments.image_vsample( + multimodal=["SMLM",], + run_simulation=True) + assert testexperiment.imager.modalities["SMLM"]["emitters"]["lateral_precision"] is not None + assert testexperiment.imager.modalities["SMLM"]["emitters"]["axial_precision"] is not None + assert testexperiment.imager.modalities["SMLM"]["emitters"]["nlocalisations"] is not None + testexperiment.update_modality(modality_name="SMLM", simulate_localistations=False) + testexperiment.build(modules=["imager"]) + assert testexperiment.imager.modalities["SMLM"]["emitters"]["lateral_precision"] is None + assert testexperiment.imager.modalities["SMLM"]["emitters"]["axial_precision"] is None + assert testexperiment.imager.modalities["SMLM"]["emitters"]["nlocalisations"] is None \ No newline at end of file From ee99a1efcccfc88bdd1cc16a8a017ce198cf6a79 Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 22 Apr 2026 16:41:31 +0100 Subject: [PATCH 16/17] update method to show probe --- src/vlab4mic/generate/labelled_instance.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/vlab4mic/generate/labelled_instance.py b/src/vlab4mic/generate/labelled_instance.py index 571534d..f8d4bc5 100644 --- a/src/vlab4mic/generate/labelled_instance.py +++ b/src/vlab4mic/generate/labelled_instance.py @@ -999,6 +999,7 @@ def show_probe( atoms_plotsize=1, atoms_plotalpha=1, use_dol=False, + axis_object=None, **kwargs, ): """ @@ -1031,8 +1032,13 @@ def show_probe( if probe_name is None: probe_name = list(self.labels.keys())[0] print(probe_name) - fig = plt.figure() - ax = fig.add_subplot(111, projection="3d") + if axis_object is None: + fig = plt.figure() + ax = fig.add_subplot(111, projection="3d") + return_plot = False + else: + ax = axis_object + return_plot = True # probe_plotting_params = self._get_label_plotting_params(probe_name) total_coordinates = copy.copy(self.labels[probe_name]["emitters"]) total_number_coordinates = total_coordinates.shape[0] @@ -1123,7 +1129,7 @@ def show_probe( if return_plot: return ax else: - fig.show() + plt.show() def show_instance( self, From 659b1bd1079b59d6fd2fb3b631367d4db2a64f6c Mon Sep 17 00:00:00 2001 From: Damian Martinez Date: Wed, 22 Apr 2026 16:42:21 +0100 Subject: [PATCH 17/17] Create script for abstract figure panels --- examples/article_figures/fig1_hiv_examples.py | 186 ++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 examples/article_figures/fig1_hiv_examples.py diff --git a/examples/article_figures/fig1_hiv_examples.py b/examples/article_figures/fig1_hiv_examples.py new file mode 100644 index 0000000..a2ca6f2 --- /dev/null +++ b/examples/article_figures/fig1_hiv_examples.py @@ -0,0 +1,186 @@ +from vlab4mic import experiments +import matplotlib.pyplot as plt +import os +seed = 1 + + +images, noisless, my_experiment = experiments.image_vsample( + structure="3J3Y", + probe_template="anti-p24_primary_antibody_HIV", + probe_DoL=3, + structural_integrity_small_cluster=20, + structural_integrity_large_cluster=100, + sample_dimensions=[1000,1000,100], + random_orientations=True, + structural_integrity=1, + clear_experiment=True, + number_of_particles=30, + multimodal=["Widefield", "Confocal", "AiryScan", "STED", "SMLM", "Reference"], + random_seed=seed, + run_simulation=False, +) +my_experiment.set_virtualsample_params(minimal_distance=110) +my_experiment.build(modules=["coordinate_field"]) +my_experiment.update_modality(modality_name="SMLM", + pixelsize_nm=2, + psf_voxel_nm=2, + depth_of_field_nm=1000, + lateral_resolution_nm=5, + simulate_localistations=True, + lateral_precision=5, + axial_precision=5, + nlocalisations=20) +my_experiment.update_modality(modality_name="STED", depth_of_field_nm=1000, lateral_resolution_nm=30) +my_experiment.set_modality_acq(modality_name="STED", exp_time=0.001) +my_experiment.update_modality(modality_name="Reference", + pixelsize_nm=2, + psf_voxel_nm=2, + depth_of_field_nm=1000, + lateral_resolution_nm=2, + simulate_localistations=True, + lateral_precision=0.001, + axial_precision=0.001, + nlocalisations=30) +my_experiment.set_modality_acq(modality_name="Reference", exp_time=1) +my_experiment.build(modules=["imager"]) +images, noiseless = my_experiment.run_simulation() +modalities = list(images.keys()) +n_modalities = len(modalities) +fig = plt.figure(figsize=[40,10]) + +for i, name in enumerate(modalities): + ax = fig.add_subplot(1, n_modalities, i+1) + ax.imshow(images[name]["ch0"][0], cmap="grey") + ax.set_axis_off() + +filename = my_experiment.date_as_string + 'vlab4mic_hiv_modalities.png' +filename2 = os.path.join(my_experiment.output_directory, filename) +fig.savefig(filename2,dpi=300, bbox_inches='tight') +plt.close() + + +target_colour="#01579D" +fig = plt.figure(figsize=[20,10]) +ax = fig.add_subplot(1, 2, 1, projection="3d") +total = my_experiment.structure.num_assembly_atoms +fraction = 100000/total +my_experiment.structure.show_target_labels( + with_assembly_atoms=True, + axis_object=ax, + show_axis=False, + assembly_fraction = fraction, + view_init=[20,0,0], + target_size = 0, + atoms_size = 10, + atoms_alpha = 0.01, + reference_point = False, + target_plotcolour=target_colour + ) +ax = fig.add_subplot(1, 2, 2, projection="3d") +total = my_experiment.structure.num_assembly_atoms +fraction = 100000/total +my_experiment.structure.show_target_labels( + with_assembly_atoms=True, + axis_object=ax, + show_axis=False, + assembly_fraction = fraction, + view_init=[20,0,0], + target_size = 15, + atoms_size = 10, + atoms_alpha = 0.01, + reference_point = False, + target_plotcolour=target_colour + ) +probe_template = list(my_experiment.probe_parameters.keys())[0] +title = "Structure: 3J3Y \n Probe: " + probe_template +title = title + "\n" + "Sequence: " + my_experiment.probe_parameters[probe_template]["target"]["value"] +ax.set_title(title) +filename = my_experiment.date_as_string + 'vlab4mic_hiv_structure_epitopes.png' +filename2 = os.path.join(my_experiment.output_directory, filename) +fig.savefig(filename2,dpi=300, bbox_inches='tight') +plt.close() + + +fig = plt.figure(figsize=[5,5]) +ax = fig.add_subplot(1, 1, 1, projection="3d") +my_experiment.particle.show_probe( + plotcolour="#984ea3", axesoff=True, + with_structural_atoms=True, + emitter_plotsize=70, + atoms_plotalpha=0.05, + atoms_plotsize=10, + atoms_fraction=0.3, + view_init=[0,40,100], + central_axis=False, + use_dol=True, + axis_object = ax, + ) + +filename = my_experiment.date_as_string + 'vlab4mic_hiv_antibody.png' +filename2 = os.path.join(my_experiment.output_directory, filename) +fig.savefig(filename2,dpi=300, bbox_inches='tight') +plt.close() + + +target_colour="#01579D" +plotmarker="o" +emitter_plotmarker = "o" +hiv_antibody=dict( + source_plotsize=3, + emitter_plotsize=50, + source_plotcolour=target_colour, + source_plotalpha=1, + source_plotmarker=plotmarker, + emitter_plotmarker=emitter_plotmarker + ) +fig = plt.figure(figsize=[10,10]) +ax = fig.add_subplot(1, 1, 1, projection="3d") +my_experiment.particle.gen_axis_plot( + reference_point=False, + view_init=[20, 0, 0], + axesoff=True, + show_axis=False, + with_sources=True, + axis_object=ax, + with_normals=False, + **hiv_antibody) +filename = my_experiment.date_as_string + 'vlab4mic_hiv_labelled_particle.png' +filename2 = os.path.join(my_experiment.output_directory, filename) +fig.savefig(filename2,dpi=300, bbox_inches='tight') +plt.close() + +n_examples = 8 +fig = plt.figure(figsize=[20, 10]) +row=2 +my_experiment.set_structural_integrity( + structural_integrity=1, + structural_integrity_small_cluster=20, + structural_integrity_large_cluster=100, + ) +my_experiment.build(modules=["particle",]) +for i in range(n_examples): + ax = fig.add_subplot(row, int(n_examples/2), i+1, projection="3d") + if i == 4: + my_experiment.set_structural_integrity( + structural_integrity=0.5 + ) + my_experiment.build(modules=["particle",]) + + my_experiment.particle.generate_instance() + my_experiment.particle.gen_axis_plot( + reference_point=False, + view_init=[20, 0, 0], + axesoff=True, + show_axis=False, + with_sources=True, + axis_object=ax, + with_normals=False, + source_plotsize=1, + source_plotalpha=0.4, + emitter_plotsize=5, + ) + +filename = my_experiment.date_as_string + 'vlab4mic_hiv_labelled_particle_examples.png' +filename2 = os.path.join(my_experiment.output_directory, filename) +fig.savefig(filename2,dpi=300, bbox_inches='tight') +plt.close() \ No newline at end of file