LowRank.Decomposition#
LowRank.LowRankInfo.py
This module contains the class LowRankInfo, which is used to store information about the components of a SecSaxsData, which is mathematically interpreted as a low rank approximation of a matrix.
- class Decomposition(ssd, xr_icurve, xr_ccurves, uv_icurve, uv_ccurves, mapped_curve=None, paired_ranges=None, **kwargs)#
Bases:
objectA class to store the result of decomposition which is a low rank approximation.
The result includes both components of X-ray and UV data and their associated information.
- ssd#
The SecSaxsData object from which the decomposition was performed.
- Type:
- xr_ranks#
The ranks for each component of the X-ray data. If None, default ranks are used.
- uv_ranks#
The ranks for each component of the UV data. If None, default ranks are used.
- mapping#
The mapping information between the X-ray and UV data.
- Type:
- mapped_curve#
The mapped curve from the X-ray to UV domain. If None, it can be computed when needed.
- Type:
MappedCurve or None
- paired_ranges#
The paired ranges for the X-ray and UV data. If None, it can be computed when needed.
- Type:
list of PairedRange or None
Initialize the Decomposition object.
- Parameters:
ssd (SecSaxsData) – The SecSaxsData object from which the decomposition was performed.
xr_icurve (Curve) – The i-curve used for the decomposition of the X-ray data.
xr_ccurves (list of Curve) – The component curves for the X-ray data.
uv_icurve (Curve) – The i-curve used for the decomposition of the UV data.
uv_ccurves (list of Curve) – The component curves for the UV data.
mapped_curve (MappedCurve, optional) – The mapped curve from the X-ray to UV domain. If None, it can be computed when needed.
paired_ranges (list of PairedRange, optional) – The paired ranges for the X-ray and UV data. If None, it can be computed when needed.
kwargs (dict, optional) – Additional keyword arguments (not used).
- copy_with_new_components(xr_ccurves, uv_ccurves, **kwargs)#
Create a new Decomposition with new component curves.
- Parameters:
- Returns:
A new Decomposition object with the specified component curves.
- Return type:
- property xr_components#
Alias for
xr_ccurves— the XR elution-curve parameter objects.Returns a list of
ComponentCurve(one per component). Each holds the EGH parameters[H, tR, sigma, tau]of the elution curve only — these objects do not carry per-component scattering profilesP[:, i]and cannot compute Rg.For per-component scattering profiles or Rg-capable objects, use:
get_xr_matrices()— returns(M, C, P, Pe)numpy arrays.get_xr_components()— returnsXrComponentobjects withget_guinier_object()andget_jcurve_array().
- property uv_components#
Alias for
uv_ccurves— the UV elution-curve parameter objects.Same caveat as
xr_components: these areComponentCurveinstances carrying only EGH elution parameters, not UV spectra. For per-component UV spectra, useget_uv_matrices().
- get_num_components()#
Get the number of components.
- Returns:
The number of components in the decomposition.
- Return type:
- get_guinier_objects(debug=False)#
Get the list of Guinier objects for the XR components.
- Returns:
The list of Guinier objects for each XR component.
- Return type:
list of Guinier
- get_rgs()#
Get the list of Rg values for the XR components.
- Returns:
rgs – Radius of gyration in Ångströms (Å) for each XR component, in the same order as
get_xr_components(). If Guinier fitting fails for a component,float('nan')is returned for that position (neverNone), so the result is always safe to use in numeric / numpy operations.Guard pattern:
import math for i, rg in enumerate(decomp.get_rgs()): if math.isnan(rg): print(f"Component {i+1}: Guinier fit failed") else: print(f"Component {i+1}: Rg = {rg:.2f} Å")
- Return type:
- get_channel_consistency()#
Check UV/XR proportion consistency across decomposition channels.
Computes the area fraction of each component in the XR and UV elution curves and reports the maximum absolute difference.
- Returns:
result – A namedtuple with fields:
inconsistency(float): max |XR_frac_i - UV_frac_i| across components. 0.0 = perfect agreement, 1.0 = completely different. Values above ~0.1 suggest the decomposition has assigned different proportions to UV and XR channels.xr_fractions(list of float): area fraction per XR componentuv_fractions(list of float): area fraction per UV component
- Return type:
ChannelConsistency
Examples
cc = decomp.get_channel_consistency() print(f"Inconsistency: {cc.inconsistency:.3f}") if cc.inconsistency > 0.1: print("WARNING: UV/XR proportions diverged")
- get_rg_curve()#
Compute the per-frame Rg curve from the raw XR data.
Runs a Guinier fit on every elution frame independently and returns the results as an
RgCurveobject. This is useful for assessing whether a peak is a pure single-component species (flat Rg vs. frame) or a heterogeneous mixture (varying Rg).Note
This can be slow for large datasets because it fits one Guinier region per frame.
- Returns:
rgcurve – An
RgCurvewith attributes:.x— frame indices (integer array).y— Rg values in Å;NaNwhere Guinier fit failed.scores— Guinier fit quality scores (0–1)
- Return type:
Examples
rgcurve = decomp.get_rg_curve() import matplotlib.pyplot as plt plt.plot(rgcurve.x, rgcurve.y, '.') plt.xlabel("Frame") plt.ylabel("Rg (Å)") plt.title("Rg vs. elution frame") plt.show()
- compute_reconstructed_rgcurve(debug=False)#
Compute the reconstructed Rg curve as a concentration-weighted average.
At each frame j, the reconstructed Rg is the weighted average of each component’s Rg, weighted by the component’s elution intensity:
Rg_recon(j) = Σ_k [C_k(j) / Σ_k C_k(j)] × Rg_k
This matches the legacy
plot_rg_curves/compute_rg_curvesinGuinierTools.RgCurveUtilsand theGuinierDeviationscoring used byoptimize_rigorously().- Returns:
rgcurve – An
RgCurvewith the same frame indices as the data.- Return type:
- get_P_at(q_target, normalize=False)#
Return the XR scattering matrix P interpolated onto q_target.
- Parameters:
q_target (array-like, shape (m,)) – Target q-values in Å⁻¹.
normalize (bool, optional) – If
True, each component column is divided by its maximum so that all columns peak at 1. DefaultFalse.
- Returns:
P_interp – Scattering matrix P evaluated at q_target.
- Return type:
np.ndarray, shape (m, n_components)
- component_quality_scores()#
Compute a per-component reliability score in [0, 1].
Scores blend Rg distinctiveness (70 %) and area proportion (30 %). A score of 0.0 means Guinier fitting failed or Rg is indistinguishable from another component’s. A score near 1.0 means the component is well-separated in Rg and carries a non-trivial fraction of the signal.
- Returns:
scores – Reliability score for each component, in the same order as
get_rgs()andget_proportions().- Return type:
See also
is_component_reliablethreshold-based boolean version.
Examples
scores = decomp.component_quality_scores() for i, s in enumerate(scores): print(f"Component {i+1}: reliability = {s:.2f}")
- is_component_reliable(index, threshold=0.5)#
Return
Trueif component index has a quality score ≥ threshold.- Parameters:
- Return type:
Examples
if not decomp.is_component_reliable(1): print("Component 2 may be a noise artifact.")
- plot_components(title=None, fig=None, axes=None, **kwargs)#
Plot the components.
- Parameters:
title (str, optional) – If specified, add a super title to the plot.
fig (matplotlib.figure.Figure, optional) – An existing Figure to draw into. If
None(default), a new figure is created automatically.axes (array-like of shape (2, 3), optional) –
A 2×3 array of Axes to draw into. Must be provided together with
figwhen injecting into an existing subplot grid. IfNone(default), axes are created automatically inside fig.Expected layout:
axes[0, 0] UV elution curves axes[0, 1] UV absorbance curves axes[0, 2] (UV spare / unused) axes[1, 0] XR elution curves axes[1, 1] XR scattering curves (log scale) axes[1, 2] XR Guinier plot ← Kratky is omitted when axes are injected
Note
When both fig and axes are provided the caller is responsible for creating axes with compatible geometry.
rgcurve (molass.Guinier.RgCurve.RgCurve, optional) –
If provided, overlays the per-frame Rg values as a scatter plot on the XR elution subplot (
axes[1, 0]), colour-coded by Guinier fit score. Obtain viadecomp.get_rg_curve().Example:
rgcurve = decomp.get_rg_curve() decomp.plot_components(rgcurve=rgcurve)
rg_score_threshold (float, optional) – Only Rg points whose Guinier fit score exceeds this value are plotted. Default is
None(all points shown).rg_marker_size (float, optional) – Marker size for the Rg scatter points. Default is
12.rg_cmap (str, optional) – Matplotlib colormap name used to colour Rg markers by score. Default is
'viridis'.
- Returns:
result – A PlotResult object which contains the following attributes.
fig: The matplotlib Figure object.
axes: A 2×3 array of Axes objects.
- Return type:
- update_xr_ranks(ranks, debug=False)#
Update the ranks for the X-ray data.
Default ranks are one for each component which means that interparticle interactions are not considered. This method allows the user to set different ranks for each component.
- get_xr_matrices(debug=False)#
Get the factorized matrices for the X-ray (SAXS) data.
- Parameters:
debug (bool, optional) – If True, enable debug mode.
- Returns:
M (np.ndarray, shape (n_q, n_frames)) – Measured scattering intensity matrix. Rows are q-points; columns are elution frames.
C (np.ndarray, shape (n_components, n_frames)) – Elution curves (concentration profiles) for each component. Each row is one component’s elution curve over frames.
P (np.ndarray, shape (n_q, n_components)) – Scattering profiles (form factors) for each component. Each column is one component’s P(q) in absolute or relative intensity units (matching the scale of M).
Pe (np.ndarray, shape (n_q, n_components)) – Estimated error (standard deviation) on P, propagated from the measurement error matrix.
Notes
The q-values corresponding to the n_q rows are stored in
decomp.xr.qv(shape(n_q,), units Å⁻¹).Example
M, C, P, Pe = decomp.get_xr_matrices() # P[:, 0] → scattering profile of component 1 # C[0, :] → elution curve of component 1
- get_xr_components(debug=False)#
Get the per-component objects for the X-ray (SAXS) data.
- Parameters:
debug (bool, optional) – If True, enable debug mode.
- Returns:
components – One
XrComponentper decomposed component, in component order.Each
XrComponentexposes:get_guinier_object()→ Guinier fit result (Rg, I0, fit range)get_jcurve_array()→np.ndarrayshape(n_q, 3): columns are[q, P(q), Pe(q)]in Å⁻¹ and intensity units.icurve_array→np.ndarrayshape(2, n_frames): rows are[frame_x, elution_y].compute_area()→ scalar, integrated elution area.
- Return type:
list of
XrComponent, length n_components
- get_scattering_profiles(debug=False)#
Get the per-component scattering profiles
Pand their errorsPe.This is a convenience accessor; equivalent to:
_, _, P, Pe = decomp.get_xr_matrices()
- Returns:
qv (np.ndarray, shape (n_q,)) – q-values in Å⁻¹ (alias of
decomp.xr.qv).P (np.ndarray, shape (n_q, n_components)) – Scattering profiles.
P[:, i]is componenti’s profile.Pe (np.ndarray, shape (n_q, n_components)) – Propagated standard error on
P.
Notes
Use this when you only need the SAXS profiles and want to skip constructing
XrComponentobjects. For full per-component objects (with Guinier fitting), useget_xr_components().
- get_uv_matrices(debug=False)#
Get the matrices for the UV data.
- get_uv_components(debug=False)#
Get the components for the UV data.
- Return type:
List of UvComponent objects.
- get_pairedranges(mapped_curve=None, area_ratio=0.7, concentration_datatype=2, debug=False)#
Get the paired ranges.
- Parameters:
mapped_curve (MappedCurve, optional) – If specified, use this mapped curve instead of computing a new one.
area_ratio (float, optional) – The area ratio for the range computation.
concentration_datatype (int, optional) – The concentration datatype for the range computation.
debug (bool, optional) – If True, enable debug mode.
- Returns:
The list of
PairedRangeobjects.- Return type:
list of PairedRange
- get_proportions()#
Get the relative area fractions of the XR components.
- Returns:
proportions – Normalised elution-curve area fraction for each component, summing to 1.0. Values are in the range [0, 1]. Proportional to the amount (concentration × volume) of each species in the SEC peak region.
- Return type:
np.ndarray, shape (n_components,)
- compute_scds(debug=False)#
Get the list of SCDs (Score of Concentration Dependence) for the decomposition.
- get_cd_color_info()#
Get the color information for the concentration dependence.
- Returns:
peak_top_xes (list of float) – The list of peak top x values for each component.
scd_colors (list of str) – The list of colors for each component based on their ranks.
- upgrade(model, *, rgcurve=None, model_params=None, debug=False, **kwargs)#
Upgrade the decomposition to a physics-aware column model (SDM or EDM).
Replaces the EGH elution model with a more physically realistic column model, using the EGH shape parameters as a starting point for column-parameter estimation.
- Parameters:
model (str) –
The name of the column model to use.
Supported models:
CEDM: Continuous EDM (shared-column variant of EDM)LKM: Lumped Kinetic ModelGRM: General Rate Model (film mass transfer + intraparticle pore diffusion)
rgcurve (Curve, optional) – The Rg curve to use for the optimization.
model_params (dict, optional) – The parameters for the model.
pore_dist (str, optional) – For SDM only: pore-size distribution to use.
'mono'(default) uses a single pore size (G1200, gamma residence time);'lognormal'uses a lognormal pore distribution (G1300). Takes precedence overmodel_params['pore_dist']when both are given.debug (bool, optional) – If True, enable debug mode.
**kwargs – Additional keyword arguments forwarded to the model’s
optimize_decompositionand downstream estimators (e.g.poresize_bounds,N0,include_M3for SDM — seemolass.SEC.Models.SdmEstimator.estimate_sdm_column_params()).
- Returns:
result – A new Decomposition object with optimized components.
- Return type:
- optimize_with_model(model_name, rgcurve=None, model_params=None, debug=False, **kwargs)#
Deprecated. Use
upgrade()instead.
- recommend_num_components(k_max=3, model='SDM', rgcurve=None, rt_dist='gamma', cond_threshold=50.0, cos_threshold=0.99, amp_threshold=0.2, quiet=True, debug=False)#
Recommend
num_componentsby detecting degeneracy atk+1.Sweeps
k in 1..k_maxon this decomposition’sssd, runsupgrade()for eachk, and applies a 4-metric diagnostic (residual,cond(C),max cos(C[i],C[j]), amp ratio) plus the decision rule from issue #116. Seemolass.LowRank.NumComponentsRecommender.recommend_num_components()for full details.- Parameters:
k_max (int, optional) – Maximum
num_componentsto try. Default 3.model (str, optional) – Model name forwarded to
upgrade(). Default'SDM'.rgcurve (Curve, optional) – Rg curve. If
None, computed viaself.ssd.xr.compute_rgcurve().rt_dist (str, optional) – SDM residence-time distribution (
'gamma'or'exponential').cond_threshold (float, optional) – Degeneracy thresholds.
cos_threshold (float, optional) – Degeneracy thresholds.
amp_threshold (float, optional) – Degeneracy thresholds.
quiet (bool, optional) – Suppress per-fit stdout/stderr. Default True.
debug (bool, optional) – If True, do not suppress output and forward downstream.
- Returns:
Named tuple
(recommended_k, reason, metrics)wheremetricsis apandas.DataFramewith one row perk.- Return type:
Examples
rec = decomp.recommend_num_components(k_max=3) print(rec.recommended_k, '-', rec.reason) print(rec.metrics)
- make_rigorous_initparams(baseparams, debug=False)#
Make initial parameters for rigorous optimization.
- Parameters:
debug (bool, optional) – If True, enable debug mode.
- Returns:
The initial parameters for rigorous optimization.
- Return type:
np.ndarray
- get_rigorous_param_count()#
Return the number of parameters for rigorous optimization.
Convenience wrapper around
make_rigorous_initparams()that handles thebaseparamssetup internally. Useful for a quick sanity-check before committing to a long run:decomp_lkm = LKM().optimize_decomposition(decomp_egh) print(decomp_lkm.get_rigorous_param_count()) # e.g. 30
Works for all supported models (EGH, SDM, EDM, CEDM, LKM).
- Returns:
Number of parameters in the flat init-params vector that will be passed to the legacy objective function (G1100 / G1200 / G1300 / G1400 / G2020).
- Return type:
- optimize_rigorously(rgcurve=None, analysis_folder=None, method='BH', niter=20, frozen_components=None, free_components=None, frozen_param_groups=None, trimmed_ssd=None, clear_jobs=True, function_code=None, in_process=True, monitor=True, async_=True, progress='dashboard', max_trials=0, debug=False, _dry_run=False, ns_narrow_bounds=True, ns_adaptive_nsteps=False, ns_nsteps=None, **kwargs)#
Perform a rigorous decomposition.
- Parameters:
rgcurve (Curve) – The Rg curve to use for the decomposition.
analysis_folder (str, required) –
The folder to save analysis results. Must be provided explicitly — passing
NoneraisesValueError. Example:analysis_folder='temp_analysis_apo_bh'. Optimization creates the following layout on disk:<analysis_folder>/ optimized/ jobs/ 000/callback.txt # job 0 001/callback.txt # job 1 (e.g. after Resume) ...
Each
callback.txtrecords per-iteration objective values and parameter vectors. Uselist_rigorous_jobs()to inspect existing jobs, orload_rigorous_result()to reconstruct aDecompositionfrom a completed job.method (str, optional) –
The optimization algorithm to use. Default is
'BH'.Valid values:
'BH'— Basin-Hopping (default). Nelder-Mead local minimization with stochastic perturbation between basins. Good general-purpose choice.'NS'— Nested Sampling (UltraNest). Explores the full parameter space; useful when the objective landscape has multiple well-separated minima.
niter (int, optional) –
Iteration budget. Meaning depends on
method:'BH': literal number of Basin-Hopping outer steps (default 20).'NS': multiplied by 7 000 to formmax_ncallsfor UltraNest (niter=20→ 140 000 likelihood evaluations).
Default is 20.
frozen_components (list of int, optional) – 0-based indices of protein components to freeze during optimization. Their EGH shape parameters (H, mu, sigma, tau), Rg, and UV scale will be held constant at the values from the initial decomposition. Mutually exclusive with
free_components.free_components (list of int, optional) – 0-based indices of protein components to optimize. All other components will be frozen. This is the complement of
frozen_components— use whichever is shorter. E.g.,free_components=[4]to optimize only the main peak. Mutually exclusive withfrozen_components.trimmed_ssd (SecSaxsData, optional) –
The trimmed but not baseline-corrected SSD — i.e., the output of
ssd.trimmed_copy()beforecorrected_copy(). When provided, the optimizer fits its model (EGH components + linear baseline) directly to this data, while using the corrected decomposition for EGH initialization. This is the recommended two-stage approach: baseline correction helps peak initialization in the quick stage, but the rigorous stage should fit baseline as a free parameter on uncorrected data.Deprecated since version The: old name
uncorrected_ssdis accepted as an alias but will be removed in a future release.clear_jobs (bool, optional) – If True (default), existing job folders are cleared before starting. Set to False after a kernel restart to preserve previous job results and reconstruct RunInfo without losing optimization history. When False and previous jobs exist, the best params found so far are automatically used as
init_paramsfor the new trial (resuming from the best known point rather than the original decomp params, see issue #169).in_process (bool, optional) – If True (default), run the optimizer in this Python process instead of spawning a subprocess. Avoids the parent/subprocess data-derivation divergence (see issues #117 / #119) and keeps the optimizer running against the same library-prepared data the parent already holds in memory. Set
Falseto use the legacy subprocess path (required by the tkinter GUI; available as an escape hatch for notebook users who need process isolation).monitor (bool, optional) – Controls the
MplMonitoripywidgets dashboard. When True (default), a live dashboard is shown whether the run is in-process or subprocess. When False, no dashboard is created — the run proceeds silently. Usemonitor=Falsefor batch / comparison runs (e.g.compare_optimization_paths) where the widget is not needed.async (bool, optional) – Only meaningful when
in_process=True. If True (default), the optimizer runs in a background daemon thread and this call returns aRunInfoobject immediately, before the run completes. PollRunInfo.is_aliveto check whether the run is still in progress, then callRunInfo.wait()(instant if already done) to join the thread before accessing results. SetFalsefor blocking (batch) runs.progress (str or None, optional) – Deprecated and ignored — use
monitor=True/Falseinstead. Kept in the signature only for backward compatibility.max_trials (int, optional) –
Maximum number of automatic sequential re-trials after each trial completes. Default
0means no automatic re-start — the user decides manually via the Resume button.Only meaningful when
in_process=Trueandmonitor=True. The subprocess path (in_process=False) always uses its own default of 30. Setmax_trials=30here to match that behaviour for unattended in-process runs.debug (bool, optional) – If True, enable debug mode.
- Returns:
A
RunInfoobject that tracks the optimization run. For blocking runs (async_=False), the run is complete when this returns. For non-blocking runs (async_=True), callrun_info.load_best()to wait for the first result and load it, orrun_info.wait()thenrun_info.load_best().- Return type:
Notes
The elution model (EGH, SDM, EDM) is not a parameter of this method — it is determined by the decomposition object itself (
self.xr_ccurves[0].model). Passingmodel=raisesTypeError: Unexpected keyword arguments.To upgrade to a different column model, use
upgrade()instead. That method handles EGH → SDM/EDM parameter conversion internally, using the EGH shape parameters as a starting point for column-parameter estimation.Typical staged workflows:
# EGH → refine with G1100 decomp = corrected.quick_decomposition() run_info = decomp.optimize_rigorously( analysis_folder='temp_analysis_apo_egh', ...) result_egh = run_info.load_best() # EGH → SDM upgrade → refine with G1200/G1300 run_info_sdm = result_egh.upgrade( 'SDM', analysis_folder='temp_analysis_apo_sdm', ...) # EGH → LKM upgrade → refine with G1400 (auto-detected) decomp_lkm = decomp.upgrade('LKM') # moment-matching run_lkm = decomp_lkm.optimize_rigorously( # G1400 auto-selected analysis_folder='temp_analysis_apo_lkm', ...)
See also
RunInfo.get_score_breakdownInspect the individual score and penalty components that make up the objective value (fv).
RunInfo.is_aliveCheck whether an async run is still in progress.
RunInfo.waitBlock until the run completes.
RunInfo.load_bestWait for the first result then load it (recommended for
async_=Trueruns instead ofwait()+load_best()).
- score_initial(trimmed_ssd=None, analysis_folder=None, function_code=None, debug=False)#
Evaluate the rigorous objective function once at initial parameters.
A lightweight alternative to
optimize_rigorously()when you only need to know the starting score before launching full BH/NS. Equivalent to the final plot of the legacy PeakEditor — UV/XR decompositions with individual score components — but callable from a notebook without triggering any optimization loop.For models other than EGH, call
upgrade()first:decomp_sdm = decomp.upgrade(model='SDM') result = decomp_sdm.score_initial(trimmed_ssd=trimmed)
- Parameters:
trimmed_ssd (SecSaxsData, optional) – Trimmed (uncorrected) SSD (Pattern B, recommended).
analysis_folder (str, optional) – Where to write optimizer setup artefacts. Defaults to a temporary directory that is deleted after the call.
function_code (str, optional) – Override auto-detected function code.
debug (bool, optional)
- Returns:
Has
.sv,.fv,.breakdown,.plot(),.diagnose(),.print_summary().- Return type:
Examples
result_auto = decomp_auto.score_initial(trimmed_ssd=trimmed) result_prop = decomp_prop.score_initial(trimmed_ssd=trimmed) result_auto.plot(title="Auto EGH") result_prop.plot(title="Proportional 1:1:1:1") result_auto.print_summary()
See also
optimize_rigorouslyFull BH/NS optimization.
RunInfo.get_score_breakdownScore breakdown after optimization.
- load_best_rigorous_result(analysis_folder, rgcurve=None, debug=False)#
Load the best rigorous optimization result from disk.
Convenience method that combines
list_rigorous_jobs()andload_rigorous_result()into a single call: finds the job with the lowest objective function value and reconstructs theDecompositionfrom it.- Parameters:
- Returns:
A new Decomposition with the best optimized components.
- Return type:
- Raises:
FileNotFoundError – If no completed jobs are found.
See also
RunInfo.get_score_breakdownInspect the individual score and penalty components that make up the objective value (fv).
Examples
result = decomp.load_best_rigorous_result("temp_analysis") result.plot_components() # Fast: skip redundant Guinier fitting by passing rgcurve result = decomp.load_best_rigorous_result("temp_analysis", rgcurve=rgcurve)
- load_rigorous_result(analysis_folder, jobid=None, rgcurve=None, debug=False)#
Load a completed rigorous optimization result from disk.
This reads saved parameters without launching a new subprocess. Use it to view results from a previous session after a kernel or VS Code restart.
- Parameters:
analysis_folder (str) – The same
analysis_folderpassed tooptimize_rigorously(). Seeoptimize_rigorously()for the folder layout.jobid (str, optional) – Specific job id (subfolder name, e.g.
'001'). If None, loads the latest job. Uselist_rigorous_jobs()to see available jobs.rgcurve (RgCurve, optional) – Pre-computed Rg curve. Avoids redundant per-frame Guinier fitting when loading results.
debug (bool, optional) – If True, reload modules from disk.
- Returns:
A new Decomposition with the optimized components.
- Return type:
Examples
After kernel restart, re-run data loading and quick decomposition, then:
result = decomp.load_rigorous_result("temp_analysis_scaffolded", rgcurve=rgcurve) result.plot_components(rgcurve=rgcurve)
- static list_rigorous_jobs(analysis_folder)#
List completed rigorous optimization jobs on disk.
- Parameters:
analysis_folder (str) – The same
analysis_folderpassed tooptimize_rigorously().- Returns:
Each entry is a
JobInfo(id, iterations, best_fv, timestamp)namedtuple. Sorted by job id.- Return type:
Examples
jobs = Decomposition.list_rigorous_jobs("temp_analysis_scaffolded") for job in jobs: print(f"Job {job.id}: {job.iterations} iters, best fv={job.best_fv:.4f}") # Then load a specific job result = decomp.load_rigorous_result("temp_analysis_scaffolded", jobid=jobs[0].id)
- static has_rigorous_results(analysis_folder)#
Check whether any rigorous optimization results are available.
Lightweight filesystem check — does not parse results. Use this to poll readiness before calling
load_rigorous_result()orlist_rigorous_jobs().- Parameters:
analysis_folder (str) – The same
analysis_folderpassed tooptimize_rigorously().- Returns:
Trueif at least one job has acallback.txtfile.- Return type:
Examples
if Decomposition.has_rigorous_results("temp_analysis"): jobs = Decomposition.list_rigorous_jobs("temp_analysis")
- static wait_for_rigorous_results(analysis_folder, timeout=600, poll_interval=5)#
Block until rigorous optimization results become available.
Polls the filesystem until at least one job has written a
callback.txt, or the timeout is reached.- Parameters:
- Returns:
Trueif results appeared,Falseif timed out.- Return type:
Examples
decomp.optimize_rigorously(analysis_folder="temp", ...) if Decomposition.wait_for_rigorous_results("temp"): result = decomp.load_rigorous_result("temp")
- static plot_convergence(analysis_folder, ax=None, title=None)#
Plot and return convergence data across rigorous optimization jobs.
Shows two subplots: (1) best fv per job, (2) per-job fv trajectory. Returns a
ConvergenceInfonamedtuple for programmatic assessment.- Parameters:
- Returns:
Namedtuple with fields:
jobs,best_fv,best_job_id,spread,trend('improving'/'worsening'/'stable'),n_jobs.- Return type:
Examples
info = Decomposition.plot_convergence("temp_analysis") print(f"Best: {info.best_fv:.4f}, trend: {info.trend}")