The amplitude spectrum's window, and what it read, beside the plot.
The Amplitude reading of a time history draws one channel's amplitude
spectrum (plot.amplitude_spectrum): each line scaled so a sine reads
its amplitude in peak units, the frames' magnitudes averaged. This
panel holds the one setting the reading is made with, above the rule:
the window, with its alpha or beta for a Tukey or Kaiser window. Hann
is the default, and flattop is the window for a tone's amplitude
wherever it falls between lines. The frames themselves are the record's
averaging, set in the Averaging reading, and the panel says so.
Under the rule are the reading's numbers: where the frames came from,
the line spacing and how many frames were averaged, the window's
coherent gain and the amplitude correction it gives, its noise
bandwidth, how far low it reads a sine midway between lines, and the
tallest line above DC in peak and in rms. Under them, in words, a
tallest line too low for the window to read, and what an amplitude
spectrum's floor is not. Nothing is made: the reading is of a
record that already exists, as the time statistics are, so there is no
Apply button.
Classes:
| Name |
Description |
AmplitudePanel |
The window setting and the reading. Edits are emitted as
|
Classes
AmplitudePanel
AmplitudePanel(parent: QWidget | None = None)
Bases: QWidget
The window setting and the reading. Edits are emitted as
settings().
Methods:
| Name |
Description |
window |
The window chosen, one of core.averaging.WINDOWS.
|
settings |
The reading's settings: 'window', and 'parameter', the Tukey
|
set_settings |
Set the fields from a settings() dict without emitting,
|
show_reading |
Write channel record of spectrum, an AmplitudeSpectrum,
|
Source code in src/visualdynamics/gui/amplitude_panel.py
| def __init__(self, parent: QWidget | None = None) -> None:
super().__init__(parent)
self.title: QLabel = QLabel('Amplitude Spectrum')
grid = panel_grid(self, self.title)
self._loading = False
self.window_box: QComboBox = QComboBox()
for name in WINDOWS:
self.window_box.addItem(name, name)
self.window_box.setCurrentIndex(self.window_box.findData(
DEFAULT_WINDOW))
self.window_box.setToolTip(
'The window each frame is multiplied by. Its amplitude '
'correction is applied, so a sine on a line reads its '
'amplitude under any window; hann reads one midway between '
'lines 1.42 dB low, flattop within 0.01 dB')
# a Tukey's alpha or a Kaiser's beta, shown only while such a
# window is chosen, as the averaging and tone panes show it
self.parameter_box: DoubleSpinBox = DoubleSpinBox()
self.parameter_box.setDecimals(2)
self.parameter_box.setToolTip(
"The window's own number: Tukey's alpha, the tapered "
"fraction, or Kaiser's beta")
names = add_settings(grid, [('Window', self.window_box),
('Alpha', self.parameter_box)])
self._parameter_label: QLabel = names[1]
add_rule(grid, 3)
self.derived: dict[str, QLabel] = {
key: value for key, (_name, value)
in add_derived(grid, ROWS, 4).items()}
self.notes: QLabel = QLabel('')
self.notes.setWordWrap(True)
grid.addWidget(self.notes, 4 + len(ROWS), 0, 1, 2)
grid.setRowStretch(5 + len(ROWS), 1)
self._restate_parameter(None)
self.window_box.currentIndexChanged.connect(self._window_edited)
self.parameter_box.valueChanged.connect(self._edited)
|
Methods:
window
The window chosen, one of core.averaging.WINDOWS.
Source code in src/visualdynamics/gui/amplitude_panel.py
| def window(self) -> str:
"""The window chosen, one of `core.averaging.WINDOWS`."""
return str(self.window_box.currentData())
|
settings
settings() -> dict[str, Any]
The reading's settings: 'window', and 'parameter', the Tukey
window's alpha or the Kaiser window's beta (None for a window
that takes none), as TimeHistory.amplitude_spectrum takes
them.
Source code in src/visualdynamics/gui/amplitude_panel.py
| def settings(self) -> dict[str, Any]:
"""The reading's settings: 'window', and 'parameter', the Tukey
window's alpha or the Kaiser window's beta (None for a window
that takes none), as `TimeHistory.amplitude_spectrum` takes
them."""
parameter = (float(self.parameter_box.value())
if self.window() in WINDOW_PARAMETERS else None)
return {'window': self.window(), 'parameter': parameter}
|
set_settings
set_settings(settings: dict[str, Any] | None) -> None
Set the fields from a settings() dict without emitting,
since the caller is about to draw.
Source code in src/visualdynamics/gui/amplitude_panel.py
| def set_settings(self, settings: dict[str, Any] | None) -> None:
"""Set the fields from a `settings()` dict without emitting,
since the caller is about to draw."""
if not settings:
return
self._loading = True
try:
self.window_box.setCurrentIndex(self.window_box.findData(
settings.get('window', DEFAULT_WINDOW)))
self._restate_parameter(settings.get('parameter'))
finally:
self._loading = False
|
show_reading
show_reading(spectrum: Any, record: int = 0, tallest: tuple[float, float] | None = None, *, scale: float = 1.0, unit: str = '', unread: str | None = None) -> None
Write channel record of spectrum, an AmplitudeSpectrum,
into the rows, with tallest its tallest line as (frequency,
amplitude in SI); amplitudes converted by scale into unit.
unread is why no line could be read, said in the notes. None
clears them.
Source code in src/visualdynamics/gui/amplitude_panel.py
| def show_reading(self, spectrum: Any, record: int = 0,
tallest: tuple[float, float] | None = None, *,
scale: float = 1.0, unit: str = '',
unread: str | None = None) -> None:
"""Write channel `record` of `spectrum`, an `AmplitudeSpectrum`,
into the rows, with `tallest` its tallest line as (frequency,
amplitude in SI); amplitudes converted by `scale` into `unit`.
`unread` is why no line could be read, said in the notes. None
clears them."""
values = dict.fromkeys(key for key, _name in ROWS)
if spectrum is not None:
frames = spectrum.frames[record]
bandwidth = f'{spectrum.noise_bandwidth:.3g}'
values.update(
channel=spectrum.label(record),
source=('the averaging' if spectrum.from_averaging
else 'each record whole'),
spacing=f'{spectrum.spacing:.4g} Hz',
frames=f'{frames}',
gain=f'{spectrum.coherent_gain:.4f}',
correction=f'×{spectrum.correction:.3f}',
bandwidth=(f'{bandwidth} line' if bandwidth == '1'
else f'{bandwidth} lines'),
scalloping=f'{spectrum.scalloping_db:.2f} dB low')
if tallest is not None:
frequency, amplitude = tallest
values.update(
frequency=f'{frequency:.4g} Hz',
amplitude=f'{amplitude * scale:.4g} {unit} peak'
.replace(' ', ' '),
rms=f'{amplitude * scale / 2.0 ** 0.5:.4g} {unit} rms'
.replace(' ', ' '))
for key, value in values.items():
self.derived[key].setText('—' if value is None else value)
if spectrum is None:
self.notes.setText('')
return
notes = [] if unread is None else [unread[:1].upper() + unread[1:]
+ '.']
mirror = None if tallest is None else spectrum.mirror_note(tallest[0])
if mirror is not None:
notes.append(mirror[:1].upper() + mirror[1:] + '.')
notes.append(FLOOR_NOTE)
if spectrum.scalloping_db > 0.1:
# the tallest line is the reading, and between lines it is
# short by as much as the window's scalloping
notes.append(f'A tone between lines reads up to '
f'{spectrum.scalloping_db:.2f} dB low under '
f'{spectrum.window}; flattop reads it within '
'0.01 dB.')
self.notes.setText('\n'.join(notes))
|
Functions: