Skip to content

Data Structure Module

Core data structures for storing and managing measurement data.

Main Container

DataSet

Attributes

time_data_list instance-attribute
time_data_list = TimeDataList()
freq_data_list instance-attribute
freq_data_list = FreqDataList()
cross_spec_data_list instance-attribute
cross_spec_data_list = CrossSpecDataList()
tf_data_list instance-attribute
tf_data_list = TfDataList()
modal_data_list instance-attribute
modal_data_list = ModalDataList()
sono_data_list instance-attribute
sono_data_list = SonoDataList()
meta_data_list instance-attribute
meta_data_list = MetaDataList()
pydvma_version instance-attribute
pydvma_version = VERSION
_LIST_ATTRS class-attribute instance-attribute
_LIST_ATTRS = ('time_data_list', 'freq_data_list', 'cross_spec_data_list', 'tf_data_list', 'modal_data_list', 'sono_data_list', 'meta_data_list')

Methods:

__init__
__init__(data=None)
__setstate__
__setstate__(state)

Restore a pickled DataSet, forward-normalising older layouts.

Unpickling instantiates the CURRENT class but restores ONLY the attributes that were actually saved, so a DataSet written by an older pydvma is missing any *_list attribute that postdates it. Historically the lists were added at different times (cross_spec_data_list with multi-channel analysis; sono_data_list with sonograms; modal_data_list with modal fitting), so a legacy .npy pickle can lack one or more of them — e.g. the 2019/4C6-era files lack modal_data_list. The rest of the code (and container.save) assumes every list is present, so loading such a file used to raise AttributeError: 'DataSet' object has no attribute 'modal_data_list'.

We fill in any absent list with an empty instance of the right type (and stamp a placeholder pydvma_version when the file predates the version field) so files saved by pydvma <= 1.4.0 load forever — the compatibility contract — on BOTH the Qt load path (file.load_datanp.load) and the browser legacy-import path (glue.legacy_to_dvmanp.loadcontainer.save_bytes). Called only when unpickling; freshly constructed DataSets go through __init__ and never touch this. Newly saved objects already carry every attribute, so this is a no-op for them.

add_to_dataset
add_to_dataset(data)
replace_data_item
replace_data_item(data, n_set)
remove_last_data_item
remove_last_data_item(data_class)
remove_data_item_by_index
remove_data_item_by_index(data_class, list_index)
calculate_fft_set
calculate_fft_set(time_range=None, window=None)

Calls analysis.calculate_fft on each TimeData item in the TimeDataList and adds FreqDataList object to dataset

calculate_tf_set
calculate_tf_set(ch_in=0, time_range=None, window=None, N_frames=1, overlap=0.5)

Calls analysis.calculate_tf on each TimeData item in the TimeDataList and adds TfDataList object to dataset

calculate_cross_spectrum_matrix_set
calculate_cross_spectrum_matrix_set(ch_in=0, time_range=None, window='hann', N_frames=1, overlap=0.5)

Calls analysis.calculate_cross_spectrum_matrix on each TimeData item in the TimeDataList and adds CrossSpecDataList object to dataset

calculate_tf_averaged
calculate_tf_averaged(ch_in=0, time_range=None, window='hann')

Calls analysis.calculate_tf_averaged on the whole TimeDataList (ensemble average) and adds a single-item TfDataList to dataset

calculate_cross_spectra_averaged
calculate_cross_spectra_averaged(time_range=None, window=None)

Calls analysis.calculate_cross_spectra_averaged on the whole TimeDataList (ensemble average) and adds a single-item CrossSpecDataList to dataset

calculate_sono_set
calculate_sono_set(nperseg=None)
clean_impulse
clean_impulse(ch_impulse=0)

Calls analysis.clean_impulse on each TimeData item in the TimeDataList and returns a copy of the new dataset.

Note that calling this function does not change the data, and just returns a copy.

subset
subset(sets)

Return a new DataSet holding chosen measurement(s) and everything derived from them.

