API Reference

This page provides a comprehensive reference for the types and functions in SMLMSim.

SMLMSim.SMLMSimModule
SMLMSim

Main module for the SMLMSim.jl package.

API Overview

For a comprehensive overview of the API, use the help mode on api_overview:

?api_overview

Or access the complete API documentation programmatically:

docs = SMLMSim.api_overview()

This package provides tools for simulating Single Molecule Localization Microscopy (SMLM) data. It includes modules for:

  • Core: Fundamental types (molecules, patterns) and photophysics simulation (CTMC, blinking).
  • StaticSMLM: Simulating static emitters with blinking and localization noise.
  • InteractionDiffusion: Simulating diffusing and interacting emitters (e.g., dimerization) using Smoluchowski dynamics.
  • CameraImages: Generating simulated camera images from emitter data, including noise models.

The main SMLMSim module re-exports key types and functions from these submodules to provide a unified user interface.

Usage

using SMLMSim

# Example: Static simulation
params_static = StaticSMLMParams(density=1.0, σ_psf=0.13)
_, _, smld_noisy = simulate(params_static)

# Example: Diffusion simulation
params_diff = DiffusionSMLMParams(density=0.5, diff_monomer=0.1)
smld_diff = simulate(params_diff)

# Example: Generate images
psf = GaussianPSF(0.15)
images = gen_images(smld_noisy, psf)
source
SMLMSim.api_overviewMethod

SMLMSim.jl API Overview

SMLMSim is a Julia package for simulating Single Molecule Localization Microscopy (SMLM) data with realistic physical properties. It provides tools for generating static SMLM simulations, diffusion-interaction simulations, and microscope image generation.

Key Concepts

Physical Units

All simulations use consistent physical units:

  • Spatial dimensions: microns (μm)
  • Time: seconds (s)
  • Diffusion coefficients: μm²/s
  • Rate constants: s⁻¹

Core Components

  • Patterns: Spatial arrangements of molecules (e.g., oligomers, lines)
  • Molecules: Photophysical models of fluorophores with state transitions
  • Simulation: Parameters and functions for different simulation types
  • Noise: Realistic localization uncertainty based on photon statistics
  • Camera Images: Generation of microscope images from simulation data

Type Hierarchy

  • AbstractSim: Base type for all simulation types

    • SMLMSimParams: Base type for simulation parameters
      • StaticSMLMParams: Parameters for static SMLM simulation
      • DiffusionSMLMParams: Parameters for diffusion simulation
  • Pattern: Base type for all molecular patterns

    • Pattern2D: Base type for 2D patterns
      • Nmer2D: N molecules arranged in a circle
      • Line2D: Molecules arranged along a line
    • Pattern3D: Base type for 3D patterns
      • Nmer3D: N molecules arranged in a circle in 3D
      • Line3D: Molecules arranged along a 3D line
  • Molecule: Base type for all photophysical models

    • GenericFluor: General fluorophore with kinetic state model
  • AbstractDiffusingEmitter: Base type for diffusing emitters

    • DiffusingEmitter2D: 2D emitter with diffusion state
    • DiffusingEmitter3D: 3D emitter with diffusion state

Essential Types

StaticSMLMParams

Parameters for static SMLM simulation with fixed molecular patterns.

Base.@kwdef mutable struct StaticSMLMParams <: SMLMSimParams
    density::Float64 = 1.0          # density in particles per square micron
    σ_psf::Float64 = 0.13           # PSF width in microns
    minphotons::Int = 50            # minimum photons for detection
    ndatasets::Int = 10             # number of datasets to simulate
    nframes::Int = 1000             # number of frames per dataset
    framerate::Float64 = 50.0       # frames per second
    ndims::Int = 2                  # dimensionality (2 or 3)
    zrange::Vector{Float64} = [-1.0, 1.0]  # axial range for 3D simulations [min_z, max_z]
end

DiffusionSMLMParams

Parameters for diffusion-based SMLM simulation using Smoluchowski dynamics.

Base.@kwdef mutable struct DiffusionSMLMParams <: SMLMSimParams
    density::Float64 = 1.0          # number density (molecules/μm²)
    box_size::Float64 = 10.0        # simulation box size (μm)
    diff_monomer::Float64 = 0.1     # monomer diffusion coefficient (μm²/s)
    diff_dimer::Float64 = 0.05      # dimer diffusion coefficient (μm²/s)
    diff_dimer_rot::Float64 = 0.5   # dimer rotational diffusion coefficient (rad²/s)
    k_off::Float64 = 0.2            # dimer dissociation rate (s⁻¹)
    r_react::Float64 = 0.01         # reaction radius (μm)
    d_dimer::Float64 = 0.05         # monomer separation in dimer (μm)
    dt::Float64 = 0.01              # time step (s)
    t_max::Float64 = 10.0           # total simulation time (s)
    ndims::Int = 2                  # number of dimensions (2 or 3)
    boundary::String = "periodic"   # boundary condition type ("periodic" or "reflecting")
    camera_framerate::Float64 = 10.0 # camera frames per second (Hz)
    camera_exposure::Float64 = 0.1   # camera exposure time per frame (s)
end

Molecular Patterns

Nmer2D

N molecules symmetrically organized around a circle with diameter d.

mutable struct Nmer2D <: Pattern2D
    n::Int               # Number of molecules in the pattern
    d::Float64           # Diameter of the circle in microns
    x::Vector{Float64}   # X positions of molecules in microns
    y::Vector{Float64}   # Y positions of molecules in microns
end

Line2D

Points with uniform random distribution between two endpoints.

mutable struct Line2D <: Pattern2D
    n::Int                # Number of molecules in the pattern
    x::Vector{Float64}    # X positions of molecules in microns
    y::Vector{Float64}    # Y positions of molecules in microns
    λ::Float64            # Linear molecule density (molecules per micron)
    endpoints::Vector{Tuple{Float64,Float64}}  # Vector of endpoint coordinates
end

Fluorophore Models

GenericFluor

Defines a fluorophore with photophysical properties.

struct GenericFluor <: Molecule
    γ::AbstractFloat     # Photon emission rate in Hz
    q::Array{<:AbstractFloat}  # Rate matrix for state transitions
end

Constructor Examples

Creating Simulation Parameters

# Static SMLM with default parameters
params_static = StaticSMLMParams()

# Custom parameters for static simulation
params_static = StaticSMLMParams(
    density = 2.0,        # 2 patterns per μm²
    σ_psf = 0.15,         # 150nm PSF width
    nframes = 2000,       # 2000 frames
    framerate = 20.0      # 20 fps
)

# Diffusion simulation with default parameters
params_diff = DiffusionSMLMParams()

# Custom parameters for diffusion simulation
params_diff = DiffusionSMLMParams(
    density = 0.5,        # molecules per μm²
    box_size = 15.0,      # 15μm box size
    diff_monomer = 0.2,   # 0.2 μm²/s diffusion coefficient
    k_off = 0.1,          # 0.1 s⁻¹ dissociation rate
    t_max = 20.0          # 20s simulation time
)

Creating Patterns

# Create an 8-molecule pattern with 100nm diameter (default)
nmer = Nmer2D()

# Create a custom pattern with 6 molecules and 200nm diameter
hexamer = Nmer2D(n=6, d=0.2)  # d is in microns

# Create a 3D pattern
octamer3d = Nmer3D(n=8, d=0.15)

# Create a line pattern
line = Line2D(λ=5.0, endpoints=[(-2.0, 0.0), (2.0, 0.0)])  # 5 molecules/μm

# Create a 3D line pattern
line3d = Line3D(λ=8.0, endpoints=[(-1.0, 0.0, -0.5), (1.0, 0.0, 0.5)])

Creating Fluorophore Models

# Create a fluorophore with default parameters
fluor = GenericFluor()

# Create a fluorophore with custom parameters
# γ=10,000 photons/s, k_off=10 Hz, k_on=0.1 Hz
fluor = GenericFluor(1e4, [-10.0 10.0; 0.1 -0.1])

# Create a fluorophore using the 2-state keyword constructor
fluor = GenericFluor(photons=1e4, k_off=5.0, k_on=0.5)

Creating a Camera

# Create a camera with 100nm pixels (128x128 pixels)
camera = IdealCamera(128, 128, 0.1)  # 128×128 pixels, 100nm pixels

# Specify field of view with an array of pixel edges
pixel_edges_x = 0.0:0.1:12.8  # 0 to 12.8μm in 0.1μm steps
pixel_edges_y = 0.0:0.1:12.8
camera = IdealCamera(pixel_edges_x, pixel_edges_y)

