Source code for ewoksfluo.tasks.example_data.monitor
from typing import Optional
import numpy
[docs]
def monitor_signal(
expo_time: float,
npoints: int,
max_decay: float = 0.8,
number_of_injections: int = 2,
seed: Optional[int] = None,
):
"""Monitor signal between :math:``max_decay`` and :math:``1`` with
a number of injections defined by :math:``number_of_injections``.
"""
# All points in time at which we want the calculate the monitor signal.
time = numpy.arange(npoints) * expo_time
tmin = 0
tmax = time[-1]
# Fixed time distance between two injections.
injection_period = (tmax - tmin) / number_of_injections
# Fix intensity decay after each injection.
decay = -numpy.log(max_decay) / injection_period
# A single random injection time within the requested time range.
tinjection0 = numpy.random.RandomState(seed=seed).uniform(tmin, tmax)
# Calculate all other injection times from the singal random one, knowing
# injections are `injection_period` apart in time between tmin and tmax.
tinjections = [tinjection0]
tinjection = tinjection0
while tinjection > tmin:
tinjection -= injection_period
if tinjection >= tmin:
tinjections.append(tinjection)
tinjection = tinjection0
while tinjection < tmax:
tinjection += injection_period
if tinjection <= tmax:
tinjections.append(tinjection)
# Add one injection before tmin and one injection after tmax.
tinjections.append(max(tinjections) + injection_period)
tinjections.append(min(tinjections) - injection_period)
tinjections = sorted(tinjections)
# Calculate the monitor intensity at all points in time
# based on where each point is between two injections,
# knowing the intensity decay after each injection.
monitor = numpy.zeros(npoints)
for t0, t1 in zip(tinjections[:-1], tinjections[1:]):
idx = (time >= t0) & (time < t1)
tperiod = time[idx] - t0
monitor[idx] = numpy.exp(-decay * tperiod)
return monitor