AMS-BP 0.0.3__py3-none-any.whl → 0.0.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- AMS_BP/__init__.py +1 -1
- AMS_BP/configio/configmodels.py +15 -14
- AMS_BP/configio/convertconfig.py +23 -32
- AMS_BP/metadata/metadata.py +2 -2
- AMS_BP/motion/condensate_movement.py +45 -0
- AMS_BP/motion/movement/fbm_BP.py +5 -4
- AMS_BP/motion/track_gen.py +6 -6
- AMS_BP/optics/camera/detectors.py +1 -1
- AMS_BP/optics/lasers/laser_profiles.py +177 -15
- AMS_BP/optics/psf/psf_engine.py +38 -93
- AMS_BP/photophysics/photon_physics.py +4 -4
- AMS_BP/photophysics/state_kinetics.py +1 -4
- AMS_BP/run_cell_simulation.py +3 -3
- AMS_BP/sim_config.toml +28 -42
- AMS_BP/sim_microscopy.py +2 -4
- {ams_bp-0.0.3.dist-info → ams_bp-0.0.11.dist-info}/METADATA +42 -20
- {ams_bp-0.0.3.dist-info → ams_bp-0.0.11.dist-info}/RECORD +20 -20
- {ams_bp-0.0.3.dist-info → ams_bp-0.0.11.dist-info}/WHEEL +0 -0
- {ams_bp-0.0.3.dist-info → ams_bp-0.0.11.dist-info}/entry_points.txt +0 -0
- {ams_bp-0.0.3.dist-info → ams_bp-0.0.11.dist-info}/licenses/LICENSE +0 -0
AMS_BP/__init__.py
CHANGED
AMS_BP/configio/configmodels.py
CHANGED
@@ -21,7 +21,9 @@ class MoleculeParameters(BaseModel):
|
|
21
21
|
diffusion_coefficient: List[List[float]] = Field(
|
22
22
|
description="Diffusion coefficients in um^2/s"
|
23
23
|
)
|
24
|
+
diffusion_track_amount: List[List[float]]
|
24
25
|
hurst_exponent: List[List[float]]
|
26
|
+
hurst_track_amount: List[List[float]]
|
25
27
|
allow_transition_probability: List[bool]
|
26
28
|
transition_matrix_time_step: List[int] = Field(description="Time step in ms")
|
27
29
|
diffusion_transition_matrix: List[List[List[float]]]
|
@@ -31,7 +33,9 @@ class MoleculeParameters(BaseModel):
|
|
31
33
|
|
32
34
|
@field_validator(
|
33
35
|
"diffusion_coefficient",
|
36
|
+
"diffusion_track_amount",
|
34
37
|
"hurst_exponent",
|
38
|
+
"hurst_track_amount",
|
35
39
|
"state_probability_diffusion",
|
36
40
|
"state_probability_hurst",
|
37
41
|
)
|
@@ -56,22 +60,19 @@ class GlobalParameters(BaseModel):
|
|
56
60
|
|
57
61
|
|
58
62
|
class CondensateParameters(BaseModel):
|
59
|
-
initial_centers: List[List[
|
60
|
-
|
61
|
-
|
62
|
-
initial_scale: List[List[float]] = Field(description="Initial scale in um")
|
63
|
-
diffusion_coefficient: List[List[float]] = Field(
|
63
|
+
initial_centers: List[List[float]] = Field(description="Initial centers in um")
|
64
|
+
initial_scale: List[float] = Field(description="Initial scale in um")
|
65
|
+
diffusion_coefficient: List[float] = Field(
|
64
66
|
description="Diffusion coefficients in um^2/s"
|
65
67
|
)
|
66
|
-
hurst_exponent: List[
|
67
|
-
density_dif:
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
#
|
68
|
+
hurst_exponent: List[float]
|
69
|
+
density_dif: int
|
70
|
+
|
71
|
+
@field_validator(
|
72
|
+
"initial_centers", "initial_scale", "diffusion_coefficient", "hurst_exponent"
|
73
|
+
)
|
74
|
+
def convert_to_array(cls, v):
|
75
|
+
return np.array(v)
|
75
76
|
|
76
77
|
|
77
78
|
class OutputParameters(BaseModel):
|
AMS_BP/configio/convertconfig.py
CHANGED
@@ -324,12 +324,11 @@ class ConfigLoader:
|
|
324
324
|
):
|
325
325
|
# Create PSFParameters instance
|
326
326
|
parameters = PSFParameters(
|
327
|
-
|
327
|
+
wavelength=wavelength,
|
328
328
|
numerical_aperture=float(params_config["numerical_aperture"]),
|
329
329
|
pixel_size=pixel_size,
|
330
330
|
z_step=float(params_config["z_step"]) if z_step is None else z_step,
|
331
331
|
refractive_index=float(params_config.get("refractive_index", 1.0)),
|
332
|
-
pinhole_diameter=params_config.get("pinhole_diameter", None),
|
333
332
|
)
|
334
333
|
|
335
334
|
# Create PSF engine
|
@@ -681,7 +680,7 @@ class ConfigLoader:
|
|
681
680
|
)
|
682
681
|
|
683
682
|
# make sampling function
|
684
|
-
|
683
|
+
sampling_function = make_samplingfunction(
|
685
684
|
condensate_params=base_config.CondensateParameters, cell=cell
|
686
685
|
)
|
687
686
|
|
@@ -690,7 +689,7 @@ class ConfigLoader:
|
|
690
689
|
molecule_params=base_config.MoleculeParameters,
|
691
690
|
cell=cell,
|
692
691
|
condensate_params=base_config.CondensateParameters,
|
693
|
-
|
692
|
+
sampling_function=sampling_function,
|
694
693
|
)
|
695
694
|
|
696
695
|
# create the track generator
|
@@ -777,42 +776,34 @@ def make_sample(global_params, cell_params) -> SamplePlane:
|
|
777
776
|
return sample_plane
|
778
777
|
|
779
778
|
|
780
|
-
def make_condensatedict(condensate_params, cell) ->
|
781
|
-
condensates_dict =
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
hurst_exponent=condensate_params.hurst_exponent[i],
|
789
|
-
cell=cell,
|
790
|
-
)
|
791
|
-
)
|
779
|
+
def make_condensatedict(condensate_params, cell) -> dict:
|
780
|
+
condensates_dict = create_condensate_dict(
|
781
|
+
initial_centers=condensate_params.initial_centers,
|
782
|
+
initial_scale=condensate_params.initial_scale,
|
783
|
+
diffusion_coefficient=condensate_params.diffusion_coefficient,
|
784
|
+
hurst_exponent=condensate_params.hurst_exponent,
|
785
|
+
cell=cell,
|
786
|
+
)
|
792
787
|
return condensates_dict
|
793
788
|
|
794
789
|
|
795
|
-
def make_samplingfunction(condensate_params, cell) ->
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
cell=cell,
|
805
|
-
)
|
806
|
-
)
|
807
|
-
return sampling_functions
|
790
|
+
def make_samplingfunction(condensate_params, cell) -> Callable:
|
791
|
+
sampling_function = tp(
|
792
|
+
num_subspace=len(condensate_params.initial_centers),
|
793
|
+
subspace_centers=condensate_params.initial_centers,
|
794
|
+
subspace_radius=condensate_params.initial_scale,
|
795
|
+
density_dif=condensate_params.density_dif,
|
796
|
+
cell=cell,
|
797
|
+
)
|
798
|
+
return sampling_function
|
808
799
|
|
809
800
|
|
810
|
-
def gen_initial_positions(molecule_params, cell, condensate_params,
|
801
|
+
def gen_initial_positions(molecule_params, cell, condensate_params, sampling_function):
|
811
802
|
initials = []
|
812
803
|
for i in range(len(molecule_params.num_molecules)):
|
813
804
|
num_molecules = molecule_params.num_molecules[i]
|
814
805
|
initial_positions = gen_points(
|
815
|
-
pdf=
|
806
|
+
pdf=sampling_function,
|
816
807
|
total_points=num_molecules,
|
817
808
|
min_x=cell.origin[0],
|
818
809
|
max_x=cell.origin[0] + cell.dimensions[0],
|
@@ -820,7 +811,7 @@ def gen_initial_positions(molecule_params, cell, condensate_params, sampling_fun
|
|
820
811
|
max_y=cell.origin[1] + cell.dimensions[1],
|
821
812
|
min_z=-cell.dimensions[2] / 2,
|
822
813
|
max_z=cell.dimensions[2] / 2,
|
823
|
-
density_dif=condensate_params.density_dif
|
814
|
+
density_dif=condensate_params.density_dif,
|
824
815
|
)
|
825
816
|
initials.append(initial_positions)
|
826
817
|
return initials
|
AMS_BP/metadata/metadata.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import
|
1
|
+
from typing import Iterator, List, Literal, Union
|
2
2
|
|
3
3
|
from pydantic import BaseModel
|
4
4
|
|
@@ -77,7 +77,7 @@ class MetaData(BaseModel):
|
|
77
77
|
PhysicalSizeXUnit: Literal["nm", "m"]
|
78
78
|
PhysicalSizeY: float
|
79
79
|
PhysicalSizeYUnit: Literal["nm", "m"]
|
80
|
-
Channel: Dict[Literal["Name"], List[str]]
|
80
|
+
# Channel: Dict[Literal["Name"], List[str]]
|
81
81
|
|
82
82
|
def __post_init__(self):
|
83
83
|
if isinstance(self.notes, (list, str)):
|
@@ -20,6 +20,7 @@ Usage:
|
|
20
20
|
condensate(times, time_unit) -> dict{"Position":np.ndarray, "Scale":float}
|
21
21
|
"""
|
22
22
|
|
23
|
+
import matplotlib.pyplot as plt
|
23
24
|
import numpy as np
|
24
25
|
|
25
26
|
from ..cells.rectangular_cell import RectangularCell
|
@@ -309,3 +310,47 @@ class Condensate:
|
|
309
310
|
# make array of length time with the last scale
|
310
311
|
scale = np.full(time.shape, last_scale)
|
311
312
|
return scale
|
313
|
+
|
314
|
+
def plot_condensate(self, ax, **kwargs):
|
315
|
+
"""
|
316
|
+
Plots the condensate
|
317
|
+
|
318
|
+
Parameters:
|
319
|
+
-----------
|
320
|
+
ax: plt.Axes
|
321
|
+
Axes to plot the condensate on.
|
322
|
+
**kwargs:
|
323
|
+
Keyword arguments to pass to the plot function.
|
324
|
+
"""
|
325
|
+
# check if the _condensate_positions exists
|
326
|
+
if not hasattr(self, "_condensate_positions"):
|
327
|
+
# if it doesn't then we need to generate the condensate positions
|
328
|
+
self.times = np.array([self.initial_time])
|
329
|
+
self.condensate_positions = np.array([self.initial_position])
|
330
|
+
self.scale = np.array([self.initial_scale])
|
331
|
+
|
332
|
+
# plot the condensate positions
|
333
|
+
ax.plot(
|
334
|
+
self.condensate_positions[:, 0], self.condensate_positions[:, 1], **kwargs
|
335
|
+
)
|
336
|
+
|
337
|
+
# plot a circle at all the positions with the scale as the radius
|
338
|
+
for i in range(len(self.condensate_positions)):
|
339
|
+
ax.add_patch(
|
340
|
+
plt.Circle(
|
341
|
+
self.condensate_positions[i], self.scale[i], color="r", fill=False
|
342
|
+
)
|
343
|
+
)
|
344
|
+
|
345
|
+
# plot the initial position in a different colour
|
346
|
+
ax.scatter(self.initial_position[0], self.initial_position[1], color="g")
|
347
|
+
# plot the final position in a different colour
|
348
|
+
ax.scatter(
|
349
|
+
self.condensate_positions[-1][0],
|
350
|
+
self.condensate_positions[-1][1],
|
351
|
+
color="b",
|
352
|
+
)
|
353
|
+
if "save_path" in kwargs:
|
354
|
+
plt.savefig(kwargs["save_path"])
|
355
|
+
# plt.show()
|
356
|
+
return ax
|
AMS_BP/motion/movement/fbm_BP.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
import numpy as np
|
2
|
-
|
2
|
+
from .boundary_conditions import _refecting_boundary, _absorbing_boundary
|
3
3
|
from ...probabilityfuncs.markov_chain import MCMC_state_selection
|
4
|
-
from .boundary_conditions import _absorbing_boundary, _refecting_boundary
|
5
4
|
|
6
5
|
BOUNDARY_CONDITIONS = {
|
7
6
|
"reflecting": _refecting_boundary,
|
@@ -162,8 +161,10 @@ class FBM_BP:
|
|
162
161
|
phi = np.zeros(self.n)
|
163
162
|
psi = np.zeros(self.n)
|
164
163
|
# construct a gaussian noise vector
|
165
|
-
gn =
|
166
|
-
|
164
|
+
gn = (
|
165
|
+
np.random.normal(0, 1, self.n)
|
166
|
+
* np.sqrt(self.dt * 2 * self._diff_a_n)
|
167
|
+
* (self.dt ** (2 * self._hurst_n))
|
167
168
|
)
|
168
169
|
# catch is all hurst are 0.5 then use the gaussian noise vector corresponding to the scale defined by the diffusion parameter
|
169
170
|
if np.all(self._hurst_n == 0.5):
|
AMS_BP/motion/track_gen.py
CHANGED
@@ -124,12 +124,12 @@ class Track_generator:
|
|
124
124
|
rel_space_lim[i] = self.space_lim[i] - initials[i]
|
125
125
|
|
126
126
|
# convert the diffusion_coefficients
|
127
|
-
|
128
|
-
|
129
|
-
|
127
|
+
diffusion_coefficient = self._convert_diffcoef_um2s_um2xms(
|
128
|
+
diffusion_coefficient
|
129
|
+
)
|
130
130
|
fbm = FBM_BP(
|
131
131
|
n=track_length,
|
132
|
-
dt=
|
132
|
+
dt=1,
|
133
133
|
hurst_parameters=[hurst_exponent],
|
134
134
|
diffusion_parameters=[diffusion_coefficient],
|
135
135
|
diffusion_parameter_transition_matrix=[1],
|
@@ -216,11 +216,11 @@ class Track_generator:
|
|
216
216
|
for i in range(3):
|
217
217
|
rel_space_lim[i] = self.space_lim[i] - initials[i]
|
218
218
|
# convert the diffusion_coefficients
|
219
|
-
|
219
|
+
diffusion_parameters = self._convert_diffcoef_um2s_um2xms(diffusion_parameters)
|
220
220
|
# initialize the fbm class
|
221
221
|
fbm = FBM_BP(
|
222
222
|
n=track_length,
|
223
|
-
dt=
|
223
|
+
dt=1,
|
224
224
|
hurst_parameters=hurst_parameters,
|
225
225
|
diffusion_parameters=diffusion_parameters,
|
226
226
|
diffusion_parameter_transition_matrix=diffusion_transition_matrix,
|
@@ -305,7 +305,7 @@ def create_binning_function(input_shape, binning_size, mode="sum"):
|
|
305
305
|
numpy.ndarray
|
306
306
|
Binned array
|
307
307
|
"""
|
308
|
-
if array.shape !=
|
308
|
+
if array.shape != input_shape:
|
309
309
|
raise ValueError(
|
310
310
|
f"Input array shape {array.shape} does not match expected shape {input_shape}"
|
311
311
|
)
|
@@ -96,10 +96,7 @@ class LaserParameters:
|
|
96
96
|
Power in watts
|
97
97
|
"""
|
98
98
|
if callable(self.power):
|
99
|
-
|
100
|
-
if power < 0:
|
101
|
-
raise ValueError("Laser Power Cannot be Negative")
|
102
|
-
return power
|
99
|
+
return self.power(t)
|
103
100
|
return self.power
|
104
101
|
|
105
102
|
def get_position(self, t: float) -> Tuple[float, float, float]:
|
@@ -371,16 +368,15 @@ class WidefieldBeam(LaserProfile):
|
|
371
368
|
Returns:
|
372
369
|
Intensity scaling factor between 0 and 1
|
373
370
|
"""
|
374
|
-
#
|
375
|
-
#
|
376
|
-
|
377
|
-
|
378
|
-
#
|
379
|
-
|
380
|
-
|
381
|
-
#
|
382
|
-
|
383
|
-
return 1.0
|
371
|
+
# Use error function for smooth transition at DoF boundaries
|
372
|
+
# Scale factor determines how sharp the transition is
|
373
|
+
scale_factor = 2.0 # Adjust this to change transition sharpness
|
374
|
+
|
375
|
+
# Normalize z by DoF and create smooth falloff
|
376
|
+
normalized_z = scale_factor * (np.abs(z) - self.dof / 2) / self.dof
|
377
|
+
|
378
|
+
# Use sigmoid function for smooth transition
|
379
|
+
return 1 / (1 + np.exp(normalized_z))
|
384
380
|
|
385
381
|
def calculate_intensity(
|
386
382
|
self,
|
@@ -417,7 +413,7 @@ class WidefieldBeam(LaserProfile):
|
|
417
413
|
base_intensity = power / (np.pi * self.max_radius**2)
|
418
414
|
|
419
415
|
# Apply radial intensity profile with smooth falloff at edges
|
420
|
-
edge_width = self.max_radius * 0.
|
416
|
+
edge_width = self.max_radius * 0.1 # 10% of max radius
|
421
417
|
radial_profile = 0.5 * (1 - np.tanh((r - self.max_radius) / edge_width))
|
422
418
|
# Apply DoF-based axial intensity profile
|
423
419
|
axial_profile = self._calculate_dof_profile(z_shifted)
|
@@ -426,6 +422,32 @@ class WidefieldBeam(LaserProfile):
|
|
426
422
|
return base_intensity * radial_profile * axial_profile
|
427
423
|
|
428
424
|
|
425
|
+
# Example usage
|
426
|
+
if __name__ == "__main__":
|
427
|
+
# Create parameters for a typical microscope objective
|
428
|
+
params = LaserParameters(
|
429
|
+
wavelength=488, # 488 nm
|
430
|
+
power=0.001, # 1 mW
|
431
|
+
beam_width=0.25, # 250 nm
|
432
|
+
numerical_aperture=1.4,
|
433
|
+
refractive_index=1.518, # Oil immersion
|
434
|
+
)
|
435
|
+
|
436
|
+
# Create beam object
|
437
|
+
beam = GaussianBeam(params)
|
438
|
+
|
439
|
+
# Get intensity map
|
440
|
+
result = beam.get_intensity_map(
|
441
|
+
volume_size=(5, 5, 10), # 5x5x10 microns
|
442
|
+
voxel_size=0.1, # 100 nm voxels
|
443
|
+
t=0, # t=0 seconds
|
444
|
+
)
|
445
|
+
|
446
|
+
# print(f"Beam waist: {params.beam_width:.3f} µm")
|
447
|
+
# print(f"Rayleigh range: {params.rayleigh_range:.3f} µm")
|
448
|
+
# print(f"Diffraction limit: {params.diffraction_limited_width:.3f} µm")
|
449
|
+
|
450
|
+
|
429
451
|
class HiLoBeam(LaserProfile):
|
430
452
|
"""
|
431
453
|
Highly Inclined Laminated Optical (HiLo) illumination profile.
|
@@ -527,3 +549,143 @@ class HiLoBeam(LaserProfile):
|
|
527
549
|
lamination_factor = np.exp(-np.abs(z_shifted) / (2 * self.axial_resolution))
|
528
550
|
|
529
551
|
return intensity * lamination_factor
|
552
|
+
|
553
|
+
|
554
|
+
class ConfocalBeam(LaserProfile):
|
555
|
+
"""
|
556
|
+
Confocal microscopy beam profile with point scanning and pinhole characteristics.
|
557
|
+
|
558
|
+
Implements key optical principles of confocal microscopy:
|
559
|
+
- Point scanning illumination
|
560
|
+
- Pinhole-based rejection of out-of-focus light
|
561
|
+
- Depth-resolved imaging capabilities
|
562
|
+
"""
|
563
|
+
|
564
|
+
def __init__(
|
565
|
+
self,
|
566
|
+
params: LaserParameters,
|
567
|
+
pinhole_diameter: float, # Pinhole diameter in microns
|
568
|
+
scanning_mode: str = "point", # 'point' or 'line'
|
569
|
+
line_orientation: str = "horizontal", # 'horizontal' or 'vertical'
|
570
|
+
):
|
571
|
+
"""
|
572
|
+
Initialize Confocal beam profile.
|
573
|
+
|
574
|
+
Args:
|
575
|
+
params: LaserParameters for the beam
|
576
|
+
pinhole_diameter: Diameter of the detection pinhole in microns
|
577
|
+
scanning_mode: Scanning method ('point' or 'line')
|
578
|
+
line_orientation: Orientation for line scanning
|
579
|
+
"""
|
580
|
+
super().__init__(params)
|
581
|
+
|
582
|
+
# Validate numerical aperture
|
583
|
+
if params.numerical_aperture is None:
|
584
|
+
raise ValueError(
|
585
|
+
"Numerical aperture must be specified for confocal microscopy"
|
586
|
+
)
|
587
|
+
|
588
|
+
# Pinhole and optical characteristics
|
589
|
+
self.pinhole_diameter = pinhole_diameter
|
590
|
+
self.scanning_mode = scanning_mode
|
591
|
+
self.line_orientation = line_orientation
|
592
|
+
|
593
|
+
# Calculate optical parameters
|
594
|
+
wavelength_microns = params.wavelength / 1000.0
|
595
|
+
na = params.numerical_aperture
|
596
|
+
|
597
|
+
# Theoretical resolution calculations
|
598
|
+
self.lateral_resolution = 0.61 * wavelength_microns / na
|
599
|
+
self.axial_resolution = 0.5 * wavelength_microns / (na**2)
|
600
|
+
|
601
|
+
# Pinhole transmission calculation
|
602
|
+
# Airy disk radius calculation
|
603
|
+
self.airy_radius = 1.22 * wavelength_microns / (2 * na)
|
604
|
+
|
605
|
+
# Transmission through pinhole
|
606
|
+
def pinhole_transmission(z):
|
607
|
+
"""
|
608
|
+
Calculate pinhole transmission as a function of z-position.
|
609
|
+
Uses an error function to model smooth transition.
|
610
|
+
"""
|
611
|
+
# Normalized z-position relative to focal plane
|
612
|
+
z_norm = z / self.axial_resolution
|
613
|
+
|
614
|
+
# Smooth transition function
|
615
|
+
return 0.5 * (1 + np.tanh(-z_norm))
|
616
|
+
|
617
|
+
self.pinhole_transmission = pinhole_transmission
|
618
|
+
|
619
|
+
# print("Confocal Microscopy Configuration:")
|
620
|
+
# print(f" Scanning Mode: {scanning_mode}")
|
621
|
+
# print(f" Pinhole Diameter: {pinhole_diameter:.2f} µm")
|
622
|
+
# print(f" Lateral Resolution: {self.lateral_resolution:.3f} µm")
|
623
|
+
# print(f" Axial Resolution: {self.axial_resolution:.3f} µm")
|
624
|
+
# print(f" Airy Disk Radius: {self.airy_radius:.3f} µm")
|
625
|
+
|
626
|
+
def calculate_intensity(
|
627
|
+
self,
|
628
|
+
x: np.ndarray | float,
|
629
|
+
y: np.ndarray | float,
|
630
|
+
z: np.ndarray | float,
|
631
|
+
t: float,
|
632
|
+
) -> np.ndarray:
|
633
|
+
"""
|
634
|
+
Calculate the confocal illumination intensity distribution.
|
635
|
+
|
636
|
+
Args:
|
637
|
+
x: X coordinates in microns (3D array)
|
638
|
+
y: Y coordinates in microns (3D array)
|
639
|
+
z: Z coordinates in microns (3D array)
|
640
|
+
t: Time in seconds
|
641
|
+
|
642
|
+
Returns:
|
643
|
+
3D array of intensities in W/µm²
|
644
|
+
"""
|
645
|
+
# Get time-dependent parameters
|
646
|
+
power = self.params.get_power(t)
|
647
|
+
pos = self.params.get_position(t)
|
648
|
+
|
649
|
+
# Shift coordinates based on current beam position
|
650
|
+
x_shifted = x - pos[0]
|
651
|
+
y_shifted = y - pos[1]
|
652
|
+
z_shifted = z - pos[2]
|
653
|
+
|
654
|
+
# Base beam parameters
|
655
|
+
w0 = self.params.beam_width # Beam waist
|
656
|
+
zR = self.params.rayleigh_range # Rayleigh range
|
657
|
+
|
658
|
+
# Calculate beam width at z
|
659
|
+
w_z = w0 * np.sqrt(1 + (z_shifted / zR) ** 2)
|
660
|
+
|
661
|
+
# Peak intensity calculation
|
662
|
+
I0 = 2 * power / (np.pi * w0**2)
|
663
|
+
|
664
|
+
# Scanning mode intensity modification
|
665
|
+
if self.scanning_mode == "point":
|
666
|
+
# Point scanning: standard Gaussian beam
|
667
|
+
radial_intensity = (
|
668
|
+
I0
|
669
|
+
* (w0 / w_z) ** 2
|
670
|
+
* np.exp(-2 * (x_shifted**2 + y_shifted**2) / w_z**2)
|
671
|
+
)
|
672
|
+
elif self.scanning_mode == "line":
|
673
|
+
# Line scanning: different intensity distribution
|
674
|
+
if self.line_orientation == "horizontal":
|
675
|
+
line_intensity = (
|
676
|
+
I0 * (w0 / w_z) ** 2 * np.exp(-2 * y_shifted**2 / w_z**2)
|
677
|
+
)
|
678
|
+
radial_intensity = line_intensity
|
679
|
+
else: # vertical line scanning
|
680
|
+
line_intensity = (
|
681
|
+
I0 * (w0 / w_z) ** 2 * np.exp(-2 * x_shifted**2 / w_z**2)
|
682
|
+
)
|
683
|
+
radial_intensity = line_intensity
|
684
|
+
else:
|
685
|
+
raise ValueError(f"Unknown scanning mode: {self.scanning_mode}")
|
686
|
+
|
687
|
+
# Pinhole transmission effect
|
688
|
+
pinhole_effect = self.pinhole_transmission(z_shifted)
|
689
|
+
|
690
|
+
# Final intensity calculation
|
691
|
+
return radial_intensity * pinhole_effect
|
AMS_BP/optics/psf/psf_engine.py
CHANGED
@@ -5,61 +5,52 @@ from typing import Literal, Optional, Tuple
|
|
5
5
|
import numpy as np
|
6
6
|
from numpy.typing import NDArray
|
7
7
|
|
8
|
-
AIRYFACTOR = 1.0
|
9
|
-
|
10
8
|
|
11
9
|
@dataclass(frozen=True)
|
12
10
|
class PSFParameters:
|
13
|
-
"""Parameters for
|
14
|
-
|
15
|
-
|
16
|
-
This class defines parameters that determine how light from a point source
|
17
|
-
(e.g., a fluorescent molecule) diffracts through the collection optics
|
18
|
-
to form a pattern at the detector.
|
11
|
+
"""Parameters for PSF (Point Spread Function) generation.
|
19
12
|
|
20
13
|
Attributes:
|
21
|
-
|
22
|
-
numerical_aperture: Numerical aperture of the
|
23
|
-
pixel_size: Size of pixels in micrometers
|
14
|
+
wavelength: Light wavelength in nanometers
|
15
|
+
numerical_aperture: Numerical aperture of the optical system
|
16
|
+
pixel_size: Size of pixels in micrometers
|
24
17
|
z_step: Axial step size in micrometers
|
25
18
|
refractive_index: Refractive index of the medium (default: 1.0 for air)
|
26
|
-
pinhole_diameter: Diameter of the pinhole in micrometers (default: None for widefield)
|
27
|
-
The pinhole spatially filters the emitted light before it reaches
|
28
|
-
the detector.
|
29
19
|
"""
|
30
20
|
|
31
|
-
|
21
|
+
wavelength: float
|
32
22
|
numerical_aperture: float
|
33
23
|
pixel_size: float
|
34
24
|
z_step: float
|
35
25
|
refractive_index: float = 1.0
|
36
|
-
pinhole_diameter: Optional[float] = None # um
|
37
26
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
27
|
+
# def __post_init__(self) -> None:
|
28
|
+
# """Validate parameters after initialization."""
|
29
|
+
# if any(
|
30
|
+
# param <= 0
|
31
|
+
# for param in (
|
32
|
+
# self.wavelength,
|
33
|
+
# self.numerical_aperture,
|
34
|
+
# self.pixel_size,
|
35
|
+
# self.z_step,
|
36
|
+
# self.refractive_index,
|
37
|
+
# )
|
38
|
+
# ):
|
39
|
+
# raise ValueError("All parameters must be positive numbers")
|
40
|
+
# if self.numerical_aperture >= self.refractive_index:
|
41
|
+
# raise ValueError("Numerical aperture must be less than refractive index")
|
42
42
|
|
43
43
|
@cached_property
|
44
|
-
def
|
45
|
-
"""
|
46
|
-
return
|
47
|
-
self.pinhole_diameter / 2.0 if self.pinhole_diameter is not None else None
|
48
|
-
)
|
44
|
+
def wavelength_um(self) -> float:
|
45
|
+
"""Wavelength in micrometers."""
|
46
|
+
return self.wavelength / 1000.0
|
49
47
|
|
50
48
|
|
51
49
|
class PSFEngine:
|
52
|
-
"""Engine for
|
53
|
-
|
54
|
-
This class calculates how light from a point source (like a fluorescent molecule)
|
55
|
-
spreads due to diffraction through the collection optics to form a pattern at
|
56
|
-
the detector. For confocal systems, it can include the effect of a pinhole
|
57
|
-
that spatially filters the light before detection.
|
50
|
+
"""Engine for generating various microscope Point Spread Functions.
|
58
51
|
|
59
|
-
|
60
|
-
|
61
|
-
excite molecules, that illumination pattern does not affect how the emitted
|
62
|
-
light diffracts to form the PSF we calculate here.
|
52
|
+
This class implements calculations for both 2D and 3D Point Spread Functions
|
53
|
+
using Gaussian approximations.
|
63
54
|
"""
|
64
55
|
|
65
56
|
def __init__(self, params: PSFParameters):
|
@@ -88,80 +79,34 @@ class PSFEngine:
|
|
88
79
|
self._norm_sigma_xy = self._sigma_xy / 2.355
|
89
80
|
self._norm_sigma_z = self._sigma_z / 2.355
|
90
81
|
|
91
|
-
# Generate pinhole mask if specified
|
92
|
-
if self.params.pinhole_radius is not None:
|
93
|
-
if self.params.pinhole_radius < AIRYFACTOR * self._sigma_xy:
|
94
|
-
raise ValueError(
|
95
|
-
f"Pinhole size ({self.params.pinhole_radius} um) is smaller than {AIRYFACTOR} times the Airy lobe. This will diffract the emission light in the pinhole; an ideal pinhole size for this setup is {self._sigma_xy} um."
|
96
|
-
)
|
97
|
-
self._pinhole_mask = self._generate_pinhole_mask()
|
98
|
-
else:
|
99
|
-
self._pinhole_mask = None
|
100
|
-
|
101
|
-
def _generate_pinhole_mask(self) -> NDArray[np.float64]:
|
102
|
-
"""Generate a binary mask representing the pinhole's spatial filtering.
|
103
|
-
The pinhole is centered on the grid, blocking emission light based on position
|
104
|
-
in the image plane, affecting what portion of the diffracted light reaches
|
105
|
-
the detector.
|
106
|
-
"""
|
107
|
-
x, y = self._grid_xy
|
108
|
-
|
109
|
-
# Calculate the grid center
|
110
|
-
x_center = (x.max() + x.min()) / 2
|
111
|
-
y_center = (y.max() + y.min()) / 2
|
112
|
-
|
113
|
-
# Calculate radial distance from grid center
|
114
|
-
r = np.sqrt((x - x_center) ** 2 + (y - y_center) ** 2)
|
115
|
-
|
116
|
-
return (r <= self.params.pinhole_radius).astype(np.float64)
|
117
|
-
|
118
82
|
@lru_cache(maxsize=128)
|
119
|
-
def psf_z(self,
|
120
|
-
"""
|
121
|
-
|
122
|
-
This represents how light from a point source at position z_val
|
123
|
-
diffracts through the collection optics to form a pattern at the
|
124
|
-
detector. If a pinhole is present, it spatially filters this pattern.
|
83
|
+
def psf_z(self, z_val: float) -> NDArray[np.float64]:
|
84
|
+
"""Generate z=z_val Gaussian approximation of PSF.
|
125
85
|
|
126
86
|
Args:
|
127
|
-
|
128
|
-
y_val: y-position of the point source in micrometers
|
129
|
-
z_val: Z-position of the point source in micrometers
|
87
|
+
z_val: Z-position in micrometers
|
130
88
|
|
131
89
|
Returns:
|
132
|
-
2D array containing the
|
90
|
+
2D array containing the PSF at given z position
|
133
91
|
"""
|
134
92
|
x, y = self._grid_xy
|
135
93
|
|
136
|
-
#
|
137
|
-
r_squared = (
|
138
|
-
(x - x_val % self.params.pixel_size) / self._norm_sigma_xy
|
139
|
-
) ** 2 + ((y - y_val % self.params.pixel_size) / self._norm_sigma_xy) ** 2
|
94
|
+
# Vectorized calculation
|
95
|
+
r_squared = (x / self._norm_sigma_xy) ** 2 + (y / self._norm_sigma_xy) ** 2
|
140
96
|
z_term = (z_val / self._norm_sigma_z) ** 2
|
141
|
-
|
142
|
-
|
143
|
-
if self._pinhole_mask is not None:
|
144
|
-
# Apply pinhole's spatial filtering
|
145
|
-
return psf_at_detector * self._pinhole_mask
|
146
|
-
|
147
|
-
return psf_at_detector
|
97
|
+
return np.exp(-0.5 * (r_squared + z_term))
|
148
98
|
|
149
99
|
@lru_cache(maxsize=128)
|
150
100
|
def psf_z_xy0(self, z_val: float) -> float:
|
151
|
-
"""
|
152
|
-
|
153
|
-
For a point source at z_val, this gives the intensity of light
|
154
|
-
that reaches the detector center (x=y=0). This point is always
|
155
|
-
within the pinhole if one is present.
|
101
|
+
"""Generate z=z_val Gaussian approximation of PSF with x=y=0.
|
156
102
|
|
157
103
|
Args:
|
158
|
-
z_val: Z-position
|
104
|
+
z_val: Z-position in micrometers
|
159
105
|
|
160
106
|
Returns:
|
161
|
-
|
107
|
+
PSF value at x=y=0 and given z position
|
162
108
|
"""
|
163
|
-
|
164
|
-
return np.exp(-0.5 * z_term)
|
109
|
+
return np.exp(-0.5 * (z_val / self._norm_sigma_z) ** 2)
|
165
110
|
|
166
111
|
@cache
|
167
112
|
def _3d_normalization_A(
|
@@ -256,7 +201,7 @@ def calculate_psf_size(
|
|
256
201
|
Tuple of dimensions (z,y,x) or (y,x) for the PSF calculation
|
257
202
|
"""
|
258
203
|
# Calculate radius to capture important features (2x Airy radius)
|
259
|
-
r_psf =
|
204
|
+
r_psf = 2 * sigma_xy
|
260
205
|
|
261
206
|
# Convert to pixels and ensure odd number
|
262
207
|
pixels_xy = int(np.ceil(r_psf / pixel_size))
|
@@ -168,11 +168,11 @@ class incident_photons:
|
|
168
168
|
photons_n = self.transmission_photon_rate.values[i] * dt
|
169
169
|
photons += photons_n
|
170
170
|
psf_gen = (
|
171
|
-
self.generator[i].
|
172
|
-
|
173
|
-
|
174
|
-
z_val=self.position[2],
|
171
|
+
self.generator[i].normalize_psf(
|
172
|
+
self.generator[i].psf_z(z_val=self.position[2]),
|
173
|
+
mode="sum",
|
175
174
|
)
|
175
|
+
* self.generator[i].psf_z_xy0(z_val=self.position[2])
|
176
176
|
* photons_n
|
177
177
|
)
|
178
178
|
|
@@ -27,7 +27,6 @@ class StateTransitionCalculator:
|
|
27
27
|
self.current_global_time = current_global_time # ms (oversample motion time)
|
28
28
|
self.laser_intensity_generator = laser_intensity_generator
|
29
29
|
self.fluorescent_state_history = {} # {fluorescent.state.name : [delta time (seconds), laser_intensites], ...}
|
30
|
-
self.current_global_time_s = self.current_global_time * 1e-3
|
31
30
|
|
32
31
|
def __call__(
|
33
32
|
self,
|
@@ -49,9 +48,7 @@ class StateTransitionCalculator:
|
|
49
48
|
time = 0
|
50
49
|
transitions = self.flurophoreobj.state_history[self.current_global_time][2]
|
51
50
|
final_state_name = transitions[0].from_state
|
52
|
-
laser_intensities = self._initialize_state_hist(
|
53
|
-
self.current_global_time, time + self.current_global_time_s
|
54
|
-
)
|
51
|
+
laser_intensities = self._initialize_state_hist(self.current_global_time, time)
|
55
52
|
|
56
53
|
while time < self.time_duration:
|
57
54
|
stateTransitionMatrixR = [
|
AMS_BP/run_cell_simulation.py
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
"""
|
2
2
|
run_cell_simulation.py
|
3
3
|
|
4
|
-
This file contains the command-line interface (CLI) for the
|
4
|
+
This file contains the command-line interface (CLI) for the SMS_BP package, which is used for simulating single molecule localization microscopy experiments.
|
5
5
|
|
6
6
|
The CLI is built using Typer and provides two main commands:
|
7
7
|
1. 'config': Generates a sample configuration file.
|
8
8
|
2. 'runsim': Runs the cell simulation using a provided configuration file.
|
9
9
|
|
10
10
|
Main Components:
|
11
|
-
-
|
11
|
+
- typer_app_sms_bp: The main Typer application object.
|
12
12
|
- cell_simulation(): Callback function that displays the version information.
|
13
13
|
- generate_config(): Command to generate a sample configuration file.
|
14
14
|
- run_cell_simulation(): Command to run the cell simulation using a configuration file.
|
@@ -37,7 +37,7 @@ from .configio.saving import save_config_frames
|
|
37
37
|
|
38
38
|
cli_help_doc = str(
|
39
39
|
"""
|
40
|
-
CLI tool to run [underline]A[/underline]dvanced [underline]M[/underline]olecule [underline]S[/underline]imulation: [underline]
|
40
|
+
CLI tool to run [underline]A[/underline]dvanced [underline]M[/underline]olecule [underline]S[/underline]imulation: [underline]ASMS[/underline]-BP. GitHub: [green]https://github.com/joemans3/AMS_BP[/green].
|
41
41
|
[Version: [bold]{0}[/bold]]
|
42
42
|
""".format(__version__)
|
43
43
|
)
|
AMS_BP/sim_config.toml
CHANGED
@@ -23,8 +23,18 @@ diffusion_coefficient = [
|
|
23
23
|
0.0,
|
24
24
|
],
|
25
25
|
] # um^2/s, size of each index (eg. len(...[0]) is the # of diffusion coefficients the system can explore.
|
26
|
-
|
26
|
+
diffusion_track_amount = [
|
27
|
+
[
|
28
|
+
0.5,
|
29
|
+
0.5,
|
30
|
+
],
|
31
|
+
[
|
32
|
+
0.5,
|
33
|
+
0.5,
|
34
|
+
],
|
35
|
+
] # only usefull for initial distribution of diffusion coefficients to trajectories.
|
27
36
|
hurst_exponent = [[0.5], [0.5]]
|
37
|
+
hurst_track_amount = [[1.0], [1.0]]
|
28
38
|
allow_transition_probability = [true, true] # bool
|
29
39
|
transition_matrix_time_step = [
|
30
40
|
20,
|
@@ -67,49 +77,20 @@ oversample_motion_time = 20 # ms
|
|
67
77
|
[Condensate_Parameters]
|
68
78
|
initial_centers = [
|
69
79
|
[
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
0.05,
|
74
|
-
],
|
75
|
-
[
|
76
|
-
5,
|
77
|
-
5,
|
78
|
-
-0.15,
|
79
|
-
],
|
80
|
-
[
|
81
|
-
5,
|
82
|
-
6,
|
83
|
-
-0.15,
|
84
|
-
],
|
85
|
-
[
|
86
|
-
5,
|
87
|
-
5.5,
|
88
|
-
-0.15,
|
89
|
-
],
|
90
|
-
[
|
91
|
-
6,
|
92
|
-
5.5,
|
93
|
-
-0.15,
|
94
|
-
],
|
80
|
+
5.5,
|
81
|
+
5,
|
82
|
+
0.05,
|
95
83
|
],
|
96
84
|
[
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
0.05,
|
101
|
-
],
|
102
|
-
[
|
103
|
-
5,
|
104
|
-
7,
|
105
|
-
-0.15,
|
106
|
-
],
|
85
|
+
5,
|
86
|
+
7,
|
87
|
+
-0.15,
|
107
88
|
],
|
108
|
-
] # um
|
109
|
-
initial_scale = [
|
110
|
-
diffusion_coefficient = [
|
111
|
-
hurst_exponent = [
|
112
|
-
density_dif =
|
89
|
+
] # um, first dimension is the # of condentates. center = [x,y,z]
|
90
|
+
initial_scale = [0.26, 0.26] # um
|
91
|
+
diffusion_coefficient = [0, 0] # um^2/s
|
92
|
+
hurst_exponent = [0.2, 0.2]
|
93
|
+
density_dif = 10 # density of the condensate vs the background.
|
113
94
|
|
114
95
|
[Output_Parameters]
|
115
96
|
output_path = "<YOUR-PATH-HERE-CAN-BE-ABSOLUTE-OR-RELATIVE>"
|
@@ -183,6 +164,12 @@ to_state = "triplet"
|
|
183
164
|
photon_dependent = false
|
184
165
|
base_rate = 1 # 1/s
|
185
166
|
|
167
|
+
[fluorophores.PAmCherry.transitions.triplet_to_bleached]
|
168
|
+
from_state = "triplet"
|
169
|
+
to_state = "bleached"
|
170
|
+
photon_dependent = false
|
171
|
+
base_rate = 1 # 1/s
|
172
|
+
|
186
173
|
[fluorophores.PAmCherry.transitions.triplet_to_dark]
|
187
174
|
from_state = "triplet"
|
188
175
|
to_state = "dark"
|
@@ -259,7 +246,6 @@ custom_path = ""
|
|
259
246
|
[psf.parameters]
|
260
247
|
numerical_aperture = 1.4 # typical range: 0.1 - 1.5
|
261
248
|
refractive_index = 1.0 # default is air (1.0)
|
262
|
-
#pinhole_diameter = 1.0 # Do not include for no pinhole else float in um units
|
263
249
|
|
264
250
|
# Multiple Laser Configuration File
|
265
251
|
|
AMS_BP/sim_microscopy.py
CHANGED
@@ -73,9 +73,7 @@ class VirtualMicroscope:
|
|
73
73
|
def _set_laser_powers(self, laser_power: Dict[str, float]) -> None:
|
74
74
|
if laser_power is not None:
|
75
75
|
for laser in laser_power.keys():
|
76
|
-
if isinstance(self.lasers[laser].params.power, float)
|
77
|
-
laser_power[laser], float
|
78
|
-
):
|
76
|
+
if isinstance(self.lasers[laser].params.power, float):
|
79
77
|
if laser_power[laser] > self.lasers[laser].params.max_power:
|
80
78
|
raise ValueError(
|
81
79
|
"Provided laser power for laser: {} nm, is larger than the maximum power: {}".format(
|
@@ -278,7 +276,7 @@ class VirtualMicroscope:
|
|
278
276
|
PhysicalSizeXUnit="m",
|
279
277
|
PhysicalSizeY=self.camera.pixel_size * 1e-6,
|
280
278
|
PhysicalSizeYUnit="m",
|
281
|
-
Channel={"Name": self.channels.names},
|
279
|
+
# Channel={"Name": self.channels.names},
|
282
280
|
)
|
283
281
|
|
284
282
|
# return frames in the format ZCTYX
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: AMS_BP
|
3
|
-
Version: 0.0.
|
4
|
-
Summary: Advanced Microscopy Simulations developed for the Weber Lab by Baljyot Singh Parmar
|
3
|
+
Version: 0.0.11
|
4
|
+
Summary: Advanced Molecule Simulations and Microscopy Simulations developed for the Weber Lab by Baljyot Singh Parmar
|
5
5
|
Project-URL: Documentation, https://joemans3.github.io/AMS_BP/
|
6
6
|
Project-URL: Source code, https://github.com/joemans3/AMS_BP
|
7
7
|
Author-email: Baljyot Singh Parmar <baljyotparmar@hotmail.com>
|
@@ -10,6 +10,7 @@ License-File: LICENSE
|
|
10
10
|
Keywords: SMS
|
11
11
|
Requires-Python: >=3.10
|
12
12
|
Requires-Dist: jsonschema>=4.23.0
|
13
|
+
Requires-Dist: matplotlib>=3.6.0
|
13
14
|
Requires-Dist: numpy>=1.21.2
|
14
15
|
Requires-Dist: pydantic>=2.9.2
|
15
16
|
Requires-Dist: scikit-image>=0.18.3
|
@@ -18,17 +19,11 @@ Requires-Dist: tomli>=2.0.2
|
|
18
19
|
Requires-Dist: typer>=0.12.5
|
19
20
|
Description-Content-Type: text/markdown
|
20
21
|
|
21
|
-
# AMS-BP
|
22
|
-
|
23
|
-
<img src="./docs/assets/icons/drawing.svg" alt="AMS-BP Logo" width="500" height="200">
|
24
|
-
</p>
|
25
|
-
|
26
|
-
## Advanced Fluorescence Microscopy Simulation Tool
|
22
|
+
# AMS-BP User Guide
|
23
|
+
## Advanced Molecule Simulation Tool
|
27
24
|
|
28
25
|
AMS-BP is a powerful simulation tool for advanced fluorescence microscopy experiments. This guide covers both command-line usage and library integration.
|
29
26
|
|
30
|
-
> **_NOTE:_** Please note that this application DOES NOT currently model the process of stimulated emission, and as such is not suitable for simulating stimulated emission microscopy ([STED](https://en.wikipedia.org/wiki/STED_microscopy))-type experiments. Work in this area is ongoing.
|
31
|
-
|
32
27
|
## Table of Contents
|
33
28
|
- [Installation](#installation)
|
34
29
|
- [Command Line Interface](#command-line-interface)
|
@@ -54,14 +49,6 @@ uv tool install AMS_BP
|
|
54
49
|
- `run_AMS_BP config` : This is a helper tool to generate a template config file for the simulation. (see `run_AMS_BP config --help` for more details)
|
55
50
|
- Note: using `run_AMS_BP --help` will show you all the available commands.
|
56
51
|
4. You can now use these tools (they are isolated in their own env created by uv, which is cool).
|
57
|
-
|
58
|
-
### ***PyPi***
|
59
|
-
|
60
|
-
1. Run:
|
61
|
-
```bash
|
62
|
-
pip install AMS_BP
|
63
|
-
```
|
64
|
-
|
65
52
|
## Command Line Interface
|
66
53
|
|
67
54
|
AMS-BP provides a command-line interface with two main commands:
|
@@ -83,7 +70,7 @@ run_AMS_BP runsim CONFIG_FILE
|
|
83
70
|
|
84
71
|
The configuration file (sim_config.toml) is divided into several key sections:
|
85
72
|
|
86
|
-
#### For a detailed description of the configuration file, refer to the [Configuration File Reference](
|
73
|
+
#### For a detailed description of the configuration file, refer to the [Configuration File Reference](./API_Documentation/sim_config.md).
|
87
74
|
### Basic Units
|
88
75
|
```toml
|
89
76
|
version = "0.1"
|
@@ -172,4 +159,39 @@ from AMS_BP.configio.saving import save_config_frames
|
|
172
159
|
save_config_frames(metadata, frames, setup_config["base_config"].OutputParameters)
|
173
160
|
```
|
174
161
|
|
175
|
-
|
162
|
+
### Key Components When Using as Library
|
163
|
+
|
164
|
+
1. **ConfigLoader**: Handles configuration file parsing and validation
|
165
|
+
2. **Microscope**: Represents the virtual microscope setup
|
166
|
+
3. **Experiment Functions**: Control experiment execution
|
167
|
+
4. **Save Functions**: Handle data output
|
168
|
+
|
169
|
+
### Custom Experiment Types
|
170
|
+
|
171
|
+
When using AMS-BP as a library, you can create custom experiment types by:
|
172
|
+
|
173
|
+
1. Extending the base experiment class
|
174
|
+
2. Implementing custom scanning patterns
|
175
|
+
3. Defining new molecule behaviors
|
176
|
+
4. Creating specialized analysis routines
|
177
|
+
|
178
|
+
## Tips and Best Practices
|
179
|
+
|
180
|
+
1. **Configuration Management**
|
181
|
+
- Keep separate config files for different experiment types
|
182
|
+
- Version control your configurations
|
183
|
+
- Document any custom modifications
|
184
|
+
|
185
|
+
2. **Resource Usage**
|
186
|
+
- Monitor memory usage for large simulations
|
187
|
+
- Use appropriate sampling rates
|
188
|
+
|
189
|
+
3. **Data Output**
|
190
|
+
- Set appropriate output paths
|
191
|
+
- Use meaningful naming conventions
|
192
|
+
- Consider data format requirements for analysis
|
193
|
+
|
194
|
+
## Troubleshooting
|
195
|
+
|
196
|
+
Common issues and their solutions:
|
197
|
+
TODO
|
@@ -1,40 +1,40 @@
|
|
1
|
-
AMS_BP/__init__.py,sha256=
|
2
|
-
AMS_BP/run_cell_simulation.py,sha256=
|
3
|
-
AMS_BP/sim_config.toml,sha256=
|
4
|
-
AMS_BP/sim_microscopy.py,sha256=
|
1
|
+
AMS_BP/__init__.py,sha256=RIbrP3fesid1_nRkAUmjla1c4p2K5T-2exkbTTssitg,327
|
2
|
+
AMS_BP/run_cell_simulation.py,sha256=fPU1Tuu7hBupGtMk07j2t8QYo_TjFLMJRU9fwmAgU9c,7502
|
3
|
+
AMS_BP/sim_config.toml,sha256=raxr-VSoVdTbaQX09rkLEiMWY2UfPShpv9v5MSVB4_g,11383
|
4
|
+
AMS_BP/sim_microscopy.py,sha256=7JQ6NQlgNZCvFE-FC1f9Ehh6DoJgn7bLzeqS_Mamq9Y,18619
|
5
5
|
AMS_BP/cells/__init__.py,sha256=yWFScBC1uOGDkeC8i1m1ZBtIREcyt4JHxYa72LxbBZU,177
|
6
6
|
AMS_BP/cells/base_cell.py,sha256=FIPB9J8F40tb53vv7C6qG-SaAFLOI8-MGIk1mmZ-gnI,1503
|
7
7
|
AMS_BP/cells/rectangular_cell.py,sha256=5yGxvTXYvgldLXyWXpE_SD9Zx2NLerC-I2j02reHsJ0,2515
|
8
8
|
AMS_BP/cells/rod_cell.py,sha256=jQ1kLEk74Pv2rcXPRJ6-QJJhux-mYiDSytzqlxCNWfA,3181
|
9
9
|
AMS_BP/cells/spherical_cell.py,sha256=n3ou3tW0nCxXIwv6uLkVKHkYCfgoNn8VI6CVTLBIll0,2140
|
10
10
|
AMS_BP/configio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
|
-
AMS_BP/configio/configmodels.py,sha256=
|
12
|
-
AMS_BP/configio/convertconfig.py,sha256=
|
11
|
+
AMS_BP/configio/configmodels.py,sha256=KK5A9aFzRuXBWlwEGr84_x3LY60p7cddRgBsSkx5iS8,2986
|
12
|
+
AMS_BP/configio/convertconfig.py,sha256=OHm9GnKXXObGWIEpeFfHOYJTHNWhjZKhoopLG85zWgY,34271
|
13
13
|
AMS_BP/configio/experiments.py,sha256=HdfaSi0gPPJ_wLF87XcW5ICja19Uezx7-ygFEwNzi30,3995
|
14
14
|
AMS_BP/configio/saving.py,sha256=596QgAadV32rzsN4B2FngGFcBWCzCDnLFN-qtQsv3bM,857
|
15
15
|
AMS_BP/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
|
-
AMS_BP/metadata/metadata.py,sha256=
|
16
|
+
AMS_BP/metadata/metadata.py,sha256=_FwbSRsUhGwigY6YYffMgEx5hlXTT_vu-9AldMFPa6w,2923
|
17
17
|
AMS_BP/motion/__init__.py,sha256=cy3W-wCRjjlN1DrTqYc-JltYwcE8SZCXMVPJ2o6q_BQ,178
|
18
|
-
AMS_BP/motion/condensate_movement.py,sha256=
|
19
|
-
AMS_BP/motion/track_gen.py,sha256=
|
18
|
+
AMS_BP/motion/condensate_movement.py,sha256=cGLHIOL7VUJ7U-JrJXetcnUF2v9SepIBznoqu6AQPxU,13252
|
19
|
+
AMS_BP/motion/track_gen.py,sha256=Z3QJLVMP1gX4SlgOXFxBg8sJhBG0Xq25ixnBoEHEAZI,19462
|
20
20
|
AMS_BP/motion/movement/__init__.py,sha256=PqovpG4dAuFFIP9M2_kt-6egQJX3P5ig4MMWVzNaswg,278
|
21
21
|
AMS_BP/motion/movement/boundary_conditions.py,sha256=jpfK3AEUY8btrTsu19bpUfx-jri7_HfyxqMFjMoxAVM,2200
|
22
|
-
AMS_BP/motion/movement/fbm_BP.py,sha256=
|
22
|
+
AMS_BP/motion/movement/fbm_BP.py,sha256=dH-JZiAInnIaZXH1wAAo8dOIX9zafclqnZ4dOhKtnO0,9327
|
23
23
|
AMS_BP/optics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
24
|
AMS_BP/optics/camera/__init__.py,sha256=eCoDUFHcoCWgbgYdLn8EH7AULM53A3XWTXNZnV8QxeY,182
|
25
|
-
AMS_BP/optics/camera/detectors.py,sha256=
|
25
|
+
AMS_BP/optics/camera/detectors.py,sha256=UJqi7owESw9nkFiQhoAe7Q1LIi_fYCzuvZLgtM3yAPk,10348
|
26
26
|
AMS_BP/optics/camera/quantum_eff.py,sha256=ZCvJ8dJESOUbjwblsJIBcCg_b-_DNdhDlkzd7HeGMDg,2378
|
27
27
|
AMS_BP/optics/filters/__init__.py,sha256=oYPk2_wuL4KrwbaZy3gktvO5biQUfdQLUColWhkU1lw,337
|
28
28
|
AMS_BP/optics/filters/filters.py,sha256=-iw7eqmDO77SEqlFTv5jJNVwpA8y93TLsjy5hhsAfiI,6406
|
29
29
|
AMS_BP/optics/filters/channels/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
30
|
AMS_BP/optics/filters/channels/channelschema.py,sha256=SConyA5yVdfnI_8sgcxVC8SV7S8tGUJYPPC6jn7lglU,906
|
31
31
|
AMS_BP/optics/lasers/__init__.py,sha256=T7dHohhyLf_pBw4TidarYHWmiwxVXGE71-Bf1aeBbuc,564
|
32
|
-
AMS_BP/optics/lasers/laser_profiles.py,sha256=
|
32
|
+
AMS_BP/optics/lasers/laser_profiles.py,sha256=J9czY646XcW8GzXx9Eb16mG7tQdWw4oVYveOrihZCeY,22745
|
33
33
|
AMS_BP/optics/psf/__init__.py,sha256=ezrKPgpTeR4gTHOvF0mhF6u2zMMTd8Bgp8PGeOf11fA,121
|
34
|
-
AMS_BP/optics/psf/psf_engine.py,sha256=
|
34
|
+
AMS_BP/optics/psf/psf_engine.py,sha256=ejmTwAKtEpXvKeMuUFcuz6HjJbEjQa_NvkE6a3hkVzk,6769
|
35
35
|
AMS_BP/photophysics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
36
|
-
AMS_BP/photophysics/photon_physics.py,sha256=
|
37
|
-
AMS_BP/photophysics/state_kinetics.py,sha256=
|
36
|
+
AMS_BP/photophysics/photon_physics.py,sha256=QRG_QIZ4csJ3g5qGP9Wtk7kzqm8_MUbVHfFef6cMtHQ,6671
|
37
|
+
AMS_BP/photophysics/state_kinetics.py,sha256=0cc7Vc4LtAbEdGDeg22IJmRGLsONOty4c32hXHO-TSU,5281
|
38
38
|
AMS_BP/probabilityfuncs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
39
|
AMS_BP/probabilityfuncs/markov_chain.py,sha256=LV6KGr8Lv4NIvBPJqsR0CEynssa_mPH30qLaK85GObA,4339
|
40
40
|
AMS_BP/probabilityfuncs/probability_functions.py,sha256=j_rIxrupGBf_FKkQBh1TvEa34A44jAasaZQRg2u3FuY,11793
|
@@ -48,8 +48,8 @@ AMS_BP/utils/decorators.py,sha256=4qFdvzPJne0dhkhD1znPxRln1Rfr5NX8rdcCDcbATRU,62
|
|
48
48
|
AMS_BP/utils/errors.py,sha256=7BOd-L4_YeKmWn3Q4EOdTnNF3Bj_exDa3eg5X0yCZrc,759
|
49
49
|
AMS_BP/utils/maskMaker.py,sha256=2ca3n2nc8rFtUh1LurKXOJJsUmhrOpWbRnVX7fjRVvs,335
|
50
50
|
AMS_BP/utils/util_functions.py,sha256=jI6WBh09_khdABnEoVK7SK1WRvCLHuw40f5ALyflzlc,9478
|
51
|
-
ams_bp-0.0.
|
52
|
-
ams_bp-0.0.
|
53
|
-
ams_bp-0.0.
|
54
|
-
ams_bp-0.0.
|
55
|
-
ams_bp-0.0.
|
51
|
+
ams_bp-0.0.11.dist-info/METADATA,sha256=unqrYIrskb0xGCrHhqiJtQ8VNxvSRvAzjizx4WUSWxg,5918
|
52
|
+
ams_bp-0.0.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
53
|
+
ams_bp-0.0.11.dist-info/entry_points.txt,sha256=MFUK9bZWW61djfsavqopMqiVPVn4lJtt6v8qzyEFyNM,76
|
54
|
+
ams_bp-0.0.11.dist-info/licenses/LICENSE,sha256=k_-JV1DQKvO0FR8WjvOisqdTl0kp6VJ7RFM3YZhao0c,1071
|
55
|
+
ams_bp-0.0.11.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|