Core Functions

Simulation

simulate

The main simulation function with multiple methods for different simulation types.

# Static SMLM simulation
# First create simulation parameters
params = StaticSMLMParams()

# Then run simulation
smld_true, smld_model, smld_noisy = simulate(
    params;
    pattern=Nmer2D(),
    molecule=GenericFluor(),
    camera=IdealCamera(128, 128, 0.1)
)

# Diffusion simulation
# First create simulation parameters
params_diff = DiffusionSMLMParams()

# Then run simulation
smld = simulate(
    params_diff;
    photons=1000.0
)

kinetic_model

Generate kinetic blinking model from existing localization data.

# Example of how to call kinetic_model
# First create or obtain the required inputs
smld_true = ... # Some BasicSMLD with true positions
fluor = GenericFluor(1e4, [-10.0 10.0; 0.5 -0.5])  # Fluorophore model
nframes = 1000    # Number of frames
framerate = 50.0  # Frames per second

# Call the function
smld_model = kinetic_model(
    smld_true,     # BasicSMLD with emitter positions
    fluor,         # Molecule with kinetic rates
    nframes,       # Number of frames
    framerate;     # Frames per second
    ndatasets=1,   # Number of independent datasets
    minphotons=50.0, # Minimum photons for detection
    state1=:equilibrium  # Initial state sampling
)

apply_noise

Add localization uncertainty to emitter positions based on photon counts.

# Example usage of apply_noise

# First, you need smld_model from a previous step
# For example, from the output of kinetic_model()

# For 2D emitters - add noise with 130nm PSF width
smld_noisy = apply_noise(smld_model, 0.13)  # 0.13 μm = 130nm PSF width

# For 3D emitters - specify PSF width in each dimension
smld_noisy_3d = apply_noise(smld_model_3d, [0.13, 0.13, 0.39])  # [x, y, z] widths in μm

Image Generation

gen_images

Generate camera images from SMLD data using the specified PSF model.

images = gen_images(
    smld::SMLD,
    psf::AbstractPSF;
    dataset::Int=1,                # Dataset number to use from SMLD
    frames=nothing,                # Specific frames to generate (default: all frames)
    support=Inf,                   # PSF support region size (see details below)
    sampling=2,                    # Supersampling factor for PSF integration
    threaded=true,                 # Enable multithreading
    bg=0.0,                        # Background signal level (photons per pixel)
    poisson_noise=false,           # Apply Poisson noise
    camera_noise=false             # Apply camera read noise
)

# The support parameter controls PSF computation region:
# 1. Inf (default): Compute PSF over entire image (most accurate but slowest)
support=Inf

# 2. Real number: Use circular region with given radius around each emitter
# Typically 3-5× the PSF width is sufficient for accuracy with better performance
support=1.0  # 1.0 µm radius around each emitter

# 3. Tuple (xmin, xmax, ymin, ymax): Explicit region in microns
support=(4.0, 6.0, 4.0, 6.0)  # Only compute PSF within this region

gen_image

Generate a single frame camera image.

# Example of generating a single frame image

# First, define variables
smld = ... # Your SMLD data
psf = GaussianPSF(0.15)  # PSF model with 150nm width
frame_number = 10  # The frame you want to generate

# Generate image for a specific frame
single_frame = gen_image(
    smld,          # SMLD data 
    psf,           # PSF model
    frame_number;  # Frame to generate
    support=1.0,   # Same keyword arguments as gen_images
    bg=5.0,
    poisson_noise=true
)

Analysis Functions

Diffusion Analysis

# Example usage of diffusion analysis functions

# First, run a diffusion simulation
params = DiffusionSMLMParams()
smld = simulate(params)

# Extract dimers from diffusion simulation
dimer_smld = get_dimers(smld)

# Extract monomers
monomer_smld = get_monomers(smld)

# Analyze dimer formation over time
frames, fractions = analyze_dimer_fraction(smld)

# Analyze average dimer lifetime
lifetime = analyze_dimer_lifetime(smld)

# Track state changes over time
state_history = track_state_changes(smld)

Track Utilities

# Example usage of track utilities

# First, run a simulation
params = StaticSMLMParams()
smld_true, smld_model, smld_noisy = simulate(params)

# Specify a track ID to extract
track_id = 1  # ID of the track to extract

# Get a specific track by ID
track_smld = get_track(smld_noisy, track_id)

# Get number of unique tracks
n_tracks = get_num_tracks(smld_noisy)

# Get all tracks as separate SMLDs
track_smlds = get_tracks(smld_noisy)

Pattern Manipulation

# Example usage of pattern manipulation

# Create patterns
pattern2d = Nmer2D(n=6, d=0.2)
pattern3d = Nmer3D(n=8, d=0.15)

# Rotate a 2D pattern by 45 degrees
rotate!(pattern2d, π/4) 

# Rotate a 3D pattern with Euler angles (ZYZ convention)
rotate!(pattern3d, π/4, π/6, π/3)  # α, β, γ angles

# Rotate a 3D pattern with a rotation matrix
θ = π/2 # 90 degrees
R = [cos(θ) -sin(θ) 0; sin(θ) cos(θ) 0; 0 0 1]  # Z-axis rotation
rotate!(pattern3d, R)

# Generate random pattern distribution in a field
field_x = 10.0 # μm
field_y = 10.0 # μm
density = 1.0  # patterns per μm²

# Get coordinates for 2D distribution
x, y = uniform2D(density, pattern2d, field_x, field_y)

# Get coordinates for 3D distribution
x, y, z = uniform3D(density, pattern3d, field_x, field_y, zrange=[-2.0, 2.0])

Common Workflows

Static SMLM Simulation Workflow

  1. Define simulation parameters
  2. Create a pattern (or use default)
  3. Define a fluorophore model (or use default)
  4. Run simulation to get true positions, kinetic model, and noisy localizations
  5. Generate microscope images or analyze the data
# 1. Define parameters
params = StaticSMLMParams(
    density = 1.0,
    σ_psf = 0.13,
    nframes = 1000
)

# 2. Create a pattern
pattern = Nmer2D(n=6, d=0.2)  # hexamer with 200nm diameter

# 3. Define fluorophore model
fluor = GenericFluor(photons=1e4, k_off=10.0, k_on=0.5)

# 4. Run simulation
smld_true, smld_model, smld_noisy = simulate(
    params;
    pattern=pattern,
    molecule=fluor
)

# 5. Create microscope images with efficient PSF support
psf = GaussianPSF(0.15)  # 150nm PSF width
images = gen_images(smld_model, psf; 
    support=1.0,         # 1.0 μm radius around each emitter
    poisson_noise=true   # Add realistic photon counting noise
)

Diffusion Simulation Workflow

  1. Define diffusion parameters
  2. Run simulation to get emitter trajectories
  3. Analyze the diffusion and interaction dynamics
  4. Generate microscope images
# 1. Define parameters
params = DiffusionSMLMParams(
    density = 0.5,        # molecules per μm²
    box_size = 10.0,      # μm
    diff_monomer = 0.1,   # μm²/s
    diff_dimer = 0.05,    # μm²/s
    k_off = 0.2,          # s⁻¹
    t_max = 10.0          # s
)

# 2. Run simulation
smld = simulate(params)

# 3. Analyze the results
dimer_smld = get_dimers(smld)
frames, fractions = analyze_dimer_fraction(smld)

# 4. Generate microscope images with finite PSF support
psf = GaussianPSF(0.15)  # 150nm PSF width
images = gen_images(smld, psf; 
    support=1.0,         # 1.0 μm PSF support radius (faster)
    bg=5.0,              # Background photons per pixel
    poisson_noise=true   # Add realistic photon counting noise
)

Complete Examples

Static SMLM with Image Generation

using SMLMSim
using MicroscopePSFs

# Define a camera and simulation parameters
camera = IdealCamera(128, 128, 0.1)  # 128×128 pixels, 100nm pixels
params = StaticSMLMParams(density=1.0, σ_psf=0.13, nframes=1000) 

# Run simulation for an 8-molecule ring pattern
smld_true, smld_model, smld_noisy = simulate(
    params;
    pattern=Nmer2D(n=8, d=0.1),  # 100nm diameter ring
    molecule=GenericFluor(1e4, [-10.0 10.0; 0.5 -0.5]),  # γ=10,000, k_off=10, k_on=0.5
    camera=camera
)

# Create a PSF model
psf = GaussianPSF(0.15)  # 150nm PSF width

