Make Informative and Nice Trends. Visualization tool for ITER, developed alongside Science Division.
This is a how-to guide for MINT - Make Informative and Nice Trends, the visualization tool developed alongside Science Division and used in the ITER control room. It retrieves both CODAC and IMAS data and is implemented in Python 3, PySide6, Matplotlib and VTK.
The current version is limited to 1-D traces. More complex plots are planned for upcoming releases.
| Term | Meaning |
|---|---|
| IMAS | Integrated Modelling Application Software |
| UDA | Unified Data Access |
| CBS | Control Breakdown Structure |
| Scsv | Semi-colon separated values |
On a CODAC environment:
$ sudo yum install codac-core-$(codac-version -v)-mint codac-core-$(codac-version -v)-uda-client-python3-utils -y
On SDCC (no installation required):
$ module load MINT
To start the tool:
$ mint
Log files live under ~/.local/1Dtool/logs/; the log file is mint.log.
Severity is controlled with the IPLOT_LOG_LEVEL environment variable, set before starting the tool. Allowed values: DEBUG, WARNING, CRITICAL, ERROR.
$ export IPLOT_LOG_LEVEL=DEBUG
$ mint
MINT always assumes UTC time, regardless of the host time zone. Timestamps follow ISO 8601.
Data can be queried by:
ITER:CWS-SCSU-BASIN-FILL-TESTS/130125. On SDCC, IMAS pulses use pulse/run, e.g. 135011/7, or an Access Layer URI such as imas:hdf5?path=/home/ITER/.../3/105027/32.
Figure 1. Querying by absolute time range.

Figure 2. Querying by pulse id on CCS.

Figure 3. Querying IMAS data by pulse id on SDCC: pulse/run.

Figure 4. Querying by pulse id on SDCC: using URI.

Figure 5. Querying by relative time range.
Multiple pulse IDs can be overlaid by separating them with commas. Use the Search button next to the Pulse ID field to browse pulses.
The toolbar above the variable table provides import / save / append actions, a Hide/Show columns menu, a Search Vars button (browse variables per data source), and Load new module to register an extra Python module for processing.

Figure 6. Icons / buttons above the variable table.
| Column | Meaning |
|---|---|
| DS | Data Source alias. Choose codacuda for ITER plant data, imasuda for IMAS data. |
| Variable | Variable name. For IMAS, full structure with [] for arrays, e.g. summary/heating_current_drive/ec[0]/power/value. |
| Stack | Up to three dot-separated digits: row, column, optional stack id. Numbering starts at 1. Stack id defaults to 1; signals sharing a stack share the X axis. |
| Row span | Rows the plot occupies (default 1). |
| Col span | Columns the plot occupies (default 1). |
| Envelope | Empty disables envelope. Set to 1 to compute min/max/avg envelope. |
| Alias | Shortcut name used in legends and expressions. |
| Pulse ID | Per-row pulse override. Use +(pulseID) to add, -(pulseID) to exclude, comma-separated. |
| Start Time / End Time | Per-row time override (ISO 8601, or relative seconds for pulse mode; negative values allowed). |
| X / Y / Z | Redefine the X, Y, Z vectors used for plotting (Z for contour and slider plots). |
| Extremities | Set to 1 to retrieve the last point before the start time (useful for PON data). |
| Plot type | Default PlotXY. |
| Output datatype | Indicates the output type of data retrieved from the archive. |
| Status | Status of the different stages (data retrieval, processing). |
| Comment | Free-text description, useful when sharing CSV/workspace files. |
Complex layouts can be built by manipulating Stack, Row span and Col span. The example workspace ExampleOfComplexLayout.json reproduces a multi-plot layout combining stacks and column spans.

Figure 7. Example of complex layout.
Once the time range or pulse IDs are set and the table populated, click Draw to plot, or Stream to subscribe to incoming data. Streaming requires a time window, entered in seconds, minutes, hours or days (up to 7 days); the value is converted automatically when the unit changes. The window seeds itself with past data from the archive before live samples arrive. Each signal retains up to 10000 samples (set through the MINT_MAX_STREAMING_POINTS environment variable); once exceeded, older samples are downsampled preserving their extremes while the most recent two minutes stay at full resolution.

Figure 8. Action buttons.

Figure 9. After clicking on Stream.
Use File > Import Workspace or File > Export workspace. Workspaces are JSON files.

Figure 10. Export / Import workspace.
The Export button opens a dialog where you choose an output path and a format (parquet or hdf5). Only signals with a valid stack id are exported. Processing signals are discarded.
While the export runs, a progress bar in the status bar reports the variable currently being written, so long exports are no longer mistaken for a frozen application.

Figure 11. Export data.
Above the canvas sits a toolbar (movable when the canvas is detached). Buttons:

