Skip to content

Commit 2fafe60

Browse files
committed
add training for visualization actor
1 parent 3532d6f commit 2fafe60

File tree

5 files changed

+316
-0
lines changed

5 files changed

+316
-0
lines changed

docs/source/images/automatic.png

293 KB
Loading

docs/source/images/ff_prime.gif

1.65 MB
Loading

docs/source/images/ip_curve.gif

1.94 MB
Loading

docs/source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Manual
2626
installing
2727
usage
2828
tips_and_tricks
29+
training
2930

3031
.. toctree::
3132
:caption: API docs

docs/source/training.rst

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
2+
.. _`training`:
3+
4+
********
5+
Training
6+
********
7+
8+
Visualization Actor Training
9+
============================
10+
11+
In this training you will learn the following:
12+
13+
- Working with live data visualization
14+
- Creating custom plotting scripts for the visualization actor
15+
- Setting up visualization components in YMMSL files
16+
- Using both MUSCLE3 and standalone modes
17+
18+
All examples assume you have an environment with IMAS-MUSCLE3 up and running.
19+
If you do not have this yet, please have a look at the :ref:`installation instructions <installing>`.
20+
21+
.. note:: The visualization actor requires a graphical environment and a browser. If you
22+
are on ITER's SDCC, it is recommended to follow the training through the NoMachine client.
23+
24+
Exercise 1a: Understanding the Basic Structure
25+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26+
27+
.. md-tab-set::
28+
.. md-tab-item:: Exercise
29+
30+
Before creating visualizations, you need to understand the basic structure of a visualization script.
31+
Every visualization script must define two classes:
32+
33+
1. **State(BaseState)**: Extracts data from incoming IDSs
34+
2. **Plotter(BasePlotter)**: Defines how to visualize the data
35+
36+
Look at the simple example below that visualizes plasma current (Ip) from an equilibrium IDS:
37+
38+
**File:** `imas_muscle3/visualization/examples/simple_1d_plot/simple_1d_plot.py`
39+
40+
.. literalinclude:: ../../imas_muscle3/visualization/examples/simple_1d_plot/simple_1d_plot.py
41+
:language: python
42+
43+
What does the ``extract`` method do in the State class?
44+
45+
What does the ``get_dashboard`` method return in the Plotter class?
46+
47+
.. hint::
48+
The State class processes incoming IDS data, while the Plotter class creates the visual display.
49+
50+
.. md-tab-item:: Solution
51+
52+
The ``extract`` method:
53+
54+
- Checks if the incoming IDS is an equilibrium IDS
55+
- Extracts the plasma current (``ts.global_quantities.ip``) and time
56+
- Stores the data in an xarray Dataset for accumulation over time
57+
58+
The ``get_dashboard`` method:
59+
60+
- Returns a HoloViews DynamicMap object
61+
- The DynamicMap automatically updates when new data arrives
62+
- It displays a line plot of plasma current versus time
63+
64+
Exercise 1b: Setting Up Your First Visualization
65+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66+
67+
.. md-tab-set::
68+
.. md-tab-item:: Exercise
69+
70+
You will now run the visualization actor for configuration of the previous exercise. First,
71+
create a YMMSL configuration file that sets up a simple visualization pipeline with:
72+
73+
1. A source actor that sends the equilibrium IDS
74+
2. A visualization actor that receives and plots the data, according to the
75+
configuration in previous exercise.
76+
77+
Use the following settings in the YMMSL:
78+
79+
- Source URI: ``imas:hdf5?path=/home/ITER/fargerb/public/imasdb/ITER/3/666666/1``
80+
- Plot script: ``imas_muscle3/visualization/examples/simple_1d_plot/simple_1d_plot.py``
81+
82+
Run the MUSCLE pipeline, supplying the YMMSL file you made:
83+
84+
.. code-block:: bash
85+
86+
muscle_manager --start-all <YMMSL file>
87+
88+
What do you see in your browser?
89+
90+
.. hint::
91+
Look at the example YMMSL file in ``imas_muscle3/visualization/examples/simple_1d_plot/simple_1d_plot.ymmsl``
92+
93+
.. md-tab-item:: Solution
94+
95+
Create a file called ``my_visualization.ymmsl`` with the following content:
96+
97+
.. code-block:: yaml
98+
99+
ymmsl_version: v0.1
100+
model:
101+
name: my_visualization
102+
components:
103+
source_component:
104+
implementation: source_component
105+
ports:
106+
o_i: [equilibrium_out]
107+
visualization_component:
108+
implementation: visualization_component
109+
ports:
110+
s: [equilibrium_in]
111+
conduits:
112+
source_component.equilibrium_out: visualization_component.equilibrium_in
113+
settings:
114+
source_component.source_uri: imas:hdf5?path=/home/ITER/fargerb/public/imasdb/ITER/3/666666/1
115+
visualization_component.plot_file_path: <path/to/IMAS-MUSCLE3>/imas_muscle3/visualization/examples/simple_1d_plot/simple_1d_plot.py
116+
implementations:
117+
visualization_component:
118+
executable: python
119+
args: -u -m imas_muscle3.actors.visualization_component
120+
source_component:
121+
executable: python
122+
args: -u -m imas_muscle3.actors.source_component
123+
resources:
124+
source_component:
125+
threads: 1
126+
visualization_component:
127+
threads: 1
128+
129+
When you launch the muscle_manger, the browser should open, and you will see the
130+
plasma current plotted over time, updating in real-time as the new time slices are
131+
received by the visualization actor.
132+
133+
.. figure:: ../source/images/ip_curve.gif
134+
135+
Exercise 1c: Extracting 1D Profile Data
136+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
137+
138+
.. md-tab-set::
139+
.. md-tab-item:: Exercise
140+
141+
Create a State class that extracts the ff' profile from an equilibrium IDS.
142+
This profile data is stored as a 1D array along with its corresponding psi coordinate.
143+
144+
Your State class should extract:
145+
146+
- The ff' values: ``ts.profiles_1d.f_df_dpsi``
147+
- The psi coordinate: ``ts.profiles_1d.psi``
148+
- Store both in an xarray Dataset with dimensions ``("time", "profile")``
149+
150+
.. hint::
151+
Profile data is 1D at each time slice, so you'll need a dimension for
152+
the profile points in addition to time.
153+
154+
Also create a Plotter class that displays the ff' profile as a function of psi
155+
for the current time step. The plot should show how the profile evolves as new
156+
data arrives.
157+
158+
Your plot should:
159+
160+
- Display f_df_dpsi on the y-axis and psi on the x-axis
161+
- Show only the profile at the current time (use ``state.sel(time=self.time)``)
162+
- Update automatically when new data arrives (use ``@param.depends("time")``)
163+
164+
.. md-tab-item:: Solution
165+
166+
.. code-block:: python
167+
168+
import holoviews as hv
169+
import numpy as np
170+
import param
171+
import xarray as xr
172+
173+
from imas_muscle3.visualization.base_plotter import BasePlotter
174+
from imas_muscle3.visualization.base_state import BaseState
175+
176+
177+
class State(BaseState):
178+
def extract(self, ids):
179+
if ids.metadata.name == "equilibrium":
180+
self._extract_equilibrium(ids)
181+
182+
def _extract_equilibrium(self, ids):
183+
ts = ids.time_slice[0]
184+
185+
profiles_data = xr.Dataset(
186+
{
187+
"f_df_dpsi": (("time", "profile"), [ts.profiles_1d.f_df_dpsi]),
188+
"psi_profile": (("time", "profile"), [ts.profiles_1d.psi]),
189+
},
190+
coords={
191+
"time": [ids.time[0]],
192+
"profile": np.arange(len(ts.profiles_1d.f_df_dpsi)),
193+
},
194+
)
195+
196+
current_data = self.data.get("equilibrium")
197+
if current_data is None:
198+
self.data["equilibrium"] = profiles_data
199+
else:
200+
self.data["equilibrium"] = xr.concat(
201+
[current_data, profiles_data], dim="time", join="outer"
202+
)
203+
204+
205+
class Plotter(BasePlotter):
206+
def get_dashboard(self):
207+
profile_plot = hv.DynamicMap(self.plot_f_df_dpsi_profile)
208+
return profile_plot
209+
210+
@param.depends("time")
211+
def plot_f_df_dpsi_profile(self):
212+
xlabel = "Psi [Wb]"
213+
ylabel = "ff'"
214+
state = self.active_state.data.get("equilibrium")
215+
216+
if state:
217+
selected_data = state.sel(time=self.time)
218+
psi = selected_data.psi_profile.values
219+
f_df_dpsi = selected_data.f_df_dpsi.values
220+
title = f"ff' profile (t={self.time:.3f}s)"
221+
else:
222+
psi, f_df_dpsi, title = [], [], "Waiting for data..."
223+
224+
return hv.Curve((psi, f_df_dpsi), kdims=[xlabel], vdims=[ylabel]).opts(
225+
framewise=True,
226+
height=400,
227+
width=600,
228+
title=title,
229+
xlabel=xlabel,
230+
ylabel=ylabel,
231+
)
232+
233+
This generates the following ff' plot over time:
234+
235+
.. figure:: ../source/images/ff_prime.gif
236+
237+
.. tip:: More complex examples of visualizations are available in the
238+
``imas_muscle3/visualization/examples/`` directory. For example, the PDS example
239+
combines data from multiple IDSs, handles machine description data, and
240+
visualizes 2-dimensional data.
241+
242+
Exercise 2: Using Automatic Mode
243+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
244+
245+
.. md-tab-set::
246+
.. md-tab-item:: Exercise
247+
248+
Modify your YMMSL configuration to enable automatic mode. This mode allows
249+
the visualization actor to automatically discover and plot time-dependent
250+
quantities without needing a custom plotting script.
251+
252+
Advantages of automatic mode:
253+
254+
- Useful for exploring unfamiliar datasets
255+
- Automatically discovers all time-dependent quantities in the IDS
256+
- Provides a dropdown menu to select quantities to visualize
257+
- Chooses appropriate plot types automatically
258+
- No need to manually extract quantities
259+
260+
Disadvantages:
261+
262+
- No fine grain control over the plots
263+
- Unable to combine data
264+
265+
Repeat exercise 1b, however this time add the following settings to the YMMSL:
266+
267+
.. code-block:: yaml
268+
269+
settings:
270+
visualization_component.automatic_mode: true
271+
visualization_component.automatic_extract_all: true
272+
273+
Run the MUSCLE pipeline, supplying the YMMSL file you made. Use dropdown menu to
274+
visualize the following parameters:
275+
276+
- ``equilibrium/time_slice[0]/profiles_1d[0]/dpressure_dpsi``
277+
- ``equilibrium/time_slice[0]/global_quantities/energy_mhd``
278+
279+
.. md-tab-item:: Solution
280+
281+
Besides the plasma current curve, which was defined in the plotter class, you
282+
should also see the p' and the MHD energy curves in separate panels:
283+
284+
.. figure:: ../source/images/automatic.png
285+
286+
Exercise 3: Using the CLI
287+
^^^^^^^^^^^^^^^^^^^^^^^^^
288+
289+
.. md-tab-set::
290+
.. md-tab-item:: Exercise
291+
292+
It is also possible to run the visualization actor from the command line instead,
293+
without setting up a MUSCLE3 workflow. Try running the simple_1d_plot example
294+
through the CLI.
295+
296+
Run the visualization with:
297+
298+
- URI: ``imas:hdf5?path=/home/ITER/fargerb/public/imasdb/ITER/3/666666/1``
299+
- IDS name: ``equilibrium``
300+
- Plotting script: ``imas_muscle3/visualization/examples/simple_1d_plot/simple_1d_plot.py``
301+
302+
.. hint::
303+
Use ``python -m imas_muscle3.visualization.cli --help`` to see available options.
304+
305+
.. md-tab-item:: Solution
306+
307+
Run the following command:
308+
309+
.. code-block:: bash
310+
311+
python -m imas_muscle3.visualization.cli \
312+
"imas:hdf5?path=/home/ITER/fargerb/public/imasdb/ITER/3/666666/1" \
313+
equilibrium \
314+
imas_muscle3/visualization/examples/simple_1d_plot/simple_1d_plot.py
315+

0 commit comments

Comments
 (0)