DataObjects.SecSaxsData#

DataObjects.SecSacsData.py

class SecSaxsData(folder=None, object_list=None, uv_only=False, xr_only=False, trimmed=False, trimming=None, remove_bubbles=False, beamline_info=None, mapping=None, time_initialized=None, datafiles=None, uv_pickat=None, uv_monitor=None, xr_pickat=None, debug=False)#

Bases: object

A class to represent a SEC-SAXS data object. It contains a pair of XrData and UvData objects. It also contains the beamline information and mapping information if available.

xr#

The XR data object.

Type:

XrData or None

uv#

The UV data object.

Type:

UvData or None

trimmed#

Indicates whether the data has been trimmed. This attribute is used to avoid minor redundant trimming operations which may cause inconsistency from the algorithmic reasons.

Type:

bool

mapping#

The mapping information between XR and UV data.

Type:

MappingInfo or None

beamline_info#

The beamline information.

Type:

BeamlineInfo or None

time_initialized#

The time when the object was initialized.

Type:

float

time_required#

The time required for processing the data.

Type:

float

time_required_total#

The total time required for processing all data. This includes the time required for processing the data

Type:

float

datafiles#

The list of data files used for the analysis.

Type:

list of str or None

logger#

The logger object for logging messages.

Type:

logging.Logger

ssd = SecSacsData(data_folder)

Creates a SEC-SAXS data object.

Parameters:
  • folder (str, optional) – Specifies the folder path where the data are stored. It is required if the data_list parameter is ommitted.

  • object_list (list, optional) – A list which includes [xr_data, uv_data] in this order to be used as corresponding data items. It is required if the folder parameter is ommitted.

  • uv_only (bool, optional) – If it is True, only UV data will be loaded to suppress unnecessary data access.

  • xr_only (bool, optional) – If it is True, only XR data will be loaded to suppress unnecessary data access.

  • trimmed (bool, optional) – If it is True, the data will be treated as trimmed.

  • remove_bubbles (bool, optional) – If it is True, bubbles will be removed from the data.

  • beamline_info (BeamlineInfo, optional) – If specified, the beamline information will be used.

  • mapping (MappingInfo, optional) – If specified, the mapping information will be used.

  • time_initialized (float, optional) – If specified, the time when the object was initialized. If it is None, the time will be set to the time taken for initialization.

  • datafiles (list of str, optional) – If specified, the list of data files used for the analysis. If it is None, the data files will be set to the list of files loaded from the folder.

  • uv_pickat (float, optional) – The wavelength (nm) at which to extract the UV elution profile. Defaults to 280 nm when None. Use 290 for samples like ATP or MY where the UV signal is measured at 290 nm.

  • uv_monitor (float, optional) – Alias for uv_pickat. Follows chromatography convention (“monitoring wavelength”). If both are given, uv_monitor wins.

  • xr_pickat (float, optional) – The q-value (Å⁻¹) at which to extract the XR elution profile. Defaults to 0.02 when None.

  • debug (bool, optional) – If True, enables debug mode for more verbose output.

Examples

>>> ssd = SecSacsData('the_data_folder')
>>> uv_only_ssd = SecSacsData('the_data_folder', uv_only=True)
has_xr()#

Returns whether the XR data is available.

Parameters:

None

Returns:

has_xr – True if the XR data is available, False otherwise.

Return type:

bool

has_uv()#

Returns whether the UV data is available.

Parameters:

None

Returns:

has_uv – True if the UV data is available, False otherwise.

Return type:

bool

plot_3d(title=None, view_init=None, view_arrows=False, with_2d_section_lines=False, **kwargs)#

Plots a pair of 3D figures of UV and XR data.

Parameters:
  • title (str, optional) – If specified, add a super title to the plot.

  • view_init (dict, optional) – A dictionary which specifies the view_init parameters. The default is dict(elev=30, azim=-60) as of matplotlib 3.10.

  • view_arrows (bool, optional) – If it is True, the 2D view arrows are drawn on the 3D plot. One of the arrows shows the elutional view, while the other shows the spectral view. The default is False.

  • with_2d_section_lines (bool, optional) – If it is True, the 2D section lines are drawn on the 3D plot. The default is False.

Returns:

result – A PlotResult object which contains the following attributes.

fig: Figure axes: Axes

Return type:

