Experiment

Experiment is the root of Blackchirp’s data model for a single acquisition. It owns an optional FtmwConfig, an optional LifConfig, a set of optional hardware sub-configurations (pulse generator, flow controller, IO board, pressure controller, temperature sensor), an AuxDataStorage for time-series auxiliary readings, and an OverlayStorage (see OverlayBase and OverlayStorage) for overlay annotations. All of these objects derive from HeaderStorage and contribute their fields to the experiment’s shared CSV header file; Experiment is the root of that tree.

Two construction paths are provided. The default constructor creates an empty experiment ready for setup via Experiment::enableFtmw() and the other configuration accessors; this path is used by the acquisition wizard. The three-argument constructor reads a saved experiment from disk by number, populating every sub-configuration from the header file, chirp file, clock file, FID data, and overlay storage; passing headerOnly = true skips FID, auxiliary, and overlay loading for lightweight summary access (for example, in the experiment browser). The on-disk format is described in Data Storage.

Experiment objectives

Active acquisition objectives — FtmwConfig and LifConfig — are tracked in the d_objectives set as non-owning pointers alongside the owning shared pointers. The Experiment::isComplete() predicate delegates to each objective’s own completion check. Calling Experiment::abort() propagates to all objectives.

Peak Up mode creates a dummy experiment: d_isDummy is set to true, the experiment number is set to -1, and no files are written to disk. The dummy flag is checked at every save site so that no disk I/O is attempted.

API Reference

class Experiment : private HeaderStorage

Top-level experiment record, owning all acquisition sub-configurations.

Experiment is the root of the HeaderStorage tree. It aggregates an optional FtmwConfig, an optional LifConfig, auxiliary hardware configurations (pulse generator, flow controller, IO board, pressure controller, temperature sensor), auxiliary time-series data, and overlay storage. All child objects contribute their fields to the shared experiment header file.

Two construction paths exist: the default constructor creates an empty experiment ready for setup, and the disk-loading constructor — which takes the experiment number, an optional base path, and a header-only flag — reads a saved experiment from disk by experiment number.

An experiment is identified as a dummy when it runs in Peak Up mode without LIF enabled; dummy experiments are not assigned a number and are not saved to disk.

Public Functions

Experiment()

Constructs a new, empty experiment ready for configuration.

Experiment(const Experiment &other) = default

Constructs a copy of other.

Experiment(const int num, QString exptPath = QString(""), bool headerOnly = false)

Constructs an experiment by reading saved data from disk.

Loads the header, hardware map, objective list, chirp file, clock file, FID data (unless headerOnly is true), LIF data, auxiliary data, and overlays for experiment number num under exptPath (or the default data directory when exptPath is empty).

Parameters:
  • numExperiment number to load.

  • exptPath – Optional override for the root data directory.

  • headerOnly – When true, FID data, auxiliary data, and overlays are not loaded; only the header and configuration are read.

~Experiment()
inline bool isAborted() const

Returns true if the experiment has been aborted.

inline bool isDummy() const

Returns true if this is a dummy (Peak Up, no-save) experiment.

inline QString path() const

The storage path override (”” follows the configured save path).

bool isComplete() const

Returns true when all active experiment objectives have completed.

HeaderStrings getSummary()

Returns a flat map of all header key-value pairs suitable for display.

inline bool ftmwEnabled() const

Returns true if FTMW acquisition is configured.

FtmwConfig *enableFtmw(FtmwConfig::FtmwType type)

Creates and registers an FtmwConfig of the given type, replacing any existing one.

Returns:

Non-owning pointer to the newly created FtmwConfig.

void disableFtmw()

Removes and destroys the active FtmwConfig.

inline FtmwConfig *ftmwConfig() const

Returns a non-owning pointer to the active FtmwConfig, or nullptr if FTMW is disabled.

inline AuxDataStorage *auxData() const

Returns a non-owning pointer to the auxiliary time-series data storage.

inline std::shared_ptr<OverlayStorage> overlayStorage() const

Returns a shared pointer to the overlay storage for this experiment.

template<typename T>
inline std::weak_ptr<T> getOptHwConfig(const QString key) const

Returns a weak pointer to the optional hardware configuration associated with key.

Returns an empty weak pointer if no configuration for key is registered.

template<typename T>
inline void addOptHwConfig(const T &c)

Registers a copy of optional hardware configuration c, keyed by its header key.

inline void removeOptHwConfig(const QString key)

Removes the optional hardware configuration registered under key.

void initOptHwFromData()

Populates optional hardware configurations from the loaded hardware data map.

