visualdynamics.core.tone_readout¶
tone_readout
¶
A tone read off an averaged autospectrum, in amplitude, and why its spike is not that amplitude.
An autospectrum (an ASD, in g²/Hz for an acceleration) is a density: mean square per hertz. A broadband floor has mean square in every slice of its band, so its density reads the same however finely the band is cut into lines. A sine has all of its mean square, A²/2 for an amplitude A, at one frequency, and the analysis spreads that over the lines the window leaks it into. The tallest of them stands about
(A²/2) / (B_w · Δf)
over the floor, where Δf is the line spacing and B_w the window's equivalent noise bandwidth in lines (1.5 for the Hann window, 1 for a rectangle). The spike's height goes as one over the spacing: the same tone analyzed at a quarter of the lines stands a quarter as tall, with the tone and the floor unchanged. It also reads lower when the tone falls between two lines than when it falls on one, by as much as 1.4 dB under Hann and 3.9 dB under a rectangle. So the height of a spike is a property of the analysis as much as of the tone, and it cannot be compared with a tone table written in amplitude.
The tone itself can be read off the same spectrum by summing instead
of by height. The lines of an autospectrum times their spacing add up
to the mean square (Parseval's theorem, for any window), so the lines
the tone leaks into, less the floor beneath them, times the spacing,
are the tone's mean square whatever the spacing and the window. Its
root is the tone's rms, and root two times that is its amplitude.
read_tone does that and returns a ToneReading, which carries the
amplitude beside the spike the spacing and the window gave, so the two
can be seen together.
The reading in steps, at a frequency near the tone:
- The window's leakage kernel, the share of a tone's mean square each
line receives as a function of where the tone sits between lines,
is worked out from the window's own shape (
leakage). It gives the noise bandwidth, the main lobe's half-width in lines (2 for Hann: the lines the tone is summed over lie within it of the tone), and the share of the tone those lines hold. - The tone's line is the tallest within the main lobe of the frequency asked, and where the tone sits between lines is found by fitting the kernel to the lines about it, floor taken away.
- The floor is the median of the lines either side, outside the main lobe and a guard of the same width, a straight floor through the two sides under the tone.
- The lines within the main lobe of the tone, less the floor, times the spacing, are the tone's mean square, divided by the share of the tone those lines hold (under 1 % of it falls outside them for Hann, about 19 % for a rectangle with the tone midway between lines).
Four things are said rather than hidden, as notes on the reading and
as a ToneWarning: a tone that sits between lines (its spike reads
lower than it would on a line; the amplitude does not move), a floor
that differs either side of the tone (a tone at the edge of the floor's
band, where there is no floor under it to take away), a tone too near
the end of the spectrum for its lines or its floor to be read, and a
frequency where nothing stands above the floor.
References
The noise bandwidth of a window and the loss of a tone's peak between lines are Harris's; that the lines of an averaged autospectrum times their spacing sum to the mean square is how the estimate is scaled.
- Harris, F. J. (1978). "On the Use of Windows for Harmonic Analysis with the Discrete Fourier Transform." Proceedings of the IEEE, 66(1), 51-83. doi:10.1109/PROC.1978.10837 Equivalent noise bandwidth, scalloping loss and the leakage of a tone between lines, window by window.
- Bendat, J. S., & Piersol, A. G. (2010). Random Data: Analysis and Measurement Procedures, 4th ed. Wiley. The one-sided autospectrum, its scaling, and its integral as the mean square.
Classes:
| Name | Description |
|---|---|
ToneWarning |
Warned when a tone reading rests on something the reader should |
Leakage |
A window's leakage, read in lines: what |
ToneReading |
One tone read off an averaged autospectrum: what |
Functions:
| Name | Description |
|---|---|
density_label |
The unit of a density whose amplitude is in |
leakage |
A window's leakage in lines: its shape, noise bandwidth and main |
noise_bandwidth |
A window's equivalent noise bandwidth, in lines: 1 for a |
spike_height |
The height a tone's spike stands above the floor on an averaged |
line_spacing |
The spacing of evenly spaced lines, in Hz. Lines that are not |
read_tone |
Read the tone near |
Classes¶
ToneWarning
¶
Bases: UserWarning
Warned when a tone reading rests on something the reader should
know: a tone between lines, a floor that differs either side, a
spectrum that ends too near the tone, or no tone at all. The reading
is returned either way; ToneReading.notes carries the same words
for a caller that shows them rather than warns.
Leakage
dataclass
¶
Leakage(window: str, parameter: float | None, shape: ndarray, noise_bandwidth: float, half_width: int)
A window's leakage, read in lines: what leakage returns.
shape holds the window's samples over the frame the kernel was
worked out on. noise_bandwidth is the equivalent noise bandwidth
in lines, N·Σw²/(Σw)². half_width is the main lobe's half-width
in whole lines, the reach of the lines a tone is summed over.
parameter is the Tukey or Kaiser window's number, None for the
others.
Methods:
| Name | Description |
|---|---|
share |
The share of a tone's mean square a line receives, at |
peak_share |
The share the tallest line receives with the tone |
scallop |
The spike's height with the tone |
Methods:¶
share
¶
The share of a tone's mean square a line receives, at
offset lines from the tone (any real number, any shape).
It is |W(δ)|²/(N·Σw²), with W the window's transform at δ
lines; it is 1/noise_bandwidth on the line under the tone, and
summed over every line it is 1, which is why the lines times
their spacing are the tone's mean square.
Source code in src/visualdynamics/core/tone_readout.py
peak_share
¶
The share the tallest line receives with the tone offset
lines from its nearest line (-0.5 to 0.5): 1/noise_bandwidth
on a line, less between lines.
Source code in src/visualdynamics/core/tone_readout.py
scallop
¶
The spike's height with the tone offset lines off a line,
as a share of its height on a line (1 on a line; 0.72 midway
between lines under Hann).
Source code in src/visualdynamics/core/tone_readout.py
ToneReading
dataclass
¶
ToneReading(frequency: float, asked: float, amplitude: float, mean_square: float, spike: float, height: float, floor: float, spacing: float, offset: float, window: str, noise_bandwidth: float, lines: tuple[int, int], captured: float, notes: tuple[str, ...] = (), uncertain: bool = False, said: tuple[tuple[str, tuple[float, ...]], ...] = ())
One tone read off an averaged autospectrum: what read_tone
returns.
amplitude is the tone's peak, in the units whose square per hertz
the spectrum is in (g for an ASD in g²/Hz, as the spectrum is
stored); mean_square its mean square. spike is the tallest line
under the tone as measured, floor included, and height the spike
this tone stands above the floor at this spacing, window and
placement: what a tone reference drawn on the spectrum would stand
at. floor is the floor estimated under the tone. frequency is
the tone's frequency as read between lines, spacing the line
spacing, offset where the tone sits from its nearest line, in
lines. lines is the (first, last) index of the lines summed, and
captured the share of the tone they hold. notes holds the
warnings the reading raised, as text, with any density in them in
the units the spectrum is stored in (notes_in gives them in
others), and uncertain says whether any of them bears on the
amplitude (a tone between lines does not; a floor that differs
either side, another spike among the tone's lines, or no tone at all
does).
Methods:
| Name | Description |
|---|---|
notes_in |
The notes with their densities in display units: |
describe |
The reading in one line, as the application shows it: |
Attributes:
| Name | Type | Description |
|---|---|---|
rms |
float
|
The tone's rms: its amplitude over root two. |
on_line |
float
|
The spike this tone would stand above the floor with the |
between_lines |
bool
|
Whether the tone sits far enough between lines that its spike |
Attributes¶
on_line
property
¶
The spike this tone would stand above the floor with the tone on a line: (A²/2)/(B_w·Δf).
between_lines
property
¶
Whether the tone sits far enough between lines that its spike
has lost more than BETWEEN_LINES of its on-line height.
Methods:¶
notes_in
¶
The notes with their densities in display units: scale
converts the amplitude into unit, and the densities take its
square, as describe does.
Source code in src/visualdynamics/core/tone_readout.py
describe
¶
The reading in one line, as the application shows it:
'19.44 Hz: 1.94 g peak; its spike 0.978 g²/Hz (1.26 on a line)
is not the tone'. scale converts the amplitude into unit;
the densities take its square.
Source code in src/visualdynamics/core/tone_readout.py
Functions:¶
density_label
¶
The unit of a density whose amplitude is in unit: 'g²/Hz' for
'g', '(m/s²)²/Hz' for 'm/s²', and '/Hz' for no unit.
Source code in src/visualdynamics/core/tone_readout.py
leakage
¶
leakage(window: Any = 'hann', length: int | None = None, parameter: float | None = None) -> Leakage
A window's leakage in lines: its shape, noise bandwidth and main lobe.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
window
|
str or Averaging
|
A window by any name |
'hann'
|
length
|
int
|
The frame length in samples. The kernel is worked out on at most
|
None
|
parameter
|
float
|
The Tukey window's alpha or the Kaiser window's beta. |
None
|
Returns:
| Type | Description |
|---|---|
Leakage
|
Cached: the same window asked for again is the same object. |
Source code in src/visualdynamics/core/tone_readout.py
noise_bandwidth
¶
noise_bandwidth(window: Any = 'hann', length: int | None = None, parameter: float | None = None) -> float
A window's equivalent noise bandwidth, in lines: 1 for a rectangle, 1.5 for Hann, 3.77 for scipy's flat top.
The width of the ideal filter that passes the same noise as one line
of the analysis does, and so the factor between a tone's mean square
and the height its spike stands on an autospectrum
(spike_height). window, length and parameter are as for
leakage.
Source code in src/visualdynamics/core/tone_readout.py
spike_height
¶
spike_height(amplitude: float, spacing: float, window: Any = 'hann', *, offset: float = 0.0, length: int | None = None, parameter: float | None = None) -> float
The height a tone's spike stands above the floor on an averaged autospectrum: (A²/2)/(B_w·Δf) on a line, less between lines.
This is what a controller that draws its tone references as spikes
on the ASD scales them to, and what the tone markers of
plot.tone_readout are drawn at.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
amplitude
|
float
|
The tone's amplitude (peak), in the units whose square per hertz the autospectrum is in. |
required |
spacing
|
float
|
The line spacing in Hz. |
required |
window
|
str or Averaging
|
As for |
'hann'
|
offset
|
float
|
Where the tone sits, in lines from its nearest line (-0.5 to 0.5). |
0
|
length
|
int | None
|
As for |
None
|
parameter
|
int | None
|
As for |
None
|
Returns:
| Type | Description |
|---|---|
float
|
The spike's height in the autospectrum's units, floor excluded. |
Source code in src/visualdynamics/core/tone_readout.py
line_spacing
¶
The spacing of evenly spaced lines, in Hz. Lines that are not
ascending and evenly spaced (to a millionth of the spacing) raise
ValueError: that test decides what a tone can be read off, here and
in Psd.tone_refusal.
Source code in src/visualdynamics/core/tone_readout.py
read_tone
¶
read_tone(frequencies: Any, density: Any, frequency: float, *, window: Any = 'hann', length: int | None = None, parameter: float | None = None, floor_lines: int = FLOOR_LINES, snap: bool = True, unit: str = '', warn: bool = True) -> ToneReading
Read the tone near frequency off an averaged autospectrum, as
an amplitude, beside the spike it stands at.
The tone's line is the tallest within the window's main lobe of
frequency, and where the tone sits between lines is fitted from
the lines about it; with snap=False the tone is taken to be at
frequency exactly, as a tone table states it. The lines within the
main lobe of the tone, less the floor estimated from the lines
either side, times the spacing, are its mean square (divided by the
share of the tone those lines hold, which the window's shape gives);
the amplitude is root two times its root. See the module's notes for the method and for
what is warned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frequencies
|
array - like
|
The spectrum's lines in Hz, ascending and evenly spaced. |
required |
density
|
array - like
|
The autospectrum, one value per line, in the square of the tone's units per hertz (g²/Hz for a tone in g). |
required |
frequency
|
float
|
A frequency at or near the tone, in Hz. |
required |
window
|
str or Averaging
|
The window the spectrum was averaged with, or the |
'hann'
|
length
|
int
|
The frame length, when |
None
|
parameter
|
float
|
The Tukey or Kaiser window's number, when |
None
|
floor_lines
|
int
|
Lines either side, beyond the tone's main lobe and a guard, that the floor is read from (other tones among them left out). |
`FLOOR_LINES`
|
snap
|
bool
|
Find the tone's own spike near |
True
|
unit
|
str
|
The tone's unit as |
''
|
warn
|
bool
|
Warn the notes as |
True
|
Returns:
| Type | Description |
|---|---|
ToneReading
|
The tone's amplitude, mean square and frequency, the spike it stands at, the floor, and the notes. |
Raises:
| Type | Description |
|---|---|
ValueError
|
When the lines and the values differ in length, hold too few
lines, are not evenly spaced, hold no finite value, or
|
Source code in src/visualdynamics/core/tone_readout.py
508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 | |