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
exc_type
options: 'f', 'a', 'v', 'd', 'e'
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
float
) is required (e.g. 10%: "exponential:0.1"
).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
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()