# Generate microscope images with finite PSF support
images = gen_images(smld_model, psf;
    support=1.0,         # 1.0 μm PSF support radius (faster than Inf)
    bg=5.0,              # 5 background photons per pixel
    poisson_noise=true   # Add realistic photon counting noise
)

println("Generated $(length(smld_noisy.emitters)) localizations and $(size(images,3)) images.")

Diffusion with Dimer Analysis

using SMLMSim
using MicroscopePSFs

# Set diffusion simulation parameters
params = DiffusionSMLMParams(
    density = 0.5,        # molecules per μm²
    box_size = 10.0,      # μm
    diff_monomer = 0.1,   # μm²/s
    diff_dimer = 0.05,    # μm²/s
    k_off = 0.2,          # s⁻¹
    t_max = 10.0,         # s
    boundary = "reflecting"  # Use reflecting boundaries
)

# Run diffusion simulation
smld = simulate(params)

# Analyze dimer formation
frames, dimer_fraction = analyze_dimer_fraction(smld)
avg_lifetime = analyze_dimer_lifetime(smld)

# Generate microscope images with finite PSF support
psf = GaussianPSF(0.15)  # 150nm PSF width
images = gen_images(smld, psf; 
    support=1.0,         # 1.0 μm PSF support radius (faster)
    bg=2.0,              # Background photons per pixel
    poisson_noise=true   # Add realistic photon counting noise
)

println("Simulation complete with $(length(smld.emitters)) emitters")
println("Average dimer fraction: $(mean(dimer_fraction))")
println("Average dimer lifetime: $(avg_lifetime) seconds")

Custom Pattern with 3D Simulation

using SMLMSim
using MicroscopePSFs

# Define a custom 3D pattern: two rings at different z-positions
mutable struct DoubleRing3D <: Pattern3D
    n::Int
    d1::Float64
    d2::Float64
    z1::Float64
    z2::Float64
    x::Vector{Float64}
    y::Vector{Float64}
    z::Vector{Float64}
end

function DoubleRing3D(; n=8, d1=0.1, d2=0.2, z1=-0.2, z2=0.2)
    total_n = 2*n
    x = zeros(total_n)
    y = zeros(total_n)
    z = zeros(total_n)
    
    # First ring (bottom)
    for i = 1:n
        θ = 2π * (i-1) / n
        x[i] = d1/2 * cos(θ)
        y[i] = d1/2 * sin(θ)
        z[i] = z1
    end
    
    # Second ring (top)
    for i = 1:n
        θ = 2π * (i-1) / n + π/n  # Offset angle for second ring
        x[n+i] = d2/2 * cos(θ)
        y[n+i] = d2/2 * sin(θ)
        z[n+i] = z2
    end
    
    return DoubleRing3D(n, d1, d2, z1, z2, x, y, z)
end

# Create camera and parameters
camera = IdealCamera(128, 128, 0.1)
params = StaticSMLMParams(
    density = 0.5,
    σ_psf = 0.13,
    nframes = 2000,
    ndims = 3,
    zrange = [-1.0, 1.0]
)

# Create custom pattern
double_ring = DoubleRing3D(n=6, d1=0.15, d2=0.3, z1=-0.3, z2=0.3)

# Run simulation
smld_true, smld_model, smld_noisy = simulate(
    params;
    pattern=double_ring,
    camera=camera
)

# Generate images with a 3D astigmatic PSF and finite support
# Create a PSF with astigmatism using Zernike coefficients
using MicroscopePSFs
zc = ZernikeCoefficients(15)
zc.phase[6] = 0.5  # Add vertical astigmatism
psf_scalar = ScalarPSF(1.4, 0.532, 1.52; zernike_coeffs=zc)

# Create SplinePSF for speed
xy_sampling, z_sampling = 0.05, 0.1
x_range = y_range = -1.0:xy_sampling:1.0
z_range = -1.0:z_sampling:1.0
psf_spline = SplinePSF(psf_scalar, x_range, y_range, z_range)

# Generate images using the spline PSF with finite support
images = gen_images(smld_model, psf_spline; 
    support=0.5,         # 0.5 μm PSF support radius for performance
    bg=5.0,              # Background photons per pixel
    poisson_noise=true   # Add realistic photon counting noise
)

println("Generated $(length(smld_noisy.emitters)) localizations in 3D")

api_overview() returns this documentation as a plain String.

source
SMLMSim.simulateMethod
simulate(sim::AbstractSim; kwargs...)

Generic interface for all simulation types. Dispatches to the appropriate method based on the concrete simulation type.

Arguments

  • sim::AbstractSim: The simulation configuration object
  • kwargs...: Additional keyword arguments specific to the simulation type

Returns

  • The result of the specific simulation method

Example

# Create a static SMLM simulation configuration
params = StaticSMLMParams(
    density = 1.0,        # Changed from ρ to density
    σ_psf = 0.13
)

# Run the simulation
results = simulate(params)
source
SMLMSim.CoreModule
Core

Core module with shared utilities for SMLM simulation.

This module contains fundamental components that can be used across different simulation types (static, diffusion, etc.) including:

  1. Abstract types for simulation
  2. Molecule and pattern definitions
  3. CTMC (Continuous Time Markov Chain) for stochastic state transitions
  4. Photophysics modeling for blinking kinetics and detection

Usage

using SMLMSim.Core
source
SMLMSim.Core.AbstractSimType
AbstractSim

Abstract type for all simulation types in SMLMSim. Concrete subtypes should implement their own simulate methods.

source
SMLMSim.Core.CTMCType
CTMC{T<:AbstractFloat, U<:Int}

A Continuous Time Markov Chain representation storing the full trajectory of state transitions.

Fields

  • simulation_time::T: Total simulation time span
  • transition_times::Vector{T}: Time points at which state changes occurred, starting at 0.0
  • states::Vector{U}: Sequence of states entered at each transition time, starting with initial state

Type Parameters

  • T: Floating point type for time values
  • U: Integer type for state indices

Note

The states and transition_times vectors have the same length, with each entry in states[i] representing the state entered at time transition_times[i]. The system remains in states[i] until time transition_times[i+1].

source
SMLMSim.Core.CTMCMethod
CTMC(q::Array{T}, simulation_time::T, state1::Int) where {T<:AbstractFloat}

Construct a Continuous Time Markov Chain simulation from a rate matrix.

Arguments

  • q::Array{T}: Rate matrix where q[i,j] for i≠j is the transition rate from state i to j, and q[i,i] is the negative exit rate from state i
  • simulation_time::T: Total time to simulate
  • state1::Int: Initial state

Returns

  • CTMC{T,Int}: Simulated CTMC with transition times and states

Details

Simulates a CTMC using the Gillespie algorithm:

  1. Start in state1 at time 0
  2. For current state i:
    • Calculate total exit rate ktot = Σj q[i,j]
    • Sample time until next transition from Exp(k_tot)
    • Sample next state j with probability q[i,j]/k_tot
  3. Repeat until exceeding simulation_time
source
SMLMSim.Core.GenericFluorType
GenericFluor <: Molecule

Defines a fluorophore with photophysical properties.

Fields

  • γ::AbstractFloat: Photon emission rate in Hz. Default: 1e5
  • q::Array{<:AbstractFloat}: Rate matrix where q[i,j] for i≠j is the transition rate from state i to j, and q[i,i] is the negative exit rate from state i. Default: standard 2-state model with on->off rate of 50Hz and off->on rate of 1e-2Hz

Examples

# Create a fluorophore with default parameters (using the 2-state keyword constructor)
fluor = GenericFluor()

# Create a fluorophore with custom parameters using the positional constructor
fluor = GenericFluor(1e5, [-50.0 50.0; 1e-2 -1e-2])

# Create a fluorophore using the 2-state keyword constructor
fluor = GenericFluor(; photons=1e5, k_off=10.0, k_on=1e-1)
source
SMLMSim.Core.GenericFluorMethod
GenericFluor(; photons::AbstractFloat=1e5, k_off::AbstractFloat=50.0, k_on::AbstractFloat=1e-2)

Create a simple two-state (on/off) fluorophore with specified parameters.

Arguments

  • photons::AbstractFloat: Photon emission rate in Hz
  • k_off::AbstractFloat: Off-switching rate (on→off) in Hz
  • k_on::AbstractFloat: On-switching rate (off→on) in Hz

Details

Creates a fluorophore with a 2-state model and the specified rates. State 1 is the on (bright) state, and state 2 is the off (dark) state. The rate matrix is constructed as: q = [-koff koff; kon -kon]

