Skip to content

visualdynamics.gui.stroke_panel

stroke_panel

The shaker's shock ratings, beside a pulse read against them.

The Stroke reading of a time history draws the record's acceleration, its velocity and its displacement, integrated raw, on one clock (plot.stroke). This panel holds what the pulse is judged against (the shaker's shock stroke, velocity and force, the moving mass, and the body's mass) and, under them, what the reading came to: the peak acceleration and velocity, the table's peak to peak beside the half-sine rule, the travel with the body counted, peak to peak and each way from center, and the force, then each demand against its rating in words.

Every edit redraws the plot at once, so a rating is seen against the pulse while it is typed. Nothing is made: the reading is of a record that already exists, as the kurtosis bars are, so there is no Apply button to press. A rating left at zero is not given, and is reported without a verdict. The same call a script makes, core.stroke.read_stroke, gives every number shown here.

The ratings are kept in SI and shown in the window's units, so a change of units restates them rather than reinterpreting them.

Classes:

Name Description
StrokePanel

The ratings and the readout. Edits are emitted as settings().

Classes

StrokePanel

StrokePanel(parent: QWidget | None = None)

Bases: QWidget

The ratings and the readout. Edits are emitted as settings().

Methods:

Name Description
settings

The ratings as core.stroke.read_stroke takes them, in SI:

set_settings

Show these ratings (SI, None or missing for none) without

set_unit_system

Show the ratings in unit_system's units.

show_reading

Write what reading came to under the ratings, in the units

Source code in src/visualdynamics/gui/stroke_panel.py
def __init__(self, parent: QWidget | None = None) -> None:
    super().__init__(parent)
    from ..units import DEFAULT_SYSTEM

    self.title: QLabel = QLabel('Stroke')
    grid = panel_grid(self, self.title)
    self._loading = False
    #: the units the boxes are shown in
    self.unit_system: UnitSystem = DEFAULT_SYSTEM
    #: the ratings in SI, None where not given: what `settings`
    #: returns, kept here so a change of units restates them
    self._ratings: dict[str, float | None] = {
        key: None for key, *_rest in RATINGS}

    rows = []
    self.boxes: dict[str, DoubleSpinBox] = {}
    for key, name, _dimension, tip in RATINGS:
        box = DoubleSpinBox()
        box.setRange(0.0, 1e9)
        box.setDecimals(4)
        box.setToolTip(tip)
        self.boxes[key] = box
        rows.append((key, name, box))
    self.names, _editors = add_keyed_settings(grid, rows)
    add_rule(grid, len(rows) + 1)
    self.derived: dict[str, QLabel] = {
        key: value for key, (_name, value) in add_derived(
            grid, READINGS, len(rows) + 2).items()}
    # the verdicts in words, a line a rating, wrapped to the panel
    self.readout: QLabel = QLabel('')
    self.readout.setWordWrap(True)
    grid.addWidget(self.readout, len(rows) + 2 + len(READINGS), 0, 1, 2)
    grid.setRowStretch(len(rows) + 3 + len(READINGS), 1)

    commit_on_enter(*self.boxes.values())
    for key, box in self.boxes.items():
        box.valueChanged.connect(
            lambda _value, key=key: self._edited(key))
    self.set_unit_system(DEFAULT_SYSTEM)
Methods:
settings
settings() -> dict[str, float | None]

The ratings as core.stroke.read_stroke takes them, in SI: 'stroke', 'velocity', 'force', 'moving_mass' and 'body_mass', each None where it is not given.

Source code in src/visualdynamics/gui/stroke_panel.py
def settings(self) -> dict[str, float | None]:
    """The ratings as `core.stroke.read_stroke` takes them, in SI:
    'stroke', 'velocity', 'force', 'moving_mass' and 'body_mass',
    each None where it is not given."""
    return dict(self._ratings)
set_settings
set_settings(settings: dict[str, float | None] | None) -> None

Show these ratings (SI, None or missing for none) without reporting an edit.

Source code in src/visualdynamics/gui/stroke_panel.py
def set_settings(self, settings: dict[str, float | None] | None) -> None:
    """Show these ratings (SI, None or missing for none) without
    reporting an edit."""
    self._ratings = {key: (None if settings is None
                           else settings.get(key))
                     for key, *_rest in RATINGS}
    self._restate()
set_unit_system
set_unit_system(unit_system: UnitSystem) -> None

Show the ratings in unit_system's units.

Source code in src/visualdynamics/gui/stroke_panel.py
def set_unit_system(self, unit_system: UnitSystem) -> None:
    """Show the ratings in `unit_system`'s units."""
    self.unit_system = unit_system
    for key, name, dimension, _tip in RATINGS:
        self.names[key].setText(
            f'{name} [{unit_system.label_text(dimension)}]')
    self._restate()
show_reading
show_reading(reading: StrokeReading | None) -> None

Write what reading came to under the ratings, in the units shown; None clears it.

Source code in src/visualdynamics/gui/stroke_panel.py
def show_reading(self, reading: StrokeReading | None) -> None:
    """Write what `reading` came to under the ratings, in the units
    shown; None clears it."""
    from ..core.stroke import _number
    from ..core.stroke import amount as _amount

    if reading is None:
        for value in self.derived.values():
            value.setText('—')
        self.readout.setText('')
        self.readout.setStyleSheet('')
        return
    us = self.unit_system

    def amount(value, dimension):
        return _amount(value, dimension, us)

    self.derived['peak'].setText(
        amount(reading.peak_acceleration, 'acceleration'))
    self.derived['peak_velocity'].setText(
        amount(reading.peak_velocity, 'velocity'))
    self.derived['peak_to_peak'].setText(
        amount(reading.peak_to_peak, 'length'))
    self.derived['rule'].setText(amount(reading.rule, 'length'))
    self.derived['travel'].setText(amount(reading.travel, 'length'))
    length = us.label_text('length')
    self.derived['each_way'].setText(
        f'{_number(float(us.from_si(reading.travel_down, "length")))} / '
        f'{_number(float(us.from_si(reading.travel_up, "length")))} '
        f'{length}')
    self.derived['force'].setText(
        '—' if reading.force is None else amount(reading.force, 'force'))
    # the lines that judge something: each rating given, and the
    # travel to the stop when it reaches one; the numbers alone are
    # above
    lines = [line for line in reading.describe(us) if ' against ' in line]
    if not lines:
        lines = ['No ratings given: the reading stands on its own.']
    self.readout.setText('\n'.join(lines))
    failed = reading.fits is False
    self.readout.setStyleSheet('font-weight: 600;' if failed else '')

Functions: