Tutorial about fluopy - io

Here we demonstrate input/output and serialization of datastructures in fluopy.

import pickle
import tempfile
from pathlib import Path

import numpy as np

import fluopy
import fluopy.analysis as an
import fluopy.blinking as bl
import fluopy.emissions as em
import fluopy.fcs as fcs_p
import fluopy.fluorophores as fl
import fluopy.miscellaneous as mi
import fluopy.prediction as pr
import fluopy.simulation as si
import fluopy.transitions as tr
# ruff: noqa: S101, S301, S403
fluopy.__version__
'0.4.0.dev4+gc3c2cb30d'

For random number generation a Generator is initialized.

rng = np.random.default_rng(seed=1)

Single dye simulation setup

For further demonstration we set up a simple fluorophore system that contains a single Cy5 fluorophore.

%%time
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=False,
    energy_transfer=False,
    dstorm=False,
)
transition_set = tr.TransitionSet(transitions, fluorophore_system)
transition_set = transition_set.remove_energy_transfers()
transition_set.finalize()

prediction = pr.Prediction(transition_set)
simulation = si.Simulation(transition_set)
simulation.run(start_at=None, size=1e6, end_time=None, seed=rng, use_memmap=None)

analysis = an.Analysis(simulation=simulation)
emissions = em.Emissions(frame_time="5ms", seed=rng, bandpass=(600, 800))
emissions.extract(simulation=simulation)
fcs = fcs_p.FCS(emissions)
blinks = bl.Blinking(emissions, threshold=5)
Floating point precision error warning:
 The higher limit of smallest increment with a probability of 1.00e-03 is 1.70e-12.
 This was estimated using the highest possible rate which occurs for example in state combination [1].
 Everything drawn below this number will be rounded to zero starting somewhere between 1.00e+03 - 1.00e+04.
CPU times: user 2.87 s, sys: 38.1 ms, total: 2.91 s
Wall time: 2.91 s

Pickle

To save data temporarily in a python environment, the data classes can be serialized (pickled), saved and reloaded.

Pickle TransitionSet

with tempfile.TemporaryDirectory() as tmpdirname:
    file_path = Path(tmpdirname) / "transition_set.pickle"

    with open(file_path, mode="wb") as file:
        pickle.dump(transition_set, file=file, protocol=pickle.HIGHEST_PROTOCOL)

    with open(file_path, mode="rb") as file:
        transition_set_new = pickle.load(file)

assert transition_set.transition_df.equals(transition_set_new.transition_df)
transition_set_new.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.S1_S0_TRANSITIONS S1S0SUM SingleState.S1 SingleState.S0 4.245818e+08 False [0] False
5 TransitionType.T1_S0_TRANSITIONS T1S0SUM SingleState.T1 SingleState.S0 5.000000e+03 False [0] False
6 TransitionType.CIS_S0_TRANSITIONS cisS0SUM SingleState.cis SingleState.S0 4.366202e+04 False [0] False

Pickle Prediction

with tempfile.TemporaryDirectory() as tmpdirname:
    file_path = Path(tmpdirname) / "prediction.pickle"
    print("created temporary", file_path)

    with open(file_path, mode="wb") as file:
        pickle.dump(prediction, file=file, protocol=pickle.HIGHEST_PROTOCOL)

    with open(file_path, mode="rb") as file:
        prediction_new = pickle.load(file)

assert np.array_equal(
    prediction.mean_transition_times, prediction_new.mean_transition_times
)
mi.print_class(prediction_new)
created temporary /tmp/tmp754o24pj/prediction.pickle
Attributes of <fluopy.prediction.Prediction object at 0x7a9728dbb750>:
.................................................................
energy_transfer = False
_________________________________________________________________
absorbing_chain = False
_________________________________________________________________
transition_set = <fluopy.transitions.TransitionSet object at 0x7a9728c0cb00>
_________________________________________________________________
frequency_transitions = array([0.49795564, 0.13444802, 0.00070262, 0.0033861 , 0.35941891,
       0.00070262, 0.0033861 ])