source
SMLMSim.Core.Line2DType
Line2D <: Pattern2D

Points with uniform random distribution between two endpoints.

Fields

  • λ::Float64: Linear molecule density (molecules per micron)
  • endpoints::Vector{Tuple{Float64,Float64}}: Vector of endpoint coordinates
  • n::Int: Number of molecules in the pattern
  • x::Vector{Float64}: X positions of molecules in microns
  • y::Vector{Float64}: Y positions of molecules in microns

Examples

# Create a line with default parameters
line = Line2D()

# Create a custom line
line = Line2D(; λ=5.0, endpoints=[(-2.0, 0.0), (2.0, 0.0)])
source
SMLMSim.Core.Line3DType
Line3D <: Pattern3D

Points with uniform random distribution between two 3D endpoints.

Fields

  • λ::Float64: Linear molecule density (molecules per micron)
  • endpoints::Vector{Tuple{Float64,Float64,Float64}}: Vector of 3D endpoint coordinates
  • n::Int: Number of molecules in the pattern
  • x::Vector{Float64}: X positions of molecules in microns
  • y::Vector{Float64}: Y positions of molecules in microns
  • z::Vector{Float64}: Z positions of molecules in microns

Examples

# Create a line with default parameters
line = Line3D()

# Create a custom 3D line
line = Line3D(; λ=5.0, endpoints=[(-1.0, 0.0, -0.5), (1.0, 0.0, 0.5)])
source
SMLMSim.Core.MoleculeType
Molecule

Abstract type for representing photophysical properties of a molecule.

This is the most general type of luminescent or scattering single molecule. Inherited types will define the properties of specific classes of molecules.

source
SMLMSim.Core.Nmer2DType
Nmer2D <: Pattern2D

N molecules symmetrically organized around a circle with diameter d.

Fields

  • n::Int: Number of molecules in the pattern
  • d::Float64: Diameter of the circle in microns
  • x::Vector{Float64}: X positions of molecules in microns
  • y::Vector{Float64}: Y positions of molecules in microns

Examples

# Create an 8-molecule pattern with 100nm diameter
nmer = Nmer2D()

# Create a custom pattern with 6 molecules and 200nm diameter
nmer = Nmer2D(; n=6, d=0.2)
source
SMLMSim.Core.Nmer3DType
Nmer3D <: Pattern3D

N molecules symmetrically organized around a circle with diameter d at z=0.

Fields

  • n::Int: Number of molecules in the pattern
  • d::Float64: Diameter of the circle in microns
  • x::Vector{Float64}: X positions of molecules in microns
  • y::Vector{Float64}: Y positions of molecules in microns
  • z::Vector{Float64}: Z positions of molecules in microns

Examples

# Create an 8-molecule pattern with 100nm diameter
nmer = Nmer3D()

# Create a custom pattern with 6 molecules and 200nm diameter
nmer = Nmer3D(; n=6, d=0.2)
source
SMLMSim.Core.SMLMSimParamsType
SMLMSimParams <: AbstractSim

Abstract type for all SMLM simulation parameter types. Provides a common parent for different types of SMLM simulations.

source
SMLMSim.Core.compute_equilibrium_distributionMethod
compute_equilibrium_distribution(q::Matrix{<:AbstractFloat})

Calculate the equilibrium probability distribution for a CTMC rate matrix.

Arguments

  • q::Matrix{<:AbstractFloat}: Rate matrix where q[i,j] for i≠j is the transition rate from state i to j, and q[i,i] is the negative exit rate from state i

Returns

  • Vector{Float64}: Equilibrium probabilities for each state

Details

For a rate matrix Q, the equilibrium distribution π satisfies π·Q = 0 subject to Σπ = 1. This function solves the linear system directly to find the equilibrium distribution.

source
SMLMSim.Core.get_nextMethod
get_next(ctmc::CTMC, t::AbstractFloat)

Get the next state transition after a specific time point.

Arguments

  • ctmc::CTMC: The CTMC to query
  • t::AbstractFloat: Current time point

Returns

  • Tuple{Int,AbstractFloat}: (nextstate, transitiontime)

Note

Returns the next state that will be entered and when it will be entered, searching from the current time point forward.

source
SMLMSim.Core.get_num_tracksMethod
get_num_tracks(smld::BasicSMLD)

Return the number of unique tracks (based on track_id) in the SMLD.

Arguments

  • smld::BasicSMLD: The SMLD to analyze

Returns

  • Int: Number of unique track IDs

Example

# Get the number of tracks
n_tracks = get_num_tracks(smld)
source
SMLMSim.Core.get_stateMethod
get_state(ctmc::CTMC, t::AbstractFloat)

Get the state of the CTMC at a specific time point.

Arguments

  • ctmc::CTMC: The CTMC to query
  • t::AbstractFloat: Time point of interest

Returns

  • Int: State of the chain at time t

Note

Searches through transition times to find the state active at time t. Returns the state that was entered at the last transition before t.

source
SMLMSim.Core.get_trackMethod
get_track(smld::BasicSMLD, id::Int)

Return a new SMLD containing only emitters with the specified track_id.

Arguments

  • smld::BasicSMLD: The original SMLD
  • id::Int: Track ID to filter by

Returns

  • BasicSMLD: New SMLD containing only emitters from the specified track

Example

# Get all emitters belonging to track 5
track_smld = get_track(smld, 5)
source
SMLMSim.Core.get_tracksMethod
get_tracks(smld::BasicSMLD)

Return a vector of SMLD objects, one for each unique track (based on track_id).

Arguments

  • smld::BasicSMLD: The original SMLD

Returns

  • Vector{BasicSMLD}: Vector of SMLD objects, one per track

Example

# Get all tracks as separate SMLD objects
track_smlds = get_tracks(smld)

# Access the first track
first_track = track_smlds[1]
source
SMLMSim.Core.intensity_traceMethod
intensity_trace(f::GenericFluor, nframes::Int, framerate::Real; state1=1)

Calculate a fluorescence intensity trace by integrating emission during fluorescent state occupancy.

Arguments

  • f::GenericFluor: Fluorophore model containing transition rates (q) and emission rate (γ)
  • nframes::Int: Number of frames to simulate
  • framerate::Real: Frame rate in Hz
  • state1::Int=1: Initial state (default: 1 for fluorescent state)

Returns

  • Vector{Float64}: Integrated photon counts for each frame

Details

For each frame:

  1. Determines state occupancy using CTMC
  2. Integrates emission (rate f.γ) during fluorescent state periods
  3. Accumulates photons within frame exposure time (1/framerate)

Example

fluor = GenericFluor(; γ=10000.0, q=[-10.0 10.0; 1e-1 -1e-1])
photons = intensity_trace(fluor, 1000, 10.0)

Note

  • State 1 is assumed to be the fluorescent state
  • Emission only occurs in state 1 with rate f.γ
  • Frame exposure is assumed to be 1/framerate (100% duty cycle)
source
SMLMSim.Core.kinetic_modelMethod
kinetic_model(smld::BasicSMLD, f::Molecule, nframes::Int, framerate::Real;
             ndatasets::Int=1, minphotons=50.0, state1::Int=2)

Generate kinetic blinking model from existing localization data.

Arguments

  • smld::BasicSMLD: Input SMLD containing true emitter positions
  • f::Molecule: Fluorophore model with kinetic rates
  • nframes::Int: Number of frames to simulate
  • framerate::Real: Frame rate in Hz
  • ndatasets::Int=1: Number of independent datasets to generate
  • minphotons::Float64=50.0: Minimum photons for detection
  • state1::Union{Int, Symbol}=:equilibrium: Initial state specification:
    • ::Int: Specific state to start in (1=on, 2=off typically)
    • :equilibrium: Sample from equilibrium distribution (default)

Returns

  • BasicSMLD: New SMLD with simulated blinking kinetics

Details

For each unique position in the input SMLD:

  1. Simulates fluorophore blinking using the kinetic model
  2. Creates emitters for frames where photon count exceeds threshold
  3. Preserves track_id for linking emitters from same position
  4. Maintains camera and extends metadata from input SMLD

Example

camera = IdealCamera(1:128, 1:128, 0.1)
pattern = Nmer2D()
smld_true, _, _ = simulate(pattern=pattern, camera=camera)

# Add blinking kinetics
fluor = GenericFluor(; γ=10000.0, q=[-10.0 10.0; 1e-1 -1e-1])
smld_model = kinetic_model(smld_true, fluor, 1000, 10.0)

