LifStorage

LifStorage extends DataStorageBase to manage LifTrace waveforms for Laser-Induced Fluorescence (LIF) acquisitions. The scan grid is fixed at construction: d_delayPoints delay steps and d_laserPoints laser positions. Each cell (di, li) maps to the flat index di * d_laserPoints + li, which is used as the stem for the per-cell CSV files written under the lif/ subdirectory of the experiment directory.

LifStorage is owned by LifConfig alongside the digitizer configuration. The on-disk layout written by this class is described in LIF Data Storage; the surrounding experiment-setup and viewing workflow is covered by LIF Experiment Setup and Viewing LIF Data.

Acquisition lifecycle

start() arms the storage; finish() disarms it. As the acquisition sweeps the grid, the calling code passes each incoming waveform to addTrace(), which accumulates it into d_currentTrace (seeding from the completed-cell map if the cell has been partially accumulated in a previous sweep). At each grid-step boundary, advance() sets the d_nextNew flag and flushes the current cell to disk via save(). save() also rewrites the lif/lifparams.csv index file, which records the grid coordinates, shot count, and calibration scalars for every completed cell.

Trace access

getLifTrace() returns the trace for cell (di, li). When the cell matches the one being accumulated it returns the in-memory d_currentTrace directly. Otherwise it searches the completed-cell map d_data; if the experiment is no longer acquiring and the cell is absent from memory, it falls back to loadLifTrace() for a disk read. currentLifTrace() returns d_currentTrace without acquiring the mutex and is intended for use on the acquisition thread only. currentTraceShots() returns the shot count of the trace being accumulated; completedShots() sums shot counts across all completed cells (plus the current cell if it is in progress).

Processing settings

writeProcessingSettings() serializes a LifTrace::LifProcSettings struct to lif/processing.csv using the keys in BC::Key::LifStorage:

Key

Meaning

lifGateStart

Start sample index of the LIF integration gate

lifGateEnd

End sample index of the LIF integration gate

refGateStart

Start sample index of the reference integration gate

refGateEnd

End sample index of the reference integration gate

lowPassAlpha

Exponential low-pass smoothing factor (0 = disabled)

savGol

Savitzky-Golay filter enabled flag

sgWin

Savitzky-Golay window length (must be odd)

sgPoly

Savitzky-Golay polynomial order

readProcessingSettings() reads the same file back into a LifProcSettings struct.

API Reference

class LifStorage : public DataStorageBase

Storage manager for LIF trace data in a two-dimensional (delay, laser) grid.

Extends DataStorageBase to manage LifTrace waveforms for Laser-Induced Fluorescence (LIF) acquisitions. The grid dimensions are fixed at construction: d_delayPoints delay points and d_laserPoints laser positions. Each cell (di, li) maps to a flat index via di * d_laserPoints + li, which is used as the filename stem for the per-cell CSV files under the lif/ subdirectory.

See also

DataStorageBase, LifTrace, LifConfig

Public Functions

LifStorage(int dp, int lp, int num, QString path = "")

Construct the storage manager for a LIF acquisition grid.

Parameters:
  • dp – Number of delay points in the scan grid.

  • lp – Number of laser positions in the scan grid.

  • numExperiment number; pass -1 for a transient (peak-up) instance.

  • path – Base path of the experiment data directory.

~LifStorage()

Destructor.

virtual void advance() override

Flush the current cell to disk and arm the storage for the next cell.

Sets d_nextNew so that the next addTrace() starts a fresh accumulation, then calls save().

virtual void save() override

Write the current LifTrace and the grid parameter index to disk.

virtual void start() override

Arm the storage for incoming trace data.

virtual void finish() override

Disarm the storage after acquisition ends.

int currentTraceShots() const

Return the shot count of the trace being accumulated in the current cell.

Returns:

Shot count of d_currentTrace.

int completedShots() const

Return the total number of shots accumulated across all completed cells.

During active acquisition, the in-progress cell is included only if it has already been started (i.e., d_nextNew is false).

Returns:

Total shot count.

LifTrace getLifTrace(int di, int li)

Return the trace for grid cell (di, li).

Returns the in-memory trace if the cell is the one being accumulated. Falls back to the completed-cell map, then to a disk read if the experiment is no longer acquiring.

Parameters:
  • di – Delay index (0-based).

  • li – Laser index (0-based).

Returns:

The corresponding LifTrace, or a default-constructed trace if not found.

inline LifTrace currentLifTrace() const

Return the trace being accumulated in the current cell (no locking).

Returns:

Copy of d_currentTrace.

LifTrace loadLifTrace(int di, int li)

Read the trace for cell (di, li) from disk.

Parameters:
  • di – Delay index (0-based).

  • li – Laser index (0-based).

Returns:

The loaded LifTrace, or a default-constructed trace on failure.

void writeLifTrace(const LifTrace t)

Write a single trace to disk (used for direct writes outside the normal acquisition flow, e.g., post-processing updates).

Parameters:

t – Trace to write.

void addTrace(const LifTrace t)

Accumulate t into the current cell.

On the first call after advance() (or start()), seeds d_currentTrace from the completed-cell map if the cell already has data, then adds t. On subsequent calls, adds t directly to d_currentTrace.

Parameters:

t – Incoming LifTrace to accumulate.

void writeProcessingSettings(const LifTrace::LifProcSettings &c)

Serialize a LifTrace::LifProcSettings struct to lif/processing.csv.

Parameters:

c – Processing settings to write.

bool readProcessingSettings(LifTrace::LifProcSettings &out)

Deserialize a LifTrace::LifProcSettings struct from lif/processing.csv.

Parameters:

out – Processing settings populated on success.

Returns:

true if the file was found and parsed successfully.

Public Members

const int d_delayPoints

Number of delay points in the scan grid.

const int d_laserPoints

Number of laser positions in the scan grid.

Private Functions

void ensureLifParamsLoaded()

Lazily parse lif/lifparams.csv into d_lifParamsCache.

The first call walks the file end-to-end and populates the map keyed by index(dIndex,lIndex); subsequent calls are no-ops. Without the cache, loadLifTrace performs an O(N) scan per call, turning a full LifDisplayWidget::reprocess() into an O(N²) walk on a grid with N cells.

int index(int dp, int lp) const

Convert a (delay, laser) pair to a flat grid index.

Parameters:
  • dp – Delay index.

  • lp – Laser index.

Returns:

Flat index: dp * d_laserPoints + lp.

Private Members

bool d_acquiring = {false}
bool d_nextNew = {true}
std::map<int, LifTrace> d_data

Completed-cell map keyed by flat grid index.

LifTrace d_currentTrace

Trace being accumulated for the current cell.

std::map<int, LifParamsRow> d_lifParamsCache
bool d_lifParamsLoaded = {false}
struct LifParamsRow

Per-cell summary row parsed from lif/lifparams.csv.

Mirrors the on-disk row layout (shots, payload sizes, sample spacing, vertical multipliers) so loadLifTrace can look up a cell’s parameters by flat grid index without rescanning the file.

Public Members

int shots = {0}
int lifSize = {0}
int refSize = {0}
double spacing = {1.0}
double lifYMult = {0.0}
double refYMult = {0.0}