Skip to content

visualdynamics.plot.limit_prediction

limit_prediction

The notch a set of limit channels would cut, drawn from one core.limit_prediction.LimitPrediction.

At the top, the control channel: the reference dashed, the control the controller could hold solid, the lower edge of the tolerance dotted, and every predicted notch hatched across its band with its depth written on it. Under it, a row per response channel: the predicted response at full level solid against its limit profile dashed, the bands where it is over hatched. Each row is titled with its reading in words.

Nothing is carried by hue alone. The curves differ by line style and are named in the legend; the notches and the exceedances are hatched as well as shaded, and labeled; and the verdicts are in the titles in words, in the abort color only as well.

Functions:

Name Description
notch_words

What a notch's band says on the plot: its depth, and its channel.

build_limit_prediction

Draw prediction into a graphics layout: the control row, then a

summary

The prediction's verdict in a line, for a status bar.

Functions:

notch_words

notch_words(notch: Any) -> str

What a notch's band says on the plot: its depth, and its channel.

Source code in src/visualdynamics/plot/limit_prediction.py
def notch_words(notch: Any) -> str:
    """What a notch's band says on the plot: its depth, and its channel."""
    return f'notch {notch.depth_db:.1f} dB, {notch.channels[0]}'

build_limit_prediction

build_limit_prediction(layout: Any, prediction: Any, *, unit_system: Any = None, theme: Any = None) -> list[Any]

Draw prediction into a graphics layout: the control row, then a row per response channel. Returns the plots, the control's first.

Source code in src/visualdynamics/plot/limit_prediction.py
def build_limit_prediction(layout: Any, prediction: Any, *,
                           unit_system: Any = None,
                           theme: Any = None) -> list[Any]:
    """Draw `prediction` into a graphics layout: the control row, then a
    row per response channel. Returns the plots, the control's first."""
    import pyqtgraph as pg
    from PySide6.QtCore import Qt

    from ..theme import theme as resolve_theme
    from ..units import DEFAULT_SYSTEM
    from . import _reading_plot, axis_label, legend_below

    colors = resolve_theme(theme)
    us = DEFAULT_SYSTEM if unit_system is None else unit_system
    ink = colors['plot_foreground']
    abort = colors['limit_abort']
    f = np.asarray(prediction.frequency, dtype=float)

    def pen(style: int, color: Any = ink, width: float = 1.5) -> Any:
        return pg.mkPen(color, width=width, style=Qt.PenStyle(style))

    plots = []
    control = _reading_plot(layout, 0)
    control.setLogMode(x=True, y=True)
    legend_below(layout, control, 0, colors)
    dimension = prediction.dimension
    _curve(control, f, _density(prediction.reference, dimension, us),
           pen(DASHED), f'reference at {prediction.control_label}')
    _curve(control, f, _density(prediction.control, dimension, us),
           pen(SOLID), 'control, predicted')
    if prediction.lower is not None:
        _curve(control, f, _density(prediction.lower, dimension, us),
               pen(DOTTED, abort, 1.0),
               f'{prediction.tolerance} tolerance, lower edge')
    shown = _density(prediction.control, dimension, us)
    for notch in prediction.notches:
        _hatch(control, f, notch.low, notch.high, abort)
        k = int(np.argmin(np.abs(f - notch.frequency)))
        _words(control, notch_words(notch), notch.frequency, shown[k], ink,
               above=False)
    control.setLabel('left', axis_label(dimension, us))
    outside = prediction.within_tolerance is False
    control.setTitle(prediction.verdict(), color=abort if outside else ink,
                     size='9pt')
    plots.append(control)

    for k, channel in enumerate(prediction.channels, start=1):
        row = _reading_plot(layout, 2 * k)
        row.setLogMode(x=True, y=True)
        row.setXLink(control)
        legend_below(layout, row, k, colors)
        _curve(row, f, _density(channel.response, channel.dimension, us),
               pen(SOLID), f'{channel.label} predicted at full level')
        if channel.profile is not None:
            _curve(row, f, _density(channel.profile, channel.dimension, us),
                   pen(DASHED), 'limit profile')
            response = _density(channel.response, channel.dimension, us)
            for over in channel.exceedances:
                _hatch(row, f, over.low, over.high, abort)
                k = int(np.argmin(np.abs(f - over.frequency)))
                _words(row, f'over {over.over_db:.1f} dB', over.frequency,
                       response[k], ink, above=True)
        row.setLabel('left', axis_label(channel.dimension, us))
        row.setTitle(channel.describe(f, us),
                     color=abort if channel.exceedances else ink, size='9pt')
        plots.append(row)
    plots[-1].setLabel('bottom', 'frequency [Hz]')
    # the lines predicted on, not the whole transmissibility: outside the
    # reference nothing is predicted
    span = f[np.isfinite(prediction.reference) & (f > 0.0)]
    if span.size > 1:
        control.setXRange(np.log10(span[0]), np.log10(span[-1]),
                          padding=0.02)
    return plots

summary

summary(prediction: Any) -> str

The prediction's verdict in a line, for a status bar.

Source code in src/visualdynamics/plot/limit_prediction.py
def summary(prediction: Any) -> str:
    """The prediction's verdict in a line, for a status bar."""
    return prediction.verdict()