plesty.fss.tracking

Following the lines of a polarization sweep while it is measured.

LineTracker fits the lines of one spectrum after another; plesty.fss.line_fit finds and fits them the way the analysis does.

LineTracking is what an experiment’s viewer holds: it says which of that experiment’s record fields hold the sweep, keeps one tracker per run, and answers both views of plesty.fss.monitor from a single fit per spectrum.

Attributes

SAME_LINE_PIXELS

Classes

SweepSoFar

The lines of a sweep as a LineTracker knows them after one spectrum.

LineTracker

Find and fit the lines of a sweep while it is measured.

LineTracking

Follows a run's emission lines while the sweep is being measured.

Functions

_spectrum_key(→ str)

Return a key identifying one spectrum, so two views reading it share one fit.

Module Contents

plesty.fss.tracking.SAME_LINE_PIXELS = 3
class plesty.fss.tracking.SweepSoFar

The lines of a sweep as a LineTracker knows them after one spectrum.

Variables:
  • label – Label of the sweep, e.g. the quantum dot, or None.

  • positions – Position of each line in nm, shortest wavelength first.

  • angles – Rotator angle of every spectrum so far, in degrees (nan if unknown).

  • centers – Fitted position of each line in each spectrum so far, (spectra, lines), nan where the fit failed or the line was not yet found.

label: str | None
positions: numpy.ndarray
angles: numpy.ndarray
centers: numpy.ndarray
property latest: numpy.ndarray

Fitted position of each line in the newest spectrum.

Return type:

numpy.ndarray

class plesty.fss.tracking.LineTracker(fit_options: Mapping[str, Any])

Find and fit the lines of a sweep while it is measured.

Lines are found the way SpectrumFit finds them for the analysis: in the average of the spectra — so far — with the same prominence, distance and average (use "median": in the mean of a few spectra a cosmic ray passes as a line). Given peaks, those positions are the lines and nothing is searched.

Each new spectrum is fitted with the analysis’s other fit options, starting from the previous spectrum’s positions. When the lines found change — a line appears or disappears — the positions fitted so far are kept for the lines that remain, so the numbering by wavelength can shift but no spectrum is refitted. A line whose position moves by up to SAME_LINE_PIXELS pixels is the same line.

One tracker serves both views of a run: each spectrum is fitted once, and a view that reads a spectrum later than the other gets the same answer. A spectrum with a different label starts a new sweep.

Validate the fit options.

Parameters:

fit_options (Mapping[str, Any]) – SpectrumFit options, with either the line positions in peaks or a prominence to find them.

Raises:

ValueError – If neither peaks nor prominence is given, or an option is invalid.

fixed: numpy.ndarray | None = None
prominence
distance
average = ''
fit_options
fits = 0
_seen: dict[str, SweepSoFar]
_label: str | None = None
_wavelength: numpy.ndarray | None = None
_spectra: list[numpy.ndarray] = []
_angles: list[float] = []
_rows: list[numpy.ndarray] = []
_positions: numpy.ndarray
observe(channels: Mapping[str, Any]) → SweepSoFar

Add one spectrum and return the sweep so far.

Parameters:

channels (Mapping[str, Any]) – One spectrum’s wavelength in nm and counts, with row (the rotator angle in degrees) and label when known.

Returns:

The lines and their positions after this spectrum.

Return type:

SweepSoFar

_reset(label: str | None) → None

Start a new sweep.

Parameters:

label (Optional[str])

Return type:

None

_update_lines() → None

Find the lines in the spectra so far; keep the columns of the lines that remain.

Return type:

None

_fit(counts: numpy.ndarray) → numpy.ndarray

Fit the lines in one spectrum, from the previous spectrum’s positions.

Parameters:

counts (numpy.ndarray)

Return type:

numpy.ndarray

plesty.fss.tracking._spectrum_key(label: str | None, angle: float, wavelength: numpy.ndarray, counts: numpy.ndarray) → str

Return a key identifying one spectrum, so two views reading it share one fit.

Parameters:
  • label (Optional[str])

  • angle (float)

  • wavelength (numpy.ndarray)

  • counts (numpy.ndarray)