_________________________________________________________________
frequency_states = {'cy5_dna': array([0.49795564, 0.49795564, 0.00070262, 0.0033861 ])}
_________________________________________________________________
transition_time_distributions = array([<scipy.stats._distn_infrastructure.rv_con...n object at 0x7a9728c65040>],
      dtype=object)
_________________________________________________________________
lifetime_distributions = {'cy5_dna': array([<scipy.stats._distn_infrastructure.rv_con...n object at 0x7a9728c65040>],
      dtype=object)}
_________________________________________________________________
mean_transition_times = array([1.71948334e-07, 1.70000000e-09, 1.7000000... 1.70000000e-09, 2.00000000e-04, 2.29032030e-05])
_________________________________________________________________
mean_lifetimes = {'cy5_dna': array([1.71948334e-07, 1.70000000e-09, 2.00000000e-04, 2.29032030e-05])}
_________________________________________________________________
state_occupations = {'cy5_dna': array([0.28114963, 0.00277964, 0.46142015, 0.25465059])}
_________________________________________________________________

Pickle Simulation

with tempfile.TemporaryDirectory() as tmpdirname:
    file_path = Path(tmpdirname) / "simulation.pickle"
    print("created temporary", file_path)

    with open(file_path, mode="wb") as file:
        pickle.dump(simulation, file=file, protocol=pickle.HIGHEST_PROTOCOL)

    with open(file_path, mode="rb") as file:
        simulation_new = pickle.load(file)

assert np.array_equal(simulation.transition_series, simulation_new.transition_series)
mi.print_class(simulation_new)
created temporary /tmp/tmpho3e3bg2/simulation.pickle
Attributes of <fluopy.simulation.Simulation object at 0x7a9728ce0190>:
.................................................................
transition_set = <fluopy.transitions.TransitionSet object at 0x7a9728c0d5b0>
_________________________________________________________________
time_series = array([0.00000000e+00, 1.15167403e-07, 1.1846002....98456388e-01, 2.98456460e-01], shape=(1000001,))
_________________________________________________________________
transition_series = array([0, 4, 0, ..., 0, 4, 0], shape=(1000000,), dtype=uint32)
_________________________________________________________________
state_series = array([[0, 1, 0, ..., 1, 0, 1]], shape=(1, 1000001), dtype=int8)
_________________________________________________________________
memmap_path = None
_________________________________________________________________

Pickle Emissions

with tempfile.TemporaryDirectory() as tmpdirname:
    file_path = Path(tmpdirname) / "emissions.pickle"
    print("created temporary", file_path)

    with open(file_path, mode="wb") as file:
        pickle.dump(emissions, file=file, protocol=pickle.HIGHEST_PROTOCOL)

    with open(file_path, mode="rb") as file:
        emissions_new = pickle.load(file)


assert emissions.event_time_series.equals(emissions_new.event_time_series)
mi.print_class(emissions_new)
created temporary /tmp/tmpk4qvpxj4/emissions.pickle
Attributes of <fluopy.emissions.Emissions object at 0x7a9728dbafd0>:
.................................................................
parameters = {'bandpass': (600, 800), 'frame_time': '5ms', 'seed': Generator(PCG64) at 0x7A9728CA19A0}
_________________________________________________________________
event_time_points = array([9.63613192e-07, 1.02199188e-06, 1.3375265...2.98454483e-01, 2.98456319e-01], shape=(134660,))
_________________________________________________________________
event_time_series[:6] = 0.000       0
0.005    2746
0.010    2452
0.015    2016
0.020    2621
0.025    2662
dtype: int32
_________________________________________________________________

Pickle Analysis