Figure 12. Canvas toolbar.
Stats icon: min/avg/max, first/last value and time, sample count. Hide unused columns via Hide/Show columns.
Create Pulse: create a UDA pulse from the visible time range — set category, status and description; leave the number empty for automatic numbering. Shown only with a write-capable UDA server.
Update Pulse: search for an existing pulse and update its time range, status or description.show_minimap flag).Right-click a plot for per-plot actions:
When the plotted values are too large for plain tick labels — e.g. a signal whose values are raw nanosecond timestamps — the axis compacts them in offset + scale form, shown in the corner of the axis. A corner label like 1e9+1.121e15 is interpreted as follows:
1e9 is the multiplier applied to each tick label;+1.121e15 is the offset added afterwards.So a tick labelled 824 really means 824 × 1e9 + 1.121e15 = 1,121,824,000,000,000. Either part may appear alone: a corner label with only a power of ten (e.g. 1e18) is just the multiplier, with no offset added. The statistics table always shows the full, uncompacted values.

Figure 13. Offset + scale tick notation: each tick is multiplied by 1e9, then 1.121e15 is added.
Opens behind the canvas when you activate the RULER tool; click the RULER button again to bring it to the front. Two layouts:
Hide/Show signals picks which signal columns (or rows, in the Columns layout) are displayed. Columns can be resized, and you can copy the selection (Ctrl+C or right-click → Copy) or the whole table (Copy table button) to paste into a spreadsheet. Export to CSV writes the whole table (every ruler and every column) to a semicolon-separated .scsv file — the same convention as the signal-set export, so it opens cleanly in a spreadsheet — or a plain comma .csv. Remove ruler deletes the selected rulers; Compute distance opens a table with the ΔX, ΔY and per-signal deltas between two or more of them — even across plots — with its own Copy button; on time axes the ΔX also shows the duration in the statistics-table format, e.g. 9.5 s (9s500ms).
Title, font size, shared time, time-range difference, round hours, auto scale, Y min/max batch update, log scale, grid, show all ticks, number of ticks, background colour, legend (visibility, position, layout), crosshair labels (X, Y, Val), crosshair colour, font colour, line style (solid / dotted / dashed / none), line size, marker style (+ or o), marker size, line path (linear or last value), focus all plots on stack.
Plot-level preferences mirror the canvas-level ones. Signal-level preferences are a subset; the variable label can also be overridden. Axis x and y0 properties allow custom labels and limits, plus disabling autoscale.
Most preference changes survive subsequent Draw calls; axis-limit changes do not. Click Apply to commit and close the panel.
To persist preferences, save them and add to your profile:
IPLOT_CANVAS_CONFIG=~/.local/1DPreferences/default_properties.json
Wrap a variable in ${...} and combine with NumPy operations. ${X}.data and ${X}.time refer to the data and time vectors of variable X.
Example: multiply UTIL-HV-S22-BUS1:TOTAL_POWER by -2 and add an offset of 10:
${UTIL-HV-S22-BUS1:TOTAL_POWER}*(-2)+10
Aliases can be reused in expressions. If the Stack column is empty, the signal is not drawn (it can still feed an expression).
Combine several variables with aliases:
${Bus1} + ${Bus2} + ${Bus4}
The processing module aligns the time vectors when they differ (union of the time vectors, interpolated using the previous-value mode).
The x column rewrites the time vector; y rewrites the data vector. Example - plot a signal as the maximum value over a relative-time window:
| Column | Value |
|---|---|
| X | (${ML4_max}.time-${ML4_max}.time[0])/86400000000000 |
| Y | np.max(${ML4_max}.data) * np.ones(${ML4_max}.data.size) |
NumPy is available via the np. prefix. The X/Y columns can also be used to plot one signal against another. Note: time vectors are nanoseconds since Unix epoch in absolute mode, or relative seconds in pulse mode.