PlotResult

plot_compact(title=None, baseline=False, ratio_curve=None, moment_lines=False, align_zero=False, **kwargs)#

Plots a pair of compact figures of UV and XR data.

Parameters:
  • title (str, optional) – If specified, add a super title to the plot.

  • baseline (bool, optional) – If it is True, the baseline will be plotted.

  • ratio_curve (Curve, optional) – If specified, the ratio curve will be plotted.

  • moment_lines (bool, optional) – If it is True, the moment lines will be plotted.

  • align_zero (bool, optional) – If True, align the zero positions of the UV (twinx) and XR axes. Default is False so each trace is autoscaled independently and fills its own panel — preventing the smaller-amplitude trace from appearing near-flat (issue #120).

Returns:

result – A PlotResult object which contains the following attributes.

fig: Figure axes: Axes mapping: MappingInfo (if available) xr_curve: Curve (if available) uv_curve: Curve (if available) mp_curve: Curve (if available) moment: Moment of the XR data (if available)

Return type:

PlotResult

make_trimming(xr_qr=None, xr_mt=None, uv_wr=None, uv_mt=None)#

Returns a pair of indeces which should be used as slices for the spectral axis and the temporal axis to trim the data.

Parameters:
  • xr_qr (tuple of (int, int), optional) – The angular range (start, stop) to be used for the XR data. If it is None, the full range will be used.

  • xr_mt (tuple of (int, int), optional) – The temporal range (start, stop) to be used for the XR data. If it is None, the full range will be used.

  • uv_wr (tuple of (int, int), optional) – The wavelength range to be used for the UV data. If it is None, the full range will be used.

  • uv_mt (tuple of (int, int), optional) – The temporal range (start, stop) to be used for the UV data. If it is None, the full range will be used.

Returns:

trimming – A TrimmingInfo object which contains the trimming information.

Return type:

TrimmingInfo

See also

ssd.copy

Examples

>>> trim = ssd.make_trimming()
plot_trimming(trim=None, baseline=False, title=None, return_fig=False, **kwargs)#

Plots a set of trimming info.

Parameters:
  • trim (TrimmingInfo or dict, optional) – The trimming information to be used for the plot.

  • baseline (bool, optional) – If it is True, the baseline will be plotted.

  • title (str, optional) – If specified, add a super title to the plot.

  • return_fig (bool, optional) – If it is True, returns the figure object.

Returns:

result – A PlotResult object which contains the following attributes.

fig: Figure axes: Axes trimming : TrimmingInfo

Return type:

PlotResult

copy(xr_slices=None, uv_slices=None)#

Returns a deep copy of this object.

Parameters:
  • xr_slices ((xr_islice, xr_jslice), optional.) – If specified, the returned copy contains the deep copies of elements xrM[xr_islice:xr_jslice] and qv[xr_islice]. Otherwise, the returned copy contains the deep copies of elements xrM and qv.

  • uv_slices ((uv_islice, uv_jslice), optional.) – If specified, the returned copy contains the deep copies of elements uvM[uv_islice:uv_jslice] and wv[uv_islice]. Otherwise, the returned copy contains the deep copies of elements uvM and wv.

Returns:

A deep copy of the SSD object with the specified slices applied.

Return type:

SecSaxsData

Examples

>>> copied_ssd = ssd.copy()
>>> trimming = ssd.make_trimming()
>>> trimmed_ssd = ssd.copy(xr_slices=trimming.xr_slices, uv_slices=trimming.uv_slices)
trimmed_copy(trimming=None, jranges=None, mapping=None, nsigmas=None, uv_wavelength=None)#
Parameters:
  • trimming (TrimmingInfo, optional) – If specified, the trimming information will be used for the copy.

  • jranges (tuple of (double, double), optional) – The temporal ranges to apply for trimming in the form of [(start1, end1), (start2, end2)].

  • mapping (MappingInfo, optional) – If specified, the mapping information will be used for the copy. It must be provided if jranges is specified.

  • nsigmas (int or float, optional) – If specified, passed to make_trimming() to control the σ-window width.

  • uv_wavelength (tuple of (float or None, float or None), optional) – UV wavelength range in nm to include, as (wl_min, wl_max). Use None for either end to keep the dataset default (None on the min side uses the instrument’s usable wavelength start, typically ~250 nm; None on the max side uses the full upper end). Example: uv_wavelength=(None, 550) trims UV to ≤ 550 nm.

Returns:

A trimmed copy of the SSD object with the specified trimming specification applied.

Return type:

SecSaxsData

set_baseline_method(method)#

Sets the baseline method to be used for the baseline correction.

See also: Baseline Correction

Parameters:

method (str or (str, str)) –

Specifies the baseline method to be used. If it is a string, it will be used for both XR and UV data. If it is a tuple of two strings, the first string will be used for XR data and the second string will be used for UV data.

The available methods are:

  • linear : Linear baseline (default)

  • uvdiff : UV differential method (for UV data only)

  • integral : Integral method

Return type:

None

get_baseline_method()#

Returns the baseline method used for the baseline correction.

See also: Baseline Correction

Parameters:

None

Returns:

method – A tuple of two strings which contains the baseline methods used for XR and UV data. If the baseline method is the same for both XR and UV data, it returns a single string instead of a tuple.

Return type:

(str, str)

set_anomaly_mask(mask=None)#

Declare that this dataset contains anomalous frames to exclude.

Delegates to self.xr.set_anomaly_mask() (and self.uv if present). See SsMatrixData.set_anomaly_mask() for full documentation.

When mask is None (the default), this method first tries detect_anomaly() on the pre-correction recognition curve. If a region is found, it is used as an explicit mask (equivalent to passing it directly). If nothing is found, the mask is stored as None and detection is deferred to corrected_copy(), which checks the post-correction recognition curve instead — with a UserWarning so the caller is aware.

Effect on downstream steps:

  • corrected_copy() — excluded frames are linearly interpolated in the XR data matrix (and the corresponding UV frames via the XR↔UV mapping), then excluded from the LPM baseline anchor pool. The interpolated data is what the corrected SSD carries.

  • optimize_rigorously() — when trimmed_ssd is provided (Pattern B), the trimmed data is interpolated in the same way before the optimizer sees it. The optimizer therefore never evaluates the objective on anomaly frames; the smooth bridge values are fitted instead. The MplMonitor dashboard marks these regions with translucent bands so the interpolated section is visually distinguishable from real data.

Note

For mild anomalies, prefer allow_negative_peaks=True in quick_decomposition() instead. This method excludes frames from the data matrix and can be too aggressive for some datasets. Use ssd.xr.get_icurve() after calling this to verify the signal is not destroyed.

Parameters:

mask (array-like of bool, slice, or None, optional) – Frames to exclude. When a slice is given, start/stop are interpreted as frame numbers. When None, auto-detection via detect_anomaly() is attempted first.

Returns:

The detected anomaly slice when auto-detection was used, or mask when an explicit mask was supplied, or None.

Return type:

slice or None

See also

SsMatrixData.detect_anomaly

Pre-correction anomaly detection algorithm.

set_allow_negative_peaks(value=True, mask=None)#

Deprecated: use set_anomaly_mask(mask) instead.

corrected_copy()#

Returns a deep copy of this object which has been corrected subtracting the baseline from the original data.

Parameters:
  • baseline (ndarray or None, optional) – Pre-computed 2D baseline array for XR data (same shape as ssd.xr.M). When provided, this baseline is used directly instead of computing one via get_baseline2d(). Note: applies to XR only — the UV baseline is always computed internally.

  • debug (bool, optional) – If True, enables debug mode for more verbose output.

  • **baseline_kwargs – Additional keyword arguments forwarded to get_baseline2d() for both XR and UV.

Returns:

A deep copy of the SSD object with the baseline correction applied.

Return type:

SecSaxsData

Examples

>>> corrected = ssd.corrected_copy()                          # standard LPM
>>> ssd.set_anomaly_mask()                                    # for negative-peak datasets
>>> corrected = ssd.corrected_copy()                          # LPM with negative frames masked
>>> corrected = ssd.corrected_copy(baseline=my_baseline)      # pre-computed XR baseline
estimate_mapping()#

Estimates the mapping information between UV and XR data. :param debug: If True, enables debug mode for more verbose output. :type debug: bool, optional

Returns:

mapping – A MappingInfo object which contains the mapping information. If the mapping information is not available, returns None.

Return type:

MappingInfo

get_mapping()#

Returns the mapping information object.

Parameters:

None

Returns:

mapping – A MappingInfo object which contains the mapping information. If the mapping information is not available, returns None.

Return type:

MappingInfo

get_concfactor()#

Returns the concentration factor from the beamline information.

Parameters:

None

Returns:

concfactor – The concentration factor from the beamline information. If the beamline information is not available, returns None.

Return type:

float or None

classmethod from_legacy_sd(sd, include_uv=False)#

Construct an SSD from a legacy SerialData (sd) object.

This is the Phase 1 bridge for the SD → SSD migration. Once an SSD is built from sd, the full library pipeline is available:

ssd_raw = SecSaxsData.from_legacy_sd(sd) ssd_trimmed = ssd_raw.trimmed_copy() # applies library q-trimming ssd_corrected = ssd_trimmed.corrected_copy() rg = ssd_corrected.get_rg_curve() # library-quality rg_curve

Parameters:
  • sd (SerialData) – Legacy data object. sd.xray_array must be of shape (n_q, n_frames, 3) where the last axis holds [q, I, E].

  • include_uv (bool) – Not yet implemented — reserved for Phase 3. Ignored for now.

Return type:

SecSaxsData (untrimmed, uncorrected — same state as loading from folder)

classmethod from_arrays(xr_M, xr_qv, xr_E, xr_jv=None, uv_M=None, uv_wv=None, uv_E=None, uv_jv=None, trimmed=False)#

Construct an SSD directly from numpy arrays, without reading from disk.

This is the array-level entry point for the SD → SSD migration path. The primary use case is reconstructing an SSD from the ip_*.npy files exported by BackRunner or prepare_rigorous_folders, so that the full library pipeline (baseline correction, rg_curve) can be applied to GUI data without re-reading the raw data files.

Parameters:
  • xr_M (ndarray of shape (n_q, n_frames)) – XR intensity matrix (corrected or uncorrected).

  • xr_qv (ndarray of shape (n_q,)) – q-values in Å⁻¹.

  • xr_E (ndarray of shape (n_q, n_frames)) – XR error matrix.

  • xr_jv (ndarray of shape (n_frames,) or None) – Original frame numbers. If None, defaults to np.arange(n_frames).

  • uv_M (ndarray or None) – UV absorbance matrix. If None, SSD is XR-only.

  • uv_wv (ndarray or None) – UV wavelengths (nm).

  • uv_E (ndarray or None) – UV error matrix (rarely used).

  • uv_jv (ndarray or None) – UV frame numbers.

  • trimmed (bool) – Whether this data is already trimmed (sets ssd.trimmed).

Return type:

SecSaxsData

Examples

Reconstruct from GUI ip_*.npy files:

import numpy as np
D   = np.load('ip_xr_D.npy')
qv  = np.load('ip_xr_qvector.npy')
E   = np.load('ip_xr_E.npy')
jv  = np.load('ip_xr_jv.npy')          # optional
ssd = SecSaxsData.from_arrays(D, qv, E, xr_jv=jv, trimmed=True)
rg  = ssd.compute_rgcurve()             # skip baseline: data already corrected
get_rg_curve(progress_cb=None)#

Compute the per-frame Rg curve from the corrected XR data, with caching.

Runs a Guinier fit on every elution frame independently and returns the results as an RgCurve object. The result is cached on this instance, so repeated calls are free.

This is the recommended entry point for obtaining the Rg curve before decomposition. Pass the returned object to quick_decomposition() and optimize_rigorously() to avoid redundant recomputation:

rgcurve = corrected.get_rg_curve()            # computed once, cached
decomp   = corrected.quick_decomposition(rgcurve=rgcurve)
run      = decomp.optimize_rigorously(rgcurve=rgcurve, ...)
Parameters:

progress_cb (callable or None, optional) – Optional callback (rg_buffer, j) called after each frame. rg_buffer is a float array of accumulated Rg values (0 for not-yet-computed frames); j is the 0-based column index. The signature is compatible with the legacy ProgressCallback so GUI callers can drive a progress bar and live Rg overlay. Ignored if the result is already cached.

Returns:

rgcurve – An RgCurve with attributes:

  • .x — frame indices (integer array)

  • .y — Rg values in Å; NaN where Guinier fit failed

  • .scores — Guinier fit quality scores (0–1)

Return type:

molass.Guinier.RgCurve.RgCurve

See also

XrData.compute_rgcurve

underlying computation (no caching)

Decomposition.get_rg_curve

same pattern on a Decomposition object

recommend_decomposition_options(egh_overlap_threshold=1.3)#

Recommend keyword arguments for quick_decomposition() by detecting peaks.

Uses EGH peeling to identify elution components robustly. Consecutive EGH peaks whose spacing/sigma_sum ratio falls below egh_overlap_threshold are merged into a single component.

Example:

opts = corrected.recommend_decomposition_options()
# → {'num_components': 2, 'xr_peakpositions': [145, 220]}
# or → {'num_components': 3, 'proportions': [1, 1, 1]}
opts['num_components'] = 3    # easy override
decomp = corrected.quick_decomposition(**opts)
Parameters:

egh_overlap_threshold (float, optional) – EGH peak pairs with spacing/sigma_sum below this value are merged into one component. Default 1.3.

Returns:

Keyword arguments for quick_decomposition().

Return type:

dict

See also

recommend_decomposition

convenience wrapper that calls this method and then quick_decomposition(**opts).

recommend_decomposition(**kwargs)#

Automatically detect peaks and return a decomposition.

Combines recommend_decomposition_options() with quick_decomposition(). Any keyword argument overrides the automatic recommendation:

# One-liner — fully automatic:
decomp = corrected.recommend_decomposition()

# Override a single field while keeping the rest automatic:
decomp = corrected.recommend_decomposition(num_components=3)
Parameters:

**kwargs – Any keyword accepted by quick_decomposition(). These are merged after the automatic options, so they take priority.

Return type:

Decomposition

quick_decomposition(num_components=None, proportions=None, xr_peakpositions=None, ranks=None, num_plates=None, **kwargs)#

Performs a quick decomposition of the SEC-SAXS data.

See also: Nontrivial Decomposition

Three decomposition algorithms are available, selected by keyword:

  1. Default (no extra keywords) — greedy peak-recognition.

  2. Proportional (proportions) — area-ratio slicing.

  3. Positioned (xr_peakpositions) — peaks pinned to specified frame positions.

proportions and xr_peakpositions are mutually exclusive.

Parameters:
  • num_components (int, optional) – Specifies the number of components which also implies the SVD rank used to denoise the matrix data.

  • proportions (list of float, optional) –

    Specifies the approximate area ratios of the elution peaks. The values do not need to be normalized; for example, [1, 1], [0.5, 0.5], and [3, 3] all produce the same result because they are normalized internally.

    When this option is given, a proportional decomposition algorithm is used instead of the default peak-recognition algorithm. The proportional algorithm divides the total elution curve by cumulative area according to the given ratios, and fits an EGH model to each slice independently. This provides better initialization for cases with highly overlapping peaks, where the default algorithm may produce unstable results.

    The exact ratios do not need to be known precisely; even a rough estimate (e.g., [2, 1] when the true ratio is [1, 1]) is usually sufficient.

  • xr_peakpositions (list of float, optional) –

    Specifies the frame positions where peaks should be pinned. Uses a penalty-based optimizer (Nelder-Mead) that fits EGH peaks with a strong position constraint. num_components is inferred from the length if not provided.

    Mutually exclusive with proportions.

  • ranks (list of int, optional) – Specifies the ranks to be used for XR data.

  • num_plates (int, optional) – Specifies the number of theoretical plates to be used for the optimization constraint.

  • tau_limit (float, optional) – Maximum allowed ratio |tau| / sigma for positioned decomposition. Default 0.6.

  • max_sigma (float, optional) – Maximum allowed Gaussian width (sigma) for positioned decomposition. Default 80.

  • min_sigma (float, optional) – Minimum allowed Gaussian width (sigma) for positioned decomposition. Default 5.

  • allow_negative_peaks (bool, optional) – If True, allow negative peak heights (H < 0) in the EGH model. This enables decomposition of components with negative scattering, such as those arising from buffer composition mismatch. Default False.

  • debug (bool, optional) – If True, reload internal modules and show diagnostic plots. Default False.

Returns:

decomposition – A Decomposition object which contains the decomposition result.

Return type:

Decomposition

rigorous_decomposition(num_components=None, proportions=None, ranks=None, num_plates=None, **kwargs)#

Performs a rigorous decomposition of the SEC-SAXS data.

Parameters:
  • num_components (int, optional) – Specifies the number of components which also implies the SVD rank used to denoise the matrix data.

  • proportions (list of float, optional) – Specifies the proportions to be used for XR data.

  • ranks (list of int, optional) – Specifies the ranks to be used for XR data.

  • num_plates (int, optional) – Specifies the number of theoretical plates to be used for the optimization constraint.

Returns:

decomposition – A Decomposition object which contains the decomposition result.

Return type:

Decomposition

inspect_ip_effect()#

Inspects the inter-particle effect of the SEC-SAXS data.

Parameters:

debug (bool, optional) – If True, enables debug mode for more verbose output.

Returns:

ip_effect_info – An IpEffectInfo object which contains the inspection result.

Return type:

IpEffectInfo

get_uv_device_id()#

Returns the UV device ID from the beamline information.

Parameters:

None

Returns:

uv_device_id – The UV device ID from the beamline information. If the beamline information is not available, returns None.

Return type:

str or None

get_beamline_name()#

Returns the beamline name from the beamline information.

Parameters:

None

Returns:

beamline_name – The beamline name from the beamline information. If the beamline information is not available, returns None.

Return type:

str or None

get_data_info()#

Returns a machine-readable summary of the dataset characteristics. Useful for automated diagnostics: an AI agent can call this to understand the data without reading plots.

Returns:

info – A namedtuple with the following fields:

  • n_xr_frames (int or None): Number of XR frames

  • n_uv_frames (int or None): Number of UV frames

  • uv_peak_wavelength (float or None): Wavelength (nm) of max absorbance at the XR peak frame

  • uv_pickat (float or None): Current UV pickat setting (default 280 nm)

  • uv_monitor (float or None): Alias for uv_pickat (monitoring wavelength)

  • xr_peak_frame (int or None): Frame index of the XR elution peak

  • is_trimmed (bool): Whether the data has been trimmed

  • pickat_mismatch (bool): True if uv_peak_wavelength differs from uv_pickat by >5 nm

  • has_negative_xr_regions (bool): True if anomalous frames are detected (Tier 1: column-sum neg_depth > 3%, OR Tier 2: baseline self-test p < 0.01), indicating that set_anomaly_mask() should be called

  • negative_xr_fraction (float or None): Fraction of XR frames with negative recognition-curve values

  • baseline_selftest_p (float or None): p-value from the baseline self-test (Wilcoxon signed-rank). Low values (< 0.01) indicate buffer-frame contamination. None if XR data is absent.

Return type:

DataInfo (namedtuple)

Examples

>>> info = ssd.get_data_info()
>>> print(info)
>>> if info.pickat_mismatch:
...     print(f"Consider using uv_monitor={info.uv_peak_wavelength:.0f}")
>>> if info.has_negative_xr_regions:
...     print("Call ssd.set_anomaly_mask() before corrected_copy()")
export(folder, prefix=None, fmt='%.18e', xr_only=False, uv_only=Fals)#

Exports the data to a file.

Parameters:
  • folder (str) – Specifies the folder path where the data will be exported.

  • prefix (str, optional) – Specifies the filename prefix to be used for the exported data. If it is None, “PREFIX_” will be used.

  • fmt (str, optional) – Specifies the format to be used for the exported data. The default is ‘%.18e’.

  • xr_only (bool, optional) – If True, only export XR data.

  • uv_only (bool, optional) – If True, only export UV data.

Returns:

filepath – The full path of the exported file.

Return type:

str

plot_varied_decompositions(proportions, **kwargs)#

Plots a set of varied decompositions.

Parameters:
  • proportions (list of float) – A list of proportions to be used for the varied decompositions.

  • rgcurve (object, optional) – A reference to the RG curve to be used for the plot.

  • best (int, optional) – number of best results to be highlighted.

  • debug (bool, optional) – If True, enables debug mode.

Returns:

result – A PlotResult object which contains the following attributes.

fig: Figure axes: Axes

Return type:

PlotResult

get_spectral_vectors()#

Returns the spectral vectors for XR and UV data.

Parameters:

None

Returns:

spectral_vectors – A list of two numpy arrays which contain the spectral vectors for XR and UV data.

Return type:

list of np.ndarray