mirror of
https://github.com/vale981/fibre_walk_project_code
synced 2025-03-05 09:51:39 -05:00
140 lines
4.5 KiB
Python
140 lines
4.5 KiB
Python
###############################################################################
|
|
# Loading the Data #
|
|
###############################################################################
|
|
|
|
import numpy as np
|
|
from pathlib import Path
|
|
import functools
|
|
from . import utils
|
|
|
|
|
|
class ScanData:
|
|
def __init__(
|
|
self,
|
|
laser: np.ndarray,
|
|
output: np.ndarray,
|
|
time: np.ndarray,
|
|
truncation: [float, float] = [0, 100],
|
|
sparcity: float = 1,
|
|
):
|
|
"""
|
|
A class to hold the data from an oscilloscope scan where the
|
|
laser frequency is stepped as per the modulation ``laser``.
|
|
The output intensity ``intensity`` is proportional to the
|
|
actual intensity measured by the oscilloscope.
|
|
|
|
:param laser: The laser modulation signal.
|
|
:param output: The output intensity signal.
|
|
:param time: The time axis for the signals.
|
|
:param truncation: The fraction of the signals to truncate
|
|
from the beginning and end.
|
|
:param sparcity: The fraction of the signals to keep.
|
|
"""
|
|
|
|
if len(laser) != len(output) or len(laser) != len(time):
|
|
raise ValueError("The signals must all be the same length.")
|
|
|
|
length = len(laser)
|
|
begin = int(truncation[0] * length / 100)
|
|
end = int(truncation[1] * length / 100)
|
|
|
|
every = int(1 / sparcity)
|
|
|
|
self._laser = laser[begin:end:every]
|
|
self._output = output[begin:end:every]
|
|
self._time = time[begin:end:every]
|
|
|
|
@classmethod
|
|
def from_dir(cls, directory: str | Path, **kwargs):
|
|
"""Load and parse the oscilloscope data from the
|
|
``directory``. The ``**kwargs`` are passed to the
|
|
constructor.
|
|
|
|
The directory should contain ``signal_laser.npy``,
|
|
``signal_outp.npy``, and ``time.npy``.
|
|
"""
|
|
|
|
directory = Path(directory)
|
|
laser = np.load(directory / "signal_laser.npy")
|
|
output = np.load(directory / "signal_outp.npy")
|
|
time = np.load(directory / "time.npy")
|
|
|
|
return cls(laser, output, time, **kwargs)
|
|
|
|
@property
|
|
def laser(self):
|
|
"""The laser modulation signal."""
|
|
|
|
return self._laser
|
|
|
|
@property
|
|
def output(self):
|
|
"""The output intensity signal."""
|
|
|
|
return self._output
|
|
|
|
@property
|
|
def time(self):
|
|
"""The time axis for the signals."""
|
|
|
|
return self._time
|
|
|
|
@functools.cache
|
|
def laser_steps(self, *args, **kwargs) -> np.ndarray:
|
|
"""Find the indices of the laser signal ``laser`` where the
|
|
frequency of the laser changes. For the parameters, see
|
|
:func:`utils.find_frequency_steps`.
|
|
|
|
The result is cached for future calls.
|
|
"""
|
|
|
|
return utils.find_frequency_steps(self._laser, *args, **kwargs)
|
|
|
|
@functools.cache
|
|
def laser_step_times(self, *args, **kwargs):
|
|
"""
|
|
The times at which the laser frequency changes. See
|
|
:any:`laser_steps`.
|
|
"""
|
|
|
|
return self._time[self.laser_steps()]
|
|
|
|
@functools.cache
|
|
def output_end_averages(
|
|
self, end_fraction: float = 0.1, steps: np.ndarray | None = None
|
|
) -> np.ndarray:
|
|
"""
|
|
The average output intensity at the end of each laser
|
|
frequency modulation step. **If** the system is in its
|
|
steady, then this will be proportional to the steady state
|
|
transmission at that frequency.
|
|
"""
|
|
|
|
if steps is None:
|
|
steps = self.laser_steps()
|
|
|
|
step_size = np.mean(np.diff(steps))
|
|
|
|
if end_fraction > 1:
|
|
raise ValueError("end_fraction must be between 0 and 1.")
|
|
|
|
window = int(step_size * end_fraction)
|
|
|
|
return np.array([self._output[step - window : step].mean() for step in steps])
|
|
|
|
def for_step(self, step: int, steps: np.ndarray | None = None):
|
|
"""Return time and output for the ``step``. If ``steps`` is
|
|
not provided, then they are retrieved using the default
|
|
settings. See :any:`laser_steps`.
|
|
"""
|
|
time_steps: np.ndarray = self.laser_steps() if steps is None else steps
|
|
|
|
if step < 0 or step >= len(time_steps):
|
|
raise ValueError("The step must be between 0 and the number of steps.")
|
|
|
|
padded_steps = [0, *time_steps, len(self._output) - 1]
|
|
return (
|
|
self._time[padded_steps[step] : padded_steps[step + 1]],
|
|
self._output[padded_steps[step] : padded_steps[step + 1]],
|
|
self._laser[padded_steps[step] : padded_steps[step + 1]],
|
|
)
|