Visualization actor

Actor for live, web-based visualization of IMAS data in a simulation using the Panel library. It launches a local web server to display the visualization. The plotting logic is user-defined in a specified Python script, allowing for customizable visualizations.

To use the visualization actor, include it in the ymmsl file:

implementations:
  visualization_component:
    executable: python
    args: -u -m imas_muscle3.actors.visualization_component

Warning

The visualization actor is still in a prototype state and may not always behave as expected!

Available Settings

  • Mandatory

    • plot_file_path: (string) The path to the Python script that defines the plotting logic. This script must contain a State class and a Plotter class, as described below.

  • Optional

    • port: (int) The port on which the visualization server will run. Defaults to 0, indicating a random available port.

    • throttle_interval: (float) The minimum time in seconds between plot updates. This can be used to prevent the visualization from slowing down if data arrives very quickly. Defaults to 0.1.

    • keep_alive: (bool) If True, the visualization server will remain active after the last MUSCLE message was received, allowing for inspection of the received data. If False, the server stops after the last MUSCLE message is received. Defaults to False.

    • open_browser: (bool) If True, automatically opens a new tab in your web browser to the visualization page upon starting. Defaults to True.

    • automatic_mode: (bool) If True, time-dependent IDS quantities can automatically be visualized using a dropdown menu. Data will automatically be extracted, and an appropriate plot for the quantity will be selected.

    • automatic_extract_all: (bool) This only works if automatic_mode is enabled. If True, automatically extracts all time dependent quantities of the IDS. If False, the data will only start to be extracted as soon as a new plot is selected. Enabling this can cause significant computation and memory overhead, depending on the size of the IDS.

Available Ports

All IDS's are available for the visualization actor. They will be active if connected in the ymmsl file and will be skipped otherwise.

  • Optional

    • <ids_name>_in (S): Any incoming IDS timeslices on the S port. Replace <ids_name> with the required IDS name (e.g., equilibrium_in).

    • <ids_name>_md_in (S): Any incoming machine description IDS's on the S port. These are typically static data like the machine wall or coil geometry. Replace <ids_name> with the required IDS name (e.g., wall_md_in).

User-defined Plotting Script

The Python script specified by plot_file_path is the core of the visualization. It must define two classes that inherit from the provided base classes:

  1. State(BaseState): This class is responsible for extracting the necessary information from an IDS into an internal data structure, typically an xarray.Dataset. It must implement an extract(self, ids) method which will be called for each incoming IDS.

  2. Plotter(BasePlotter): This class uses the data managed by the State object to define and arrange the plots in a Panel dashboard. It must implement a get_dashboard(self) method that returns a Panel object.

Command Line Interface

A command line interface is made available if you want to run the visualization actor directly from the terminal instead of through a MUSCLE3 actor. You will need to provide at least both the URI of the data, as well as the plot_file_path, for example:

python ./imas_muscle3/visualization/cli.py <URI> ./imas_muscle3/visualization/examples/pds/pds.py

Usage details, such as how to supply separate URIs for machine description data, can be found by supplying the --help option:

python ./imas_muscle3/visualization/cli.py --help

Example

This example demonstrates how to set up a simple live plot of a single variable: the plasma current (Ip) of an equilibrium IDS. More complex examples are available in the imas_muscle3/visualization/examples directory.

ymmsl configuration

This configuration consists of two main components:

  • A source actor is set up to send an equilibrium IDS.

  • A visualization actor is set up to receive this IDS and visualize it.

simple_1d_plot.ymmsl
ymmsl_version: v0.1
model:
  name: test_model
  components:
    source_component:
      implementation: source_component
      ports:
        o_i: [equilibrium_out]
    visualization_component:
      implementation: visualization_component
      ports:
        s: [equilibrium_in]
  conduits:
    source_component.equilibrium_out: visualization_component.equilibrium_in
settings:
  source_component.source_uri: imas:hdf5?path=/home/ITER/blokhus/public/imasdb/ITER/4/666666/3/
  visualization_component.plot_file_path: /home/ITER/blokhus/projects/IMAS-MUSCLE3/imas_muscle3/visualization/examples/simple_1d_plot/simple_1d_plot.py
  visualization_component.throttle_interval: 0
  visualization_component.keep_alive: true
implementations:
  visualization_component:
    executable: python
    args: -u -m imas_muscle3.actors.visualization_component
  source_component:
    executable: python
    args: -u -m imas_muscle3.actors.source_component
resources:
  source_component:
    threads: 1
  visualization_component:
    threads: 1

Plotting Script

This script tells the visualization actor what to extract from the data and how to plot it.

State Class

The State class extracts the plasma current from the equilibrium IDS. When it receives a new equilibrium IDS time slice, it extracts out the plasma current (ts.global_quantities.ip) and time, then stores this in an xarray Dataset for accumulation over time.

Plotter Class

The Plotter class creates a live-updating line plot. It returns a HoloViews DynamicMap object that automatically calls plot_ip_vs_time() when data updates. This method plots all plasma current data received up to the current time as a time series curve.

simple_1d_plot.py
"""
Simple example plot which plots the plasma current over time.
"""

import holoviews as hv
import param
import xarray as xr

from imas_muscle3.visualization.base_plotter import BasePlotter
from imas_muscle3.visualization.base_state import BaseState


class State(BaseState):
    def extract(self, ids):
        if ids.metadata.name == "equilibrium":
            self._extract_equilibrium(ids)

    def _extract_equilibrium(self, ids):
        ts = ids.time_slice[0]
        new_point = xr.Dataset(
            {
                "ip": ("time", [ts.global_quantities.ip]),
            },
            coords={
                "time": [ids.time[0]],
            },
        )

        current_data = self.data.get("equilibrium")
        if current_data is None:
            self.data["equilibrium"] = new_point
        else:
            self.data["equilibrium"] = xr.concat(
                [current_data, new_point], dim="time", join="outer"
            )


class Plotter(BasePlotter):
    def get_dashboard(self):
        ip_vs_time = hv.DynamicMap(self.plot_ip_vs_time)
        return ip_vs_time

    @param.depends("time")
    def plot_ip_vs_time(self):
        xlabel = "Time [s]"
        ylabel = "Ip [A]"
        state = self.active_state.data.get("equilibrium")

        if state:
            mask = state.time <= self.time
            time = state.time[mask]
            ip = state.ip[mask]
            title = "Ip over time"
        else:
            time, ip, title = [], [], "Waiting for data..."

        return hv.Curve((time, ip), kdims=["time_ip"], vdims=["ip"]).opts(
            framewise=True,
            height=300,
            width=960,
            title=title,
            xlabel=xlabel,
            ylabel=ylabel,
        )

General

The visualization actor is not bound to a specific DD version.


Last update: 2025-12-11