Tutorial about fluopy - distributed simulation

Here we outline parallel computing with fluopy.

Install ray for distributing multiple simulations on different cores or machines.

%matplotlib inline

import matplotlib.pyplot as plt
import numpy as np
import ray

import fluopy
import fluopy.fluorophores as fl
import fluopy.simulation as si
import fluopy.transitions as tr
2026-06-02 15:45:12,131	INFO util.py:154 -- Missing packages: ['ipywidgets']. Run `pip install -U ipywidgets`, then restart the notebook server for rich notebook output.
fluopy.__version__
'0.4.0.dev4+gc3c2cb30d'

Define a fluorophore and transition set

fluorophore = fl.Fluorophore(name="cy5_dna", position=[0, 0])
fluorophore_system = fl.FluorophoreSystem(fluorophores=[fluorophore])
transitions = fluorophore_system.load_transitions(
    summarize=True,
    irradiance=2,
    wavelength=640,
    bleaching=True,
    energy_transfer=False,
    dstorm=False,
)
transition_set = tr.TransitionSet(transitions, fluorophore_system)
transition_set.finalize()
<fluopy.transitions.TransitionSet at 0x7ba79d927e00>
transition_set.transition_df
transition_type abbreviation initial_state final_state rate photon fluorophore_ids absorbing
Fluorophore identity
cy5_dna 0 TransitionType.EXCITATION EXC SingleState.S0 SingleState.S1 5.815700e+06 False [0] False
1 TransitionType.FLUORESCENT_EMISSION FLU SingleState.S1 SingleState.S0 1.588235e+08 True [0] False
2 TransitionType.INTERSYSTEM_CROSSING_ST ISC_ST SingleState.S1 SingleState.T1 8.300000e+05 False [0] False
3 TransitionType.ISOMERIZATION ISO SingleState.S1 SingleState.cis 4.000000e+06 False [0] False
4 TransitionType.PHOTOBLEACHING_1 BLE SingleState.T1 SingleState.B 1.000000e+01 False [0] True
5 TransitionType.S1_S0_TRANSITIONS S1S0SUM SingleState.S1 SingleState.S0 4.245818e+08 False [0] False
6 TransitionType.T1_S0_TRANSITIONS T1S0SUM SingleState.T1 SingleState.S0 5.000000e+03 False [0] False
7 TransitionType.CIS_S0_TRANSITIONS cisS0SUM SingleState.cis SingleState.S0 4.366202e+04 False [0] False

Run a simulation in parallel using ray

ray.init()
2026-06-02 15:45:14,873	WARNING services.py:2213 -- WARNING: The object store is using /tmp/ray instead of /dev/shm because /dev/shm has only 67108864 bytes available. This will harm performance! You may be able to free up space by deleting files in /dev/shm. If you are inside a Docker container, you can increase /dev/shm size by passing '--shm-size=1.89gb' to 'docker run' (or add it to the run_options list in a Ray cluster config). Make sure to set this to more than 30% of available RAM.
2026-06-02 15:45:18,049	INFO worker.py:2012 -- Started a local Ray instance.
/home/docs/checkouts/readthedocs.org/user_builds/fluopy/envs/latest/lib/python3.13/site-packages/ray/_private/worker.py:2051: FutureWarning: Tip: In future versions of Ray, Ray will no longer override accelerator visible devices env var if num_gpus=0 or num_gpus=None (default). To enable this behavior and turn off this error message, set RAY_ACCEL_ENV_VAR_OVERRIDE_ON_ZERO=0
  warnings.warn(
%%time


@ray.remote
def worker(transition_set, seed):
    simulation = si.Simulation(transition_set)
    simulation.run(start_at=None, size=1e6, end_time=None, seed=seed)
    return simulation


n_processes = 10
ss = np.random.SeedSequence()
child_seeds = ss.spawn(n_processes)

futures = [
    worker.remote(transition_set=transition_set, seed=seed) for seed in child_seeds
]
simulations = ray.get(futures)
(worker pid=1153) Floating point precision error warning:
(worker pid=1153)  The higher limit of smallest increment with a probability of 1.00e-03 is 1.70e-12.
(worker pid=1153)  This was estimated using the highest possible rate which occurs for example in state combination [1].
(worker pid=1153)  Everything drawn below this number will be rounded to zero starting somewhere between 1.00e+03 - 1.00e+04.
(worker pid=1153) Floating point precision error warning: [repeated 7x across cluster] (Ray deduplicates logs by default. Set RAY_DEDUP_LOGS=0 to disable log deduplication, or see https://docs.ray.io/en/master/ray-observability/user-guides/configure-logging.html#log-deduplication for more options.)
(worker pid=1153)  The higher limit of smallest increment with a probability of 1.00e-03 is 1.70e-12. [repeated 7x across cluster]
(worker pid=1153)  This was estimated using the highest possible rate which occurs for example in state combination [1]. [repeated 7x across cluster]
(worker pid=1153)  Everything drawn below this number will be rounded to zero starting somewhere between 1.00e+03 - 1.00e+04. [repeated 7x across cluster]
CPU times: user 38.1 ms, sys: 10.7 ms, total: 48.8 ms
Wall time: 7.26 s
ray.shutdown()  # might be needed to reinitialize ray if executed multiple times

Extract and present data

final_times = [simulation_.time_series[-1] for simulation_ in simulations]
len(final_times)
10
plt.hist(final_times)
plt.gca().set(
    title=f"The mean bleaching time of {len(simulations)} simulations is {np.mean(final_times):0.2f} s",
    xlabel="bleaching time / s",
    ylabel="counts",
);
../../_images/5ba27ad8679f9402713ed7e82dac6433692690420f26a1824583d436f5d93ab1.png