|
5 | 5 | [](https://github.com/JuliaSMLM/SMLMSim.jl/actions) |
6 | 6 | [](https://codecov.io/gh/JuliaSMLM/SMLMSim.jl) |
7 | 7 |
|
8 | | -Generate simulated SMLM coordinate data. Patterns, Cameras, Fluorophores, and SMLD data organization can be configured. |
| 8 | +## Overview |
9 | 9 |
|
10 | | -Simulation parameters use physical units. Resulting `SMLMData.SMLD` structures are in units of pixels and frames. |
| 10 | +SMLMSim is a Julia package for simulating Single Molecule Localization Microscopy (SMLM) data with realistic physical properties. The package builds upon SMLMData, reexporting essential types and functions so you typically don't need to import SMLMData directly. |
11 | 11 |
|
| 12 | +The package provides tools for: |
12 | 13 |
|
13 | | -The high level interface for simulating SMLM super-resolution coordinate data is the `SMLMSim.sim()` function. |
| 14 | +- Generating spatial patterns of fluorophores in 2D and 3D |
| 15 | +- Simulating fluorophore photophysics with stochastic kinetic models |
| 16 | +- Adding realistic localization uncertainty based on photon counts |
| 17 | +- Simulating diffusion and interactions between molecules |
| 18 | +- Generating microscope images with configurable PSFs |
14 | 19 |
|
| 20 | +All simulations use physical units, with coordinates in microns and time in seconds. The resulting data is organized into `SMLMData.SMLD` structures compatible with the broader JuliaSMLM ecosystem. |
| 21 | + |
| 22 | +## Installation |
| 23 | + |
| 24 | +```julia |
| 25 | +using Pkg |
| 26 | +Pkg.add("SMLMSim") |
15 | 27 | ``` |
| 28 | + |
| 29 | +## Basic Usage |
| 30 | + |
| 31 | +The high-level interface for simulating SMLM super-resolution coordinate data is the `simulate()` function with a `StaticSMLMParams` object. |
| 32 | + |
| 33 | +```julia |
16 | 34 | using SMLMSim |
17 | | -using SMLMData |
18 | 35 |
|
19 | | -smld_true, smld_model, smld_noisy = SMLMSim.sim(; |
20 | | - ρ=1.0, |
21 | | - σ_PSF=0.13, |
22 | | - minphotons=50, |
23 | | - ndatasets=10, |
24 | | - nframes=1000, |
25 | | - framerate=50.0, # 1/s |
26 | | - pattern=SMLMSim.Nmer2D(), |
27 | | - molecule=SMLMSim.GenericFluor(; q=[0 50; 1e-2 0]), #1/s |
28 | | - camera=SMLMSim.IdealCamera(; ypixels=256, xpixels=128, pixelsize=0.1) #pixelsize is microns |
| 36 | +# Basic simulation with default parameters |
| 37 | +camera = IdealCamera(1:128, 1:128, 0.1) # 128×128 pixels, 100nm pixels |
| 38 | +params = StaticSMLMParams() # Default parameters |
| 39 | +smld_true, smld_model, smld_noisy = simulate( |
| 40 | + params, |
| 41 | + camera=camera |
| 42 | +) |
| 43 | +``` |
| 44 | + |
| 45 | +This basic example creates a 2D simulation using default parameters: |
| 46 | +- 8-molecule circular patterns (Nmer2D with n=8, d=0.1μm) |
| 47 | +- 1 pattern per square micron (ρ=1.0) |
| 48 | +- PSF width of 130nm (σ_psf=0.13μm) |
| 49 | +- Two-state fluorophore kinetics with realistic blinking behavior |
| 50 | +- 1000 frames at 50 frames per second |
| 51 | +- Minimum photon threshold of 50 for detection |
| 52 | + |
| 53 | +The function returns three SMLD objects with SMLM coordinates: |
| 54 | +- `smld_true`: Ground truth emitter positions (spatial coordinates only) |
| 55 | +- `smld_model`: Positions with simulated blinking kinetics (subset of true positions appearing in different frames) |
| 56 | +- `smld_noisy`: Positions with both blinking and localization uncertainty (realistic SMLM data with position errors) |
| 57 | + |
| 58 | +For more control, you can customize the parameters: |
| 59 | + |
| 60 | +```julia |
| 61 | +# More customized simulation |
| 62 | +params = StaticSMLMParams( |
| 63 | + ρ=1.0, # emitters per μm² |
| 64 | + σ_psf=0.13, # PSF width in μm (130nm) |
| 65 | + minphotons=50, # minimum photons for detection |
| 66 | + ndatasets=10, # number of independent datasets |
| 67 | + nframes=1000, # frames per dataset |
| 68 | + framerate=50.0 # frames per second |
| 69 | +) |
| 70 | + |
| 71 | +smld_true, smld_model, smld_noisy = simulate( |
| 72 | + params, |
| 73 | + pattern=Nmer2D(n=6, d=0.2), # hexamer with 200nm diameter |
| 74 | + molecule=GenericFluor(; q=[0 50; 1e-2 0]), # rates in 1/s |
| 75 | + camera=IdealCamera(1:256, 1:128, 0.1) # 128×256 pixels, 100nm pixels |
| 76 | +) |
| 77 | +``` |
| 78 | + |
| 79 | +This customized example: |
| 80 | +- Creates hexagonal patterns (6 molecules in a 200nm circle) |
| 81 | +- Uses 10 independent datasets of 1000 frames each |
| 82 | +- Simulates fluorophores with specific on/off transition rates |
| 83 | +- Uses a rectangular camera field of view (128×256 pixels) |
| 84 | + |
| 85 | +In both cases, the output SMLD objects contain emitter information (x, y coordinates, photon counts, frame numbers, etc.) that can be used for further analysis or visualization. |
| 86 | + |
| 87 | +## Pattern Types |
| 88 | + |
| 89 | +SMLMSim includes several built-in pattern types for positioning fluorophores: |
| 90 | + |
| 91 | +### 2D Patterns |
| 92 | + |
| 93 | +```julia |
| 94 | +# N molecules arranged in a circle |
| 95 | +nmer = Nmer2D(n=8, d=0.1) # 8 molecules in a 100nm diameter circle |
| 96 | + |
| 97 | +# Linear pattern with random positions |
| 98 | +line = Line2D(λ=5.0, endpoints=[(-2.0, 0.0), (2.0, 0.0)]) # 5 molecules per μm along line |
| 99 | +``` |
| 100 | + |
| 101 | +### 3D Patterns |
| 102 | + |
| 103 | +```julia |
| 104 | +# N molecules arranged in a circle at z=0 |
| 105 | +nmer3d = Nmer3D(n=8, d=0.1) # 8 molecules in a 100nm diameter circle |
| 106 | + |
| 107 | +# 3D line with random positions |
| 108 | +line3d = Line3D(λ=5.0, endpoints=[(-1.0, 0.0, -0.5), (1.0, 0.0, 0.5)]) |
| 109 | +``` |
| 110 | + |
| 111 | +## Molecule Models |
| 112 | + |
| 113 | +SMLMSim supports different fluorophore photophysical models: |
| 114 | + |
| 115 | +```julia |
| 116 | +# Generic fluorophore with two-state kinetics |
| 117 | +fluor = GenericFluor( |
| 118 | + γ=10000.0, # photon emission rate in Hz |
| 119 | + q=[0 10; 1e-2 0] # transition rate matrix: state 1 ↔ state 2 |
29 | 120 | ) |
30 | 121 | ``` |
| 122 | + |
| 123 | +## Diffusion and Interaction Simulation |
| 124 | + |
| 125 | +The package includes tools for simulating diffusion and interactions between molecules: |
| 126 | + |
| 127 | +```julia |
| 128 | +# Set up parameters for Smoluchowski diffusion simulation |
| 129 | +params = SmoluchowskiParams( |
| 130 | + density = 0.5, # molecules per μm² |
| 131 | + box_size = 10.0, # μm |
| 132 | + diff_monomer = 0.1, # μm²/s |
| 133 | + diff_dimer = 0.05, # μm²/s |
| 134 | + k_off = 0.2, # s⁻¹ |
| 135 | + r_react = 0.01, # μm |
| 136 | + d_dimer = 0.05, # μm |
| 137 | + dt = 0.01, # s |
| 138 | + t_max = 10.0 # s |
| 139 | +) |
| 140 | + |
| 141 | +# Run simulation |
| 142 | +systems = simulate(params) |
| 143 | + |
| 144 | +# Visualize the simulation |
| 145 | +visualize_sequence(systems, filename="diffusion.mp4", framerate=round(Int64,1/params.dt)) |
| 146 | + |
| 147 | +# Generate microscope images |
| 148 | +psf = Gaussian2D(0.15) # 150nm PSF width |
| 149 | +images = gen_image_sequence( |
| 150 | + psf, |
| 151 | + systems, |
| 152 | + frame_integration=10 |
| 153 | +) |
| 154 | + |
| 155 | +# Extract only dimers |
| 156 | +dimer_systems = get_dimers(systems) |
| 157 | +dimer_images = gen_image_sequence( |
| 158 | + psf, |
| 159 | + dimer_systems, |
| 160 | + frame_integration=10 |
| 161 | +) |
| 162 | +``` |
| 163 | + |
| 164 | +## Example Workflows |
| 165 | + |
| 166 | +### 2D Simulation with Visualization |
| 167 | + |
| 168 | +```julia |
| 169 | +using SMLMSim |
| 170 | +using CairoMakie |
| 171 | + |
| 172 | +# Create camera with physical pixel size |
| 173 | +camera = IdealCamera(1:128, 1:256, 0.1) # 128×256 pixels, 100nm pixels |
| 174 | + |
| 175 | +# Create simulation parameters |
| 176 | +params = StaticSMLMParams( |
| 177 | + ρ=1.0, # emitters per μm² |
| 178 | + σ_psf=0.13 # PSF width in μm |
| 179 | +) |
| 180 | + |
| 181 | +# Run simulation |
| 182 | +smld_true, smld_model, smld_noisy = simulate( |
| 183 | + params, |
| 184 | + pattern=Nmer2D(n=6, d=0.2), # hexamer with 200nm diameter |
| 185 | + camera=camera |
| 186 | +) |
| 187 | + |
| 188 | +# Extract coordinates from emitters |
| 189 | +x_noisy = [e.x for e in smld_noisy.emitters] |
| 190 | +y_noisy = [e.y for e in smld_noisy.emitters] |
| 191 | +photons = [e.photons for e in smld_noisy.emitters] |
| 192 | + |
| 193 | +# Create figure and plot results |
| 194 | +fig = Figure(size=(800, 600)) |
| 195 | +ax = Axis(fig[1, 1], |
| 196 | + title="Simulated SMLM Localizations", |
| 197 | + xlabel="x (μm)", |
| 198 | + ylabel="y (μm)", |
| 199 | + aspect=DataAspect(), |
| 200 | + yreversed=true # This makes (0,0) at top-left |
| 201 | +) |
| 202 | + |
| 203 | +# Scatter plot with photon counts as color |
| 204 | +scatter!(ax, x_noisy, y_noisy, |
| 205 | + color=photons, |
| 206 | + colormap=:viridis, |
| 207 | + markersize=4, |
| 208 | + alpha=0.6 |
| 209 | +) |
| 210 | + |
| 211 | +Colorbar(fig[1, 2], colormap=:viridis, label="Photons") |
| 212 | + |
| 213 | +# Show or save the figure |
| 214 | +display(fig) |
| 215 | +# save("smlm_simulation.png", fig) |
| 216 | +``` |
| 217 | + |
| 218 | +### 3D Simulation |
| 219 | + |
| 220 | +```julia |
| 221 | +using SMLMSim |
| 222 | + |
| 223 | +# Create camera with physical pixel size |
| 224 | +camera = IdealCamera(1:128, 1:256, 0.1) # 128×256 pixels, 100nm pixels |
| 225 | + |
| 226 | +# Create 3D simulation parameters |
| 227 | +params = StaticSMLMParams( |
| 228 | + ρ=0.5, # emitters per μm² |
| 229 | + ndims=3, # 3D simulation |
| 230 | + zrange=[-2.0, 2.0] # 4μm axial range |
| 231 | +) |
| 232 | + |
| 233 | +# Run simulation |
| 234 | +smld_true, smld_model, smld_noisy = simulate( |
| 235 | + params, |
| 236 | + pattern=Nmer3D(n=8, d=0.3), # 3D pattern |
| 237 | + camera=camera |
| 238 | +) |
| 239 | +``` |
| 240 | + |
| 241 | +## Contributors |
| 242 | + |
| 243 | +- [JuliaSMLM Team](https://github.com/JuliaSMLM) |
| 244 | + |
| 245 | +## License |
| 246 | + |
| 247 | +This project is licensed under the MIT License - see the LICENSE file for details. The MIT License is a permissive license that allows for reuse with few restrictions. It permits use, modification, distribution, and private use while preserving copyright and license notices. |
0 commit comments