Called during the disk-load constructor after the hardware map has been read.

bool addAuxData(AuxDataStorage::AuxDataMap m)

Records a batch of auxiliary data points; returns false if any value fails validation.

void setValidationMap(const ExperimentValidator::ValidationMap &m)

Installs a validation map used to range-check incoming auxiliary data values.

bool validateItem(const QString key, const QVariant val)

Validates a single key-value pair against the installed validation map.

Sets d_errorString and returns false if the value is out of range.

inline bool lifEnabled() const

Returns true if LIF acquisition is configured.

inline LifConfig *lifConfig() const

Returns a non-owning pointer to the active LifConfig, or nullptr if LIF is disabled.

LifConfig *enableLif()

Creates and registers a LifConfig, replacing any existing one.

Returns:

Non-owning pointer to the newly created LifConfig.

void disableLif()

Removes and destroys the active LifConfig.

bool initialize()

Assigns an experiment number, creates the on-disk directory, and writes initial files.

Must be called before acquisition begins. Returns false and sets d_errorString on failure. For Peak Up experiments without LIF, the experiment is marked as a dummy and no files are written.

void abort()

Marks the experiment as aborted and propagates the abort to all objectives.

bool canBackup()

Returns true if a periodic backup is due.

void backup()

Writes an incremental backup of FTMW FID data to disk.

void finalSave()

Calls each objective’s cleanup-and-save routine and writes the overlay storage.

bool saveObjectives()

Writes the objectives list CSV file for this experiment.

bool saveHardware()

Writes the hardware map CSV file for this experiment.

bool saveHeader()

Writes the experiment header CSV file.

bool saveChirpFile() const

Writes the chirp segment CSV file via the active FtmwConfig's chirp config.

bool saveMarkersFile() const

Writes the marker channel CSV file via the active FtmwConfig's chirp config.

bool saveClockFile() const

Writes the clock steps CSV file via the active FtmwConfig's RF config.

Public Members

bool d_hardwareSuccess = {false}

Set to true after the hardware map loads successfully.

bool d_initSuccess = {false}

Set to true after initialize() succeeds.

BC::Data::HardwareDataContainer d_hardwareData

Hardware type-to-key map recorded at acquisition time.

int d_number = {0}

Experiment number; -1 for dummy (Peak Up) experiments.

QDateTime d_startTime

Wall-clock time when the experiment started.

QDateTime d_lastBackupTime

Wall-clock time of the most recent backup (periodic or manual); used to schedule the next periodic backup.

int d_timeDataInterval = {300}

Auxiliary data sampling period in seconds.

int d_backupIntervalMinutes = {0}

Periodic backup interval in minutes; 0 disables backups.

QString d_errorString

Human-readable description of the last error, if any.

QString d_startLogMessage

Message written to the log when the experiment starts.

QString d_endLogMessage

Message written to the log when the experiment ends.

LogHandler::MessageCode d_endLogMessageCode = {LogHandler::Highlight}

Severity of the end-of-experiment log message.

QString d_majorVersion = {STRINGIFY(BC_MAJOR_VERSION)}

Blackchirp major version string.

QString d_minorVersion = {STRINGIFY(BC_MINOR_VERSION)}

Blackchirp minor version string.

QString d_patchVersion = {STRINGIFY(BC_PATCH_VERSION)}

Blackchirp patch version string.

QString d_releaseVersion = {STRINGIFY(BC_RELEASE_VERSION)}

Blackchirp release label string.

QString d_buildVersion = {STRINGIFY(BC_BUILD_VERSION)}

Blackchirp build version string.

QSet<ExperimentObjective*> d_objectives

Non-owning pointers to all active experiment objectives (FTMW, LIF).

Protected Functions

virtual void storeValues() override

Writes experiment-level scalar fields to the header storage tree.

virtual void retrieveValues() override

Reads experiment-level scalar fields back from the header storage tree.

virtual void prepareChildren() override

Registers all child HeaderStorage nodes (FtmwConfig, validator, optional hardware, LIF).

Private Members

bool d_isAborted = {false}
bool d_isDummy = {false}
std::shared_ptr<FtmwConfig> ps_ftmwConfig
std::shared_ptr<AuxDataStorage> ps_auxData
std::shared_ptr<ExperimentValidator> ps_validator
std::shared_ptr<OverlayStorage> ps_overlayStorage
std::map<QString, std::shared_ptr<HeaderStorage>, std::less<>> d_optHwData
QString d_path
std::shared_ptr<LifConfig> ps_lifCfg