This is the Python counterpart of the web app's Save "Choose sets…" picker (subsetDataset in webui/src/lib/analysis/actions.ts) — the same inclusion rule, mirrored here so a notebook workflow and the browser produce the same subset from the same dataset:

  1. the chosen TimeData item(s) themselves;
  2. every FreqData / CrossSpecData / TfData / SonoData item whose id_link resolves into a chosen item's unique_id. A scalar id_link (analysis.calculate_fft, analysis.calculate_tf, analysis.calculate_cross_spectrum_matrix, analysis.calculate_sonogram/calculate_cwt) matches directly; a LIST id_link (analysis.calculate_tf_averaged, analysis.calculate_cross_spectra_averaged, analysis.calculate_bla — one entry per source TimeData in the ensemble) matches on ANY member, not all — an ensemble result whose sources only partly overlap the pick still rides along;
  3. a ModalData fit when ANY of its links lands in the chosen lineage — see _modal_item_in_subset for the exact link shapes checked (own id_link, scalar or nested-list, plus a browser-authored source_targets extra when present). This is deliberately an ANY rule, not ALL: a fit is worth carrying with any set it describes. Note the web app's own loader is stricter — it re-seeds a live, editable fit only when EVERY source_targets link resolves — so a subset spanning only part of a shared-pole fit still carries the ModalData as data (readable, replottable, reloadable) without silently re-seeding a fit session for a model that no longer has all its sources; carrying the modes as DATA is the contract here, not re-seeding a fit.
  4. MetaData, and any derived item whose id_link cannot be resolved into the pick (an orphan, or a link to a TimeData outside the pick), are excluded — that is the point of a subset.

Items are SHARED, not copied. The returned DataSet's lists hold the SAME objects as self's, so mutating a TimeData (or any derived item) reached through either dataset is visible through both — consistent with the rest of this class (add_to_dataset, replace_data_item never copy either). Take your own copy.deepcopy first if independent objects are needed. Lists keep their original relative order.

Unlike the web app's subsetDataset, there is no "picking every set returns the live document" short-circuit: this always builds a fresh DataSet (still item-SHARING, per above), so passing every valid index is not the same as "everything" — a genuinely unattributable item (an orphan derived item, MetaData) is excluded even then, whereas the web app's "everything" pick keeps such items because it returns the untouched document unchanged.

Parameters:

  • sets (int or Iterable[int]) –

    Index or indices into time_data_list to keep (0-based). Duplicate indices are ignored after the first.

Returns:

  • dataset ( DataSet ) –

    A new DataSet, with pydvma_version copied from self, containing the chosen measurements and their resolved derived/modal items, sharing objects with self.

Raises:

  • IndexError

    sets contains an index outside range(len(self.time_data_list)).

save_data
save_data(filename=None, sets=None)

Saves the whole DataSet via file.save_data — writes the .dvma container format by default (legacy pickle format if filename explicitly ends in .npy). Shows a save dialog if no filename is given.

Parameters:

  • filename (str, default: None ) –

    Output filename, dialog shown if not provided.

  • sets (int or Iterable[int], default: None ) –

    If given, saves self.subset(sets) instead of the whole dataset — see subset for the exact inclusion rule. None (the default) saves everything, unchanged.

export_to_matlab
export_to_matlab(filename=None, overwrite_without_prompt=False)
export_to_matlab_jwlogger
export_to_matlab_jwlogger(filename=None, overwrite_without_prompt=False)
plot_time_data
plot_time_data(sets='all', channels='all')
plot_freq_data
plot_freq_data(sets='all', channels='all')
plot_tf_data
plot_tf_data(sets='all', channels='all')
plot_sono_data
plot_sono_data(n_set=0, n_chan=0, db_range=60)
__repr__
__repr__()

Time Domain Data

TimeData

One block of acquired time-series data plus its acquisition metadata.

Held inside a DataSet.time_data_list. Produced by log_data, by the test-data factories in testdata, and on import from Matlab. The numeric content is in volts (see "Voltage-Based I/O" in the user-guide acquisition page); apply channel_cal_factors to convert to engineering units at display or fit time. analysis.calculate_* functions copy units and channel_cal_factors onto their derived FreqData / TfData / CrossSpecData / SonoData outputs.