Note

The emitter type (2D/3D) is automatically determined from the input SMLD. Position uncertainties are initialized to 0 and can be set using the apply_noise() function.

source
SMLMSim.Core.rotate!Method
rotate!(p::Pattern2D, θ::Float64)

Rotate a 2D pattern by angle θ (in radians).

Arguments

  • p::Pattern2D: Pattern to rotate
  • θ::Float64: Rotation angle in radians

Example

nmer = Nmer2D()
rotate!(nmer, π/4)  # Rotate 45 degrees
source
SMLMSim.Core.rotate!Method
rotate!(p::Pattern3D, R::Matrix{Float64})

Rotate a 3D pattern by rotation matrix R.

Arguments

  • p::Pattern3D: Pattern to rotate
  • R::Matrix{Float64}: 3x3 rotation matrix

Example

nmer = Nmer3D()
# Create a rotation matrix for 90 degrees around z-axis
θ = π/2
R = [cos(θ) -sin(θ) 0; sin(θ) cos(θ) 0; 0 0 1]
rotate!(nmer, R)
source
SMLMSim.Core.rotate!Method
rotate!(p::Pattern3D, α::Float64, β::Float64, γ::Float64)

Rotate a 3D pattern by Euler angles α, β, γ (in radians). Uses ZYZ convention.

