API Reference¶
This page documents the stable public API exposed from the top-level
fdscore namespace. Internal helper modules, compatibility plumbing,
and implementation details are intentionally excluded from this
reference.
The structure below follows the public workflows described in
README.md and CONTRACTS.md.
Configuration Models¶
These classes define the main numerical settings and workflow inputs used throughout the library.
- class fdscore.SNParams(slope_k, ref_stress=1.0, ref_cycles=1.0, amplitude_from_range=True)[source]¶
S-N curve parameters used in Miner damage.
- Parameters:
slope_k (
float) – Fatigue slope exponent \(k\). Must be positive.ref_stress (
float) – Reference stress \(S_{ref}\) in user units, for example MPa.ref_cycles (
float) – Reference cycle count \(N_{ref}\).amplitude_from_range (
bool) – IfTrue, interpret the rainflow range as twice the alternating amplitude, so the damage-driving amplitude isrange / 2. This convention must remain consistent across FDS computation and inversion.
Notes
Two usage modes are common.
Physical workflows provide
ref_stress,ref_cycles, and an application-specificp_scalewhen absolute damage magnitude matters.Normalized workflows use
SNParams.normalized(...)together withp_scale=1.0when only relative FDS shape and the equivalent inverted PSD matter.
- class fdscore.SDOFParams(q, metric='pv', f=None, fmin=None, fmax=None, df=None)[source]¶
SDOF oscillator-grid definition and response metric.
- Parameters:
q (
float) – Oscillator quality factor.metric (
str, optional) – Response metric reported by the SDOF bank. Accepted values are"pv","acc","vel", and"disp".f (
numpy.ndarrayorNone, optional) – Explicit frequency grid in Hz. When provided, it must be strictly increasing and strictly positive.fmin (
floatorNone, optional) – Minimum oscillator frequency in Hz for an implicit linear grid.fmax (
floatorNone, optional) – Maximum oscillator frequency in Hz for an implicit linear grid.df (
floatorNone, optional) – Frequency increment in Hz for an implicit linear grid.
Notes
The grid can be defined either by an explicit vector
for by the linear-grid tuple(fmin, fmax, df), but not both.
- class fdscore.PSDParams(method='welch', window='hann', nperseg=None, noverlap=None, detrend='constant', scaling='density', onesided=True, fmin=None, fmax=None)[source]¶
PSD-estimation settings used by spectral workflows.
- Parameters:
method (
{"welch"}, optional) – PSD estimation method. The current implementation supports only Welch.window (
str, optional) – Window passed to the Welch estimator.nperseg (
intorNone, optional) – Segment length passed to the Welch estimator.noverlap (
intorNone, optional) – Segment overlap passed to the Welch estimator.detrend (
{"constant", "linear", "none"}, optional) – Detrending mode used during PSD estimation.scaling (
{"density"}, optional) – PSD scaling convention.onesided (
bool, optional) – Whether a one-sided PSD is requested.fmin (
floatorNone, optional) – Optional lower cropping limit in Hz.fmax (
floatorNone, optional) – Optional upper cropping limit in Hz.
- class fdscore.IterativeInversionParams(iters=30, gamma=0.8, gain_min=0.2, gain_max=5.0, alpha_sharpness=1.0, floor=1e-30, smooth_enabled=True, smooth_window_bins=11, smooth_every_n_iters=1, prior_blend=0.0, prior_power=1.0, edge_anchor_hz=0.0, edge_anchor_blend=0.0, tail_cap_start_hz=0.0, tail_cap_ratio=0.0, low_cap_ratio=0.0, post_smooth_window_bins=0, post_smooth_blend=1.0, post_refine_iters=0, post_refine_gamma=0.5, post_refine_min=0.7, post_refine_max=2.2)[source]¶
Configuration parameters for iterative PSD inversion.
- Parameters:
iters (
int, optional) – Number of main-loop iterations.gamma (
float, optional) – Multiplicative update exponent.gain_min (
float, optional) – Lower clip applied to oscillator-wise gains.gain_max (
float, optional) – Upper clip applied to oscillator-wise gains.alpha_sharpness (
float, optional) – Exponent used to sharpen or soften the influence matrix.floor (
float, optional) – Minimum PSD floor maintained during iteration.smooth_enabled (
bool, optional) – Whether periodic smoothing is enabled during the main loop.smooth_window_bins (
int, optional) – Smoothing-window width in PSD bins.smooth_every_n_iters (
int, optional) – Smoothing cadence in iterations.prior_blend (
float, optional) – Blend factor against the seed PSD in log space.prior_power (
float, optional) – Sensitivity weighting exponent applied to prior blending.edge_anchor_hz (
float, optional) – Frequency span used for edge anchoring.edge_anchor_blend (
float, optional) – Blend factor used for low- and high-frequency edge anchoring.tail_cap_start_hz (
float, optional) – Frequency above which the spectral tail cap becomes active.tail_cap_ratio (
float, optional) – Maximum allowed high-frequency tail ratio relative to the seed PSD.low_cap_ratio (
float, optional) – Maximum allowed low-frequency ratio relative to the seed PSD.post_smooth_window_bins (
int, optional) – Smoothing-window width used in the optional post-smoothing stage.post_smooth_blend (
float, optional) – Blend factor applied between the best PSD and the post-smoothed PSD.post_refine_iters (
int, optional) – Number of optional refinement iterations after post-smoothing.post_refine_gamma (
float, optional) – Update exponent used during the refinement stage.post_refine_min (
float, optional) – Lower gain clip used during refinement.post_refine_max (
float, optional) – Upper gain clip used during refinement.
Notes
Use
meta["diagnostics"]returned by inversion functions to track convergence.Parameter usage is not fully symmetric across engines. The time-domain iterative engine currently ignores the spectral-only subset, while
PSDResult.meta["param_usage"]records the per-engine interpretation explicitly.
- class fdscore.SineDwellSegment(freq_hz, amp, duration_s, input_motion='acc', label=None)[source]¶
Single deterministic harmonic dwell segment.
- Parameters:
freq_hz (
float) – Harmonic excitation frequency in Hz.amp (
float) – Input amplitude expressed in the units implied byinput_motion.duration_s (
float) – Dwell duration in seconds.input_motion (
str, optional) – Type of the prescribed harmonic input quantity. Accepted values are"acc","vel", and"disp".label (
strorNone, optional) – Optional user-facing identifier for the segment.
Result Models¶
These classes carry the structured outputs returned by the main fatigue, ERS, PSD, and shock workflows.
- class fdscore.FDSResult(f, damage, meta=<factory>)[source]¶
Fatigue Damage Spectrum result container.
- Parameters:
f (
numpy.ndarray) – Oscillator frequency grid in Hz.damage (
numpy.ndarray) – Miner-damage values evaluated onf.meta (
dict, optional) – Auxiliary metadata such as compatibility signatures and provenance.
- class fdscore.ERSResult(f, response, meta=<factory>)[source]¶
Extreme-response spectrum result container.
- Parameters:
f (
numpy.ndarray) – Oscillator frequency grid in Hz.response (
numpy.ndarray) – Response-spectrum values evaluated onf.meta (
dict, optional) – Auxiliary metadata such as compatibility signatures and provenance.
- class fdscore.PSDResult(f, psd, meta=<factory>)[source]¶
Power Spectral Density result container.
- Parameters:
f (
numpy.ndarray) – Frequency grid in Hz.psd (
numpy.ndarray) – One-sided PSD values evaluated onf.meta (
dict, optional) – Auxiliary metadata such as provenance and reconstruction diagnostics.
- class fdscore.PSDMetricsResult(rms_acc_g, rms_acc_m_s2, peak_acc_g, peak_acc_m_s2, peak_factor, zero_upcrossing_hz, effective_cycles, rms_vel_m_s, peak_vel_m_s, rms_disp_mm, peak_disp_mm, disp_pk_pk_mm, band_rms_g=<factory>, meta=<factory>)[source]¶
Summary metrics computed from an acceleration PSD.
meta stores auxiliary details such as band coverage and peak-statistics diagnostics used to interpret the scalar outputs.
- class fdscore.FDSTimePlan(fs, n_samples, f, zeta, metric, H)[source]¶
Precomputed transfer plan for repeated time-domain FDS calls.
- Parameters:
fs (
float) – Sampling rate in Hz.n_samples (
int) – Number of samples expected in reused time histories.f (
numpy.ndarray) – Validated oscillator frequency grid in Hz.zeta (
float) – Oscillator damping ratio implied by the sourceSDOFParams.metric (
str) – Response metric encoded in the plan. Accepted values are"pv","acc","vel", and"disp".H (
numpy.ndarray) – Complex transfer matrix used during FFT-domain reconstruction.
Notes
A plan stores the frequency grid and transfer matrix for a fixed
(fs, n_samples, sdof)configuration and can be reused across channels and signals with the same sampling setup.The stored transfer matrix
His materialized as acomplex128array with shape(len(f), n_fft_bins). This trades memory for speed by avoiding transfer rebuilds during repeatedcompute_fds_time(...)calls.
- class fdscore.ShockSpectrumPair(neg, pos, meta=<factory>)[source]¶
Positive and negative shock-spectrum pair.
- Parameters:
neg (
fdscore.types.ERSResult) – Negative-sided response spectrum.pos (
fdscore.types.ERSResult) – Positive-sided response spectrum.meta (
dict, optional) – Auxiliary metadata associated with the pair.
- class fdscore.ShockEvent(peak_index, start_index, stop_index, peak_time_s, start_time_s, stop_time_s, peak_value, peak_abs, polarity)[source]¶
Single detected shock event in a one-dimensional time history.
- Parameters:
peak_index (
int) – Sample index of the event peak.start_index (
int) – Start sample index of the extracted event window.stop_index (
int) – Stop sample index of the extracted event window.peak_time_s (
float) – Peak time in seconds.start_time_s (
float) – Start time in seconds.stop_time_s (
float) – Stop time in seconds.peak_value (
float) – Signed peak value.peak_abs (
float) – Absolute peak magnitude.polarity (
{"pos", "neg"}) – Peak polarity classification.
- class fdscore.ShockEventSet(events, fs, n_samples, meta=<factory>)[source]¶
Detected shock events together with extraction metadata.
- Parameters:
events (
tupleofShockEvent) – Detected events in chronological order.fs (
float) – Sampling rate in Hz of the source signal.n_samples (
int) – Total number of samples in the analyzed signal.meta (
dict, optional) – Auxiliary metadata describing detector settings and provenance.
- class fdscore.RollingERSResult(f, t_center_s, response, meta=<factory>)[source]¶
Rolling response spectra stacked over multiple time windows.
- Parameters:
f (
numpy.ndarray) – Oscillator frequency grid in Hz.t_center_s (
numpy.ndarray) – Time coordinate associated with each response row.response (
numpy.ndarray) – Two-dimensional response matrix with one row per time window.meta (
dict, optional) – Auxiliary metadata associated with the rolling result.
Fatigue and Inversion Workflows¶
These are the main FDS computation, algebra, and inversion entry points.
- fdscore.compute_fds_time(x, fs, sn, sdof, *, p_scale=None, detrend='linear', strict_nyquist=True, batch_size=64, plan=None, engine='incremental', zoh_r_max=0.2)[source]¶
Compute a time-domain Fatigue Damage Spectrum from an input history.
The returned spectrum contains Miner damage evaluated independently for each SDOF oscillator in the grid defined by
sdof. The result also carries a compatibility signature inmeta["compat"]so that downstream operations, especially inversion, can verify that the same fatigue conventions were used.Pipeline
The computation follows this sequence for a base-acceleration time history
x:Optionally preprocess the signal with
preprocess_signal(...)using the requesteddetrendmode.Validate the oscillator grid against Nyquist and derive the shared damping ratio and S-N parameters.
Evaluate the oscillator bank with the selected internal engine:
engine="incremental"integrates each SDOF oscillator sample-by-sample using exact ZOH state-transition matrices. For oscillators close to Nyquist, the input is adaptively upsampled to control ZOH attenuation error.engine="fft"builds or reuses the FFT-domain transfer matrix, applies it torfft(x), and reconstructs each oscillator response withirfftin batches.
Apply ASTM-style rainflow counting and Miner’s linear damage rule to each oscillator response or response reversal stream.
Return
FDSResulttogether with compatibility and provenance metadata describing the selected engine and preprocessing choices.
- Parameters:
x (
numpy.ndarray) – One-dimensional base-acceleration time history.fs (
float) – Sampling rate in Hz.sn (
fdscore.types.SNParams) – S-N curve definition used for Miner damage accumulation.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition and response metric.p_scale (
floatorNone) – Optional scale factor applied to each oscillator response before rainflow counting. In physical workflows this represents the stress-response proportionality used to convert response to the fatigue-driving quantity.detrend (
str) – Optional preprocessing mode passed topreprocess_signal(...). Supported values are"linear","mean", and"none".strict_nyquist (
bool) – IfTrue, oscillator frequencies above Nyquist raiseValidationError. IfFalse, the grid is truncated to the valid Nyquist range and the truncation is recorded in the result metadata.batch_size (
int) – Number of oscillators processed per inverse FFT batch. Only used whenengine="fft".plan (
fdscore.types.FDSTimePlanorNone) – Optional precomputed transfer plan created byprepare_fds_time_plan(). Only used whenengine="fft".engine (
{"incremental", "fft"}) –Internal computation engine.
"incremental"(default)Sample-by-sample SDOF integration via exact ZOH state-transition matrices. Rainflow counting is performed online during integration so the full
(n_osc, n_samples)response matrix is never materialised. Provides super-linear speedup over"fft"for long signals and low memory overhead regardless of signal length."fft"Original FFT-based engine. Applies the continuous SDOF frequency response function to the signal spectrum and reconstructs each oscillator response with
irfft. Use this engine when exact bit-for-bit reproducibility with pre-existing results is required.
Note
The two engines use different SDOF discretisation schemes (ZOH vs. continuous FRF on discrete FFT bins) and will therefore produce slightly different damage values, particularly for oscillators above roughly
0.3 * fs / 2. For the typical configuration offs = 1000 Hzandfmax = 400 Hzthe discrepancy in Miner damage is below 5 % across the full grid and below 1 % below 150 Hz.zoh_r_max (
float) –Maximum tolerated
f0 / Nyquist_effectiveratio for the"incremental"engine. Controls the adaptive upsampling that corrects the ZOH attenuation error for high-frequency oscillators. Ignored whenengine="fft".Smaller values yield higher accuracy at the cost of larger upsample factors for oscillators near the top of the frequency grid. Larger values prioritise throughput.
0.30- max error about 0.5 dB, upsample up to 3x0.20- max error about 0.1 dB, upsample up to 4x (default)0.15- max error about 0.05 dB, upsample up to 6x
- Returns:
Damage spectrum on the validated oscillator grid.
meta["compat"]records the fatigue and response conventions required by downstream operations.- Return type:
Notes
The computation assumes a linear SDOF transfer from base acceleration to the selected metric and evaluates fatigue on the reconstructed response histories. For fixed
slope_k, the absolute damage level scales globally as\[\frac{p_{scale}^k}{N_{ref} S_{ref}^k}\]Therefore
p_scale,ref_stress, andref_cycleschange the magnitude ofdamage(f)but not its relative shape. When only the spectral shape and a compatible FDS-to-PSD inversion matter, a normalized S-N definition together withp_scale=1.0is usually sufficient.The choice of
detrendcan materially affect low-frequency damage, especially for displacement- and pseudo-velocity-based metrics, because offsets and slow drifts are amplified by the low-frequency dynamics of the oscillator bank.If
p_scaleis omitted,p_scale=1.0is assumed only for normalized S-N parameters withref_stress=1andref_cycles=1. Physical workflows must passp_scaleexplicitly.References
- ASTM E1049-85(2017). Standard Practices for Cycle Counting in Fatigue
Analysis.
- Miner, M. A. (1945). “Cumulative Damage in Fatigue.” Journal of Applied
Mechanics, 12(3), A159-A164.
- Crandall, S. H., & Mark, W. D. (1963). Random Vibrations in Mechanical
Systems. Academic Press.
- fdscore.prepare_fds_time_plan(*, fs, n_samples, sdof, strict_nyquist=True)[source]¶
Precompute the FFT-domain transfer data for repeated FDS evaluations.
A time-domain FDS call repeatedly uses the same oscillator grid, damping, and FFT-bin transfer matrix when the sampling configuration is fixed.
FDSTimePlanstores that reusable state so that repeated calls can skip transfer-matrix reconstruction.- Parameters:
fs (
float) – Sampling rate in Hz.n_samples (
int) – Number of samples in the time histories that will reuse this plan.sdof (
SDOFParams) – Oscillator-grid definition and chosen response metric.strict_nyquist (
bool) – IfTrue, frequencies above Nyquist raiseValidationError. IfFalse, the frequency grid is truncated to the valid Nyquist range.
- Returns:
Reusable transfer plan containing the validated oscillator grid, the implied damping ratio, and the complex FFT-domain transfer matrix.
- Return type:
Notes
The stored matrix
His materialized ascomplex128with shape(len(f0), n_fft_bins). Memory therefore scales approximately as\[len(f_0) \times n_{fft\_bins} \times 16 \text{ bytes}\]so plans trade memory for speed. For example, 400 oscillators and a 4 s signal sampled at 1 kHz require roughly 12 MB for the matrix alone.
- fdscore.compute_fds_spectral_psd(f_psd_hz, psd_baseacc, *, duration_s, sn, sdof, p_scale=None)[source]¶
Compute a spectral Fatigue Damage Spectrum from an acceleration PSD.
This routine evaluates fatigue damage oscillator by oscillator using a PSD-domain response model and the library’s internal Dirlik spectral fatigue approximation.
Pipeline
The computation first builds the oscillator grid defined by
sdofand the transfer matrix from base acceleration PSD to the selected response metric. For each oscillator, the response PSD is then computed as\[P_{resp}(f; f_0) = p_{scale}^2 \left| H(f; f_0) \right|^2 P_{base}(f)\]Dirlik’s method is applied to that response PSD to estimate life, and Miner damage is recovered through
\[D(f_0) = \frac{T}{life(f_0)}\]- Parameters:
f_psd_hz (
numpy.ndarray) – One-sided input PSD frequency grid in Hz.psd_baseacc (
numpy.ndarray) – One-sided base-acceleration PSD defined onf_psd_hz.duration_s (
float) – Exposure duration associated with the PSD.sn (
fdscore.types.SNParams) – S-N curve definition used by the Dirlik life calculation.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition and response metric.p_scale (
floatorNone) – Additional scale factor applied to the response quantity before damage evaluation. This must match the fatigue convention used elsewhere in the workflow.
- Returns:
Damage spectrum on the oscillator grid defined by
sdof.- Return type:
Notes
Dirlik is a spectral fatigue approximation derived from response-PSD moments. It is not the same algorithm as rainflow counting on a realized time history, so absolute levels from
compute_fds_spectral_psd(...)andcompute_fds_time(...)should not be expected to match exactly.Agreement with time-domain rainflow tends to improve when the response is well represented as a stationary Gaussian process and the record is long enough that the PSD is a stable descriptor. Differences grow for short records, strongly non-stationary environments, transient content, and non-Gaussian responses.
For fixed
slope_k,p_scale,ref_stress, andref_cyclesact only as a global damage scaling factor. They change the magnitude ofdamage(f)but not its relative shape. UseSNParams.normalized(...)withp_scale=1.0when a normalized workflow is sufficient.Input PSD values are expected to be non-negative. Tiny negative values consistent with numerical noise are clamped to zero; materially negative values raise
ValidationError.References
Dirlik, T. (1985). Application of computers in fatigue analysis. Miner, M. A. (1945). “Cumulative Damage in Fatigue.” Journal of Applied Mechanics, 12(3), A159-A164.
- fdscore.compute_fds_spectral_time(x, fs, *, sn, sdof, psd, duration_s=None, p_scale=None)[source]¶
Compute a spectral FDS from a time history through Welch plus Dirlik.
This convenience route first estimates a one-sided acceleration PSD from the input time history and then delegates to
fdscore.compute_fds_spectral_psd().- Parameters:
x (
numpy.ndarray) – One-dimensional base-acceleration time history.fs (
float) – Sampling rate in Hz.sn (
fdscore.types.SNParams) – S-N curve definition used for the fatigue calculation.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition and response metric.psd (
fdscore.types.PSDParams) – PSD-estimation configuration passed tocompute_psd_welch(...).duration_s (
floatorNone) – Exposure duration associated with the damage estimate. IfNone, useslen(x) / fs.p_scale (
floatorNone) – Optional scale factor applied to the response quantity before damage evaluation.
- Returns:
Spectral damage spectrum evaluated from the internally estimated PSD.
- Return type:
Notes
This route combines two approximation layers:
Welch estimation of the PSD from a finite realization.
Dirlik spectral fatigue damage from the estimated PSD.
Differences relative to
compute_fds_time(...)or tocompute_fds_spectral_psd(...)with a reference PSD are therefore expected for finite-length signals.References
Dirlik, T. (1985). Application of computers in fatigue analysis.
- fdscore.scale_fds(fds, factor)[source]¶
Scale all damage ordinates of a fatigue damage spectrum.
- Parameters:
fds (
fdscore.types.FDSResult) – Input fatigue damage spectrum to be scaled.factor (
float) – Positive finite multiplicative factor applied uniformly to all damage values.
- Returns:
New fatigue damage spectrum with the same frequency grid as the input and damage values multiplied by
factor.- Return type:
Notes
This operation is purely algebraic. It is appropriate when a known post hoc scaling of damage is required, for example to account for an external calibration factor or to compare normalized spectra on a common basis. The function does not revisit the underlying stress cycles, SDOF response model, or S-N assumptions used to generate the original result.
The returned object stores provenance metadata indicating that the spectrum was produced by
scale_fds(), together with the applied factor and the upstream provenance chain of the input spectrum.
- fdscore.sum_fds(fds_list, weights=None)[source]¶
Form a weighted sum of mutually compatible fatigue damage spectra.
- Parameters:
fds_list (
collections.abc.Sequenceoffdscore.types.FDSResult) – Sequence of fatigue damage spectra defined on compatible frequency grids and generated under the same compatibility contract.weights (
collections.abc.SequenceoffloatorNone, optional) – Non-negative weights applied to each spectrum before summation. When omitted, unit weights are used for all inputs.
- Returns:
Weighted sum of the input fatigue damage spectra on the reference frequency grid.
- Return type:
Notes
Compatibility is enforced internally before summation so that the spectra can be meaningfully combined without mixing damage metrics, oscillator assumptions, or incompatible S-N definitions. This function therefore acts as a safe superposition utility for spectra that already satisfy a shared engineering interpretation.
The summation is performed directly on the damage ordinates. No normalization is applied to the weights, so the caller controls whether the result represents a simple sum, a convex combination, or another weighted aggregate.
Provenance metadata is preserved and extended to record the number of inputs, the applied weights, and the provenance chain of each contributing spectrum.
- fdscore.invert_fds_closed_form(fds, *, test_duration_s, strict_metric=True)[source]¶
Invert an FDS to an equivalent acceleration PSD using the closed-form Henderson-Piersol method.
Overview
The inversion proceeds in two steps. First, Miner damage is converted to a Damage Potential spectrum using the proportionality factor
Kderived from the S-N parameters andp_scale:\[DP(f) = \frac{Damage(f)}{K}\]Second, the closed-form inverse of H&P (1995), Eq. 12 is applied:
\[G_{aa}(f) = f \zeta \left[\frac{DP(f)}{f T}\right]^{2 / b}\]The round-trip reconstruction error stored in
meta["reconstruction"]["med_abs_log10"]is the median absolute value of\[\log_{10}\left(\frac{D_{recon}}{D_{target}}\right)\]Metric restriction
This method is valid only for
metric="pv"(pseudo-velocity).The physical justification follows from two independent lines of argument that converge on pseudo-velocity as the stress-relevant quantity:
Empirical / experimental: Gaberson & Chalmers (1969) established that modal velocity is the best single predictor of shock and vibration severity across a wide range of structures. Their work is explicitly cited by Henderson & Piersol (1995) as the basis for using velocity rather than acceleration or displacement to estimate stress.
Theoretical: Crandall (1962) derived analytically that, for a structure vibrating at resonance, peak stress is proportional to peak velocity, not peak acceleration or displacement. This result holds for geometrically simple structures (beams, plates under bending) and is the theoretical foundation cited by H&P (1995) in their Eq. 9.
For a lightly damped SDOF oscillator (\(\zeta < 0.1\)), pseudo-velocity
\[PV = 2 \pi f_0 x_{rel}\]and relative velocity \(v_{rel}\) are approximately equal at resonance, because the phase between displacement and velocity at the resonant peak makes
\[|v_{rel}| \approx \omega_0 |x_{rel}|\]This equivalence justifies using
metric="pv"as a numerically convenient proxy for relative velocity in the closed-form derivation.Using
metric="acc","vel", or"disp"would require a different transfer function at resonance and a different proportionality to stress, yielding a structurally different inversion equation that is not implemented here. Passingstrict_metric=Falsesuppresses the guard but does not make the derivation valid for those metrics.Global damage scaling cancellation¶
When
fdswas computed with compatible settings, the absolute damage scaling carried byp_scale,ref_stress, andref_cyclescancels exactly in the inversion: those parameters affect the magnitude ofdamage(f)and ofKin equal proportion, leaving the inverted PSD unchanged. This invariance is verified bytest_closed_form_psd_is_invariant_to_global_damage_scaling.Requirements
fds.meta["compat"]must exist and containmetric,q,p_scale, andsn.metricmust be"pv"unlessstrict_metric=False.test_duration_smust be the intended test duration, not the original signal duration.
- type fds:
- param fds:
Target FDS result. It must carry
meta["compat"]produced by anycompute_fds_*function in this library.- type fds:
- type test_duration_s:
- param test_duration_s:
Duration of the equivalent test \(T\) in seconds. This is the denominator in the DP-to-PSD step and directly controls the amplitude of the inverted PSD.
- type test_duration_s:
- type strict_metric:
- param strict_metric:
If
True(default), raiseValidationErrorwhenfds.meta["compat"]["metric"] != "pv".- type strict_metric:
- returns:
Equivalent acceleration PSD on the same frequency grid as
fds.f.meta["reconstruction"]contains the round-trip log10 error used for quality assessment.- rtype:
References
- Henderson, G. R. & Piersol, A. G. (1995). “Fatigue Damage Related
Descriptor for Random Vibration Test Environments.” Sound and Vibration, October 1995, 20-24. Equations 11-12.
- Gaberson, H. A. & Chalmers, R. H. (1969). “Modal Velocity as a
Criterion of Shock Severity.” Shock and Vibration Bulletin, No. 40, Pt. 2, 31-49.
- Crandall, S. H. (1962). “Relationship between Stress and Velocity in
Resonant Vibration.” Journal of the Acoustical Society of America, 34(12), 1960-1961.
- Crandall, S. H. & Mark, W. D. (1963). Random Vibrations in Mechanical
Systems. Academic Press, New York. pp. 113-117.
- fdscore.invert_fds_iterative_spectral(target, *, f_psd_hz, psd_seed, duration_s, sn, sdof, p_scale, params=IterativeInversionParams(iters=30, gamma=0.8, gain_min=0.2, gain_max=5.0, alpha_sharpness=1.0, floor=1e-30, smooth_enabled=True, smooth_window_bins=11, smooth_every_n_iters=1, prior_blend=0.0, prior_power=1.0, edge_anchor_hz=0.0, edge_anchor_blend=0.0, tail_cap_start_hz=0.0, tail_cap_ratio=0.0, low_cap_ratio=0.0, post_smooth_window_bins=0, post_smooth_blend=1.0, post_refine_iters=0, post_refine_gamma=0.5, post_refine_min=0.7, post_refine_max=2.2))[source]¶
Iteratively synthesize a PSD that matches a target FDS with a spectral predictor.
This routine solves the inverse problem “find an acceleration PSD whose predicted FDS matches
target” by repeatedly calling the spectral predictorfdscore.compute_fds_spectral_psd().Algorithm
Let \(F_{target}\) be the target damage spectrum and let \(F(P)\) be the spectral predictor evaluated at candidate PSD \(P\). The method builds a PSD-to-oscillator influence matrix from the SDOF transfer model and converts it to a normalized redistribution matrix \(\alpha\).
Oscillator-wise multiplicative gains are computed as
\[s_i = \left(\frac{F_{target, i}}{F_i(P)}\right)^{2 / k}\]and clipped to the interval defined by
gain_minandgain_max. Those gains are projected back to PSD bins through\[u = \exp\left(\alpha^T \log(s)\right)\]The candidate PSD is then updated multiplicatively as
\[P \leftarrow P \, u^{\gamma}\]followed by optional smoothing, prior blending, and edge capping. The updated PSD is re-evaluated and scored by the median absolute log10-domain mismatch.
The function always outputs a one-sided acceleration PSD on the user supplied
f_psd_hzgrid.- Parameters:
target (
fdscore.types.FDSResult) – Target FDS result, expressed as damage versus oscillator frequency.f_psd_hz (
numpy.ndarray) – Frequency grid in Hz for the synthesized acceleration PSD.psd_seed (
numpy.ndarray) – Strictly positive seed PSD defined onf_psd_hz.duration_s (
float) – Exposure duration used by the spectral predictor.sn (
fdscore.types.SNParams) – S-N curve definition used by the predictor.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition and response metric used by the predictor.p_scale (
float) – Response scale factor used by the predictor. It must be compatible with the waytargetwas computed.params (
fdscore.types.IterativeInversionParams) – Iteration and regularization parameters.
- Returns:
Synthesized acceleration PSD on
f_psd_hz. The result metadata includes convergence diagnostics, reconstructed FDS traces, and explicit per-engine parameter usage.- Return type:
Notes
The update strategy implemented here is a library-specific multiplicative inversion heuristic. It is not claimed as a closed-form method from the fatigue literature.
The convergence metric stored in
meta["diagnostics"]["best_err"]is the median absolute log10-domain mismatch over bins where both target and predicted damage are positive:\[median\left(\left|\log_{10} F_{pred} - \log_{10} F_{target}\right|\right)\]The main loop performs two predictor evaluations per iteration: one on the current PSD to derive oscillator-wise gains, and one after the multiplicative update to score the candidate that may become the new best solution.
If post-smoothing and post-refinement are enabled, an additional spectral inversion pass is launched from the smoothed candidate using a reduced parameter set. The metadata distinguishes whether the best result came from the main loop, the post-smooth stage, or the post-refine stage.
References
Dirlik, T. (1985). Application of computers in fatigue analysis. Miner, M. A. (1945). “Cumulative Damage in Fatigue.” Journal of Applied Mechanics, 12(3), A159-A164.
- fdscore.invert_fds_iterative_time(target, *, f_psd_hz, psd_seed, fs, duration_s, sn, sdof, p_scale, params=IterativeInversionParams(iters=30, gamma=0.8, gain_min=0.2, gain_max=5.0, alpha_sharpness=1.0, floor=1e-30, smooth_enabled=True, smooth_window_bins=11, smooth_every_n_iters=1, prior_blend=0.0, prior_power=1.0, edge_anchor_hz=0.0, edge_anchor_blend=0.0, tail_cap_start_hz=0.0, tail_cap_ratio=0.0, low_cap_ratio=0.0, post_smooth_window_bins=0, post_smooth_blend=1.0, post_refine_iters=0, post_refine_gamma=0.5, post_refine_min=0.7, post_refine_max=2.2), n_realizations=1, seed=0, nfft=None, target_duration_s=None)[source]¶
Iteratively synthesize a PSD that matches a target FDS with a time predictor.
This routine solves the inverse problem “find an acceleration PSD whose time-domain FDS matches
target” by repeatedly synthesizing time histories from the candidate PSD and re-evaluatingfdscore.compute_fds_time().Algorithm
Let \(F_{target}\) be the target damage spectrum and let \(F(P)\) be the average time-domain predictor response for candidate PSD \(P\). The method builds a PSD-to-oscillator influence matrix from the SDOF transfer model and converts it to a normalized redistribution matrix \(\alpha\).
For each predictor call, the routine synthesizes
n_realizationsrandom-phase time histories from \(P\), evaluates their FDS withfdscore.compute_fds_time(), and averages the resulting damage spectra.Oscillator-wise multiplicative gains are computed as
\[s_i = \left(\frac{F_{target, i}}{F_i(P)}\right)^{2 / k}\]and clipped to the interval defined by
gain_minandgain_max. Those gains are projected back to PSD bins through\[u = \exp\left(\alpha^T \log(s)\right)\]The candidate PSD is then updated multiplicatively as
\[P \leftarrow P \, u^{\gamma}\]followed by optional smoothing and prior blending. The updated PSD is re-evaluated and scored by the median absolute log10-domain mismatch.
- Parameters:
target (
fdscore.types.FDSResult) – Target FDS result. It must carry compatibility metadata.f_psd_hz (
numpy.ndarray) – Frequency grid in Hz for the synthesized acceleration PSD.psd_seed (
numpy.ndarray) – Strictly positive seed PSD defined onf_psd_hz.fs (
float) – Sampling rate in Hz used during time synthesis and FDS evaluation.duration_s (
float) – Synthetic duration in seconds used for each predictor realization.sn (
fdscore.types.SNParams) – S-N curve definition used by the time-domain predictor.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition and response metric used by the predictor.p_scale (
float) – Response scale factor used by the predictor. It must be compatible with the waytargetwas computed.params (
fdscore.types.IterativeInversionParams) – Iteration and regularization parameters.n_realizations (
int) – Number of random-phase synthesized histories averaged per predictor call.seed (
intorNone) – Seed for reproducible synthesis. Realizationrusesseed + r.nfft (
intorNone) – FFT length used during synthesis. IfNone, the synthesis routine chooses the next power of two.target_duration_s (
floatorNone) –Optional duration to which the predictor damage is rescaled through
\[D_{scaled} = D_{synth} \frac{T_{target}}{T_{synth}}\]If
None, no duration scaling is applied.
- Returns:
Synthesized acceleration PSD on
f_psd_hz. The result metadata includes convergence diagnostics, predictor configuration, and explicit per-engine parameter usage.- Return type:
Notes
The inversion heuristic implemented here is library-specific. It combines a stochastic time-history predictor with a multiplicative PSD update and does not correspond to a published closed-form inversion formula.
The convergence metric stored in
meta["diagnostics"]["best_err"]is the median absolute log10-domain mismatch over bins where both target and predicted damage are positive.The main loop performs two predictor evaluations per iteration: one on the current PSD to derive oscillator-wise gains, and one after the update to score the candidate that may become the best solution.
Because the predictor is stochastic, convergence depends on
n_realizations,seed,duration_s, andnfft. The fixed internal predictor policy is recorded inmeta["diagnostics"]["predictor_config"]and currently usessynthesize_time_from_psd(remove_mean=True)together withcompute_fds_time(detrend="none", batch_size=64).References
ASTM E1049-85(2017). Standard Practices for Cycle Counting in Fatigue Analysis. Miner, M. A. (1945). “Cumulative Damage in Fatigue.” Journal of Applied Mechanics, 12(3), A159-A164.
PSD Analysis and Signal Synthesis¶
These functions estimate acceleration PSDs, derive scalar PSD metrics, and synthesize stationary Gaussian realizations.
- fdscore.compute_psd_welch(x, fs, psd)[source]¶
Compute a one-sided PSD using Welch’s method.
- Parameters:
x (
numpy.ndarray) – One-dimensional input time history.fs (
float) – Sampling rate in Hz.psd (
fdscore.types.PSDParams) – PSD-estimation settings. The current implementation supports onlymethod="welch".
- Return type:
- Returns:
f_hz (
numpy.ndarray) – One-dimensional frequency grid in Hz.psd_values (
numpy.ndarray) – One-dimensional PSD values in units squared per hertz.
Notes
This helper is purely numerical and performs no file I/O.
The output is the one-sided PSD returned by Welch’s method under the requested detrending, window, overlap, and segment-length settings. When
psd.fminorpsd.fmaxis provided, the spectrum is cropped after estimation.Tiny negative PSD values caused by floating-point noise are clipped to zero. Materially negative values are rejected because they would invalidate downstream log-domain operations and stochastic synthesis.
References
Welch, P. D. (1967). The use of the fast Fourier transform for the estimation of power spectra: A method based on time averaging over short, modified periodograms. IEEE Transactions on Audio and Electroacoustics, 15(2), 70-73.
- fdscore.compute_psd_metrics(psd, *, f_hz=None, duration_s=None, acc_unit=None, acc_to_m_s2=None, bands_hz=((5.0, 20.0), (20.0, 80.0), (80.0, 200.0), (200.0, 400.0)))[source]¶
Compute scalar summary metrics from an acceleration PSD.
The routine derives RMS, Gaussian peak estimates, velocity and displacement metrics, and band-limited RMS values from a one-sided acceleration PSD.
- Parameters:
psd (
fdscore.types.PSDResultornumpy.ndarray) – Either aPSDResultor a one-dimensional PSD array.f_hz (
numpy.ndarrayorNone) – Frequency vector in Hz whenpsdis passed as a raw array. Must be omitted whenpsdis aPSDResult.duration_s (
floatorNone) – Exposure duration used for Gaussian peak estimation. IfNone, peak-related outputs are returned asnan.acc_unit (
strorNone) – Acceleration unit of the PSD values. Supported values are"g"and"m/s2".acc_to_m_s2 (
floatorNone) – Explicit conversion factor from the PSD acceleration unit to \(m/s^2\). If provided, overridesacc_unit.bands_hz (
collections.abc.Sequence) – Sequence of(f_lo, f_hi)frequency-band pairs used to compute band-limited RMS acceleration ing.
- Returns:
Structured set of scalar metrics including acceleration RMS and peak, zero-upcrossing rate, effective cycles, velocity metrics, displacement metrics, and per-band RMS values.
- Return type:
Notes
RMS values are obtained by integrating the one-sided PSD. Velocity and displacement PSDs are derived from acceleration through division by \(\omega^2\) and \(\omega^4\), respectively, for nonzero angular frequency.
When
duration_sis provided, the peak factor is estimated with a Gaussian extreme-value approximation of Davenport form:\[\nu_0 = \frac{1}{2 \pi} \sqrt{\frac{m_2}{m_0}}\]\[n_{eff} = \nu_0 T\]\[u = \sqrt{2 \ln(n_{eff})}\]\[peak\_factor \approx u + \frac{\gamma_E}{u}\]where \(m_0\) and \(m_2\) are spectral moments and \(\gamma_E\) is the Euler-Mascheroni constant. The implementation floors \(n_{eff}\) at \(e\) to avoid a singular or negative argument in the logarithm for very short exposures or very low zero-upcrossing rates.
These peak estimates assume a stationary Gaussian response process. They should be interpreted cautiously for strongly non-stationary environments, deterministic transients, or markedly non-Gaussian signals.
References
- Davenport, A. G. (1964). “Note on the Distribution of the Largest Value of
a Random Function with Application to Gust Loading.” Proceedings of the Institution of Civil Engineers, 28(2), 187-196.
- fdscore.synthesize_time_from_psd(*, f_psd_hz, psd, fs, duration_s, seed=None, nfft=None, remove_mean=True)[source]¶
Synthesize a stationary Gaussian time history from a one-sided PSD.
- Parameters:
f_psd_hz (
numpy.ndarray) – One-dimensional one-sided PSD frequency grid in Hz.psd (
numpy.ndarray) – One-dimensional one-sided PSD values in units squared per hertz.fs (
float) – Sampling rate in Hz.duration_s (
float) – Desired duration in seconds. The output length isN = round(duration_s * fs).seed (
intorNone) – Random seed used for reproducible phase generation.nfft (
intorNone) – FFT length used for synthesis. IfNone, the next power of two greater than or equal toNis used. If provided, it must satisfynfft >= N.remove_mean (
bool) – IfTrue, subtract the sample mean after synthesis.
- Returns:
Synthesized time history of length
N.- Return type:
Notes
This routine is typically used by iterative inversion predictors that map a PSD to a synthetic time history.
The generated realization is stationary and Gaussian by construction and preserves the target PSD only in the statistical, ensemble sense. It does not reproduce transient structure, non-stationarity, or non-Gaussian tails.
The PSD is first interpolated onto the FFT frequency bins associated with
nfft. Random phases are then assigned to the interior one-sided bins, while the singleton DC and Nyquist bins are handled separately to preserve the Hermitian structure required by the real inverse FFT.For finite durations, Welch estimates from the synthesized signal will not match the input PSD exactly point by point.
Deterministic Harmonic Workflows¶
These APIs cover single-tone, dwell-profile, and dwell-discretized sweep analyses.
- fdscore.compute_ers_sine(*, freq_hz, amp, sdof, input_motion='acc', peak_mode='abs')[source]¶
Compute deterministic ERS for a single harmonic base excitation.
The returned spectrum is the response-amplitude spectrum of the selected SDOF metric. For a pure sinusoid, the absolute peak response is equal to the response amplitude, so the ERS is obtained directly from the harmonic transfer magnitude.
- Parameters:
freq_hz (
float) – Excitation frequency of the sinusoid in Hz.amp (
float) – Input amplitude expressed in the units implied byinput_motion.sdof (
SDOFParams) – Oscillator-grid definition and response metric.input_motion (
Literal['acc','vel','disp']) –Type of the specified harmonic amplitude. The routine converts the input to equivalent base-acceleration amplitude through
\[\begin{split}a_{base,amp} = \begin{cases} amp, & \text{if input\_motion = "acc"} \\ \omega \, amp, & \text{if input\_motion = "vel"} \\ \omega^2 \, amp, & \text{if input\_motion = "disp"} \end{cases}\end{split}\]where \(\omega = 2 \pi f\).
peak_mode (
Literal['abs']) – Peak convention for the ERS. Only"abs"is currently supported.
- Returns:
Response-amplitude spectrum on the oscillator grid.
- Return type:
Notes
The result is deterministic and contains no cycle counting or statistical assumptions. It is obtained from the magnitude of the linear SDOF transfer function at the single forcing frequency.
- fdscore.compute_fds_sine(*, freq_hz, amp, duration_s, sn, sdof, input_motion='acc', p_scale=None)[source]¶
Compute deterministic FDS for a single harmonic base excitation.
This routine evaluates the damage caused by a sinusoidal base input of frequency
freq_hzacting forduration_sseconds. Each oscillator is driven at the same forcing frequency and its steady-state response amplitude is converted directly to Miner damage.- Parameters:
freq_hz (
float) – Excitation frequency of the sinusoid in Hz.amp (
float) – Input amplitude expressed in the units implied byinput_motion.duration_s (
float) – Exposure duration in seconds.sn (
fdscore.types.SNParams) – S-N curve definition used for Miner damage accumulation.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition and response metric.input_motion (
str) – Optional input-motion type. Accepted values are"acc","vel", and"disp". Internally the routine converts velocity and displacement amplitudes to equivalent base-acceleration amplitude using \(\omega amp\) and \(\omega^2 amp\), respectively.p_scale (
floatorNone) – Optional response scale factor applied before damage evaluation.
- Returns:
Deterministic damage spectrum on the oscillator grid.
- Return type:
Notes
For a single harmonic input, the damage model reduces to
\[D(f_0) = N_{cycles} \frac{\left(p_{scale} S(f_0)\right)^k}{C}\]where \(N_{cycles} = f \, T\), \(S(f_0)\) is the response load amplitude derived from the chosen metric, and \(C\) is the S-N intercept. When
sn.amplitude_from_rangeisFalse, the full range2 S(f_0)is used instead of alternating amplitude.References
- Miner, M. A. (1945). “Cumulative Damage in Fatigue.” Journal of Applied
Mechanics, 12(3), A159-A164.
- fdscore.compute_ers_dwell_profile(segments, *, sdof, peak_mode='abs')[source]¶
Compute mission-level ERS as the envelope of harmonic dwell segments.
- Parameters:
segments (
Sequence[SineDwellSegment]) – Sequence of deterministic harmonic dwell segments.sdof (
SDOFParams) – Oscillator-grid definition and response metric.peak_mode (
Literal['abs']) – Peak convention for the ERS. Only"abs"is currently supported.
- Returns:
Pointwise envelope of the ERS results produced by the individual segments.
- Return type:
Notes
Each segment is evaluated independently with
compute_ers_sine(), and the final result is the pointwise maximum across segments on a compatible oscillator grid.
- fdscore.compute_fds_dwell_profile(segments, *, sn, sdof, p_scale=None)[source]¶
Compute mission-level FDS as the sum of harmonic dwell-segment damage.
- Parameters:
segments (
collections.abc.Sequence) – Sequence offdscore.types.SineDwellSegmentdwell segments.sn (
fdscore.types.SNParams) – S-N curve definition used for Miner damage accumulation.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition and response metric.p_scale (
floatorNone) – Optional response scale factor applied before damage evaluation.
- Returns:
Damage spectrum equal to the sum of the per-segment deterministic FDS results.
- Return type:
Notes
The function assumes linear cumulative damage and therefore sums the independent damage spectra computed for each dwell segment.
References
- Miner, M. A. (1945). “Cumulative Damage in Fatigue.” Journal of Applied
Mechanics, 12(3), A159-A164.
- fdscore.compute_ers_sine_sweep(*, f_start_hz, f_stop_hz, amp, duration_s, sdof, input_motion='acc', peak_mode='abs', spacing='log', n_steps=200)[source]¶
Approximate deterministic ERS for a sine sweep via dwell discretization.
- Parameters:
f_start_hz (
float) – Sweep start frequency in Hz.f_stop_hz (
float) – Sweep stop frequency in Hz.amp (
float) – Input amplitude expressed in the units implied byinput_motion.duration_s (
float) – Total sweep duration in seconds.sdof (
SDOFParams) – Oscillator-grid definition and response metric.input_motion (
Literal['acc','vel','disp']) – Type of the specified harmonic amplitude.peak_mode (
Literal['abs']) – Peak convention for the ERS. Only"abs"is currently supported.spacing (
Literal['linear','log']) – Frequency spacing of the dwell discretization, either"linear"or"log".n_steps (
int) – Number of dwell segments used to approximate the sweep.
- Returns:
Deterministic ERS approximation of the sweep.
- Return type:
Notes
The sweep is approximated as a sequence of constant-frequency dwell segments of equal duration. Convergence improves as
n_stepsincreases, especially near sharp resonances and for logarithmic sweeps spanning large frequency ranges.
- fdscore.compute_fds_sine_sweep(*, f_start_hz, f_stop_hz, amp, duration_s, sn, sdof, input_motion='acc', p_scale=None, spacing='log', n_steps=200)[source]¶
Approximate deterministic FDS for a sine sweep via dwell discretization.
- Parameters:
f_start_hz (
float) – Sweep start frequency in Hz.f_stop_hz (
float) – Sweep stop frequency in Hz.amp (
float) – Input amplitude expressed in the units implied byinput_motion.duration_s (
float) – Total sweep duration in seconds.sn (
fdscore.types.SNParams) – S-N curve definition used for Miner damage accumulation.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition and response metric.input_motion (
str) – Optional input-motion type. Accepted values are"acc","vel", and"disp".p_scale (
floatorNone) – Optional response scale factor applied before damage evaluation.spacing (
str) – Optional spacing mode for the dwell discretization. Accepted values are"linear"and"log".n_steps (
int) – Number of dwell segments used to approximate the sweep.
- Returns:
Deterministic FDS approximation of the sweep.
- Return type:
Notes
The result is obtained by discretizing the sweep into harmonic dwell segments and summing their individual damage spectra. Convergence with respect to
n_stepsshould be checked whenever the sweep crosses narrow resonances or when the requested damage estimate is used quantitatively.References
- Miner, M. A. (1945). “Cumulative Damage in Fatigue.” Journal of Applied
Mechanics, 12(3), A159-A164.
ERS Workflows¶
These functions compute and combine generic extreme-response spectra.
- fdscore.compute_ers_time(x, fs, sdof, *, detrend='linear', strict_nyquist=True, batch_size=64, peak_mode='abs', plan=None, engine='incremental', zoh_r_max=0.2)[source]¶
Compute time-domain ERS by evaluating an SDOF bank on an input history.
- Parameters:
x (
numpy.ndarray) – One-dimensional input time history.fs (
float) – Sampling rate in Hz.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition and response metric.detrend (
{"linear", "mean", "none"}, optional) – Preprocessing mode applied before the FFT.strict_nyquist (
bool, optional) – Whether oscillator frequencies at or above Nyquist should raise an error instead of being clipped.batch_size (
int, optional) – Number of oscillator responses reconstructed simultaneously in each FFT batch. Only used whenengine="fft".peak_mode (
{"abs"}, optional) – Peak convention for the ERS. The current implementation supports only absolute peaks.plan (
fdscore.types.FDSTimePlanorNone, optional) – Optional reusable transfer plan matching the current sampling and oscillator configuration. Only used whenengine="fft".engine (
{"fft", "incremental"}, optional) –Internal computation engine.
"fft"Original FFT-domain engine. Applies the continuous SDOF transfer function to
rfft(x)and reconstructs each oscillator response withirfftin batches."incremental"(default)Sample-by-sample SDOF integration using exact ZOH state- transition matrices. Peaks are tracked online, so the full
(n_osc, n_samples)response matrix is never materialized. Oscillators near Nyquist are integrated with adaptive upsampling controlled byzoh_r_max.
zoh_r_max (
float, optional) – Maximum toleratedf0 / Nyquist_effectiveratio for the incremental ZOH engine. Smaller values reduce the high-frequency ZOH attenuation error at the cost of larger upsample factors. Ignored whenengine="fft".
- Returns:
Extreme-response spectrum evaluated on the validated oscillator grid.
- Return type:
Notes
The ERS is tied to the selected
sdof.metricand therefore may represent absolute acceleration, relative displacement, relative velocity, or pseudo-velocity depending on the chosen SDOF setup.A compatible
FDSTimePlancan be reused by the FFT engine because it stores only the transfer data for a fixed(fs, n_samples, metric, q, f-grid)configuration. Reuse avoids rebuilding the transfer matrix on repeated calls with the same sampling contract.The computational pipeline is:
Validate the SDOF definition and requested frequency grid.
Enforce or apply Nyquist handling.
Preprocess the input signal.
Evaluate the oscillator bank with the selected engine.
Extract the peak absolute response for each oscillator.
The incremental engine is designed to match the FFT baseline while avoiding the cost of inverse FFT reconstruction for every oscillator. Small differences near the top of the frequency grid remain possible because the two engines use different discretization schemes (continuous FRF on discrete FFT bins versus causal ZOH state integration).
- fdscore.compute_ers_spectral_psd(f_psd_hz, psd_baseacc, *, duration_s, sdof, nyquist_hz=None, edge_correction=True)[source]¶
Compute a spectral/random ERS from a one-sided acceleration PSD.
This workflow interprets the ERS as the expected extreme response of a stationary Gaussian process over
duration_s. It is therefore a different quantity fromfdscore.compute_ers_time(), which extracts the maximum observed in a realized time history.For generic metrics, the response PSD is built as
\[P_{resp}(f; f_n) = \left| H(f; f_n) \right|^2 P_{base}(f)\]and the response moments
\[m_0 = \int P_{resp}(f) \, df\]\[m_2 = \int (2\pi f)^2 P_{resp}(f) \, df\]are used to estimate the peak rate and the expected Gaussian maximum.
For
sdof.metric="acc", the implementation uses a Lalanne-style relative-displacement/random-peak formulation that is better aligned with classical random-vibration ERS practice for acceleration spectra. Other metrics use the exact response-PSD moment route.- Parameters:
f_psd_hz (
numpy.ndarray) – One-sided PSD frequency grid in Hz.psd_baseacc (
numpy.ndarray) – One-sided base-acceleration PSD defined onf_psd_hz.duration_s (
float) – Exposure duration associated with the expected extreme response.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition and response metric.nyquist_hz (
floatorNone, optional) – Original Nyquist limit of the underlying time-history sampling. This is used only whenedge_correction=Trueand the PSD has been cropped below that limit.edge_correction (
bool, optional) – Whether to apply an automatic high-frequency edge correction for cropped PSDs. The correction is a per-oscillator raised-cosine taper over a bandwidth proportional tozeta * f_nand is a no-op when the PSD already reachesnyquist_hz.
- Returns:
Spectral/random ERS evaluated on the oscillator grid defined by
sdof.- Return type:
Notes
This route assumes that the PSD is an adequate descriptor of the environment and that Gaussian extreme-value statistics are an acceptable approximation for the response process.
The high-frequency edge correction exists because PSD exports are often cropped below the original Nyquist frequency for plotting or exchange. Near the top of the oscillator grid, that cropping can artificially suppress the response moments unless the missing tail is reconstructed.
References
Davenport, A. G. (1964). Note on the Distribution of the Largest Value of a Random Function with Application to Gust Loading. Lalanne, C. Mechanical Vibration and Shock Analysis, Volume 3 (Random Vibration).
- fdscore.compute_ers_spectral_time(x, fs, *, sdof, psd, duration_s=None, edge_correction=True)[source]¶
Compute a spectral/random ERS from a time history through Welch.
This convenience route first estimates a one-sided acceleration PSD with
fdscore.compute_psd_welch()and then delegates tofdscore.compute_ers_spectral_psd().- Parameters:
x (
numpy.ndarray) – One-dimensional base-acceleration time history.fs (
float) – Sampling rate in Hz.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition and response metric.psd (
fdscore.types.PSDParams) – PSD-estimation settings passed tocompute_psd_welch(...).duration_s (
floatorNone, optional) – Exposure duration associated with the expected extreme response. IfNone, useslen(x) / fs.edge_correction (
bool, optional) – Whether to enable the automatic high-frequency edge correction when the internally estimated PSD is cropped below Nyquist.
- Returns:
Spectral/random ERS evaluated from the internally estimated PSD.
- Return type:
Notes
This function is a convenience wrapper. It is not equivalent to
fdscore.compute_ers_time(), which operates on the realized time history directly and extracts the maximum observed response.
- fdscore.envelope_ers(results)[source]¶
Compute a pointwise envelope across compatible ERS results.
- Parameters:
results (
collections.abc.Sequenceoffdscore.types.ERSResult) – Response spectra to combine. All inputs must share the same frequency grid and ERS compatibility signature.- Returns:
Envelope spectrum whose response at each oscillator frequency is the maximum of the corresponding input values.
- Return type:
Notes
Compatibility is enforced internally, so the function will reject inputs that mix different response metrics, peak conventions, oscillator assumptions, or incompatible frequency grids.
The returned result preserves the reference grid and stores provenance metadata recording the number and origin of contributing spectra.
Shock Workflows¶
These functions cover transient shock analysis, event-based workflows, rolling spectra, sided envelopes, and half-sine reduction.
- fdscore.compute_srs_time(x, fs, sdof, *, detrend='mean', strict_nyquist=True, peak_mode='abs')[source]¶
Compute a shock response spectrum (SRS) from a base-acceleration time history.
- Parameters:
x (
numpy.ndarray) – One-dimensional base-acceleration time history.fs (
float) – Sampling rate in Hz.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition. For this wrapper,sdof.metricmust be"acc".detrend (
{"linear", "mean", "median", "none"}, optional) – Detrending mode applied before the shock-spectrum calculation.strict_nyquist (
bool, optional) – Whether oscillator frequencies at or above Nyquist should raise an error instead of being clipped.peak_mode (
{"abs", "pos", "neg", "both"}, optional) – Requested peak convention."both"returns separate negative and positive spectra.
- Returns:
One-sided results are returned as
ERSResult. Whenpeak_mode="both", the function returns aShockSpectrumPaircontaining the negative and positive sides.- Return type:
Notes
This wrapper uses the dedicated recursive shock engine implemented in
fdscore._shock_iir.The returned spectrum is tagged with
ers_kind="shock_response_spectrum"so that downstream envelope and compatibility operations can distinguish it from generic ERS or PVSS results.
- fdscore.compute_pvss_time(x, fs, sdof, *, detrend='mean', strict_nyquist=True, peak_mode='abs')[source]¶
Compute a pseudo-velocity shock spectrum (PVSS) from a base-acceleration time history.
- Parameters:
x (
numpy.ndarray) – One-dimensional base-acceleration time history.fs (
float) – Sampling rate in Hz.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition. For this wrapper,sdof.metricmust be"pv".detrend (
{"linear", "mean", "median", "none"}, optional) – Detrending mode applied before the shock-spectrum calculation.strict_nyquist (
bool, optional) – Whether oscillator frequencies at or above Nyquist should raise an error instead of being clipped.peak_mode (
{"abs", "pos", "neg", "both"}, optional) – Requested peak convention."both"returns separate negative and positive spectra.
- Returns:
One-sided results are returned as
ERSResult. Whenpeak_mode="both", the function returns aShockSpectrumPaircontaining the negative and positive sides.- Return type:
Notes
This wrapper uses the dedicated recursive shock engine implemented in
fdscore._shock_iir.The returned spectrum is tagged with
ers_kind="pseudo_velocity_shock_spectrum"so that downstream tooling can distinguish PVSS results from generic ERS and classical acceleration-based SRS.
- fdscore.detect_shock_events(x, fs, *, detrend='median', polarity='abs', threshold_reference='rms', threshold_multiplier=5.0, threshold_value=None, min_separation_s=0.05, window_s=None)[source]¶
Detect discrete shock events in a 1D acceleration time history.
- Parameters:
x (
numpy.ndarray) – One-dimensional acceleration time history.fs (
float) – Sampling rate in Hz.detrend (
{"linear", "mean", "median", "none"}, optional) – Preprocessing mode applied before peak detection.polarity (
{"abs", "pos", "neg"}, optional) – Whether detection is performed on absolute, positive-only, or negative-only peaks.threshold_reference (
{"rms", "std", "peak"}, optional) – Reference statistic used whenthreshold_valueis not provided.threshold_multiplier (
float, optional) – Positive multiplier applied to the selected threshold reference.threshold_value (
floatorNone, optional) – Explicit absolute threshold. When provided, it overrides the reference-based threshold calculation.min_separation_s (
float, optional) – Minimum temporal separation enforced between detected peaks.window_s (
floatorNone, optional) – Total extraction-window duration centered on each detected peak. When omitted, the detector derives the window frommin_separation_s.
- Returns:
Detected events returned as a
ShockEventSet, together with sampling metadata and detector settings.- Return type:
Notes
This is an axis-first detector intended for event-oriented shock workflows. It is most useful when a long recording contains multiple isolated transients and each transient should be analyzed with a dedicated local spectrum.
The stored event windows are index based. They can therefore be used directly to slice the original signal without recomputing detection state.
- fdscore.compute_rolling_srs_time(x, fs, sdof, events, *, detrend='median', strict_nyquist=True, peak_mode='abs')[source]¶
Compute SRS on each detected shock-event window.
- Parameters:
x (
numpy.ndarray) – One-dimensional source signal containing the detected events.fs (
float) – Sampling rate in Hz.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition. For this wrapper,sdof.metricmust be"acc".events (
object) – Detected event windows that define the rolling segments. The input must be aShockEventSetinstance.detrend (
{"linear", "mean", "median", "none"}, optional) – Preprocessing mode applied independently to each event window.strict_nyquist (
bool, optional) – Whether oscillator frequencies at or above Nyquist should raise an error instead of being clipped.peak_mode (
{"abs", "pos", "neg"}, optional) – Peak convention used for each event-local spectrum.
- Returns:
Rolling result returned as a
RollingERSResult. Each row corresponds to one detected event and each column corresponds to one oscillator frequency.- Return type:
Notes
Rolling shock spectra are currently event-window based rather than fixed-hop or sliding-window based. The time coordinate stored in the result corresponds to the detected peak time of each event.
If no events are present, the function still returns a valid empty matrix with the validated oscillator frequency grid.
- fdscore.compute_rolling_pvss_time(x, fs, sdof, events, *, detrend='median', strict_nyquist=True, peak_mode='abs')[source]¶
Compute PVSS on each detected shock-event window.
- Parameters:
x (
numpy.ndarray) – One-dimensional source signal containing the detected events.fs (
float) – Sampling rate in Hz.sdof (
fdscore.types.SDOFParams) – Oscillator-grid definition. For this wrapper,sdof.metricmust be"pv".events (
object) – Detected event windows that define the rolling segments. The input must be aShockEventSetinstance.detrend (
{"linear", "mean", "median", "none"}, optional) – Preprocessing mode applied independently to each event window.strict_nyquist (
bool, optional) – Whether oscillator frequencies at or above Nyquist should raise an error instead of being clipped.peak_mode (
{"abs", "pos", "neg"}, optional) – Peak convention used for each event-local spectrum.
- Returns:
Rolling result returned as a
RollingERSResult. Each row corresponds to one detected event and each column corresponds to one oscillator frequency.- Return type:
Notes
Rolling shock spectra are currently event-window based rather than fixed-hop or sliding-window based. The time coordinate stored in the result corresponds to the detected peak time of each event.
If no events are present, the function still returns a valid empty matrix with the validated oscillator frequency grid.
- fdscore.envelope_srs(results)[source]¶
Compute an envelope across compatible shock-response spectra.
- Parameters:
results (
collections.abc.Sequence) – Sequence containing either one-sidedERSResultvalues or two-sidedShockSpectrumPairvalues. Mixing the two forms in a single call is not allowed.- Returns:
Enveloped one-sided or two-sided shock-response spectrum, matching the representation of the input sequence.
- Return type:
Notes
This function accepts only spectra whose ERS compatibility metadata identifies them as
"shock_response_spectrum". For pair-valued inputs, the negative and positive sides are enveloped independently.
- fdscore.envelope_pvss(results)[source]¶
Compute an envelope across compatible pseudo-velocity shock spectra.
- Parameters:
results (
collections.abc.Sequence) – Sequence containing either one-sidedERSResultvalues or two-sidedShockSpectrumPairvalues. Mixing the two forms in a single call is not allowed.- Returns:
Enveloped one-sided or two-sided PVSS result, matching the representation of the input sequence.
- Return type:
Notes
This function accepts only spectra whose ERS compatibility metadata identifies them as
"pseudo_velocity_shock_spectrum". For pair-valued inputs, the negative and positive sides are enveloped independently.
- fdscore.fit_half_sine_to_pvss(pvss, *, polarity='pos')[source]¶
Fit a half-sine acceleration pulse whose PVSS envelopes the input PVSS.
- Parameters:
pvss (
fdscore.types.ERSResult) – One-sided pseudo-velocity shock spectrum compatible with the library’s PVSS contract.polarity (
{"pos", "neg"}, optional) – Polarity assigned to the fitted half-sine pulse.
- Returns:
Fitted pulse returned as a
HalfSinePulse, expressed in acceleration amplitude and pulse duration.- Return type:
Notes
pvssmust be a one-sidedERSResultproduced bycompute_pvss_time(...)or an otherwise compatible PVSS workflow.The fitted amplitude is expressed in the same acceleration units that were used to generate the time history behind
pvss. The duration is inferred from the pair of envelope statisticsmax(PVSS)andmax(f * PVSS)together with the damping-dependent peak factor used by the half-sine model.The method is intended as a compact pulse characterization rather than an exact waveform reconstruction of the original transient.
- fdscore.synthesize_half_sine_pulse(pulse, fs, *, total_duration_s=None, t_start_s=0.0)[source]¶
Synthesize a half-sine acceleration pulse as a one-dimensional signal.
- Parameters:
pulse (
object) – Half-sine pulse definition to synthesize. The input must be aHalfSinePulseinstance.fs (
float) – Sampling rate in Hz.total_duration_s (
floatorNone, optional) – Total output duration in seconds. When omitted, the signal is long enough to contain the pulse plus one additional pulse duration of trailing zeros.t_start_s (
float, optional) – Pulse start time in seconds within the synthesized output.
- Returns:
One-dimensional acceleration time history containing the half-sine pulse.
- Return type:
Notes
The waveform is zero outside the interval
[t_start_s, t_start_s + pulse.duration_s). Within that interval, the pulse follows a half-sine profile with the signed amplitude implied bypulse.polarity.