with tempfile.TemporaryDirectory() as tmpdirname:
    file_path = Path(tmpdirname) / "analysis.pickle"
    print("created temporary", file_path)

    with open(file_path, mode="wb") as file:
        pickle.dump(analysis, file=file, protocol=pickle.HIGHEST_PROTOCOL)

    with open(file_path, mode="rb") as file:
        analysis_new = pickle.load(file)

assert np.array_equal(
    analysis.mean_transition_times, analysis_new.mean_transition_times
)
mi.print_class(analysis_new)
created temporary /tmp/tmpjz_toxd7/analysis.pickle
Attributes of <fluopy.analysis.Analysis object at 0x7a9728ce0550>:
.................................................................
simulation = <fluopy.simulation.Simulation object at 0x7a9728ce0690>
_________________________________________________________________
frequency_transitions = array([0.497969, 0.13466 , 0.000713, 0.00335 , 0.359245, 0.000713,
       0.00335 ])
_________________________________________________________________
frequency_states = {'cy5_dna': array([0.4979685, 0.4979685, 0.000713 , 0.00335  ])}
_________________________________________________________________
transition_time_distributions = [array([1.15167403e-07, 2.00370096e-07, 1.0292414...1.12367102e-08, 7.21566451e-08], shape=(497969,)), array([2.70692579e-09, 1.04365849e-09, 1.1245765...1.29471978e-09, 6.46454268e-09], shape=(134660,)), array([8.13131923e-11, 1.12316811e-09, 3.2367626...3992e-10, 2.32103559e-09,
       2.62631206e-09]), array([2.78520366e-11, 4.96192080e-11, 5.2462151..., 3.58498120e-10, 2.22540164e-09], shape=(3350,)), array([3.29261818e-09, 3.21472349e-10, 4.8111509...9.61658420e-10, 3.52746099e-09], shape=(359245,)), array([2.09049322e-04, 4.70720770e-05, 3.1177580...6248e-04, 1.16242998e-04,
       3.21913307e-04]), ...]
_________________________________________________________________
lifetime_distributions = {'cy5_dna': [array([1.15167403e-07, 2.00370096e-07, 1.0292414...1.12367102e-08, 7.21566451e-08], shape=(497969,)), array([3.29261818e-09, 3.21472349e-10, 4.8111509...9.61658420e-10, 3.52746099e-09], shape=(497968,)), array([2.09049322e-04, 4.70720770e-05, 3.1177580...6248e-04, 1.16242998e-04,
       3.21913307e-04]), array([2.30303049e-05, 1.90388200e-05, 9.5060313..., 2.28209101e-05, 1.06549123e-04], shape=(3350,))]}
_________________________________________________________________
mean_transition_times = array([1.72148478e-07, 1.69768543e-09, 1.6061989... 1.70026013e-09, 1.88729078e-04, 2.30810957e-05])
_________________________________________________________________
mean_lifetimes = {'cy5_dna': array([1.72148478e-07, 1.69960986e-09, 1.88729078e-04, 2.30810957e-05])}
_________________________________________________________________
state_occupations = {'cy5_dna': array([0.2872265 , 0.00283577, 0.45086587, 0.25907186])}
_________________________________________________________________

Pickle FCS

with tempfile.TemporaryDirectory() as tmpdirname:
    file_path = Path(tmpdirname) / "fcs.pickle"
    print("created temporary", file_path)

    with open(file_path, mode="wb") as file:
        pickle.dump(fcs, file=file, protocol=pickle.HIGHEST_PROTOCOL)

    with open(file_path, mode="rb") as file:
        fcs_new = pickle.load(file)

assert np.array_equal(fcs.autocorrelation, fcs_new.autocorrelation)
mi.print_class(fcs_new)
created temporary /tmp/tmp9dr_ury0/fcs.pickle
Attributes of <fluopy.fcs.FCS object at 0x7a9728ce07d0>:
.................................................................
emissions = <fluopy.emissions.Emissions object at 0x7a9728ce0a50>
_________________________________________________________________
autocorrelation = None
_________________________________________________________________
tau = None
_________________________________________________________________