Modules¶
Core Types¶
postmodal.types
¶
Custom types and data classes for modal analysis.
ComplexityMetrics
dataclass
¶
Container for modal complexity metrics.
Attributes:
| Name | Type | Description |
|---|---|---|
mpc |
ndarray
|
Modal Phase Collinearity values [n_modes] |
map |
ndarray
|
Modal Amplitude Proportionality values [n_modes] |
mpd |
ndarray
|
Mean Phase Deviation values [n_modes] in degrees |
Source code in postmodal/types.py
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | |
__post_init__() -> None
¶
Validate the metrics after initialization.
Source code in postmodal/types.py
94 95 96 97 98 99 100 101 102 | |
ModalData
dataclass
¶
Container for modal analysis data.
Attributes:
| Name | Type | Description |
|---|---|---|
frequencies |
ndarray
|
Array of natural frequencies [n_modes]. Must be positive real values. |
modeshapes |
ndarray
|
Array of mode shapes [n_modes x n_dof] |
damping |
(ndarray, optional)
|
Array of damping ratios [n_modes], defaults to zeros. Must be real-valued positive numbers in range [0, 1]. |
Source code in postmodal/types.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
__post_init__() -> None
¶
Validate the data after initialization.
Source code in postmodal/types.py
69 70 71 72 73 | |
options: show_root_heading: true show_source: true
Validation¶
postmodal.validation
¶
Validation utilities for modal analysis data.
ModalValidator
¶
Validator for modeshape data.
Source code in postmodal/validation.py
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | |
validate(modeshape: np.ndarray) -> None
staticmethod
¶
Validate a modeshape array.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
The modeshape array to validate |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If modeshape is not a numpy array |
ValueError
|
If modeshape has incorrect dimensions |
Source code in postmodal/validation.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
validate_frequency(frequency: np.ndarray) -> None
staticmethod
¶
Validate frequency data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frequency
|
ndarray
|
Array of frequencies to validate |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If frequency is not a numpy array |
ValueError
|
If frequency is not 1D or contains non-positive values |
Source code in postmodal/validation.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | |
validate_pair(phi_1: np.ndarray, phi_2: np.ndarray) -> None
staticmethod
¶
Validate a pair of modeshapes for comparison.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
phi_1
|
ndarray
|
First modeshape |
required |
phi_2
|
ndarray
|
Second modeshape |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If modeshapes have different shapes |
Source code in postmodal/validation.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | |
validate_modal_data(frequencies: np.ndarray, modeshapes: np.ndarray) -> None
¶
Validate modal data (frequencies and modeshapes).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frequencies
|
ndarray
|
Array of natural frequencies [n_modes] |
required |
modeshapes
|
ndarray
|
Array of mode shapes [n_modes x n_dof] |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If data dimensions are incompatible |
Source code in postmodal/validation.py
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | |
options: show_root_heading: true show_source: true
Complexity Metrics¶
postmodal.complexity
¶
Functions for calculating modal complexity metrics.
calculate_complexity_metrics(modeshape: np.ndarray) -> ComplexityMetrics
¶
Calculate all complexity metrics for a modeshape or set of modeshapes.
This function computes all available complexity metrics: - Modal Phase Collinearity (MPC) - Modal Amplitude Proportionality (MAP) - Mean Phase Deviation (MPD)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
Single modeshape [n_dof] or set of modeshapes [n_modes x n_dof]. Can be real or complex-valued. |
required |
Returns:
| Type | Description |
|---|---|
ComplexityMetrics
|
Container with all computed complexity metrics. Each metric has shape [] for single modeshape or [n_modes] for multiple modeshapes. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If modeshape has incorrect dimensions |
Source code in postmodal/complexity.py
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | |
calculate_map(modeshape: np.ndarray) -> np.ndarray
¶
Calculate Modal Amplitude Proportionality (MAP) for a modeshape or set of modeshapes.
MAP assesses the amplitude proportionality of a complex mode shape. A higher MAP value (≈ 1) indicates that the mode shape amplitudes are largely proportional to their real parts, suggesting a more 'real' amplitude distribution. A lower MAP value (< 1) indicates a deviation from real amplitude proportionality, suggesting a more complex amplitude distribution and significant imaginary components.
Math:
.. math:: MAP_r = \frac{ \sum_{j=1}^{n} |Re(\Phi_{jr})| }{ \sum_{j=1}^{n} |\Phi_{jr}| }
Where:
- :math:\Phi_{jr}: j-th component of the r-th complex mode shape.
- :math:Re(\Phi_{jr}): Real part of :math:\Phi_{jr}.
- :math:n: Number of DOFs.
- :math:| ... |: Magnitude (absolute value for scalar, modulus for complex).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
Single modeshape [n_dof] or set of modeshapes [n_modes x n_dof]. Can be real or complex-valued. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
MAP value(s). - Scalar if input is a single modeshape []. - 1D array [n_modes] if input is a set of modeshapes. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the input |
NotImplementedError
|
If the input |
Source code in postmodal/complexity.py
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | |
calculate_mpc(modeshape: np.ndarray, method: str = 'mac') -> np.ndarray
¶
Calculate Modal Phase Collinearity (MPC) for a modeshape or set of modeshapes.
MPC quantifies the 'realness' of a mode shape by measuring the phase alignment of its components. A higher MPC value (≈ 1) indicates a more 'real' mode shape with phases close to 0° or 180°, suggesting proportionally damped or undamped behavior. A lower MPC value (≈ 0) suggests a more complex mode shape with scattered phases, indicating non-proportional damping or mode coupling.
Math:
.. math:: MPC(\phi_j) = \frac{||Re(\tilde{\phi}j)||_2^2 + ||Im(\tilde{\phi}_j)||_2^2} {||Re(\tilde{\phi}_j)||_2^2 + \epsilon{MPC}^{-1} Re(\tilde{\phi}j^T)Im(\tilde{\phi}_j) (2(\epsilon{MPC}^2 + 1)\sin^2(\theta_{MPC}) - 1)}
Where:
- :math:\tilde{\phi}_j: Centered mode shape
- :math:\epsilon_{MPC}: MPC epsilon parameter
- :math:\theta_{MPC}: MPC angle parameter
- :math:||...||_2^2: Squared L2 norm
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
Single modeshape [n_dof] or set of modeshapes [n_modes x n_dof]. Can be real or complex-valued. |
required |
method
|
str
|
Method to use for MPC calculation: - "old": Original implementation using epsilon and theta parameters - "eigenvalue": Implementation using eigenvalue decomposition - "mac": Implementation using Modal Assurance Criterion formula (default) |
'mac'
|
Returns:
| Type | Description |
|---|---|
ndarray
|
MPC value(s). - Scalar if input is a single modeshape []. - 1D array [n_modes] if input is a set of modeshapes. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the input |
NotImplementedError
|
If the input |
Source code in postmodal/complexity.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
calculate_mpd(modeshape: np.ndarray, weights: str = 'magnitude') -> np.ndarray
¶
Calculate Mean Phase Deviation (MPD) for a modeshape or set of modeshapes.
MPD quantifies the phase scatter within a mode shape by measuring the weighted average of phase deviations from the mean phase angle. The mean phase is determined by solving a total least squares problem using SVD to find the best straight line fit through the mode shape in the complex plane.
Math:
.. math:: MP(\phi_j) = \arctan\left(\frac{-V_{12}}{V_{22}}\right)
MPD(\phi_j) = \frac{\sum_{o=1}^{n_y} w_o \arccos\left|\frac{Re(\phi_{jo})V_{22} - Im(\phi_{jo})V_{12}}{\sqrt{V_{12}^2 + V_{22}^2}|\phi_{jo}|}\right|}{\sum_{o=1}^{n_y} w_o}
Where:
- :math:MP(\phi_j): Mean phase angle determined by SVD
- :math:V_{12}, V_{22}: Elements of the V matrix from SVD of [Re(φj) Im(φj)]
- :math:w_o: Weighting factors (either |φjo| or 1 for equal weights)
- :math:\phi_{jo}: Complex mode shape components
- :math:n_y: Number of DOFs
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
Single modeshape [n_dof] or set of modeshapes [n_modes x n_dof]. Can be real or complex-valued. |
required |
weights
|
str
|
Weighting scheme for phase deviations: - "magnitude": weights are the magnitude of each mode shape component (default) - "equal": equal weights for all components |
'magnitude'
|
Returns:
| Type | Description |
|---|---|
ndarray
|
MPD value(s) in degrees. - Scalar if input is a single modeshape []. - 1D array [n_modes] if input is a set of modeshapes. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the input |
NotImplementedError
|
If the input |
ValueError
|
If |
Source code in postmodal/complexity.py
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 | |
options: show_root_heading: true show_source: true
Comparison¶
postmodal.comparison
¶
Modal comparison module.
best_match(match_matrix: np.ndarray, threshold: float = 0.6) -> tuple[int, int] | None
¶
Find indices of best matching mode below threshold.
This function finds the pair of modes with the lowest matching value that is still below the specified threshold. It is used internally by match_modes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
match_matrix
|
ndarray
|
Matching matrix [n_modes_1 x n_modes_2] where lower values indicate better matches |
required |
threshold
|
float
|
Threshold for acceptable matches, by default 0.6 |
0.6
|
Returns:
| Type | Description |
|---|---|
Optional[Tuple[int, int]]
|
Indices of best match, or None if no match below threshold |
Raises:
| Type | Description |
|---|---|
ValueError
|
If matrix contains non-positive values or is not 2D |
Source code in postmodal/comparison/matrix.py
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | |
calculate_mac(phi_1: np.ndarray, phi_2: np.ndarray) -> float
¶
Calculate the MAC value of two (complex) modeshape vectors.
The Modal Assurance Criterion (MAC) is a measure of the correlation between two mode shapes. A MAC value close to 1 indicates strong correlation between the mode shapes, while a value close to 0 indicates weak correlation.
Math:
.. math:: MAC = \frac{ |\phi_1^H \phi_2|^2 }{ (\phi_1^H \phi_1)(\phi_2^H \phi_2) }
Where:
- :math:\phi_1, \phi_2: Complex mode shape vectors
- :math:^H: Hermitian transpose
- :math:|...|: Magnitude of complex number
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
phi_1
|
ndarray
|
First modeshape vector [n_dof] |
required |
phi_2
|
ndarray
|
Second modeshape vector [n_dof] |
required |
Returns:
| Type | Description |
|---|---|
float
|
MAC value between 0 and 1 |
Raises:
| Type | Description |
|---|---|
ValueError
|
If modeshapes have different shapes |
Source code in postmodal/comparison/mac.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | |
calculate_mac_matrix(phi_1: np.ndarray, phi_2: np.ndarray) -> NDArray
¶
Calculate the MAC matrix between two sets of modeshapes.
The Modal Assurance Criterion (MAC) matrix quantifies the correlation between all pairs of mode shapes from two sets. Each element (i,j) represents the MAC value between mode i from the first set and mode j from the second set.
Math:
.. math:: MAC_{ij} = \frac{ |\phi_{1i}^H \phi_{2j}|^2 }{ (\phi_{1i}^H \phi_{1i})(\phi_{2j}^H \phi_{2j}) }
Where:
- :math:\phi_{1i}: i-th mode shape from first set
- :math:\phi_{2j}: j-th mode shape from second set
- :math:^H: Hermitian transpose
- :math:|...|: Magnitude of complex number
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
phi_1
|
ndarray
|
First set of modeshapes [n_modes_1 x n_dof] |
required |
phi_2
|
ndarray
|
Second set of modeshapes [n_modes_2 x n_dof] |
required |
Returns:
| Type | Description |
|---|---|
NDArray
|
MAC matrix [n_modes_1 x n_modes_2] with values between 0 and 1 |
Raises:
| Type | Description |
|---|---|
ValueError
|
If modeshapes have different shapes |
Source code in postmodal/comparison/matrix.py
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | |
calculate_mode_matching_matrix(frequencies_1: np.ndarray, modeshapes_1: np.ndarray, frequencies_2: np.ndarray, modeshapes_2: np.ndarray, modeshape_weight: float = 1.0) -> NDArray
¶
Calculate mode matching matrix considering frequency and MAC.
Based on Simoen et al., 2014, "Dealing with uncertainty in model updating in damage assessment". The matching matrix combines frequency differences and MAC values to find corresponding modes between two sets. A lower value indicates a better match.
Math:
.. math:: M_{ij} = w(1 - MAC_{ij}) + |1 - f_{1i}/f_{2j}|
Where:
- :math:MAC_{ij}: MAC value between modes i and j
- :math:f_{1i}: Frequency of mode i from first set
- :math:f_{2j}: Frequency of mode j from second set
- :math:w: Weight for modeshape contribution
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frequencies_1
|
ndarray
|
Frequencies of first set [n_modes_1] |
required |
modeshapes_1
|
ndarray
|
Modeshapes of first set [n_modes_1 x n_dof] |
required |
frequencies_2
|
ndarray
|
Frequencies of second set [n_modes_2] |
required |
modeshapes_2
|
ndarray
|
Modeshapes of second set [n_modes_2 x n_dof] |
required |
modeshape_weight
|
float
|
Weight for modeshape contribution, by default 1.0 |
1.0
|
Returns:
| Type | Description |
|---|---|
NDArray
|
Matching matrix [n_modes_1 x n_modes_2] where lower values indicate better matches |
Raises:
| Type | Description |
|---|---|
ValueError
|
If input arrays have incompatible shapes |
Source code in postmodal/comparison/matrix.py
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
match_modes(match_matrix: np.ndarray, threshold: float = 0.6) -> tuple[Sequence[int], Sequence[int]]
¶
Find best matching modes using matching matrix.
This function finds pairs of modes that best match based on the matching matrix. It uses a greedy approach to find the best matches below the specified threshold. Each mode can only be matched once.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
match_matrix
|
ndarray
|
Matching matrix [n_modes_1 x n_modes_2] where lower values indicate better matches |
required |
threshold
|
float
|
Threshold for acceptable matches, by default 0.6 |
0.6
|
Returns:
| Type | Description |
|---|---|
Tuple[Sequence[int], Sequence[int]]
|
Indices of matching modes from first and second set |
Raises:
| Type | Description |
|---|---|
ValueError
|
If matrix contains non-positive values or is not 2D |
Source code in postmodal/comparison/matrix.py
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | |
options: show_root_heading: true show_source: true
Manipulation¶
postmodal.manipulation
¶
Modeshape manipulation utilities.
This module provides functions for manipulating modeshapes, including normalization, phase alignment, and complex-to-real conversion.
.. note::
The :func:normalize_modeshape function is deprecated and will be removed in a future version.
Use :func:normalize_modeshape_unit_norm_vector_length instead.
align_phase(modeshape: NDArray[np.complex128], reference_dof: int | None = None) -> NDArray[np.complex128]
¶
Align the phase of a modeshape to a reference DOF.
This function aligns the phase of a modeshape by rotating it so that the phase at a reference DOF is zero. If no reference DOF is specified, the DOF that minimizes the phase range is used.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
Complex modeshape array [n_dof] |
required |
reference_dof
|
Optional[int]
|
Index of the reference DOF, by default None |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Phase-aligned modeshape [n_dof] |
Notes
The phase alignment is achieved by multiplying the modeshape by
:math:e^{-i\phi_{ref}}, where :math:\phi_{ref} is the phase
angle at the reference DOF.
Source code in postmodal/manipulation/phase.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
calculate_conversion_error(complex_modeshape: np.ndarray, real_modeshape: np.ndarray) -> tuple[float, float]
¶
Calculate the error between complex and real modeshapes.
This function computes two error metrics: 1. Magnitude error: Relative difference in magnitudes 2. Phase error: Average absolute phase difference
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
complex_modeshape
|
ndarray
|
Original complex modeshape [n_dof] |
required |
real_modeshape
|
ndarray
|
Converted real modeshape [n_dof] |
required |
Returns:
| Type | Description |
|---|---|
tuple[float, float]
|
Tuple containing (magnitude_error, phase_error) - magnitude_error: Relative difference in magnitudes - phase_error: Average absolute phase difference in radians |
Source code in postmodal/manipulation/complex_to_real.py
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
calculate_phase_distribution(modeshape: NDArray[np.complex128], bins: int = 36) -> tuple[NDArray[np.int_], NDArray[np.float64]]
¶
Calculate the phase angle distribution of a modeshape.
This function computes a histogram of phase angles in the modeshape, which can be useful for analyzing phase clustering and identifying dominant phase patterns.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
Complex modeshape array [n_dof] |
required |
bins
|
int
|
Number of bins for the histogram, by default 36 |
36
|
Returns:
| Type | Description |
|---|---|
tuple[ndarray, ndarray]
|
Tuple containing (histogram, bin_edges) - histogram: Array of phase angle counts - bin_edges: Array of bin edges in radians |
Source code in postmodal/manipulation/phase.py
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | |
complex_to_real_batch(modeshapes: np.ndarray, method: str = 'phase', reference_dof: int | None = None) -> np.ndarray
¶
Convert a batch of complex modeshapes to real-valued modeshapes.
This function converts multiple complex modeshapes to real-valued modeshapes using the specified method.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshapes
|
ndarray
|
Array of complex modeshapes [n_modes x n_dof] |
required |
method
|
str
|
Conversion method, by default "phase" |
'phase'
|
reference_dof
|
Optional[int]
|
Index of the reference DOF for phase alignment, by default None |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of real-valued modeshapes [n_modes x n_dof] |
See Also
complex_to_real : Convert a single complex modeshape
Source code in postmodal/manipulation/complex_to_real.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | |
normalize_modeshape(modeshape: np.ndarray) -> np.ndarray
¶
Normalize a single modeshape or set of modeshapes (real part only).
.. deprecated:: 1.0.0
Use :func:normalize_modeshape_unit_norm_vector_length instead, which supports both real and complex modeshapes.
This function will be removed in a future version.
This function normalizes only the real part of the modeshape(s) to unit norm. For a single modeshape, the 2-norm is used. For multiple modeshapes, each modeshape is normalized independently.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
Single modeshape [n_dof] or set of modeshapes [n_modes x n_dof] |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Normalized modeshape(s) with the same shape as input |
Raises:
| Type | Description |
|---|---|
ValueError
|
If modeshape has incorrect dimensions |
Source code in postmodal/manipulation/normalize.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
normalize_modeshape_reference_dof(modeshape: np.ndarray, ref_dof_index: int) -> np.ndarray
¶
Normalize a single modeshape or set of modeshapes using a reference degree of freedom (DOF).
This normalization method scales each mode shape vector such that the component at the specified reference DOF index is normalized to unity (value of 1). This is useful when you want to scale mode shapes relative to a specific point on the structure, often a sensor location in experimental modal analysis. Works for both real and complex mode shapes.
Math:
For a mode shape :math:\vec{\Phi}_r and a chosen reference DOF index k (ref_dof_index),
the normalized mode shape :math:\vec{\Phi}_{r, normalized} is:
.. math:: \vec{\Phi}{r, normalized} = \frac{\vec{\Phi}_r}{\Phi{kr}}
Where :math:\Phi_{kr} is the component of the mode shape vector at the reference DOF index k.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
Single modeshape [n_dof] or set of modeshapes [n_modes x n_dof]. Can be real or complex-valued. |
required |
ref_dof_index
|
int
|
Index of the reference degree of freedom (0-indexed). Must be a valid index within the modeshape dimension (0 <= ref_dof_index < n_dof). |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Normalized modeshape(s) with the same shape as input. Each mode shape will have value 1 at the reference DOF. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If modeshape has incorrect dimensions or ref_dof_index is invalid |
Source code in postmodal/manipulation/normalize.py
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | |
normalize_modeshape_unit_norm_max_amplitude(modeshape: np.ndarray) -> np.ndarray
¶
Normalize a single modeshape or set of modeshapes to unit norm (maximum amplitude).
This normalization method scales each mode shape vector such that the component with the maximum absolute value is normalized to unity (magnitude of 1). This method emphasizes the largest displacement component and is useful when you want to scale mode shapes based on their peak amplitude. Works for both real and complex mode shapes.
Math:
For a mode shape :math:\vec{\Phi}_r, let :math:\Phi_{max, r} be the component with the maximum absolute value in :math:\vec{\Phi}_r.
The normalized mode shape :math:\vec{\Phi}_{r, normalized} is:
.. math:: \vec{\Phi}{r, normalized} = \frac{\vec{\Phi}_r}{\Phi{max, r}}
Note: In case of multiple components having the same maximum magnitude, the first encountered component with maximum magnitude is used as the reference.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
Single modeshape [n_dof] or set of modeshapes [n_modes x n_dof]. Can be real or complex-valued. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Normalized modeshape(s) with the same shape as input. Each mode shape will have maximum amplitude of 1. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If modeshape has incorrect dimensions |
Source code in postmodal/manipulation/normalize.py
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | |
normalize_modeshape_unit_norm_vector_length(modeshape: np.ndarray) -> np.ndarray
¶
Normalize a single modeshape or set of modeshapes to unit norm (vector length).
This normalization method scales each mode shape vector such that its Euclidean norm (vector length, 2-norm) becomes unity (length of 1). This is a mathematically simple and common method for general mode shape normalization, especially when focusing on the shape itself rather than physical scaling. Works for both real and complex mode shapes.
Math:
For a mode shape :math:\vec{\Phi}_r, the normalized mode shape :math:\vec{\Phi}_{r, normalized} is:
.. math:: \vec{\Phi}_{r, normalized} = \frac{\vec{\Phi}_r}{||\vec{\Phi}_r||_2}
Where :math:||\vec{\Phi}_r||_2 is the Euclidean norm (2-norm) of the mode shape vector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
Single modeshape [n_dof] or set of modeshapes [n_modes x n_dof]. Can be real or complex-valued. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Normalized modeshape(s) with the same shape as input. Each mode shape vector will have unit length (2-norm = 1). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If modeshape has incorrect dimensions |
Source code in postmodal/manipulation/normalize.py
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | |
normalize_phase(modeshape: NDArray[np.complex128], method: str = 'reference', reference_dof: int | None = None) -> NDArray[np.complex128]
¶
Normalize the phase of a modeshape.
This function normalizes the phase of a modeshape using one of several methods: - "reference": Align phase to a reference DOF - "unwrap": Unwrap phase to ensure continuity - "both": Apply both reference alignment and unwrapping
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
Complex modeshape array [n_dof] |
required |
method
|
str
|
Phase normalization method, by default "reference" |
'reference'
|
reference_dof
|
Optional[int]
|
Index of the reference DOF for reference method, by default None |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Phase-normalized modeshape [n_dof] |
Raises:
| Type | Description |
|---|---|
ValueError
|
If method is not one of ["reference", "unwrap", "both"] |
Source code in postmodal/manipulation/phase.py
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | |
optimize_conversion(modeshape: np.ndarray, method: str = 'phase', reference_dof: int | None = None) -> tuple[np.ndarray, float, float]
¶
Optimize the conversion of a complex modeshape to real.
This function finds the optimal real-valued modeshape by minimizing the conversion error. It tries different reference DOFs and returns the one with the smallest error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
Complex modeshape array [n_dof] |
required |
method
|
str
|
Conversion method, by default "phase" |
'phase'
|
reference_dof
|
Optional[int]
|
Initial reference DOF to try, by default None |
None
|
Returns:
| Type | Description |
|---|---|
tuple[ndarray, float, float]
|
Tuple containing (optimal_modeshape, magnitude_error, phase_error) - optimal_modeshape: Best real-valued modeshape - magnitude_error: Magnitude error for optimal conversion - phase_error: Phase error for optimal conversion |
Source code in postmodal/manipulation/complex_to_real.py
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | |
unwrap_phase(modeshape: NDArray[np.complex128], axis: int | None = None) -> NDArray[np.complex128]
¶
Unwrap the phase of a modeshape.
Source code in postmodal/manipulation/phase.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | |
options: show_root_heading: true show_source: true
Visualization¶
postmodal.visualization
¶
MAC matrix visualization module.
plot_mac_matrix(mac_matrix: np.ndarray, x_tick_labels: list[str], y_tick_labels: list[str], text_color_variable: bool = True, invert_scale: bool = False, ax: Axes | None = None) -> tuple[Figure, Axes]
¶
Plot the MAC matrix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mac_matrix
|
ndarray
|
MAC matrix [n_modes_1 x n_modes_2] |
required |
x_tick_labels
|
list[str]
|
Labels for x-axis ticks (columns of the MAC matrix) |
required |
y_tick_labels
|
list[str]
|
Labels for y-axis ticks (rows of the MAC matrix) |
required |
text_color_variable
|
bool
|
Whether to vary text color based on MAC value, by default True |
True
|
invert_scale
|
bool
|
Whether to invert the colormap scale, by default False |
False
|
ax
|
Optional[Axes]
|
Matplotlib axes to plot on, by default None |
None
|
Returns:
| Type | Description |
|---|---|
tuple[Figure, Axes]
|
The figure and axes objects |
Raises:
| Type | Description |
|---|---|
ValueError
|
If dimensions of inputs are incompatible |
Source code in postmodal/visualization.py
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | |
plot_modeshape_complexity(modeshape: np.ndarray, ax: PolarAxes | None = None) -> tuple[Figure, PolarAxes]
¶
Plot the complexity of a modeshape using a polar Argand diagram.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modeshape
|
ndarray
|
Complex modeshape vector |
required |
ax
|
Optional[PolarAxes]
|
Matplotlib polar axes to plot on, by default None |
None
|
Returns:
| Type | Description |
|---|---|
tuple[Figure, PolarAxes]
|
The figure and axes containing the complexity plot |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the provided axes is not a polar projection |
Source code in postmodal/visualization.py
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | |
plot_modeshape_complexity_grid(frequencies: np.ndarray, modeshapes: np.ndarray, figsize: tuple[float, float] | None = None, n_row: int | None = None, n_col: int | None = None, hspace: float = 0.4, wspace: float = 0.4) -> tuple[Figure, np.ndarray]
¶
Plot multiple modeshape complexity plots in a grid layout.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frequencies
|
ndarray
|
Array of frequencies for each mode |
required |
modeshapes
|
ndarray
|
Array of complex modeshapes |
required |
figsize
|
Optional[tuple[float, float]]
|
Figure size, by default None |
None
|
n_row
|
Optional[int]
|
Number of rows in grid, by default None |
None
|
n_col
|
Optional[int]
|
Number of columns in grid, by default None |
None
|
hspace
|
float
|
Horizontal spacing between plots, by default 0.4 |
0.4
|
wspace
|
float
|
Vertical spacing between plots, by default 0.4 |
0.4
|
Returns:
| Type | Description |
|---|---|
tuple[Figure, ndarray]
|
The figure and array of axes containing the complexity plots |
Source code in postmodal/visualization.py
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | |
options: show_root_heading: true show_source: true