The tutorial

A case of typical usage is presented here.

For a more detailed use with real examples visit the showcase page.

Installation

To use pyFRF, first install it using pip:

$ pip install pyFRF

Instance of the FRF class

We start by creating the FRF object the following way:

a = pyFRF.FRF(
    sampling_freq,
    exc=None,
    resp=None,
    exc_type='f', resp_type='a',
    window='none',
    resp_delay=0.,
    weighting='linear',
    fft_len=None,
    nperseg=None,
    noverlap=None,
    archive_time_data=False,
    frf_type='H1',
    copy=True
)

sampling_freq argument

This argument determines the sampling frequency of excitation and response signals. If sampling_freq is of type int, its is asumed that both excitation and response signals have the same sampling frequency. It is possible to use signals with different sampling frequencies for exciatation and response signals if we pass the sampling_freq argumnet as list[int, int] or tuple(int, int), where the first element represents the excitation sampling frequency and the second element represents the response sampling frequency.

exc and resp arguments

Excitation and response signal arrays. The arrays can be of different shapes:

  • 1D array (single measurement, single input/output): (time_series)

  • 2D array (multiple/single measurements, single input/output): (n_measurements, time_series)

  • 3D array (general array shape, multiple/single measurements, multiple/single inputs/outputs): (n_measurements, exc_dofs or resp_dofs, time_series)

Note

For multiple inputs or multiple outputs in one measurement, the 3D array shape (general array shape) is required. 2D array shape is reserved for single input/output multiple measurements.

exc_type and resp_type arguments

Used for the correct conversion of the FRF.

Note

Available exc_type options: 'f', 'a', 'v', 'd', 'e'
Available resp_type options: 'a', 'v', 'd', 'e'

window argument

This argument determines the window used on the excitation and response signals or window that is used for cross spectral density computation. If window is of type list(str, str) or tuple(str, str), the first element represents the window that is used on the excitation signal and the second element represents the window that is used on response signal. If window is of type str, the window is used for cross spectral density computation (used for averaging, random signals and MIMO systems).

Note

Available windows: 'none', 'force', 'exponential', 'hann', 'hamming', 'bartlett', 'blackman', 'kaiser'

Note

For exponential window the percentage of the starting amplitude (float) is required (e.g. 10%: "exponential:0.1").
For force window the length of window (percentage (float) of full signal) is required (e.g. 10%: "force:0.1").

resp_delay argument

Used if there is response time delay present (in seconds) with regards to the excitation - used for FFT (phase) correction.

weighting argument

Weighting that is used for newly added measurements to FRF object or when adding separate contionuous measurements. If all the measurements are added to FRF object at the same time the weighting argument has no effect - linear averaging is used.

Note

Available wighting types: 'linear', 'exponential'

Note

For exponential weighting, the number of averages (int) has to be specified (e.g. 5 averages: "exponential:5").

fft_len argument

The length of the FFT (zero-padding if longer than length of data). If None then the fft_len matches the time length.

nperseg argument

Length of each segment used for averaging while computing cross power spectral density. If None, the whole time signal (data length) is used (no averaging).

noverlap argument

Optional segments overlap. By default (if None), then noverlap = nperseg // 2. If nperseg is not specified (data length is used), then noverlap has no effect.

archive_time_data argument

Used for archiving time data.

Note

Can consume a lot of memory.

frf_type argument

Default FRF type returned at self.get_frf().

copy argument

Determines if the excitation and response arrays are copied (if data is not copied the applied window affects the source arrays).

Adding new data

Data can be added at object creation, by passing the excitation and response signals into exc and resp arguments. Data can also be added later via add_data() method - also useful for continuous measurements:

a.add_data(exc, resp)

Single input/output

The most general array shape of excitation and response signals for all different systems (SISO, SIMO, MISO, MIMO) is a 3D ndarray of shape (n_measurements, exc_dofs or resp_dofs, time_series).

When dealing with measurements where the excitation and/or response signals are measured at only one location (DOF) at the same time, the excitation/response array shape can be of 3 different shapes:

  • 1D array (single measurement): (time_series)

  • 2D array (multiple/single measurements): (n_measurements, time_series)

  • 3D array (general shape, multiple/single measurements): (n_measurements, 1, time_series)

Multiple inputs/outputs

For measurements where the excitation and/or response signals are measured at multiple locations (DOFs) at the same time the general array shape must be used:

  • 3D array: (n_measurements, exc_dofs or resp_dofs, time_series)

Checking data

Before adding data, it is useful to check if the measurements are ok. The is_data_ok() method checks if any of the provided excitation signals contains double impacts (for modal hammer impact testing measurements), or if excitation and response signals are overflowed.

Argument overflow_samples represents the number of samples that need to be equal to max for overflow identification.

Argument double_impact_limit represents the ratio of freqency content of the double vs single hit. Smaller number means more sensitivity.

We can show the status of overflow and double impact measurements via argument verbose.

a.is_data_ok(exc, resp, overflow_samples=3, double_impact_limit=1e-3, verbose=0)

Getting frequency and time axis

To get the frequency axis array, we use the method get_f_axis() or get_w_axis() for angular frequency. We can also get delta frequency via get_df() method. For time axis we use the method get_t_axis():

freq = a.get_f_axis()
w = a.get_w_axis()
df = a.get_df()
time = a.get_t_axis()

Obtaining FRF

get_FRF() method

Preferable way to get the frequency response functions is via get_FRF() method, where we use the type argument to specify the type of FRF. By default the returned FRF type is the one set at object creation (if no type is specified at object creation then the type is set to H1). With the argument form we control the returned form of the FRF (receptance by default).

As result we get the FRF matrix (ndarray) of shape (resp_dofs, exc_dofs, frequency_series):

frf = a.get_FRF(type="default", form="receptance")

Note

type argument options: 'H1', 'H2', 'Hv', 'ODS'
form argumnet options: 'accelerance', 'mobility', 'receptance'

Other (direct) methods

We can also directly get the requested FRF via other methods: get_H1(), get_H2(), get_Hv() and, get_ods_frf(). That way we can not control the form of the returned FRF. The returned FRF form of these methods is receptance:

H1 = a.get_H1()
H2 = a.get_H2()
Hv = a.get_Hv()
ods_frf = a.get_ods_frf()

Coherence

To get coherence we simply use the methods get_coherence(), which returns the coherence ndarray of shape (resp_dofs, frequency_series):

coh = a.get_coherence()