A Python package for simulating realistic fluorescence microscopy experiments with biological samples. Perfect for testing super-resolution algorithms, training AI models, and teaching microscopy concepts.
For installation, usage, and contribution instructions, see:
- 🔬 Realistic Microscopy Simulation: Accurate modeling of photon noise, bleaching, and detector characteristics
- 🦠 Bacterial Cell Dynamics: Simulate Staphylococcus-like cells with growth, septum formation, and division
- 📸 Stage Control: Move and scan across large samples with precise positioning
- 🔆 Laser Control: Adjustable laser power with realistic photobleaching effects
- 🧪 Extensible: Easy to create custom sample types and imaging modalities
- Python 3.10 or higher
- pip package manager
- Clone the repository:
git clone https://github.com/HenriquesLab/mAIcroscopysandbox.git
cd mAIcroscopysandbox- Install the package:
pip install -e .- For development (includes testing and linting tools):
pip install -e ".[dev,test]"Run the same lint, test, coverage, and build checks used by the automation:
./scripts/run_ci_locally.shThe package automatically installs the following dependencies:
numpy<2- Numerical computingscikit-image- Image processingnumba- JIT compilation for performancescipy- Morphology and filtering utilitiestifffile- Binary sample loading and TIFF export
Here's a minimal example to get you started:
import numpy as np
from matplotlib import pyplot as plt
from maicroscopy_sandbox import mAIcroscopySandbox
from maicroscopy_sandbox.samples.staph import StaphMembrane
# Create a virtual microscope
microscope = mAIcroscopySandbox(
fov_size=[500, 500], # Field of view in pixels
laser_intensity=1000 # Photons per pixel
)
# Create a bacterial cell sample
sample = StaphMembrane(
sample_size=microscope.stage_size,
n_objects=5, # Number of cells
pixel_size=30 # nm per pixel
)
# Load sample and acquire image
microscope.set_laser_power(100)
frame = microscope.load_sample(sample, acquire=True)
# Display the image
plt.imshow(frame, cmap="gray")
plt.title("Simulated Fluorescence Microscopy")
plt.colorbar(label="Intensity (ADU)")
plt.show()Control the microscope stage and laser settings:
from maicroscopy_sandbox import mAIcroscopySandbox
from maicroscopy_sandbox.samples.ellipsoid import Ellipsoid
# Initialize microscope
microscope = mAIcroscopySandbox(
stage_size=[5000, 5000],
fov_size=[300, 300],
laser_intensity=100000
)
# Configure detector parameters
microscope.set_readout_noise(50) # Camera noise
microscope.set_ADC_offset(100) # Baseline offset
microscope.set_gaussian_sigma(2.0) # PSF blur
# Create and load a simple ellipsoid sample
sample = Ellipsoid(
sample_size=microscope.stage_size,
n_objects=10
)
# Acquire image
microscope.set_laser_power(50) # 50% laser power
frame = microscope.load_sample(sample, acquire=True)
# Move stage and acquire another image
new_frame = microscope.move_stage([100, 50], acquire=True)Simulate realistic bacterial cell growth and division:
from maicroscopy_sandbox import mAIcroscopySandbox
from maicroscopy_sandbox.samples.staph import StaphMembrane
import matplotlib.pyplot as plt
# Create microscope
microscope = mAIcroscopySandbox(fov_size=[500, 500], laser_intensity=1000)
# Create bacterial sample with specific parameters
sample = StaphMembrane(
sample_size=microscope.stage_size,
n_objects=3, # Initial number of cells
pixel_size=30, # 30 nm/pixel
bleaching_rate=0.05, # 5% bleaching per frame
progression_rate=10, # Cell cycle progression speed
p1_rate=42, # Growth phase percentage
p2_rate=29 # Septum formation percentage
)
# Load sample
microscope.set_laser_power(100)
frame = microscope.load_sample(sample, acquire=True)
# Visualize
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
ax.imshow(frame, cmap="gray")
ax.set_title("Bacterial Membrane Simulation")
ax.axis('off')
plt.tight_layout()
plt.show()
# Access cell information
print(f"Number of cells: {len(sample.cells)}")
for cell_id, cell in sample.cells.items():
print(f"Cell {cell_id}: progression={cell.progression}%")Capture a time series showing cell dynamics:
from maicroscopy_sandbox import mAIcroscopySandbox
from maicroscopy_sandbox.samples.staph import StaphMembrane
import matplotlib.pyplot as plt
# Setup
microscope = mAIcroscopySandbox(fov_size=[500, 500], laser_intensity=1000)
sample = StaphMembrane(
sample_size=microscope.stage_size,
n_objects=1,
pixel_size=30,
progression_rate=20 # Faster progression for demo
)
microscope.set_laser_power(100)
microscope.load_sample(sample)
# Acquire time series
n_frames = 10
frames = []
for i in range(n_frames):
frame = microscope.acquire_image()
frames.append(frame)
print(f"Frame {i+1}/{n_frames}: {len(sample.cells)} cells")
# Display montage
fig, axes = plt.subplots(2, 5, figsize=(15, 6))
for i, (ax, frame) in enumerate(zip(axes.flat, frames)):
ax.imshow(frame, cmap="gray")
ax.set_title(f"t={i}")
ax.axis('off')
plt.tight_layout()
plt.show()Main microscope simulation class.
stage_size(array): Stage size in pixels [height, width]. Default: [5000, 5000]fov_size(array): Field of view in pixels [height, width]. Default: [300, 300]laser_intensity(float): Maximum laser intensity in photons/pixel. Default: 100000pixel_size(float): Physical pixel size in nanometers. Default: 100
load_sample(sample, acquire=False): Load a sample onto the stageacquire_image(): Capture an image at the current positionmove_stage(movement, acquire=False): Move stage by offset [row, col]set_laser_power(power): Set laser power (0-100%)set_readout_noise(noise): Set camera readout noiseset_gaussian_sigma(sigma): Set PSF blur amount
Bacterial cell sample with growth and division.
sample_size(array): Sample area in pixels. Default: [1000, 1000]n_objects(int): Initial number of cells. Default: 1pixel_size(int): Pixel size in nanometers. Default: 100bleaching_rate(float): Bleaching rate per frame. Default: 0.001progression_rate(int): Cell cycle progression speed. Default: 2p1_rate(int): Growth phase percentage. Default: 42p2_rate(int): Septum formation percentage. Default: 29
Each cell in sample.cells has:
center_row,center_col: Positionmajor_axis,minor_axis: Sizeorientation: Angle in radiansprogression: Cell cycle progress (0-100%)p1,p2,p3: Phase boundaries
Extend the Sample base class to create custom samples:
from maicroscopy_sandbox.samples.sample import Sample
import numpy as np
class CustomSample(Sample):
def __init__(self, sample_size=[1000, 1000], **kwargs):
super().__init__(sample_size=sample_size, **kwargs)
# Your initialization code
def generate_mask(self):
# Return 2D array with fluorophore distribution
mask = np.zeros(self.sample_size, dtype=np.float32)
# ... your custom mask generation ...
return mask
def calculate_dynamics(self):
# Update sample state between frames
passFine-tune the microscope optics:
microscope.set_wavelenght(488) # Excitation wavelength (nm)
microscope.set_NA(1.4) # Numerical aperture
microscope.set_sigma(0.21) # Fluorophore emission spread
microscope.set_ADC_per_photon_conversion(1.5) # Detector gainMonitor and control photobleaching:
# Create sample with high bleaching
sample = StaphMembrane(
sample_size=microscope.stage_size,
bleaching_rate=0.1 # 10% per frame
)
microscope.load_sample(sample)
# Reduce laser power to minimize bleaching
microscope.set_laser_power(30) # 30% power
# Acquire multiple frames
for i in range(10):
frame = microscope.acquire_image()
# Bleaching is automatically appliedExport image sequences:
import tifffile
import numpy as np
frames = []
for i in range(100):
frame = microscope.acquire_image()
frames.append(frame)
# Save as multi-page TIFF
stack = np.stack(frames, axis=0)
tifffile.imwrite("timelapse.tif", stack)mAIcroscopysandbox/
├── .github/
│ └── workflows/
│ ├── ci.yml
│ └── publish.yml
├── src/
│ └── maicroscopy_sandbox/
│ ├── __init__.py
│ ├── maicroscopy_sandbox.py # Main microscope class
│ ├── fluorescence_sim.py # Image generation
│ └── samples/
│ ├── __init__.py
│ ├── sample.py # Base sample class
│ ├── staph.py # Bacterial cells
│ ├── ellipsoid.py # Simple ellipsoids
│ └── binary.py # Binary structures
├── scripts/
│ ├── run_ci_locally.sh
│ └── release_to_pypi.sh
├── notebooks/
│ ├── example_usage.ipynb # Usage examples
│ └── example_from_binary.ipynb # Binary sample demo
├── tests/
│ └── test_maicroscopy_sandbox.py
├── noxfile.py
├── Makefile
├── README.md
├── pyproject.toml
└── LICENSE.txt
Contributions are welcome! Please feel free to submit a Pull Request. For major changes:
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
# Clone the repo
git clone https://github.com/HenriquesLab/mAIcroscopysandbox.git
cd mAIcroscopysandbox
# Install in development mode with all extras
pip install -e ".[dev,test]"
# Run tests
pytest
# Or run the full local CI flow
./scripts/run_ci_locally.sh
# Run linter
ruff check src/
# Format code
ruff format src/- GitHub Actions CI lives in
.github/workflows/ci.yml - PyPI publishing lives in
.github/workflows/publish.yml - Local release validation and optional upload lives in:
./scripts/release_to_pypi.shIf PYPI_TOKEN is unset, the script stops after test, build, and distribution validation.
If you use this software in your research, please cite:
@software{maicroscopy_sandbox,
author = {Saraiva, Bruno},
title = {mAIcroscopy Sandbox: Realistic Fluorescence Microscopy Simulation},
year = {2025},
publisher = {GitHub},
url = {https://github.com/HenriquesLab/mAIcroscopysandbox}
}This project is licensed under the MIT License - see the LICENSE.txt file for details.
- Developed at the Henriques Lab
- Built on scikit-image, scipy, and numpy
- Inspired by real microscopy workflows and challenges
- Author: Bruno Saraiva
- Email: bruno.msaraiva2@gmail.com
- Lab: Henriques Lab
ImportError: No module named 'maicroscopy_sandbox'
- Make sure you installed the package:
pip install -e . - Check you're in the correct virtual environment
Cells not appearing/disappearing
- Restart the Jupyter kernel after code changes
- The module caches the old version until restart
Slow performance
- Reduce
fov_sizefor faster rendering - Lower
n_objectsto simulate fewer cells - Disable plotting during time-lapse acquisition
Images too dark/bright
- Adjust
laser_intensityandlaser_power - Check
ADC_per_photon_conversionandADC_offset - Verify sample mask has appropriate fluorophore density
For more help, please open an issue on GitHub.