| Badge | Status |
|---|---|
| Python versions | |
| Documentation | |
| Scientific article | |
| Continuous integration | |
| Test coverage | |
| Google Colab | |
| PyPI package | |
| PyPI downloads | |
| Anaconda package | |
| Anaconda downloads | |
| Latest Anaconda release |
PyMieSim is an open-source Python package for fast and flexible Mie scattering simulations. It supports spherical, cylindrical and core--shell particles and provides helper classes for custom sources and detectors. The project targets both quick single-scatterer studies and large parametric experiments.
Try the live web GUI: PyMieSim Parameter Sweep Lab.
- Solvers for spheres, cylinders and core--shell geometries.
- Built-in models for plane wave and Gaussian sources.
- Multiple detector types including photodiodes and coherent modes.
- Simple data analysis with pandas DataFrame outputs.
PyMieSim is available on PyPI and Anaconda. Install it with:
pip install PyMieSim
conda install PyMieSim --channels MartinPdeSVerify the installation with the same Python interpreter that you will use for your simulations:
python -c "import PyMieSim; print(PyMieSim.__version__)"The released wheels are the easiest option. Building from source requires a C++20 compiler, Fortran, CMake, pybind11, and OpenMP; see troubleshooting if the compiled extension cannot be imported.
Create a source, a scatterer, and a Simulation. Physical quantities use
the built-in ureg unit registry, while refractive indices are
dimensionless real or complex values.
from PyMieSim import (
Gaussian,
PolarizationState,
Simulation,
Sphere,
ureg,
)
source = Gaussian(
wavelength=633 * ureg.nanometer,
polarization=PolarizationState(angle=0 * ureg.degree),
optical_power=1e-3 * ureg.watt,
numerical_aperture=0.2,
)
scatterer = Sphere(
diameter=200 * ureg.nanometer,
material=1.5 + 0.01j,
medium=1.0,
)
simulation = Simulation(scatterer=scatterer, source=source)
qsca = simulation.run("Qsca")
print(qsca)This prints a dimensionless scattering efficiency, approximately:
0.2080989068292113 dimensionless
Inspect the measures supported by the configured simulation with:
print(simulation.available_measures)For explicit measure and unit metadata, request a typed result:
result = simulation.run("Qsca", as_result=True)
print(result.measure, result.quantity, result.units)Always attach units to wavelengths, lengths, powers, and angles:
633 * ureg.nanometer
200 * ureg.nanometer
1e-3 * ureg.watt
0 * ureg.degreeRefractive indices are dimensionless. A complex index such as
1.5 + 0.01j represents an absorbing material under PyMieSim's optical
convention. Built-in and tabulated materials have supported wavelength
ranges; use load_material and validate_wavelength when working with
real material data.
Use Experiment when you want to evaluate several wavelengths, particle
sizes, or material parameters. Results retain named dimensions and
coordinates, and can be converted to NumPy or pandas explicitly.
import numpy as np
from PyMieSim import (
Experiment,
GaussianSet,
PolarizationSet,
SphereSet,
ureg,
)
source = GaussianSet(
wavelength=np.linspace(500, 700, 5) * ureg.nanometer,
polarization=PolarizationSet(angles=0 * ureg.degree),
optical_power=1e-3 * ureg.watt,
numerical_aperture=0.2,
)
scatterer = SphereSet(
diameter=np.linspace(100, 500, 9) * ureg.nanometer,
material=1.5,
medium=1.0,
)
experiment = Experiment(scatterer_set=scatterer, source_set=source)
result = experiment.get("Qsca")
values = result.as_numpy()
dataframe = result.as_dataframe()The experiment grid has five wavelength values and nine diameter values, so
values.shape is (5, 9). See the
parameter sweep guide
for multiple measures and plotting.
Add a detector when you need collected or coupled power rather than only a scatterer property:
from PyMieSim import (
Gaussian,
Photodiode,
PolarizationState,
Simulation,
Sphere,
ureg,
)
single_source = Gaussian(
wavelength=633 * ureg.nanometer,
polarization=PolarizationState(angle=0 * ureg.degree),
optical_power=1e-3 * ureg.watt,
numerical_aperture=0.2,
)
single_scatterer = Sphere(
diameter=200 * ureg.nanometer,
material=1.5 + 0.01j,
medium=1.0,
)
detector = Photodiode(
sampling=500,
numerical_aperture=0.2,
phi_offset=0 * ureg.degree,
gamma_offset=0 * ureg.degree,
medium=1.0,
)
simulation = Simulation(
scatterer=single_scatterer,
source=single_source,
detector=detector,
)
coupling = simulation.run("coupling")
print(coupling)coupling requires a detector. Other available detector types include
CoherentMode and IntegratingSphere; see the
detector coupling guide.
- If
import PyMieSimfails, runpython -m pip show PyMieSimand check that it uses the same Python executable as your script. - If a constructor reports a unit error, check that every dimensional input
has units and convert it with
.to(...)when necessary. - If
couplingis unavailable, add a detector and inspectsimulation.available_measures. - For slow or memory-heavy sweeps, print
experiment.array_shapeandexperiment.total_iterationsbefore requesting a result. - On servers or in CI, select a non-interactive Matplotlib backend such as
Aggbefore importing plotting code.
See the online documentation for theory, performance guidance, runnable examples, and advanced near-field and far-field workflows.
Here is the architecture for a standard workflow using PyMieSim:
For development or manual compilation, clone the repository and run:
git submodule update --init
mkdir build && cd build
cmake ../ -G"Unix Makefiles"
sudo make install
cd ..
python -m pip install .Run the unit tests with:
pip install PyMieSim[testing]
pytestIf you use PyMieSim in academic work, please cite:
@article{PoinsinetdeSivry-Houle:23,
author = {Martin Poinsinet de Sivry-Houle and Nicolas Godbout and Caroline Boudoux},
journal = {Opt. Continuum},
title = {PyMieSim: an open-source library for fast and flexible far-field Mie scattering simulations},
volume = {2},
number = {3},
pages = {520--534},
year = {2023},
doi = {10.1364/OPTCON.473102},
}
For questions or contributions, contact martin.poinsinet.de.sivry@gmail.com.


