Skip to content

visualdynamics.report.prediction

prediction

Responses against prediction in a report (report feature prediction).

A prediction block reads one measured object, the response PSDs of a run say, against the project's predictions (core.prediction). With the feature on it draws, for each response channel with a prediction, a figure of the measurement over its prediction scaled to the level run, and after them one table: a row per predicted peak, giving the channel, the frequency, level and Q predicted and measured, the frequency difference, the ratio of the levels (named once, in the column's heading, as an ASD ratio or an amplitude ratio, and given in decibels) and the uncertainty the model stated. A note beneath says how the predictions were scaled, where they came from (the customer's, where they are), which predicted peaks have no measured peak in their band, and what the half-power reader warned of.

Whether a response is as predicted, different and explained, or different and not explained is the analyst's answer and is never written here; the table is what lets a reader give it. The figures and the table fall in the Results section of the skeleton, which the program fills; nothing is offered as the author's text.

Where the comparison takes its predictions and its level is one function, inputs, so a later source of run levels (a run log) feeds the comparison there and nowhere else. With the feature off a prediction block is not drawn at all.

Functions:

Name Description
inputs

What a block compares: (predictions, the measured object, its

build

The page blocks for one prediction block: a figure per channel

Functions:

inputs

inputs(block: Mapping[str, Any], objects: Mapping[str, Any], object_groups: Sequence[Mapping[str, Any]] | None = None) -> tuple[Any, Any, str, float | None] | None

What a block compares: (predictions, the measured object, its name, the level stated for the run), or None while either binding does not resolve.

Today the predictions are the project's object the block names, and the level is the one the block states ('level', dB relative to full level; None leaves it to the scaling a PSD holds, core.prediction.level_run). This is the one place the comparison takes them from, so a later source of predictions or run levels is read here.

Raises:

Type Description
TypeError

When the block's predictions are not a predictions object, or its level is not a number.

Source code in src/visualdynamics/report/prediction.py
def inputs(block: Mapping[str, Any], objects: Mapping[str, Any],
           object_groups: Sequence[Mapping[str, Any]] | None = None
           ) -> tuple[Any, Any, str, float | None] | None:
    """What a block compares: (predictions, the measured object, its
    name, the level stated for the run), or None while either binding
    does not resolve.

    Today the predictions are the project's object the block names, and
    the level is the one the block states (`'level'`, dB relative to
    full level; None leaves it to the scaling a PSD holds,
    `core.prediction.level_run`). This is the one place the comparison
    takes them from, so a later source of predictions or run levels is
    read here.

    Raises
    ------
    TypeError
        When the block's predictions are not a predictions object, or
        its level is not a number.
    """
    from ..core.prediction import Predictions
    from ..core.report import resolve_binding

    source = resolve_binding(block.get('source'), objects, object_groups)
    name = resolve_binding(block.get('measured'), objects, object_groups)
    if source not in objects or name not in objects:
        return None
    predictions = objects[source]
    if not isinstance(predictions, Predictions):
        raise TypeError(f'{source!r} is a {type(predictions).__name__}, '
                        'not a predictions object')
    level = block.get('level')
    if level is not None and (isinstance(level, bool)
                              or not isinstance(level, (int, float))):
        raise TypeError(f'the level run is a number of dB, not {level!r}')
    return predictions, objects[name], str(name), level

build

build(block: Mapping[str, Any], objects: Mapping[str, Any], us: Any, object_groups: Sequence[Mapping[str, Any]] | None = None) -> list[dict[str, Any]] | None

The page blocks for one prediction block: a figure per channel compared, then the table, then its note. None while a binding does not resolve; a single paragraph saying why when the comparison is refused, since a comparison that read nothing says so.

Source code in src/visualdynamics/report/prediction.py
def build(block: Mapping[str, Any], objects: Mapping[str, Any], us: Any,
          object_groups: Sequence[Mapping[str, Any]] | None = None
          ) -> list[dict[str, Any]] | None:
    """The page blocks for one `prediction` block: a figure per channel
    compared, then the table, then its note. None while a binding does
    not resolve; a single paragraph saying why when the comparison is
    refused, since a comparison that read nothing says so."""
    from ..core.prediction import compare

    try:
        found = inputs(block, objects, object_groups)
        if found is None:
            return None
        predictions, measured, name, level = found
        comparison = compare(predictions, measured, level)
    except (TypeError, ValueError) as refusal:
        return [{'kind': 'text',
                 'text': f'**{CAPTION}:** nothing compared; {refusal}.'}]
    compared = [channel for channel in comparison.channels
                if not channel.note]
    if not compared:
        # a numbered table with no rows is a handle to nothing: the
        # note alone says what was not compared and why (2026-10-28)
        return [{'kind': 'text',
                 'text': f'**{CAPTION}:** nothing compared.\n\n'
                         + _note(comparison)}]
    grid = _grid(measured)
    out = [_figure(channel, comparison, measured, us, grid)
           for channel in compared]
    out.append(_table(block, comparison, measured, name, us))
    out.append({'kind': 'text', 'text': _note(comparison)})
    return out