Arguments

  • p::Pattern3D: Pattern to rotate
  • α::Float64: First rotation angle (around Z axis)
  • β::Float64: Second rotation angle (around Y' axis)
  • γ::Float64: Third rotation angle (around Z'' axis)

Example

nmer = Nmer3D()
rotate!(nmer, π/4, π/6, π/3)
source
SMLMSim.Core.sample_discreteMethod
sample_discrete(p::Vector{<:AbstractFloat})

Sample from a discrete probability distribution.

Arguments

  • p::Vector{<:AbstractFloat}: Probability distribution

Returns

  • Int: Sampled state index

Details

Samples a state index i with probability p[i] using the inverse CDF method.

source
SMLMSim.Core.sample_discrete_with_probsMethod
sample_discrete_with_probs(indices, probs)

Sample a discrete value from indices with corresponding probabilities.

Arguments

  • indices::Vector{Int}: Vector of possible indices to sample
  • probs::Vector{<:AbstractFloat}: Corresponding probabilities

Returns

  • Int: Sampled index
source
SMLMSim.Core.uniform2DMethod
uniform2D(ρ::Float64, p::Pattern2D, field_x::Float64, field_y::Float64)

Create coordinate arrays for randomly placed and rotated 2D patterns.

Arguments

  • ρ::Float64: Pattern density (patterns per square micron)
  • p::Pattern2D: Pattern to replicate
  • field_x::Float64: Field width in microns
  • field_y::Float64: Field height in microns

Returns

  • Tuple{Vector{Float64}, Vector{Float64}}: (x, y) coordinates in microns

Example

# Generate coordinates for randomly placed Nmer2D patterns
nmer = Nmer2D(; n=6, d=0.2)
x, y = uniform2D(1.0, nmer, 10.0, 10.0)
source
SMLMSim.Core.uniform3DMethod
uniform3D(ρ::Float64, p::Pattern3D, field_x::Float64, field_y::Float64; 
         zrange::Vector{Float64}=[-1.0, 1.0])

Create coordinate arrays for randomly placed and rotated 3D patterns.

Arguments

  • ρ::Float64: Pattern density (patterns per square micron)
  • p::Pattern3D: Pattern to replicate
  • field_x::Float64: Field width in microns
  • field_y::Float64: Field height in microns
  • zrange::Vector{Float64}=[-1.0, 1.0]: [minz, maxz] range in microns

Returns

  • Tuple{Vector{Float64}, Vector{Float64}, Vector{Float64}}: (x, y, z) coordinates

Example

# Generate coordinates for randomly placed Nmer3D patterns
nmer = Nmer3D(; n=6, d=0.2)
x, y, z = uniform3D(1.0, nmer, 10.0, 10.0; zrange=[-2.0, 2.0])
source
SMLMSim.StaticSMLMModule
StaticSMLM

Module for simulating static (non-diffusing) SMLM data with blinking kinetics.

This module provides functionality for:

  1. Generating spatial distributions of emitters based on patterns
  2. Simulating fluorophore blinking based on stochastic kinetic models
  3. Adding realistic localization uncertainties
  4. Creating complete SMLM datasets

Usage

using SMLMSim.StaticSMLM
source
SMLMSim.StaticSMLM.StaticSMLMParamsType
StaticSMLMParams <: SMLMSimParams

Parameters for static SMLM simulation.

Fields

  • density::Float64: density in particles per square micron
  • σ_psf::Float64: PSF width in microns
  • minphotons::Int: minimum photons for detection
  • ndatasets::Int: number of datasets to simulate
  • nframes::Int: number of frames per dataset
  • framerate::Float64: frames per second
  • ndims::Int: dimensionality (2 or 3)
  • zrange::Vector{Float64}: axial range for 3D simulations [minz, maxz]

Examples

# Default parameters
params = StaticSMLMParams()

# Custom parameters
params = StaticSMLMParams(
    density = 2.0,              # 2 particles per μm²
    σ_psf = 0.15,         # 150nm PSF width
    minphotons = 100,     # minimum photons for detection
    ndatasets = 5,        # 5 independent datasets
    nframes = 2000,       # 2000 frames per dataset
    framerate = 100.0,    # 100 frames per second
    ndims = 3,            # 3D simulation
    zrange = [-2.0, 2.0]  # 4μm axial range
)
source
SMLMSim.StaticSMLM.add_coordinate_noiseMethod
add_coordinate_noise(emitter, σ)

Helper function to add position noise to an emitter with appropriate uncertainty. Returns new coordinate values and uncertainty values.

For 2D emitters, σ is a scalar. For 3D emitters, σ is a 3-element vector.

source
SMLMSim.StaticSMLM.apply_noiseMethod
apply_noise(smld::BasicSMLD, σ_psf::AbstractFloat)

Add localization uncertainty to 2D emitter positions based on photon counts.

Arguments

  • smld::BasicSMLD: Input SMLD containing 2D emitters
  • σ_psf::AbstractFloat: PSF width in microns

Returns

  • BasicSMLD: New SMLD with noisy positions and updated uncertainties

Example

# Then add localization noise with specific PSF width
smld_noisy = apply_noise(smld_model, 0.13)  # 130nm PSF width
source
SMLMSim.StaticSMLM.apply_noiseMethod
apply_noise(smld::BasicSMLD, σ_psf::Vector{<:AbstractFloat})

Add localization uncertainty to 3D emitter positions based on photon counts.

Arguments

  • smld::BasicSMLD: Input SMLD containing 3D emitters
  • σ_psf::Vector{<:AbstractFloat}: PSF widths [σx, σy, σz] in microns

Returns

  • BasicSMLD: New SMLD with noisy positions and updated uncertainties

Example

# Then add localization noise with specific PSF widths
σ_psf = [0.13, 0.13, 0.39]  # 130nm lateral, 390nm axial
smld_noisy = apply_noise(smld_model, σ_psf)
source
SMLMSim.simulateMethod
simulate(params::StaticSMLMParams; 
         starting_conditions::Union{Nothing, SMLD, Vector{<:AbstractEmitter}}=nothing,
         pattern::Pattern=nothing,
         molecule::Molecule=GenericFluor(photons=1e4, k_off=50.0, k_on=1e-2),
         camera::AbstractCamera=IdealCamera(1:128, 1:128, 0.1))

Generate simulated static SMLM data with realistic blinking kinetics and localization uncertainty.

Arguments

  • params::StaticSMLMParams: Simulation parameters
  • starting_conditions::Union{Nothing, SMLD, Vector{<:AbstractEmitter}}: Optional starting conditions instead of generating patterns
  • pattern::Pattern: Pattern to use (default depends on params.ndims)
  • molecule::Molecule: Fluorophore model for blinking simulation
  • camera::AbstractCamera: Camera model for detection simulation

Returns

  • Tuple{BasicSMLD, BasicSMLD, BasicSMLD}: (truepositions, modelkinetics, noisy_data)
    • true_positions: Ground truth emitter positions
    • model_kinetics: Positions with simulated blinking
    • noisy_data: Positions with blinking and localization uncertainty

Example

# Create parameters
params = StaticSMLMParams(
    density = 2.0,              # 2 patterns per μm²
    σ_psf = 0.15,         # 150nm PSF width
    minphotons = 100,     # 100 photons for detection
    ndatasets = 5,        # 5 independent datasets
    nframes = 2000,       # 2000 frames
    framerate = 100.0     # 100 frames per second
)

# Run simulation with Nmer pattern
pattern = Nmer3D(n=6, d=0.2)
smld_true, smld_model, smld_noisy = simulate(params; pattern=pattern)

# Run with custom starting conditions
custom_emitters = [
    Emitter2DFit{Float64}(x, y, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0; track_id=i)
    for (i, (x, y)) in enumerate(zip(rand(10), rand(10)))
]
smld_true, smld_model, smld_noisy = simulate(params; starting_conditions=custom_emitters)

Note

  • The params.σ_psf value is used directly for lateral uncertainty (σx, σy) in both 2D and 3D.
  • For 3D simulations, the axial uncertainty (σz) is scaled by a factor of 3 (i.e., σz = 3 * σ_psf).
  • If starting_conditions is provided, it will be used instead of generating patterns.
source
SMLMSim.InteractionDiffusionModule
InteractionDiffusion

This module provides simulation tools for diffusion and interaction between particles.

Overview

Simulates diffusion and interaction dynamics between particles in 2D/3D space. Includes functionality for generating microscope images, analyzing dimers, and visualizing particle dynamics.

Components

  • Abstract and concrete emitter types (AbstractDiffusingEmitter, DiffusingEmitter2D, DiffusingEmitter3D)
  • Smoluchowski dynamics simulation
  • Analysis tools for dimers and state transitions
  • SMLD conversion utilities

Examples

# Set up simulation parameters
params = DiffusionSMLMParams(
    density = 0.5,            # molecules per μm²
    box_size = 10.0,          # μm
    diff_monomer = 0.1,       # μm²/s
    diff_dimer = 0.05,        # μm²/s
    k_off = 0.2,              # s⁻¹
    r_react = 0.01,           # μm
    d_dimer = 0.05,           # μm
    dt = 0.01,                # s
    t_max = 10.0,             # s
    camera_framerate = 20.0,  # fps
    camera_exposure = 0.04    # s
)

# Run simulation - returns a single SMLD with all emitters
smld = simulate(params)

# Generate images for microscopy
psf = GaussianPSF(0.15)  # 150nm PSF width
images = gen_images(psf, smld)

# Analyze results
dimer_smld = get_dimers(smld)
frames, dimer_fractions = analyze_dimer_fraction(smld)
source
SMLMSim.InteractionDiffusion.DiffusingEmitter2DType
DiffusingEmitter2D{T<:AbstractFloat} <: AbstractDiffusingEmitter

A 2D emitter type for diffusion simulations that contains both spatial and temporal information, plus molecular state information.

Fields

  • x::T: x-coordinate in microns
  • y::T: y-coordinate in microns
  • photons::T: number of photons emitted
  • timestamp::T: actual simulation time in seconds
  • frame::Int: camera frame number based on framerate and exposure
  • dataset::Int: dataset identifier
  • track_id::Int: unique molecule identifier
  • state::Symbol: molecular state (:monomer or :dimer)
  • partner_id::Union{Int,Nothing}: ID of linked molecule (for dimers), or nothing for monomers
source
SMLMSim.InteractionDiffusion.DiffusingEmitter3DType
DiffusingEmitter3D{T<:AbstractFloat} <: AbstractDiffusingEmitter

A 3D emitter type for diffusion simulations that contains both spatial and temporal information, plus molecular state information.

Fields

  • x::T: x-coordinate in microns
  • y::T: y-coordinate in microns
  • z::T: z-coordinate in microns
  • photons::T: number of photons emitted
  • timestamp::T: actual simulation time in seconds
  • frame::Int: camera frame number based on framerate and exposure
  • dataset::Int: dataset identifier
  • track_id::Int: unique molecule identifier
  • state::Symbol: molecular state (:monomer or :dimer)
  • partner_id::Union{Int,Nothing}: ID of linked molecule (for dimers), or nothing for monomers
source
SMLMSim.InteractionDiffusion.DiffusionSMLMParamsType
DiffusionSMLMParams <: SMLMSimParams

Parameters for diffusion-based SMLM simulation using Smoluchowski dynamics.

Fields

  • density::Float64: number density (molecules/μm²)
  • box_size::Float64: simulation box size (μm)
  • diff_monomer::Float64: monomer diffusion coefficient (μm²/s)
  • diff_dimer::Float64: dimer diffusion coefficient (μm²/s)
  • diff_dimer_rot::Float64: dimer rotational diffusion coefficient (rad²/s)
  • k_off::Float64: dimer dissociation rate (s⁻¹)
  • r_react::Float64: reaction radius (μm)
  • d_dimer::Float64: monomer separation in dimer (μm)
  • dt::Float64: time step (s)
  • t_max::Float64: total simulation time (s)
  • ndims::Int: number of dimensions (2 or 3)
  • boundary::String: boundary condition type ("periodic" or "reflecting")
  • camera_framerate::Float64: camera frames per second (Hz)
  • camera_exposure::Float64: camera exposure time per frame (s)

Examples

# Default parameters
params = DiffusionSMLMParams()

# Custom parameters
params = DiffusionSMLMParams(
    density = 1.0,           # 1 molecule per μm²
    box_size = 20.0,         # 20μm × 20μm box
    diff_monomer = 0.2,      # 0.2 μm²/s
    diff_dimer = 0.1,        # 0.1 μm²/s
    diff_dimer_rot = 0.8,    # 0.8 rad²/s
    k_off = 0.1,             # 0.1 s⁻¹
    r_react = 0.02,          # 20nm reaction radius
    d_dimer = 0.06,          # 60nm dimer separation
    dt = 0.005,              # 5ms time step
    t_max = 20.0,            # 20s simulation
    ndims = 3,               # 3D simulation
    boundary = "reflecting", # reflecting boundaries
    camera_framerate = 20.0, # 20 frames per second
    camera_exposure = 0.04   # 40ms exposure per frame
)
source
Base.copyMethod
Base.copy(e::DiffusingEmitter2D)

Create a copy of a 2D diffusing emitter.

source
Base.copyMethod
Base.copy(e::DiffusingEmitter3D)

Create a copy of a 3D diffusing emitter.

source
SMLMSim.InteractionDiffusion.add_camera_frame_emitters!Method
add_camera_frame_emitters!(camera_emitters, emitters, time, frame_num, params)

Add emitters to camera frames when they fall within an exposure window.

Arguments

  • camera_emitters::Vector{<:AbstractDiffusingEmitter}: Collection of emitters for camera frames
  • emitters::Vector{<:AbstractDiffusingEmitter}: Current emitters from simulation
  • time::Float64: Current simulation time
  • frame_num::Int: Current frame number
  • params::DiffusionSMLMParams: Simulation parameters

Returns

  • Nothing
source
SMLMSim.InteractionDiffusion.analyze_dimer_fractionMethod
analyze_dimer_fraction(smld::BasicSMLD)

Calculate the fraction of dimers per frame.

Arguments

  • smld::BasicSMLD: SMLD containing all emitters

Returns

  • Tuple{Vector{Int}, Vector{Float64}}: Frame numbers and dimer fractions

Example

# Calculate dimer fraction over time
frames, fractions = analyze_dimer_fraction(smld)
plot(frames, fractions, xlabel="Frame", ylabel="Dimer Fraction")
source
SMLMSim.InteractionDiffusion.apply_boundaryMethod
apply_boundary(e::AbstractDiffusingEmitter, box_size::Float64, boundary::String)

Apply boundary conditions to an emitter (generic fallback).

Arguments

  • e::AbstractDiffusingEmitter: Emitter to apply boundary to
  • box_size::Float64: Simulation box size in microns
  • boundary::String: Boundary condition type ("periodic" or "reflecting")

Returns

  • AbstractDiffusingEmitter: Emitter with boundary conditions applied
source
SMLMSim.InteractionDiffusion.apply_boundaryMethod
apply_boundary(e::DiffusingEmitter2D, box_size::Float64, boundary::String)

Apply boundary conditions to a 2D emitter.

Arguments

  • e::DiffusingEmitter2D: Emitter to apply boundary to
  • box_size::Float64: Simulation box size in microns
  • boundary::String: Boundary condition type ("periodic" or "reflecting")

Returns

  • DiffusingEmitter2D: New emitter with position constrained to the box
source
SMLMSim.InteractionDiffusion.apply_boundaryMethod
apply_boundary(e::DiffusingEmitter3D, box_size::Float64, boundary::String)

Apply boundary conditions to a 3D emitter.

Arguments

  • e::DiffusingEmitter3D: Emitter to apply boundary to
  • box_size::Float64: Simulation box size in microns
  • boundary::String: Boundary condition type ("periodic" or "reflecting")

Returns

  • DiffusingEmitter3D: New emitter with position constrained to the box
source
SMLMSim.InteractionDiffusion.can_dimerizeMethod
can_dimerize(e1::AbstractDiffusingEmitter, e2::AbstractDiffusingEmitter, r_react::Float64)

Check if two emitters can form a dimer.

Arguments

  • e1::AbstractDiffusingEmitter: First emitter
  • e2::AbstractDiffusingEmitter: Second emitter
  • r_react::Float64: Reaction radius in microns

Returns

  • Bool: True if emitters can form a dimer
source
SMLMSim.InteractionDiffusion.convert_to_diffusing_emittersFunction
convert_to_diffusing_emitters(emitters::Vector{<:AbstractEmitter}, photons::Float64=1000.0, state::Symbol=:monomer)

Convert regular emitters to diffusing emitters for use as starting conditions.

Arguments

  • emitters::Vector{<:AbstractEmitter}: Vector of static emitters to convert
  • photons::Float64=1000.0: Number of photons to assign
  • state::Symbol=:monomer: Initial state (:monomer or :dimer)

Returns

  • Vector{<:AbstractDiffusingEmitter}: Vector of diffusing emitters

Example

# Convert static emitters to diffusing emitters
static_emitters = smld_static.emitters
diffusing_emitters = convert_to_diffusing_emitters(static_emitters)

# Use as starting conditions for a diffusion simulation
params = DiffusionSMLMParams(t_max=10.0)
smld = simulate(params; starting_conditions=diffusing_emitters)
source
SMLMSim.InteractionDiffusion.create_smldMethod
create_smld(emitters::Vector{<:AbstractDiffusingEmitter}, camera::AbstractCamera, params::DiffusionSMLMParams)

Convert a collection of diffusing emitters to a BasicSMLD object.

Arguments

  • emitters::Vector{<:AbstractDiffusingEmitter}: Collection of emitters from simulation
  • camera::AbstractCamera: Camera model for imaging
  • params::DiffusionSMLMParams: Simulation parameters

Returns

  • BasicSMLD: SMLD containing all emitters for further analysis or visualization
source
SMLMSim.InteractionDiffusion.diffuseMethod
diffuse(e::DiffusingEmitter2D, diff_coef::Float64, dt::Float64)

Create a new emitter with updated position based on Brownian motion.

Arguments

  • e::DiffusingEmitter2D: Emitter to update
  • diff_coef::Float64: Diffusion coefficient (μm²/s)
  • dt::Float64: Time step (s)

Returns

  • DiffusingEmitter2D: New emitter with updated position
source
SMLMSim.InteractionDiffusion.diffuseMethod
diffuse(e::DiffusingEmitter3D, diff_coef::Float64, dt::Float64)

Create a new 3D emitter with updated position based on Brownian motion.

Arguments

  • e::DiffusingEmitter3D: Emitter to update
  • diff_coef::Float64: Diffusion coefficient (μm²/s)
  • dt::Float64: Time step (s)

Returns

  • DiffusingEmitter3D: New emitter with updated position
source
SMLMSim.InteractionDiffusion.diffuse_dimerMethod
diffuse_dimer(e1::DiffusingEmitter2D, e2::DiffusingEmitter2D, diff_trans::Float64, diff_rot::Float64, d_dimer::Float64, dt::Float64)

Diffuse a dimer with both translational and rotational components.

Arguments

  • e1::DiffusingEmitter2D: First emitter in dimer
  • e2::DiffusingEmitter2D: Second emitter in dimer
  • diff_trans::Float64: Translational diffusion coefficient (μm²/s)
  • diff_rot::Float64: Rotational diffusion coefficient (rad²/s)
  • d_dimer::Float64: Dimer separation distance (μm)
  • dt::Float64: Time step (s)

Returns

  • Tuple{DiffusingEmitter2D, DiffusingEmitter2D}: Two new emitters with updated positions
source
SMLMSim.InteractionDiffusion.diffuse_dimerMethod
diffuse_dimer(e1::DiffusingEmitter3D, e2::DiffusingEmitter3D, diff_trans::Float64, diff_rot::Float64, d_dimer::Float64, dt::Float64)

Diffuse a 3D dimer with both translational and rotational components.

Arguments

  • e1::DiffusingEmitter3D: First emitter in dimer
  • e2::DiffusingEmitter3D: Second emitter in dimer
  • diff_trans::Float64: Translational diffusion coefficient (μm²/s)
  • diff_rot::Float64: Rotational diffusion coefficient (rad²/s)
  • d_dimer::Float64: Dimer separation distance (μm)
  • dt::Float64: Time step (s)

Returns

  • Tuple{DiffusingEmitter3D, DiffusingEmitter3D}: Two new emitters with updated positions
source
SMLMSim.InteractionDiffusion.dimerizeMethod
dimerize(e1::DiffusingEmitter2D, e2::DiffusingEmitter2D, d_dimer::Float64)

Create two new emitters in dimer state from two monomers.

Arguments

  • e1::DiffusingEmitter2D: First emitter
  • e2::DiffusingEmitter2D: Second emitter
  • d_dimer::Float64: Dimer separation distance in microns

Returns

  • Tuple{DiffusingEmitter2D, DiffusingEmitter2D}: Two new emitters in dimer state
source
SMLMSim.InteractionDiffusion.dimerizeMethod
dimerize(e1::DiffusingEmitter3D, e2::DiffusingEmitter3D, d_dimer::Float64)

Create two new emitters in dimer state from two monomers in 3D.

Arguments

  • e1::DiffusingEmitter3D: First emitter
  • e2::DiffusingEmitter3D: Second emitter
  • d_dimer::Float64: Dimer separation distance in microns

Returns

  • Tuple{DiffusingEmitter3D, DiffusingEmitter3D}: Two new emitters in dimer state
source
SMLMSim.InteractionDiffusion.dissociateMethod
dissociate(e::DiffusingEmitter2D, emitters::Vector{<:AbstractDiffusingEmitter})

Create two new monomers from a dimer.

Arguments

  • e::DiffusingEmitter2D: Emitter part of a dimer
  • emitters::Vector{<:AbstractDiffusingEmitter}: All emitters in the system

Returns

  • Tuple{DiffusingEmitter2D, DiffusingEmitter2D}: Two new emitters in monomer state
source
SMLMSim.InteractionDiffusion.dissociateMethod
dissociate(e::DiffusingEmitter3D, emitters::Vector{<:AbstractDiffusingEmitter})

Create two new monomers from a 3D dimer.

Arguments

  • e::DiffusingEmitter3D: Emitter part of a dimer
  • emitters::Vector{<:AbstractDiffusingEmitter}: All emitters in the system

Returns

  • Tuple{DiffusingEmitter3D, DiffusingEmitter3D}: Two new emitters in monomer state
source
SMLMSim.InteractionDiffusion.extract_final_stateMethod
extract_final_state(smld::SMLD)

Extract the emitters from the final frame of a simulation to use as starting conditions.

Arguments

  • smld::SMLD: SMLD containing emitters from a simulation

Returns

  • Vector{<:AbstractEmitter}: Emitters from the final frame

Example

# Run a simulation
params = DiffusionSMLMParams(t_max=5.0)
smld = simulate(params)

# Extract final state
final_state = extract_final_state(smld)

# Continue simulation with new parameters
params_new = DiffusionSMLMParams(t_max=10.0, diff_monomer=0.2)
smld_continued = simulate(params_new; starting_conditions=final_state)
source
SMLMSim.InteractionDiffusion.filter_by_stateMethod
filter_by_state(smld::BasicSMLD, state::Symbol)

Filter emitters by their state (monomer or dimer).

Arguments

  • smld::BasicSMLD: The original SMLD with diffusing emitters
  • state::Symbol: State to filter by (:monomer or :dimer)

Returns

  • BasicSMLD: New SMLD containing only emitters with the specified state

Example

# Get only monomers
monomer_smld = filter_by_state(smld, :monomer)

# Get only dimers
dimer_smld = filter_by_state(smld, :dimer)
source
SMLMSim.InteractionDiffusion.get_dimersMethod
get_dimers(smld::BasicSMLD)

Extract a new BasicSMLD containing only emitters in dimer state.

Arguments

  • smld::BasicSMLD: Original SMLD with all emitters

Returns

  • BasicSMLD: New SMLD containing only dimers

Example

# Extract only dimers from simulation results
smld = simulate(params)
dimer_smld = get_dimers(smld)
source
SMLMSim.InteractionDiffusion.get_frameMethod
get_frame(smld::BasicSMLD, frame_num::Int)

Extract emitters from a specific frame.

Arguments

  • smld::BasicSMLD: SMLD containing all emitters
  • frame_num::Int: Frame number to extract

Returns

  • BasicSMLD: New SMLD containing only emitters from the specified frame
source
SMLMSim.InteractionDiffusion.get_monomersMethod
get_monomers(smld::BasicSMLD)

Extract a new BasicSMLD containing only emitters in monomer state.

Arguments

  • smld::BasicSMLD: Original SMLD with all emitters

Returns

  • BasicSMLD: New SMLD containing only monomers
source
SMLMSim.InteractionDiffusion.initialize_emittersFunction
initialize_emitters(params::DiffusionSMLMParams, photons::Float64=1000.0; override_count::Union{Nothing, Int}=nothing)

Create initial emitter positions for the simulation.

Arguments

  • params::DiffusionSMLMParams: Simulation parameters
  • photons::Float64=1000.0: Number of photons per emitter
  • override_count::Union{Nothing, Int}=nothing: Optional override for the number of molecules

Returns

  • Vector{<:AbstractDiffusingEmitter}: Vector of initialized emitters
source
SMLMSim.InteractionDiffusion.should_dissociateMethod
should_dissociate(e::AbstractDiffusingEmitter, k_off::Float64, dt::Float64)

Check if a dimer should dissociate based on stochastic rate.

Arguments

  • e::AbstractDiffusingEmitter: Emitter to check
  • k_off::Float64: Dissociation rate (s⁻¹)
  • dt::Float64: Time step (s)

Returns

  • Bool: True if dimer should dissociate
source
SMLMSim.InteractionDiffusion.track_state_changesMethod
track_state_changes(smld::BasicSMLD)

Track state changes of molecules over time.

Arguments

  • smld::BasicSMLD: SMLD containing all emitters

Returns

  • Dict{Int, Vector{Tuple{Int, Symbol}}}: Dictionary mapping molecule IDs to vectors of (frame, state) pairs

Example

# Track state changes of molecules
state_history = track_state_changes(smld)

# Plot state history for molecule 1
history = state_history[1]
frames = [h[1] for h in history]
states = [h[2] for h in history]
source
SMLMSim.InteractionDiffusion.update_systemMethod
update_system(emitters::Vector{<:AbstractDiffusingEmitter}, params::DiffusionSMLMParams, dt::Float64)

Update all emitters based on Smoluchowski diffusion dynamics.

Arguments

  • emitters::Vector{<:AbstractDiffusingEmitter}: Current emitters state
  • params::DiffusionSMLMParams: Simulation parameters
  • dt::Float64: Time step

Returns

  • Vector{<:AbstractDiffusingEmitter}: Updated emitters
source
SMLMSim.simulateMethod
simulate(params::DiffusionSMLMParams; 
         starting_conditions::Union{Nothing, SMLD, Vector{<:AbstractDiffusingEmitter}}=nothing,
         photons::Float64=1000.0, 
         override_count::Union{Nothing, Int}=nothing,
         kwargs...)

Run a Smoluchowski diffusion simulation and return a BasicSMLD object with emitters that have both frame number and timestamp information.

Arguments

  • params::DiffusionSMLMParams: Simulation parameters
  • starting_conditions::Union{Nothing, SMLD, Vector{<:AbstractDiffusingEmitter}}: Optional starting emitters
  • photons::Float64=1000.0: Number of photons per emitter
  • override_count::Union{Nothing, Int}=nothing: Optional override for the number of molecules

Keyword Arguments

  • Any additional parameters are ignored (allows unified interface with other simulate methods)

Returns

  • BasicSMLD: Single SMLD object containing all emitters across all frames

Example

# Set up parameters with camera settings
params = DiffusionSMLMParams(
    density = 0.5,           # molecules per μm²
    box_size = 10.0,         # μm
    camera_framerate = 20.0, # 20 fps
    camera_exposure = 0.04   # 40ms exposure
)

# Run basic simulation
smld = simulate(params)

# Run simulation with exactly 2 particles
smld = simulate(params; override_count=2)

# Use previous simulation state as starting conditions for a new simulation
final_frame = maximum([e.frame for e in smld.emitters])
final_state_emitters = filter(e -> e.frame == final_frame, smld.emitters)
smld_continued = simulate(params; starting_conditions=final_state_emitters)
source
SMLMSim.CameraImagesModule
CameraImages

Module for generating simulated camera images from SMLM data.

This module provides functions to:

  1. Generate ideal camera images by integrating emitter photons over a PSF.
  2. Add realistic camera noise (e.g., Poisson noise).

Usage

using SMLMSim.CameraImages
source
SMLMSim.CameraImages.gen_imageMethod
gen_image(smld::SMLD, psf::AbstractPSF, frame::Int; kwargs...) -> Matrix{T} where T<:Real

Generate a single camera image for a specific frame from SMLD data. See gen_images for full documentation of parameters.

Returns

  • A 2D camera image as Matrix{T} where T matches the type of emitter.photons
source
SMLMSim.CameraImages.gen_imagesMethod
gen_images(smld::SMLD, psf::AbstractPSF; kwargs...) -> Array{T, 3} where T<:Real

Generate camera images from SMLD data using the specified PSF model.

Arguments

  • smld::SMLD: Single molecule localization data container
  • psf::AbstractPSF: Point spread function model

Keyword arguments

  • dataset::Int=1: Dataset number to use from SMLD
  • frames=nothing: Specific frames to generate (default: all frames in smld.n_frames)
  • support::Union{Real,Tuple{<:Real,<:Real,<:Real,<:Real}}=Inf: PSF support region size:
    • Inf (default): Calculate PSF over the entire image (most accurate but slowest)
    • Real: Circular region with specified radius (in microns) around each emitter
    • Tuple{<:Real,<:Real,<:Real,<:Real}: Explicit region as (xmin, xmax, ymin, ymax) in microns
  • sampling::Int=2: Supersampling factor for PSF integration
  • threaded::Bool=true: Enable multithreading for faster computation
  • bg::Float64=0.0: Background signal level (photons per pixel)
  • poisson_noise::Bool=false: Apply Poisson noise
  • camera_noise::Bool=false: Apply camera read noise (Note: This feature is not yet implemented)

Returns

  • 3D array of camera images with dimensions [height, width, num_frames]
  • The element type T matches the type of emitter.photons (typically Float64)

Performance Note

For the support parameter, using a finite radius (typically 3-5× the PSF width) provides a good balance between accuracy and performance. For example, with a PSF width of 0.15μm, a support radius of 0.5-1.0μm is usually sufficient.

source
SMLMSim.CameraImages.poisson_noise!Method
poisson_noise!(image::AbstractArray{T}) where T<:Real -> nothing

Apply Poisson noise to an image or image stack in-place.

Arguments

  • image::AbstractArray{T}: Input image or image stack with values representing photon counts

Returns

  • nothing: The input array is modified in-place

Details

Same as poisson_noise, but modifies the input array directly instead of creating a new one. This can be more memory-efficient for large images or when processing multiple frames.

Example

# Add Poisson noise to an image in-place
image = ones(100, 100) * 100.0  # 100 expected photons per pixel
poisson_noise!(image)  # image is modified in-place
source
SMLMSim.CameraImages.poisson_noiseMethod
poisson_noise(image::AbstractArray{T}) where T<:Real -> Array{Float64}

Apply Poisson noise to an image or image stack.

Arguments

  • image::AbstractArray{T}: Input image or image stack with values representing photon counts

Returns

  • Array with same dimensions as input, with Poisson noise applied to each pixel

Details

This function creates a copy of the input array and applies Poisson noise to each pixel using the in-place poisson_noise! function.

Non-integer and negative values are handled specially:

  • Non-integer values are accepted (treating them as expected photon counts)
  • Negative values are clipped to zero before applying noise
  • Zero values remain zero (as Poisson(0) always returns 0)

Example

# Add Poisson noise to a clean image
clean_image = ones(100, 100) * 100.0  # 100 expected photons per pixel
noisy_image = poisson_noise(clean_image)
source