endaq.calc
¶
endaq.calc
is a module comprising a collection of common calculations
for vibration analysis. It leverages the standard Python scientific
stack (NumPy, SciPy, Pandas) in order to enable engineers to perform
domain-specific calculations in a few lines of code, without having to
first master Python and its scientific stack in their entireties.
endaq.calc.filters
¶
- endaq.calc.filters.butterworth(df, low_cutoff=1.0, high_cutoff=None, half_order=3, tukey_percent=0.0)¶
Apply a lowpass and/or a highpass Butterworth filter to an array.
This function uses Butterworth filter designs, and implements the filter(s) as bi-directional digital biquad filters, split into second-order sections.
- Parameters
df (pandas.core.frame.DataFrame) – the input data; cutoff frequencies are relative to the timestamps in df.index
low_cutoff (Optional[float]) – the low-frequency cutoff, if any; frequencies below this value are rejected, and frequencies above this value are preserved
high_cutoff (Optional[float]) – the high-frequency cutoff, if any; frequencies above this value are rejected, and frequencies below this value are preserved
half_order (int) – half of the order of the filter; higher orders provide more aggressive stopband reduction
tukey_percent (float) – the alpha parameter of a preconditioning Tukey filter; if 0 (default), no filter is applied
- Returns
the filtered data
- Return type
pandas.core.frame.DataFrame
See also
SciPy Butterworth filter design Documentation for the butterworth filter design function.
SciPy Tukey window Documentation for the Tukey window function used in preprocessing.
endaq.calc.integrate
¶
- endaq.calc.integrate.integrals(df, n=1, zero='start', highpass_cutoff=None, tukey_percent=0.0)¶
Calculate n integrations of the given data.
- Parameters
df (pandas.core.frame.DataFrame) – the data to integrate, indexed with timestamps
n (int) – the number of integrals to calculate; defaults to 1
zero (Union[Literal['start', 'mean', 'median'], Callable]) – the output quantity driven to zero by the integration constant; “start” (default) chooses an integration constant of
-output[0]
, “mean” chooses-np.mean(output)
& “median” chooses-np.median(output)
highpass_cutoff (Optional[float]) – the cutoff frequency for the initial highpass filter; this is used to remove artifacts caused by DC trends
tukey_percent (float) – the alpha parameter of a preconditioning Tukey filter; if 0 (default), no filter is applied
- Returns
a length n+1 list of the kth-order integrals from 0 to n (inclusive)
- Return type
List[pandas.core.frame.DataFrame]
See also
SciPy trapezoid integration Documentation for the integration function used internally.
SciPy Butterworth filter design Documentation for the butterworth filter design function used in preprocessing.
SciPy Tukey window Documentation for the Tukey window function used in preprocessing.
- endaq.calc.integrate.iter_integrals(df, zero='start', highpass_cutoff=None, tukey_percent=0.0)¶
Iterate over conditioned integrals of the given original data.
- Parameters
df (pandas.core.frame.DataFrame) – the input data
zero (Union[Literal['start', 'mean', 'median'], Callable]) – the output quantity driven to zero by the integration constant; “start” (default) chooses an integration constant of
-output[0]
, “mean” chooses-np.mean(output)
& “median” chooses-np.median(output)
highpass_cutoff (Optional[float]) – the cutoff frequency of a preconditioning highpass filter; if None, no filter is applied
tukey_percent (float) – the alpha parameter of a preconditioning Tukey filter; if 0 (default), no filter is applied
- Returns
an iterable over the data’s successive integrals; the first item is the preconditioned input data
- Return type
Iterable[pandas.core.frame.DataFrame]
See also
SciPy trapezoid integration Documentation for the integration function used internally.
SciPy Butterworth filter design Documentation for the butterworth filter design function used in preprocessing.
SciPy Tukey window Documentation for the Tukey window function used in preprocessing.
endaq.calc.psd
¶
- endaq.calc.psd.differentiate(df, n=1.0)¶
Perform time-domain differentiation on periodogram data.
- Parameters
df (pandas.core.frame.DataFrame) – a periodogram
n (float) – the time derivative order; negative orders represent integration
- Returns
a periodogram of the time-derivated data
- Return type
pandas.core.frame.DataFrame
- endaq.calc.psd.to_jagged(df, freq_splits, agg='mean')¶
Calculate a periodogram over non-uniformly spaced frequency bins.
- Parameters
df (pandas.core.frame.DataFrame) – the returned values from
endaq.calc.psd.welch
freq_splits (numpy.array) – the boundaries of the frequency bins; must be strictly increasing
agg (Union[Literal['mean', 'sum'], Callable[[numpy.ndarray, int], float]]) – the method for aggregating values into bins; ‘mean’ preserves the PSD’s area-under-the-curve, ‘sum’ preserves the PSD’s “energy”
- Returns
a periodogram with the given frequency spacing
- Return type
pandas.core.frame.DataFrame
- endaq.calc.psd.to_octave(df, fstart=1.0, octave_bins=12.0, **kwargs)¶
Calculate a periodogram over log-spaced frequency bins.
- Parameters
df (pandas.core.frame.DataFrame) – the returned values from
endaq.calc.psd.welch
fstart (float) – the first frequency bin, in Hz; defaults to 1 Hz
octave_bins (float) – the number of frequency bins in each octave; defaults to 12
kwargs – other parameters to pass directly to
to_jagged
- Returns
a periodogram with the given logarithmic frequency spacing
- Return type
pandas.core.frame.DataFrame
- endaq.calc.psd.vc_curves(accel_psd, fstart=1.0, octave_bins=12.0)¶
Calculate Vibration Criterion (VC) curves from an acceration periodogram.
- Parameters
accel_psd (pandas.core.frame.DataFrame) – a periodogram of the input acceleration
fstart (float) – the first frequency bin
octave_bins (float) – the number of frequency bins in each octave; defaults to 12
- Returns
the Vibration Criterion (VC) curve of the input acceleration
- Return type
pandas.core.frame.DataFrame
- endaq.calc.psd.welch(df, bin_width=1.0, scaling=None, **kwargs)¶
Perform scipy.signal.welch with a specified frequency spacing.
- Parameters
df (pandas.core.frame.DataFrame) – the input data
bin_width (float) – the desired width of the resulting frequency bins, in Hz; defaults to 1 Hz
scaling (Optional[Literal[None, 'density', 'spectrum', 'parseval']]) – the scaling of the output; “density” & “spectrum” correspond to the same options in
scipy.signal.welch
; “parseval” will maintain the “energy” between the input & output, s.t.welch(df, scaling="parseval").sum(axis="rows")
is roughly equal todf.abs().pow(2).sum(axis="rows")
kwargs – other parameters to pass directly to
scipy.signal.welch
- Returns
a periodogram
- Return type
pandas.core.frame.DataFrame
See also
SciPy Welch’s method Documentation for the periodogram function wrapped internally.
Parseval’s Theorem - the theorem relating the RMS of a time-domain signal to that of its frequency spectrum
endaq.calc.shock
¶
- class endaq.calc.shock.HalfSineWavePulse(amplitude, duration)¶
The output data type for
enveloping_half_sine
.The significant data members are amplitude and duration, which can simply be unpacked as if from a plain tuple:
ampl, T = enveloping_half_sine(df_pvss)
However, users can also elect to use the other methods of this class to generate other kinds of outputs.
Note
This class is not intended to be instantiated manually.
- to_time_series(tstart=None, tstop=None, dt=None, tpulse=None)¶
Generate a time-series of the half-sine pulse.
- Parameters
tstart (Optional[float]) – the starting time of the resulting waveform; if None (default), the range starts at tpulse
tstop (Optional[float]) – the ending time of the resulting waveform; if None (default), the range ends at tpulse + duration
dt (Optional[float]) – the sampling period of the resulting waveform; defaults to 1/20th of the pulse duration
tpulse (Optional[float]) –
the starting time of the pulse within the resulting waveform; if None (default), the pulse starts at either:
tstart
, if providedtstop - self.duration.max())
, if tstop is provided0.0
otherwise
- Returns
a time-series of the half-sine pulse
- Return type
pandas.core.frame.DataFrame
- endaq.calc.shock.abs_accel(accel, omega, damp=0.0)¶
Calculate the absolute acceleration for a SDOF system.
- The “absolute acceleration” follows the transfer function:
H(s) = L{x”(t)}(s) / L{y”(t)}(s) = X(s)/Y(s)
- for the PDE:
x” + (2ζω)x’ + (ω²)x = (2ζω)y’ + (ω²)y
- Parameters
accel (pandas.core.frame.DataFrame) – the absolute acceleration y”
omega (float) – the natural frequency ω of the SDOF system
damp (float) – the damping coefficient ζ of the SDOF system
- Returns
the absolute acceleration x” of the SDOF system
- Return type
pandas.core.frame.DataFrame
See also
An Introduction To The Shock Response Spectrum, Tom Irvine, 9 July 2012
SciPy transfer functions Documentation for the transfer function class used to characterize the relative displacement calculation.
SciPy biquad filter Documentation for the biquad function used to implement the transfer function.
- endaq.calc.shock.enveloping_half_sine(pvss, damp=0.0)¶
Characterize a half-sine pulse whose PVSS envelopes the input.
- Parameters
pvss (pandas.core.frame.DataFrame) – the PVSS to envelope
damp (float) – the damping factor used to generate the input PVSS
- Returns
a tuple of amplitudes and periods, each pair of which describes a half-sine pulse
- Return type
- endaq.calc.shock.rel_displ(accel, omega, damp=0.0)¶
Calculate the relative displacement for a SDOF system.
- The “relative” displacement follows the transfer function:
H(s) = L{z(t)}(s) / L{y”(t)}(s) = (1/s²)(Z(s)/Y(s))
- for the PDE:
z” + (2ζω)z’ + (ω²)z = -y”
- Parameters
accel (pandas.core.frame.DataFrame) – the absolute acceleration y”
omega (float) – the natural frequency ω of the SDOF system
damp (float) – the damping coefficient ζ of the SDOF system
- Returns
the relative displacement z of the SDOF system
- Return type
pandas.core.frame.DataFrame
See also
Pseudo Velocity Shock Spectrum Rules For Analysis Of Mechanical Shock, Howard A. Gaberson
SciPy transfer functions Documentation for the transfer function class used to characterize the relative displacement calculation.
SciPy biquad filter Documentation for the biquad function used to implement the transfer function.
- endaq.calc.shock.shock_spectrum(accel, freqs, damp=0.0, mode='srs', two_sided=False, aggregate_axes=False)¶
Calculate the shock spectrum of an acceleration signal.
- Parameters
accel (pandas.core.frame.DataFrame) – the absolute acceleration y”
freqs (numpy.ndarray) – the natural frequencies across which to calculate the spectrum
damp (float) – the damping coefficient ζ, related to the Q-factor by ζ = 1/(2Q); defaults to 0
mode (Literal['srs', 'pvss']) –
the type of spectrum to calculate:
’srs’ (default) specifies the Shock Response Spectrum (SRS)
’pvss’ specifies the Pseudo-Velocity Shock Spectrum (PVSS)
two_sided (bool) – whether to return for each frequency: both the maximum negative and positive shocks (True), or simply the maximum absolute shock (False; default)
aggregate_axes (bool) – whether to calculate the column-wise resultant (True) or calculate spectra along each column independently (False; default)
- Returns
the shock spectrum
- Return type
pandas.core.frame.DataFrame
See also
Pseudo Velocity Shock Spectrum Rules For Analysis Of Mechanical Shock, Howard A. Gaberson
An Introduction To The Shock Response Spectrum, Tom Irvine, 9 July 2012
SciPy transfer functions Documentation for the transfer function class used to characterize the relative displacement calculation.
SciPy biquad filter Documentation for the biquad function used to implement the transfer function.
endaq.calc.stats
¶
- endaq.calc.stats.L2_norm(array, axis=None, keepdims=False)¶
Compute the L2 norm (a.k.a. the Euclidean Norm).
- Parameters
array (np.ndarray) – the input array
axis (Union[None, typing.SupportsIndex, Sequence[typing.SupportsIndex]]) – the axis/axes along which to aggregate; if None (default), the L2 norm is computed along the flattened array
keepdims (bool) – if True, the axes which are reduced are left in the result as dimensions of size one; if False (default), the reduced axes are removed
- Returns
an array containing the computed values
- Return type
np.ndarray
- endaq.calc.stats.max_abs(array, axis=None, keepdims=False)¶
Compute the maximum of the absolute value of an array.
This function should be equivalent to, but generally use less memory than
np.amax(np.abs(array))
.Specifically, it generates the absolute-value maximum from
np.amax(array)
and-np.amin(array)
. Thus instead of allocating space for the intermediate arraynp.abs(array)
, it allocates for the axis-collapsed smaller arraysnp.amax(array)
&np.amin(array)
.Note
This method does not work on complex-valued arrays.
- Parameters
array (np.ndarray) – the input data
axis (Union[None, typing.SupportsIndex, Sequence[typing.SupportsIndex]]) – the axis/axes along which to aggregate; if None (default), the absolute maximum is computed along the flattened array
keepdims (bool) – if True, the axes which are reduced are left in the result as dimensions with size one; if False (default), the reduced axes are removed
- Returns
an array containing the computed values
- Return type
np.ndarray
- endaq.calc.stats.rms(array, axis=None, keepdims=False)¶
Calculate the root-mean-square (RMS) along a given axis.
- Parameters
array (np.ndarray) – the input array
axis (Union[None, typing.SupportsIndex, Sequence[typing.SupportsIndex]]) – the axis/axes along which to aggregate; if None (default), the RMS is computed along the flattened array
keepdims (bool) – if True, the axes which are reduced are left in the result as dimensions with size one; if False (default), the reduced axes are removed
- Returns
an array containing the computed values
- Return type
np.ndarray
- endaq.calc.stats.rolling_rms(df, window_len, *args, **kwargs)¶
Calculate a rolling root-mean-square (RMS) over a pandas DataFrame.
This function is equivalent to, but computationally faster than the following:
df.rolling(window_len).apply(endaq.calc.stats.rms)
- Parameters
df (Union[pandas.core.frame.DataFrame, pandas.core.series.Series]) – the input data
window_len (int) – the length of the rolling window
args – the positional arguments to pass into
df.rolling().mean
kwargs – the keyword arguments to pass into
df.rolling().mean
- Returns
the rolling-windowed RMS
- Return type
Union[pandas.core.frame.DataFrame, pandas.core.series.Series]
See also
Pandas Rolling Mean - official documentation for
df.rolling().mean
Pandas Rolling Standard Deviation method - similar to this function, but first removes the windowed mean before squaring
endaq.calc.utils
¶
- endaq.calc.utils.logfreqs(df, init_freq=None, bins_per_octave=12.0)¶
Calculate a sequence of log-spaced frequencies for a given dataframe.
- Parameters
df (pandas.core.frame.DataFrame) – the input data
init_freq (Optional[float]) – the initial frequency in the sequence; if None (default), use the frequency corresponding to the data’s duration
bins_per_octave (float) – the number of frequencies per octave
- Returns
an array of log-spaced frequencies
- Return type
numpy.ndarray
- endaq.calc.utils.resample(df, sample_rate=None)¶
Resample a dataframe to a desired sample rate (in Hz)
- Parameters
df (pandas.core.frame.DataFrame) – The DataFrame to resample, indexed by time
sample_rate (Optional[float]) – The desired sample rate to resample the given data to. If one is not supplied, then it will use the same as it currently does, but make the time stamps uniformally spaced
- Returns
The resampled data in a DataFrame
- Return type
pandas.core.frame.DataFrame
- endaq.calc.utils.sample_spacing(data, convert='to_seconds')¶
Calculate the average spacing between individual samples.
For time indices, this calculates the sampling period dt.
- Parameters
data (Union[numpy.ndarray, pandas.core.frame.DataFrame]) – the input data; either a pandas DataFrame with the samples spaced along its index, or a 1D-array-like of sample times
convert (Literal[None, 'to_seconds']) – if “to_seconds” (default), convert any time objects into floating-point seconds
- endaq.calc.utils.to_dB(data, reference, squared=False)¶
Scale data into units of decibels.
Decibels are a log-scaled ratio of some value against a reference; typically this is expressed as follows:
By convention, “decibel” units tend to operate on units of power. For units that are proportional to power when squared (e.g., volts, amps, pressure, etc.), their “decibel” representation is typically doubled (i.e.,
). Users can specify which scaling to use with the squared parameter.Note
Decibels can NOT be calculated from negative values.
For example, to calculate dB on arbitrary time-series data, typically data is first aggregated via a total or a rolling RMS or PSD, and the non-negative result is then scaled into decibels.
- Parameters
data (numpy.ndarray) – the input data
reference (float) – the reference value corresponding to 0dB
squared (bool) – whether the input data & reference value are pre-squared; defaults to False
See also
endaq.calc.stats.rms
endaq.calc.stats.rolling_rms
endaq.calc.psd.welch