Attributes:

  • time_axis (ndarray) –

    1D sample times in seconds.

  • time_data (ndarray) –

    Shape (n_samples, n_channels) voltage samples.

  • settings (MySettings) –

    Snapshot of the acquisition configuration.

  • timestamp (datetime) –

    Capture start time.

  • timestring (str) –

    Filesystem-safe rendering of timestamp.

  • units (list[str] or None) –

    Engineering units per channel (e.g. ['N', 'm/s', 'g']). None if unset.

  • channel_cal_factors (ndarray) –

    Per-channel multipliers from volts to engineering units. Defaults to all-ones.

  • id_link

    Reference to a source TimeData (used when this object is derived rather than freshly acquired).

  • test_name (str or None) –

    Free-form label, displayed in plots.

  • unique_id (UUID) –

    Generated at construction; used by derived objects to link back to their source via id_link.

Attributes

time_axis instance-attribute
time_axis = time_axis
time_data instance-attribute
time_data = time_data
settings instance-attribute
settings = settings
timestamp instance-attribute
timestamp = timestamp
timestring instance-attribute
timestring = timestring
units instance-attribute
units = units
channel_cal_factors instance-attribute
channel_cal_factors = channel_cal_factors
id_link = id_link
test_name instance-attribute
test_name = test_name
unique_id instance-attribute
unique_id = uuid.uuid4()

Methods:

__init__
__init__(time_axis, time_data, settings, timestamp=None, timestring=None, units=None, channel_cal_factors=None, id_link=None, test_name=None)
__repr__
__repr__()

TimeDataList

Bases: list

Methods:

calculate_fft_set
calculate_fft_set(time_range=None, window=None)

Calls analysis.calculate_fft on each item in the list and returns FreqDataList object

calculate_tf_set
calculate_tf_set(ch_in=0, time_range=None, window=None, N_frames=1, overlap=0.5)

Calls analysis.calculate_tf on each item in the list and returns TfDataList object

calculate_cross_spectrum_matrix_set
calculate_cross_spectrum_matrix_set(ch_in=0, time_range=None, window=None, N_frames=1, overlap=0.5)

Calls analysis.calculate_tf on each item in the list and returns TfDataList object

calculate_tf_averaged
calculate_tf_averaged(ch_in=0, time_range=None, window='hann')

Calls analysis.calculate_tf_averaged on whole list and returns TfData object

calculate_cross_spectra_averaged
calculate_cross_spectra_averaged(time_range=None, window=None)

Calls analysis.calculate_cross_spectra_averaged on whole list and returns CrossSpecData object

calculate_sono_set
calculate_sono_set(nperseg=None)

Calls analysis.calculate_sonogram on each item in the list and returns SonoDataList object

get_calibration_factors
get_calibration_factors()
set_calibration_factors_all
set_calibration_factors_all(factors)
set_calibration_factor
set_calibration_factor(factor, n_set=0, n_chan=0)
export_to_csv
export_to_csv(filename=None, overwrite_without_prompt=False)

Frequency Domain Data

FreqData

One-sided complex frequency spectrum of a TimeData capture.

Produced by analysis.calculate_fft. The spectrum is the raw np.fft.rfft of the (optionally windowed) time data — i.e. it is not scaled to a PSD or amplitude spectrum; consumers that need PSD should square the magnitude themselves. units and channel_cal_factors are copied verbatim from the source TimeData.