Return type:

str

class plesty.fss.tracking.LineTracking(options: Mapping[str, Any] | None = None, *, at: Sequence[str] = ('analysis', 'fit_options'), counts: str = 'counts', wavelength: str = 'wavelength', angle: str = '', label: str = '', fit_key: str = 'line_fit_document', budget: int = 4)

Follows a run’s emission lines while the sweep is being measured.

Hand the same instance to both views. A tracker fits each spectrum once and answers from its own record afterwards, so two views cost one fit per spectrum rather than two.

The fit options are the analysis’s own, so the lines followed during the sweep are the lines reported after it. Without line positions (peaks) or a prominence to find them nothing is tracked: every bump of the noise would otherwise be a line, and the views simply show none.

Variables:

options – The fit options, or None to read them from each run’s own configuration.

Parameters:
  • options (Optional[Mapping[str, Any]])

  • at (Sequence[str])

  • counts (str)

  • wavelength (str)

  • angle (str)

  • label (str)

  • fit_key (str)

  • budget (int)

Say where the sweep is in the records, and how its lines are found.

Parameters:
  • options (Optional[Mapping[str, Any]]) – SpectrumFit options, or None to take them from the run’s frozen configuration.

  • at (Sequence[str]) – Keys leading to the fit options in that configuration, used only when options is None. The default is where an experiment that configures a plesty.fss.FineStructure under analysis keeps them.

  • counts (str) – Record field holding each spectrum’s counts.

  • wavelength (str) – Record field holding its wavelength axis, in nm.

  • angle (str) – Record field holding the rotator angle in degrees; "" when the run does not record one.

  • label (str) – Record field labelling the sweep — the quantum dot, say. A spectrum with a different label starts a new sweep.

  • fit_key (str) – Record field naming the analysis’s saved line fit. Once a run has written one there is nothing left to track: the analysis fitted every spectrum of the sweep already, and its answer is the one the run reports. Reading it costs one file instead of re-fitting the whole sweep.

  • budget (int) – How many spectra one sweep() may fit. Fitting happens inside a view’s draw, on the thread that answers the window, so an unbounded call is a window that stops answering for as long as the backlog takes. The rest are fitted on the calls that follow. 0 removes the bound, for a caller that is not drawing — a script, or a test that wants the whole sweep in one go.

options = None
at = ('analysis', 'fit_options')
counts = 'counts'
wavelength = 'wavelength'
angle = ''
label = ''
fit_key = 'line_fit_document'
budget = 4
_analysed: dict[str, SweepSoFar | None]
_trackers: dict[str, LineTracker | None]
tracker(data: Any) → LineTracker | None

The tracker that finds this run’s lines, built once per run.

Parameters:

data (Any) – The run’s data.

Returns:

The tracker, or None when this run gives it nothing to find lines by.

Return type:

Optional[LineTracker]

_configured(data: Any) → dict[str, Any]

Return the fit options the run’s own configuration carries at at.

Parameters:

data (Any)

Return type:

dict[str, Any]

sweep(data: Any) → SweepSoFar | None

The lines of the current sweep, as far as it has been measured.

While the sweep runs, every spectrum committed so far is handed to the tracker in order; it fits each one once and answers from its own record afterwards, so calling this from both views costs one fit per spectrum.

Once the analysis has written its line fit there is nothing left to track, and the tracker is not used at all. That matters for opening a finished run: re-fitting ninety spectra to draw a marker on one of them took seconds before the first frame appeared, and produced a worse answer than the analysis had already saved beside it.

Parameters:

data (Any) – The run’s data.

Returns:

The sweep so far, or None when nothing is tracked or no spectrum has been committed.

Return type:

Optional[SweepSoFar]

_analysis(data: Any) → SweepSoFar | None

The sweep as the analysis fitted it, or None before it wrote one.

Read once per run and kept: a view redrawn twice a second must not re-parse the document each tick.

Parameters:

data (Any) – The run’s data.

Returns:

The fitted positions of every line in every spectrum of the sweep.

Return type:

Optional[SweepSoFar]