visualdynamics.core.half_power¶
half_power
¶
Q read from the half-power width of one peak.
A resonance on a magnitude curve (an FRF magnitude, a transmissibility, a tracked sine level) has two numbers a test engineer reads off it: the frequency of its peak and how sharp it is. The sharpness is Q, the peak frequency over the half-power width, the width between the two frequencies where the curve has fallen to 1/sqrt(2) of its peak (0.707, 3 dB down; half power because power goes with amplitude squared). The damping ratio is 1/(2Q). For one mode well clear of its neighbors this agrees with the mode's own damping to within a few times the damping squared: read finely off a one-mass accelerance, Q comes out 1 % low at a Q of 10, 0.25 % at 20 and 0.04 % at 50 (a receptance or a transmissibility half that).
read_half_power takes the curve and a frequency near the peak and
returns a HalfPower: the peak's frequency and height, the two
crossings, the width, Q, the damping ratio and how many lines span the
width. The reading is the one the eye makes off a plot, put in numbers,
and it is not a modal fit: it reads where the curve is, not the
resonator that made it. Two modes closer than their widths read as one
wide peak, and a swept level read too fast reads wide and low; both are
properties of the curve, and the reading reports the curve faithfully.
Three things are said rather than hidden:
- A crossing that is not inside the curve. The curve stops before it
falls to 0.707 of the peak on that side (the peak is near an end of
the measured band, or rides a shoulder). The crossing is None, so are
the width, Q and damping, and a
HalfPowerWarningsays which side. Borrowing the other side's width, as the modal fit's seed does, is a guess about a curve that was not measured; a seed may guess, a reading may not. - Too few lines across the peak. A peak sampled at a line spacing near
its own width is read low (the tallest line misses the top) and wide
(the crossings are interpolated across straight segments of a curved
flank), and so its Q comes out wrong, nearly always low. The reading
is still returned, since it is what the curve says, but with a
HalfPowerWarningwhen fewer thanMIN_LINESlines span the width. - A peak so much narrower than its lines that the top, placed between them, stands more than 3 dB over every line. No crossing can be placed at all, so neither is, and the warning says why.
References
The half-power reading is a standard method; this is where it is described. The parabola through the logarithm of the tallest line and its two neighbors, which places the top between lines, is worked through where the top is read.
- Piersol, A. G., & Paez, T. L. (Eds.) (2010). Harris' Shock and Vibration Handbook, 6th ed. McGraw-Hill. The half-power bandwidth of a resonance: its Q as the peak frequency over the width between the points where the response has fallen to 1/sqrt(2) of its peak, and the damping ratio as 1/(2Q).
Classes:
| Name | Description |
|---|---|
HalfPowerWarning |
Warned when a half-power reading is missing a crossing or rests |
HalfPower |
One peak read by its half-power width: what |
Functions:
| Name | Description |
|---|---|
crossings |
Where the curve first falls below |
read_half_power |
Read Q from the half-power width of the peak nearest |
Classes¶
HalfPowerWarning
¶
Bases: UserWarning
Warned when a half-power reading is missing a crossing or rests
on too few lines. The reading is returned either way; the warning
says what it cannot be trusted for, and HalfPower.notes carries
the same words for a caller that shows them rather than warns.
HalfPower
dataclass
¶
HalfPower(frequency: float, height: float, low: float | None, high: float | None, spacing: float, notes: tuple[str, ...] = (), min_lines: float = MIN_LINES)
One peak read by its half-power width: what read_half_power
returns.
Frequencies are in Hz and height is in the curve's own units.
low and high are None where the curve ends before falling to the
half-power level on that side, and then width, q and damping
are None too. lines is the width over the line spacing at the
peak: how many lines the reading rests on. notes holds the
warnings the reading raised, as text, empty when it raised none.
min_lines is the count resolved is judged against: the
min_lines the reading was taken with.
Methods:
| Name | Description |
|---|---|
describe |
The reading in one line, as the application shows it: |
Attributes:
| Name | Type | Description |
|---|---|---|
level |
float
|
The half-power level: 0.707 of the height. |
width |
float | None
|
The half-power width in Hz, |
q |
float | None
|
Q: the peak frequency over the half-power width. |
damping |
float | None
|
The damping ratio, a fraction of critical: 1/(2Q). |
lines |
float | None
|
How many lines span the half-power width. |
resolved |
bool
|
True when both crossings were found and at least |
Attributes¶
resolved
property
¶
True when both crossings were found and at least min_lines
lines span the width.
Methods:¶
describe
¶
The reading in one line, as the application shows it: 'Q 19.9 at 179.9 Hz, half-power 175.3 to 184.3 Hz (9.03 Hz, 14 lines)'. Numbers are given to four figures (the width and Q to three) and never in exponent form.
Source code in src/visualdynamics/core/half_power.py
Functions:¶
crossings
¶
crossings(frequencies: Any, magnitude: Any, index: int, level: float) -> tuple[float | None, float | None]
Where the curve first falls below level on each side of line
index, as (low, high) in Hz, interpolated linearly between the
last line at or above the level and the first below it.
A side that never falls below the level inside the curve gives
None. The level must not be above line index itself, which is the
top the crossings are measured down from; a ValueError says so. This
is the one place the package finds half-power crossings: the reading
here and the modal fit's damping seed both call it.
Source code in src/visualdynamics/core/half_power.py
read_half_power
¶
read_half_power(frequencies: Any, magnitude: Any, near: float, *, within: tuple[float, float] | None = None, min_lines: float = MIN_LINES, warn: bool = True, stacklevel: int = 1) -> HalfPower
Read Q from the half-power width of the peak nearest near.
The peak is the one the line nearest near sits on, found by
climbing uphill from that line, so a frequency anywhere on a peak's
flank reads that peak and not a taller one elsewhere. With within,
a (low, high) band in Hz, the peak is instead the tallest line
inside the band, which is the reading for a band that holds one
mode. The top is placed between lines by a parabola through the
logarithms of the tallest line and its two neighbors, and the two
crossings of 0.707 of that height are interpolated linearly between
lines. Q is the peak frequency over the width between the
crossings, and the damping ratio is 1/(2Q).
A HalfPowerWarning is warned, and its text kept in notes, when a
crossing is not inside the curve and when fewer than min_lines
lines span the width (see the module's notes on resolution). Pass
warn=False to keep the notes without warning, as a display that
reads on every mouse move does.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frequencies
|
array - like
|
The curve's frequencies in Hz, ascending. They need not be evenly spaced. |
required |
magnitude
|
array - like
|
The curve, one value per frequency. Complex values are read by their magnitude. |
required |
near
|
float
|
A frequency on the peak to read, in Hz. |
required |
within
|
tuple of float
|
A band (low, high) in Hz; the tallest line inside it is the
peak, and |
None
|
min_lines
|
float
|
The fewest lines across the half-power width read without a warning. |
`MIN_LINES`
|
warn
|
bool
|
Warn the notes as |
True
|
stacklevel
|
int
|
Which line the warning names: 1 is the line that called this
function, 2 its caller, as for |
1
|
Returns:
| Type | Description |
|---|---|
HalfPower
|
The peak's frequency and height, the two crossings, the line spacing at the peak, and any notes. |
Raises:
| Type | Description |
|---|---|
ValueError
|
When the frequencies and the magnitude differ in length, hold
fewer than three lines, are not ascending, or |
Source code in src/visualdynamics/core/half_power.py
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 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 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 | |