Figure 14. Using X and Y columns in a complex processing.
The default configuration lives under /etc/opt/codac/mint/datasources_def.cfg. Example:
{
"codacuda": {
"type": "CODAC_UDA",
"host": "io-ls-udasrv1.iter.org",
"port": 3090,
"rturl": "https://controls.iter.org/dashboard/backend/sse",
"rtheaders": "REMOTE_USER:$USERNAME,User-Agent:python_client",
"rtauth": null,
"default": true,
"uda_for_export": "io-ls-udasrv2.iter.org"
},
"imaspy": {
"type": "IMASPY",
"database": "iter",
"path": "public",
"backend": "MDSPLUS"
}
}
Override the default file with IPLOT_SOURCES_CONFIG. conninfo contains connection info; for UDA it is host=...,port=...; for IMAS database=...,path=...,backend=MDSPLUS. varprefix can be left empty. rturl is optional (SSE streaming endpoint). rtheaders contains expected headers. rtauth is the authentication mechanism (None if none). uda_for_export is optional: set it to export data from a different UDA server than the one you plot from. The same port is used.
See also: Reference - Supported data source types for the list of source types MINT recognises.
MINT is installed on all CODAC XPOZ terminals. The CCI team grants access to the relevant machines. The tool connects to the central UDA servers; IMAS data is not yet accessible from CODAC terminals.
$ module load MINT
$ mint
From SDCC you can plot IMAS and CODAC data on the same canvas. IMAS data is only accessible by pulse IDs (no absolute time range).
Until CCS v6.2 the pulse was a number; from CCS v6.3 it is a string with three parts: location, category, number, e.g. ITER:PCS/12000. Both syntaxes are supported; bare numbers fall back to the central UDA defaults. IMAS pulses currently use <pulse>/<run>, e.g. 130012/2; Access Layer URIs of the form imas:<backend>?path=/path/to/data/entry are also supported.
This section is auto-generated from the code at build time. Do not edit by hand — edits are overwritten.
| Shortcut | What it does |
|---|---|
Ctrl+C | Copy the current selection from the variable table to the clipboard |
Ctrl+V | Paste from the clipboard into the variable table |
F1 | Open the user manual at the section relevant to the focused area |
Ctrl+F | Open the search box in the user manual |
Ctrl+Q | Quit MINT |
Esc | Close the user manual window |
| Mode | Label | Description |
|---|---|---|
TIME_RANGE | Time range | Select data by time range |
PULSE_NUMBER | Pulse Id | Select data by pulse/run (ITER:PCS/123) or IMAS URI (imas:hdf5?path=/path/to/data/entry). In case of multiple pulse id, the separator used is coma |
RELATIVE_TIME | Relative | Select data by relative time to now |
| Type | Module | Class |
|---|---|---|
CODAC_UDA | iplotDataAccess.udaAccess | UdaAccess |
CSV | iplotDataAccess.csvAccess | CsvAccess |
IMASPY | iplotDataAccess.imaspyAccess | IMASPYDataAccess |
QT_SCALE_FACTOR=2 (or another value) before starting MINT.~/.local/1Dtool/dumps.
Figure 15. Moving the canvas toolbar (visible after Detach).
OverlayPulsesID.json.CustomizedPulsesPlots.json.CustomizedPulsesPlotsWithStartEnd.json.WeekComparison.json.WeekComparisonSamePlot.json.scipy.fft as sfft.Where are the workspaces?
$ ls `rpm -ql ${CODAC_RPM_PREFIX}-mint | grep workspaces | head -n 1` # CODAC
$ ls `echo $(dirname "$IPLOT_SOURCES_CONFIG")/data/workspaces` # SDCC
Cell too small to write an expression? Right-click and pick Editor mode; the resulting window is resizable.
MINT reports two kinds of feedback. Validation messages (e.g. Invalid date format, Alias already in use) are written to the log when you edit the table; they are self-explanatory and not duplicated here. Conceptual errors (network problems, mismatched signal shapes, permission issues) are the ones that benefit from extra context — those are catalogued below and are reachable from popups, the Status column tooltip and the Help menu.
Most issues fall into one of the following families.
Raised when MINT asks a data source for a signal and either cannot reach the server, cannot find the variable, or finds no data in the requested interval. Typical symptoms: the Status cell shows Data-Access | 0 points or a network/timeout message, the affected row turns red, and other rows in the same plot may turn orange (downstream errors). Most of the time the fix is to widen the time range, verify the variable name, or check that the data source is reachable.
Raised while MINT evaluates an expression or aligns signals before plotting. The two most common variants are arrays of incompatible shapes (signals with different sample counts that NumPy cannot broadcast) and expressions that return a scalar instead of an array. Mixing envelope and non-envelope signals also lives here. The Status cell carries the underlying NumPy or parser message; hover it for the human-readable explanation.
Raised by the Export dialog. The export only delivers raw data straight from the data source, so per-signal time overrides, custom x/y/z processing and signals defined as expressions in the Variable column are skipped (with a warning listing which aliases were skipped). A genuine failure — for example writing to a folder where the user has no permission — produces a red Export failed popup with the underlying reason and a Learn more button.
Raised at startup or while loading workspaces. Examples: no data sources found, exiting (the data sources file is missing or empty), Blueprint does not have a DataSource key (the blueprint JSON is malformed), Could not load the embedded manual (a packaged resource is missing). These almost always point at an environment or installation problem rather than user input.
Raised when MINT rejects a value typed in the signals table — invalid date formats, duplicated aliases, non-numeric stack identifiers, out-of-range values. These messages already describe both the problem and the remedy, so they only appear in the log; no further explanation is needed.
Raised by the streaming pipeline. Symptoms include occasional operands could not be broadcast together warnings while the X and Y buffers of a signal are being updated, and PlotItem not found followed by an IndexError in the date axis formatter when a workspace is imported with a stream still active. The first one is transient and recovers on the next frame; the second one is a known race for which the workaround is to stop the stream before importing.