Attributes:

  • freq_axis (ndarray) –

    Frequency bins in Hz (length N//2+1).

  • freq_data (ndarray) –

    Shape (n_freq, n_channels) complex spectrum, one column per channel.

  • settings (MySettings) –

    Snapshot of the analysis configuration (includes the window choice and the time range that was used).

  • units (list[str] or None) –

    Engineering units per channel.

  • channel_cal_factors (ndarray) –

    Per-channel multipliers from volts to engineering units; applied at display time.

  • id_link (UUID) –

    unique_id of the source TimeData.

  • unique_id (UUID) –

    This item's own identity, minted at construction. It is what makes a pull → modify → push round trip through :class:pydvma.session.Session REPLACE this result in place instead of appending a second copy beside it. Optional in the container: a file written before derived items carried ids restores without the attribute.

  • test_name (str or None) –

    Free-form label.

  • timestamp (datetime) –

    When this FreqData was constructed.

  • timestring (str) –

    Filesystem-safe rendering of timestamp.

  • source_signature (str) –

    OPTIONAL, set post-construction by analysis.calculate_fft — a 16-hex-character hash of the SOURCE samples and rate (pydvma._signature), so a loaded file can tell an intact compute chain from one whose time data changed after the compute. Genuinely optional (needs a hasattr guard): items written before signatures existed make no claim about their chain.

  • source_settings (dict) –

    OPTIONAL, set alongside source_signature — the analysis knobs that call used, as JSON-safe scalars, so the result is self-describing. A settings change does NOT invalidate a stored result; only a source-sample change does.

Attributes

freq_axis instance-attribute
freq_axis = freq_axis
freq_data instance-attribute
freq_data = freq_data
settings instance-attribute
settings = settings
test_name instance-attribute
test_name = test_name
units instance-attribute
units = units
channel_cal_factors instance-attribute
channel_cal_factors = channel_cal_factors
id_link = id_link
timestamp instance-attribute
timestamp = t
timestring instance-attribute
timestring = '_' + str(t.year) + '_' + str(t.month) + '_' + str(t.day) + '_at_' + str(t.hour) + '_' + str(t.minute) + '_' + str(t.second)
unique_id instance-attribute
unique_id = uuid.uuid4()

Methods:

__init__
__init__(freq_axis, freq_data, settings, units=None, channel_cal_factors=None, id_link=None, test_name=None)
__repr__
__repr__()

FreqDataList

Bases: list

Methods:

get_calibration_factors
get_calibration_factors()
set_calibration_factors_all
set_calibration_factors_all(factors)
set_calibration_factor
set_calibration_factor(factor, n_set=0, n_chan=0)
export_to_csv
export_to_csv(filename=None, overwrite_without_prompt=False)

Transfer Function Data

TfData

Transfer function H(f) from one input channel to one or more outputs.

Produced by analysis.calculate_tf (single TimeData), analysis.calculate_tf_averaged (ensemble TimeDataList) or analysis.calculate_bla (a best-linear-approximation run). For the first two the convention is Pxy[in, out] / Pxy[in, in] per output channel and tf_coherence carries the corresponding coherence.

BLA sets are different: no cross-spectrum estimator is involved at all — the FRF comes from inverting the excitation matrix at each excited bin — so the Pxy convention does not describe them, tf_coherence is None (the bla_sigma_* pair is the quality measure instead), settings.ch_in may be None (commanded-drive mode has no measured input channel), and freq_axis holds only the excited bins rather than a full rfft grid. bla is non-None exactly on those sets.

Calibration: channel_cal_factors[k] holds the ratio cal[out_k] / cal[in] — i.e. multiplying tf_data[:, k] * channel_cal_factors[k] at display time gives the TF in engineering units. Units are constructed as "<out_unit>/<in_unit>" per output channel.

Attributes:

  • freq_axis (ndarray) –

    One-sided frequency bins in Hz.

  • tf_data (ndarray) –

    Shape (n_freq, n_outputs), complex. One column per non-input channel.

  • tf_coherence (ndarray) –

    Same shape, real, in [0, 1].

  • settings (MySettings) –

    Snapshot including the chosen ch_in and the derived ch_out_set (the channel indices in tf_data's second axis).

  • units (list[str] or None) –

    Per-output-channel unit strings (e.g. ['m/s/N', 'g/N']).

  • channel_cal_factors (ndarray) –

    Per-output cal ratios (cal[out] / cal[in]). A manual override here overwrites the inherited ratio.

  • id_link

    unique_id of the source TimeData (or list when averaged).

  • unique_id (UUID) –

    This item's own identity, minted at construction — see FreqData.unique_id for why a derived item needs one.

  • test_name (str or None) –

    Free-form label.

  • timestamp (datetime) –

    When constructed.

  • timestring (str) –

    Filesystem-safe rendering of timestamp.

  • flag_modal_TF (bool) –

    True after a modal fit has consumed this TfData (avoids double-fitting); used by modal.py.

  • bla_sigma_nl (ndarray or None) –

    Nonlinear-distortion standard deviation, shape (n_freq, n_outputs), real, in the same linear units as abs(tf_data) — a std, not a variance, so it goes straight onto a dB axis with no further square root. PER-REALISATION: it is the distortion level of one realisation, not the error bar on tf_data, which is sqrt(M) smaller. Set by analysis.calculate_bla; None on an ordinary transfer function.

  • bla_sigma_n (ndarray or None) –

    Measurement-noise standard deviation, same shape, units and per-realisation reading as bla_sigma_nl. Set by analysis.calculate_bla; None on an ordinary transfer function.

  • bla (dict or None) –

    The BLA run spec that produced this estimate (multisine design, x-mode, channel roles, capture fs, excited bins and which excitation q this TfData belongs to). JSON-clean scalars only, so it round-trips through the .dvma manifest. None on an ordinary transfer function.

  • source_signature (str) –

    OPTIONAL, set post-construction by analysis.calculate_tf / analysis.calculate_tf_averaged — a 16-hex-character hash of the SOURCE samples and rate (pydvma._signature; for an ensemble, every source in list order), so a loaded file can tell an intact compute chain from one whose time data changed after the compute. Genuinely optional (needs a hasattr guard): items written before signatures existed, and BLA estimates, carry no signature and make no claim about their chain.

  • source_settings (dict) –

    OPTIONAL, set alongside source_signature — the analysis knobs that call used, as JSON-safe scalars, so the result is self-describing. A settings change does NOT invalidate a stored result; only a source-sample change does.

All three BLA attributes are set in __init__ and are declared container fields, so they survive a .dvma round trip as None or as their value — no hasattr guard needed, unlike the genuinely optional iw_power_counter.

Attributes

freq_axis instance-attribute
freq_axis = freq_axis
tf_data instance-attribute
tf_data = tf_data
tf_coherence instance-attribute
tf_coherence = tf_coherence
settings instance-attribute
settings = settings
test_name instance-attribute
test_name = test_name
units instance-attribute
units = units
channel_cal_factors instance-attribute
channel_cal_factors = channel_cal_factors
id_link = id_link
timestamp instance-attribute
timestamp = t
timestring instance-attribute
timestring = '_' + str(t.year) + '_' + str(t.month) + '_' + str(t.day) + '_at_' + str(t.hour) + '_' + str(t.minute) + '_' + str(t.second)
flag_modal_TF instance-attribute
flag_modal_TF = False
bla_sigma_nl instance-attribute
bla_sigma_nl = None
bla_sigma_n instance-attribute
bla_sigma_n = None
bla instance-attribute
bla = None
unique_id instance-attribute
unique_id = uuid.uuid4()

Methods:

__init__
__init__(freq_axis, tf_data, tf_coherence, settings, units=None, channel_cal_factors=None, id_link=None, test_name=None)
__repr__
__repr__()

TfDataList

Bases: list

Methods:

get_calibration_factors
get_calibration_factors()
set_calibration_factors_all
set_calibration_factors_all(factors)
set_calibration_factor
set_calibration_factor(factor, n_set=0, n_chan=0)
add_modal_reconstruction
add_modal_reconstruction(tf_data, mode='replace')
export_to_csv
export_to_csv(filename=None, overwrite_without_prompt=False)

Sonogram Data

SonoData

Short-time-FFT spectrogram (sonogram) of a multi-channel TimeData.

Produced by analysis.calculate_sonogram. Each frame is a windowed FFT of a nperseg-sample segment of the source data; segments are overlapped by noverlap and the resulting matrix lets you see how spectral content evolves over time. analysis.calculate_cwt produces the same object from a Morlet wavelet transform instead. Used by analysis.calculate_damping_from_sono to extract per-mode damping from free-decay measurements.

Also produced by the WEB APP, when a Save is told to include the sonogram. Such an item differs in one way a reader must know about: its third axis holds only the channels the user chose to save, in the order they were saved, NOT every channel of the source. So sono_data[:, :, k], units[k] and channel_cal_factors[k] are all indexed by PLANE, and the source channel each plane came from is recorded in source_settings['channels'][k]. A single-channel save is the common case (it is the default the prompt offers), and then sono_data.shape[2] == 1 however many channels the measurement has.

Attributes:

  • time_axis (ndarray) –

    Frame midpoints in seconds.

  • freq_axis (ndarray) –

    One-sided frequency bins in Hz.

  • sono_data (ndarray) –

    Shape (n_freq, n_frames, n_channels), complex. Magnitude-squared gives a per-bin power spectrogram. For an app-written item the last axis is the SAVED channel subset — see above.

  • settings (MySettings) –

    Snapshot including pretrig_samples (used by calculate_damping_from_sono to pick the free-decay start time).

  • units (list[str] or None) –

    Engineering units, one per PLANE of sono_data.

  • channel_cal_factors (ndarray) –

    Multipliers from volts to engineering units, one per PLANE of sono_data.

  • id_link

    unique_id of the source TimeData.

  • unique_id (UUID) –

    This item's own identity, minted at construction — see FreqData.unique_id for why a derived item needs one.

  • test_name (str or None) –

    Free-form label.

  • timestamp (datetime) –

    When constructed.

  • timestring (str) –

    Filesystem-safe rendering of timestamp.

Attributes

time_axis instance-attribute
time_axis = time_axis
freq_axis instance-attribute
freq_axis = freq_axis
sono_data instance-attribute
sono_data = sono_data
settings instance-attribute
settings = settings
test_name instance-attribute
test_name = test_name
units instance-attribute
units = units
channel_cal_factors instance-attribute
channel_cal_factors = channel_cal_factors
id_link = id_link
timestamp instance-attribute
timestamp = t
timestring instance-attribute
timestring = '_' + str(t.year) + '_' + str(t.month) + '_' + str(t.day) + '_at_' + str(t.hour) + '_' + str(t.minute) + '_' + str(t.second)
unique_id instance-attribute
unique_id = uuid.uuid4()

Methods:

__init__
__init__(time_axis, freq_axis, sono_data, settings, units=None, channel_cal_factors=None, id_link=None, test_name=None)
__repr__
__repr__()

SonoDataList

Bases: list

Cross-Spectrum Data

CrossSpecData

Full cross-spectrum matrix Pxy[i,j,f] and coherence matrix Cxy[i,j,f].

Produced by analysis.calculate_cross_spectrum_matrix (single TimeData) or analysis.calculate_cross_spectra_averaged (ensemble TimeDataList). The diagonal Pxy[i, i, :] is the per-channel auto-spectrum (= scipy.signal.welch with scaling='spectrum'); off-diagonal Pxy[i, j, :] matches scipy.signal.csd with the same settings. Pxy is Hermitian — Pxy[j, i, :] = conj(Pxy[i, j, :]).

Attributes:

  • freq_axis (ndarray) –

    One-sided frequency bins in Hz.

  • Pxy (ndarray) –

    Shape (n_channels, n_channels, n_freq), complex. Cross-spectrum matrix.

  • Cxy (ndarray) –

    Same shape, real, in [0, 1]. Coherence matrix.

  • settings (MySettings) –

    Includes window, time_range, N_frames, overlap actually used.

  • units (list[str] or None) –

    Engineering units per channel.

  • channel_cal_factors (ndarray) –

    Per-channel multipliers from volts to engineering units.

  • id_link

    unique_id of the source TimeData (or list of ids when averaged across a TimeDataList).

  • unique_id (UUID) –

    This item's own identity, minted at construction — see FreqData.unique_id for why a derived item needs one.

  • test_name (str or None) –

    Free-form label.

  • timestamp (datetime) –

    When constructed.

  • timestring (str) –

    Filesystem-safe rendering of timestamp.

Attributes

freq_axis instance-attribute
freq_axis = freq_axis
Pxy instance-attribute
Pxy = Pxy
Cxy instance-attribute
Cxy = Cxy
settings instance-attribute
settings = settings
test_name instance-attribute
test_name = test_name
units instance-attribute
units = units
channel_cal_factors instance-attribute
channel_cal_factors = channel_cal_factors
id_link = id_link
timestamp instance-attribute
timestamp = t
timestring instance-attribute
timestring = '_' + str(t.year) + '_' + str(t.month) + '_' + str(t.day) + '_at_' + str(t.hour) + '_' + str(t.minute) + '_' + str(t.second)
unique_id instance-attribute
unique_id = uuid.uuid4()

Methods:

__init__
__init__(freq_axis, Pxy, Cxy, settings, units=None, channel_cal_factors=None, id_link=None, test_name=None)
__repr__
__repr__()

CrossSpecDataList

Bases: list

ModalData

A set of fitted modes — each row of M is one mode's (fn, zn, an[chan...], pn[chan...], rk[chan...], rm[chan...]) parameter vector as produced by modal.modal_fit_all_channels.

Use add_mode to append further modes (e.g. across separate frequency-band fits); rows are kept sorted by fn. After any add/delete, the summary arrays fn, zn, an, pn are refreshed and indexable per mode.

Attributes:

  • M (ndarray) –

    Shape (n_modes, 2 + 4*n_channels). Each row packs [fn, zn, an_0..an_C, pn_0..pn_C, rk_0..rk_C, rm_0..rm_C].

  • fn (ndarray) –

    Per-mode natural frequencies in Hz.

  • zn (ndarray) –

    Per-mode damping ratios.

  • an (ndarray) –

    Shape (n_modes, n_channels) modal-constant amplitudes.

  • pn (ndarray) –

    Same shape; modal-constant phases in radians.

  • channels (int) –

    Number of channels (= n_channels above).

  • settings (MySettings) –

    Snapshot including the source TF's settings.

  • units

    Engineering units (passed through from source).

  • id_link

    unique_id(s) of the TFs that produced these modes.

  • unique_id (UUID) –

    This item's own identity, minted at construction — see FreqData.unique_id. Modal fits are pushed back from notebooks like any other item, and without an id every push would append another copy of the fit.

  • test_name (str or None) –

    Free-form label.

Attributes

M instance-attribute
M = []
test_name instance-attribute
test_name = test_name
settings instance-attribute
settings = copy.copy(settings) if settings is not None else None
channels instance-attribute
channels = 0
units instance-attribute
units = units
id_link = id_link
timestamp instance-attribute
timestamp = t
timestring instance-attribute
timestring = '_' + str(t.year) + '_' + str(t.month) + '_' + str(t.day) + '_at_' + str(t.hour) + '_' + str(t.minute) + '_' + str(t.second)
unique_id instance-attribute
unique_id = uuid.uuid4()

Methods:

__init__
__init__(xn=None, settings=None, units=None, id_link=None, test_name=None)
add_mode
add_mode(xn)

Appends one mode (a packed parameter row as per 'x' in modal.py: [fn, zn, an x N, pn x N, rk x N, rm x N]) to the modal matrix, keeping rows sorted by natural frequency and refreshing the unpacked summary properties (fn, zn, an, pn).

delete_mode
delete_mode(mode_number)

Deletes one or more modes (rows) from the modal matrix by index and refreshes the unpacked summary properties (fn, zn, an, pn).

Deleting the LAST remaining mode is valid: the matrix becomes an empty (0, 2+4*channels) and the summaries become zero-length (fn/zn) / (0, channels) (an/pn). This no longer raises the IndexError that modal.unpack_matrix used to throw on an emptied matrix (the round-4 "Fit -> Reject" crash, and the same latent crash on Qt's Reject). channels is preserved — it is encoded in the column count, not the number of mode rows.

__repr__
__repr__()

ModalDataList

Bases: list

Metadata

MetaData

Dataset-level units and calibration, kept for legacy datasets.

Attributes:

  • units

    Engineering units.

  • channel_cal_factors

    Per-channel multipliers (legacy; always None here — calibration lives on each data item instead).

  • tf_cal_factors

    Per-TF multipliers (legacy; always None here).

  • timestamp (datetime) –

    When this MetaData was built.

  • timestring (str) –

    Filesystem-safe rendering of timestamp.

  • unique_id (UUID) –

    This item's own identity, minted at construction — see FreqData.unique_id.

Attributes

units instance-attribute
units = units
channel_cal_factors instance-attribute
channel_cal_factors = None
tf_cal_factors instance-attribute
tf_cal_factors = None
timestamp instance-attribute
timestamp = t
timestring instance-attribute
timestring = '_' + str(t.year) + '_' + str(t.month) + '_' + str(t.day) + '_at_' + str(t.hour) + '_' + str(t.minute) + '_' + str(t.second)
unique_id instance-attribute
unique_id = uuid.uuid4()

Methods:

__init__
__init__(units=None, channel_cal_factors=None, tf_cal_factors=None, test_name=None)
__repr__
__repr__()

MetaDataList

Bases: list