Using FDD or EFDD in Multistep configuration
keltouny opened this issue · 3 comments
Hello,
I am getting the following error when trying to use either FDD or EFDD with multistep configuration with 1 reference sensor and 3 roving sensors:
Cell In[1], line 303
msp.MPE_fromPlot("FDD", freqlim=(0,freq_threshold))File C:\Python39\envs\pyoma2\lib\site-packages\pyoma2\OMA.py:202 in MPE_fromPlot
self[name].mpe_fromPlot(*args, **kwargs)File C:\Python39\envs\pyoma2\lib\site-packages\pyoma2\algorithm\fdd.py:191 in mpe_fromPlot
Fn_FDD, Phi_FDD = FDD_funct.FDD_MPE(File C:\Python39\envs\pyoma2\lib\site-packages\pyoma2\functions\FDD_funct.py:293 in FDD_MPE
diffS1S2 = Sval[0, 0, idxlim[0] : idxlim[1]] / Sval[1, 1, idxlim[0] : idxlim[1]]IndexError: index 1 is out of bounds for axis 0 with size 1
Dear @keltouny,
thank you for the feedback and for using our module.
You encountered this error because with only one reference sensor, the algorithm fails when it tries to verify that the peak you selected is indeed the point with the maximum ratio between the first and second singular values (since you only have one). While this check isn't strictly necessary to obtain a result, it is the expected behavior of the algorithm (as described in the books by Brinker & Ventura and Rainieri & Fabbrocino).
I will consider adding only a warning in such situations and will get back to you after further consideration.
Thank you for your response.
I have made changes to the FDD_MPE function "in src/pyoma2/functions/FDD_funct.py" to allow single-ref-channel FDD/EFDD to accommodate my project. I am sharing them here with you in case they help fix the problem. Also, thanks to your suggestion, I have added the warning message.
`def FDD_MPE(
Sval,
Svec,
freq,
sel_freq,
DF=0.1,
):
"""
Extracts modal parameters using the Frequency Domain Decomposition (FDD) method.
Parameters
----------
Sval : ndarray
A 3D array of singular values. Dimensions are [Nch, Nref, Nf], where Nch is the
number of channels, Nref is the number of reference channels, and Nf is the
number of frequency points.
Svec : ndarray
A 3D array of singular vectors corresponding to Sval. Dimensions are the same as Sval.
freq : ndarray
1D array of frequency values corresponding to the singular values and vectors.
sel_freq : list or ndarray
Selected frequencies around which modal parameters are to be extracted.
DF : float, optional
Frequency bandwidth around each selected frequency within which the function
searches for a peak. Default is 0.1.
Returns
-------
tuple
Fn : ndarray
Extracted modal frequencies.
Phi : ndarray
Corresponding normalized mode shapes (each column corresponds to a mode shape).
Note
-----
The function assumes that the first singular value and vector correspond to the dominant
mode at each frequency point.
"""
# Sval, Svec = SD_svalsvec(Sy)
Nch, Nref, Nf = Sval.shape
Freq = []
Fi = []
index = []
maxSy_diff = []
logger.info("Extracting FDD modal parameters")
if Nref == 1:
logging.warning("Only 1 reference channel is used - Peak-searching is disabled")
for sel_fn in tqdm(sel_freq):
if Nref > 1: # peak serching is not available for single ref. ch.
# Frequency bandwidth where the peak is searched
lim = (sel_fn - DF, sel_fn + DF)
idxlim = (
np.argmin(np.abs(freq - lim[0])),
np.argmin(np.abs(freq - lim[1])),
) # Indices of the limits
# Ratios between the first and second singular value
diffS1S2 = Sval[0, 0, idxlim[0] : idxlim[1]] / Sval[1, 1, idxlim[0] : idxlim[1]]
maxDiffS1S2 = np.max(diffS1S2) # Looking for the maximum difference
idx1 = np.argmin(np.abs(diffS1S2 - maxDiffS1S2)) # Index of the max diff
idxfin = idxlim[0] + idx1 # Final index
maxSy_diff.append(maxDiffS1S2)
else:
idxfin = np.argmin(np.abs(freq - sel_fn))
# Modal properties
fn_FDD = freq[idxfin] # Frequency
phi_FDD = Svec[0, :, idxfin] # Mode shape
# Normalized (unity displacement)
phi_FDDn = phi_FDD / phi_FDD[np.argmax(np.abs(phi_FDD))]
Freq.append(fn_FDD)
Fi.append(phi_FDDn)
index.append(idxfin)
logger.debug("Done!")
Fn = np.array(Freq)
Phi = np.array(Fi).T
index = np.array(index)
return Fn, Phi`