ISIS Reflectometry Plotting Tab Internals#

This document describes the implementation of the Plotting tab in the ISIS Reflectometry Interface. It is intended for developers changing the plotting workspace tree, plot output types, plot controls, or the connection to Mantid’s matplotlib plotting functions.

The implementation follows Model-View-Presenter (MVP):

  • the model owns plotting data and creates plot-ready workspaces;

  • the view owns Qt widgets and translates between Qt and view-facing data;

  • the presenter coordinates the model, view, batch interface, and plotting services.

The source is under qt/scientific_interfaces/ISISReflectometry/GUI/Plotting. Shared plot request and rendering code is under the adjacent GUI/Common directory.

Architecture#

The principal dependencies are:

BatchPresenter
    |
    v
PlottingPresenter
    |
    +-- owns --> PlottingWorkspaceTree
    |
    +-- owns --> PlottingViewStateProvider --> PlotOutputTypeProperties
    |
    +-- uses --> IPlottingModel (PlottingModel)
    |
    +-- uses --> IPlotOptionsProvider (PlotOptionsProvider)
    |
    +-- uses --> IPlotter (Plotter)
    |
    +-- uses --> IActiveFigureMonitor (QtActiveFigureMonitor)
    |
    `-- updates --> IPlottingView (QtPlottingView)
                                   |
                                   v
                      QtPlottingWorkspaceTreeViewAdapter
                                   |
                                   v
                      QtPlottingWorkspaceTreeView

Names in parentheses are the production implementations of the preceding interfaces. PlottingViewStateProvider and PlottingWorkspaceTree are concrete, presenter-owned collaborators and therefore do not have interfaces.

PlottingWorkspaceTree is presenter-owned domain state rather than a Qt tree model. The presenter converts this state into PlottingWorkspaceTreeItemState objects through PlottingViewStateProvider before passing it to the view. The provider uses PlotOutputTypeProperties to determine display and selection state. This keeps output-type selection policy out of the model and Qt-specific tree handling out of the presenter.

The two providers perform different transformations:

  • PlottingViewStateProvider converts model and presenter state into toolkit-independent state that IPlottingView can display.

  • PlotOptionsProvider converts the user’s scientific output and layout selection into rendering options that IPlotter can execute.

Key Terminology#

Plot output type

The scientific result requested by the user: a reflectivity curve, detector map, spin asymmetry, or alignment plot. It is represented by PlotOutputType.

Reduced workspace output type

The reduction-stage data represented by a plotting workspace tree item, such as IvsQ, IvsLambda, or IvsQBinned. It is represented by ReducedWorkspaceOutputType and is distinct from the requested plot output type.

Plotting workspace tree

The presenter-owned hierarchy of successful reduction groups, runs, ADS workspace groups, and workspaces that can supply data for plotting. A reduction group comes from the Runs table; an ADS workspace group is a Mantid WorkspaceGroup containing workspaces.

Postprocessed reduction-group output

A stitched or otherwise group-level reduced workspace produced from multiple runs. It appears directly beneath a reduction group and can be excluded from output types for which it is not meaningful.

Plot output selection

The user’s chosen PlotOutputType together with any output-specific detector-map or alignment axes. It is represented by PlotOutputSelection.

View state

Toolkit-independent labels, visibility, enabled state, muted state, and selection modes calculated by PlottingViewStateProvider for the Qt view to apply.

Plot options

The rendering configuration calculated by PlotOptionsProvider, including layout, style, axis metadata, error bars, markers, and title. It is represented by PlotOptions.

Model Files#

The model directory contains data derived from completed reductions and the operations that prepare selected data for plotting.

model/PlottingWorkspace.h#

Defines the domain types shared by the plotting model and presenter:

  • PlottingWorkspaceTreeItemType identifies reduction groups, runs, ADS workspace groups, and individual workspaces in the hierarchy.

  • ReducedWorkspaceOutputType identifies the reduced output represented by a workspace item, such as IvsQ, IvsLambda, or IvsQBinned.

  • PlottingWorkspaceTreeItem is one node in the model-side hierarchy. It contains domain data only and has no selection or display state.

  • PlottingWorkspace contains the metadata needed to turn one reduced workspace into a requested plot output. This includes its ADS name, run numbers, containing workspace group, and period number.

model/IPlottingModel.h and model/PlottingModel.h/.cpp#

Defines:

  • IPlottingModel, the presenter-facing interface for obtaining plot-ready ADS workspace names; and

  • PlottingModel, the implementation that either selects existing reduced workspaces or generates derived plotting workspaces.

PlottingModel::workspacesForPlotting dispatches according to the selected PlotOutputType:

  • reflectivity curves use the selected reduced workspace names directly;

  • spin asymmetry creates a cached workspace from the up and down members of a polarization workspace group;

  • alignment creates a detector profile and optional fitted-peak workspaces from the corresponding raw time-of-flight workspace;

  • detector maps extract detector spectra, optionally convert the x axis to wavelength, and create the selected numeric y axis.

Generated workspaces have private ISIS Reflectometry prefixes and are reused if they already exist in the ADS. The model uses run and period metadata from PlottingWorkspace to find the matching raw workspace in TOF or __TOF.

model/PlottingWorkspaceTree.h/.cpp#

PlottingWorkspaceTree owns the plotting workspace hierarchy and a name-to-PlottingWorkspace lookup. rebuild derives both collections from a RunsTable:

  • only successful reduction groups and rows are considered;

  • an output is added only when its named workspace still exists in the ADS;

  • ADS workspace groups are expanded into child workspace items;

  • run-number and period metadata is read from matrix workspaces;

  • empty runs and groups are omitted.

items exposes the hierarchy to the presenter. plottingWorkspacesForNames resolves leaf names selected in the view back to their model metadata. It preserves the order supplied by the view and ignores names that are not in the current tree.

Presenter Files#

The presenter directory contains orchestration and all policy that determines what the user may select or plot.

presenter/IPlottingPresenter.h#

Defines IPlottingPresenter, the interface used by BatchPresenter. It receives the parent batch presenter, processing state changes, instrument changes, and updated RunsTable data. This allows the Batch component to coordinate the tab without depending on PlottingPresenter directly.

presenter/PlottingPresenter.h/.cpp#

Defines PlottingPresenter, which coordinates the complete tab workflow. Its responsibilities are to:

  • subscribe to view notifications and active-figure changes;

  • enable or disable plot output selection while reduction or autoreduction runs;

  • rebuild the model-side plotting workspace tree when the runs table changes;

  • ask PlottingViewStateProvider for output-specific tree and control state;

  • resolve the user’s selected workspace names;

  • request plot-ready workspaces from IPlottingModel;

  • request rendering options from IPlotOptionsProvider;

  • warn before creating five or more plot items; and

  • submit one or more PlotRequest objects to IPlotter.

An individual layout is submitted as one request per workspace. Overplot and tiled layouts are submitted as one request containing all selected workspaces.

presenter/PlottingPresenterFactory.h#

Defines PlottingPresenterFactory, which owns the production Plotter, PlotOptionsProvider, and PlottingModel, and injects them into a new PlottingPresenter. BatchPresenterFactory uses this factory when constructing a Batch tab.

presenter/PlotOutputTypeProperties.h/.cpp#

Defines:

  • PlotOutputTypeCapabilities, the flags describing support for overplotting, adding to an existing figure, postprocessed reduction-group outputs, and multi-plot selection based on ADS workspace groups;

  • PlotOutputTypeProperties, the display name, accepted plotting workspace tree item types, accepted reduced workspace output types, and capabilities for one PlotOutputType; and

  • plotOutputTypeProperties, the lookup that returns the configured properties for an output type.

The presenter and PlottingViewStateProvider query these properties instead of containing output-type conditionals. This is the main extension point for tree selection and action behavior when adding another plot output type.

presenter/PlottingViewStateProvider.h/.cpp#

Defines PlottingViewStateProvider, the stateless provider for all state passed from the presenter to the view. For the plotting workspace tree, it converts model-side PlottingWorkspaceTreeItem objects into view-facing PlottingWorkspaceTreeItemState objects for the selected output type. It evaluates whether each node:

  • is included by the output type;

  • is a postprocessed reduction-group output that must be excluded;

  • can be selected directly;

  • can contribute when an ancestor is selected; and

  • should be visually muted.

Keeping this policy in the presenter layer means that PlottingWorkspaceTree knows nothing about GUI selection behavior.

The same provider creates state for the other parts of the Plotting tab:

  • plot output selector labels;

  • visibility of detector-map and alignment controls; and

  • enabled states for the Individual, Overplot, and Tiled actions, plus enabled and checked states for the vertical-tiling and add-to-existing options.

Action state depends on processing state, selected workspace and ADS workspace-group counts, output-type capabilities, and compatibility with the active Reflectometry figure. When adding to an existing figure, one selected item is enough for a tiled or overplot request because the figure already contains a plot.

presenter/QtActiveFigureMonitor.h/.cpp#

Defines:

  • IActiveFigureMonitor, the interface for notifications that the active matplotlib figure may have changed; and

  • QtActiveFigureMonitor, which bridges active-order changes from Workbench’s global figure manager observer facility to Qt.

The presenter uses these notifications to refresh add-to-existing and overplot action state immediately when plots are opened, focused, or closed outside the tab.

View Files#

The view directory contains Qt widgets and simple data transferred from the presenter to the view.

view/IPlottingView.h#

Defines:

  • PlottingViewSubscriber, the user-action notifications implemented by the presenter; and

  • IPlottingView, the state setters and user-input getters used by the presenter.

The interface uses standard C++ and plotting domain types. Qt is limited to the plot parent QWidget required by the plotting service.

view/PlottingViewState.h#

Defines the toolkit-independent types produced by PlottingViewStateProvider:

  • PlotOutputTypeViewItem pairs an output type with the label displayed in the selector;

  • PlotOutputControlsState controls visibility of output-specific controls;

  • PlotActionState controls enabled and checked states for plotting actions;

  • PlottingWorkspaceTreeSelectionMode specifies whether a plotting workspace tree row can be selected directly, through a parent, both, or neither; and

  • PlottingWorkspaceTreeItemState is one evaluated node containing its label, domain metadata, children, muted state, and selection mode.

These types let the presenter update related controls without exposing Qt types. The Qt view applies the decisions but does not recalculate them.

view/QtPlottingView.h/.cpp#

Defines QtPlottingView, the QWidget implementation of IPlottingView used as the Plotting tab. It:

  • initialises controls defined in PlottingWidget.ui;

  • connects Qt signals to PlottingViewSubscriber notifications;

  • applies presenter-provided control state;

  • reads the current plot output, axes, layout options, and plotting workspace tree selection;

  • owns QtPlottingWorkspaceTreeViewAdapter; and

  • displays the confirmation dialog for large plot requests.

The view reports user actions but does not decide which actions or tree entries are valid.

view/QtPlottingWorkspaceTreeViewAdapter.h/.cpp#

Defines QtPlottingWorkspaceTreeViewAdapter, which adapts PlottingWorkspaceTreeItemState objects to a QStandardItemModel displayed by QtPlottingWorkspaceTreeView. It owns the Qt-specific details of:

  • columns and custom data roles;

  • output and item type display names;

  • palette-aware muted rendering;

  • row and subtree selection propagation;

  • direct-selection and parent-selection modes; and

  • extracting selected leaf workspace names and selected ADS workspace-group counts.

The adapter applies selection behavior already specified by the presenter. It does not determine whether a particular output type permits a workspace.

view/QtPlottingWorkspaceTreeView.h/.cpp#

Defines QtPlottingWorkspaceTreeView, the specialised QTreeView used by the tab. Its painting logic extends selected-row backgrounds across muted cells and obtains disabled colors from the active Qt palette, allowing the tree to work in light and dark themes.

view/PlottingWidget.ui#

Qt Designer definition for the Plotting tab. It declares the plotting workspace tree, plot output selector, detector-map and alignment axis controls, plotting buttons, vertical-tiling checkbox, and add-to-existing checkbox. Control policy is not encoded in the UI file; the presenter supplies it through PlotActionState and PlotOutputControlsState.

Shared Plotting Files#

The following files under GUI/Common are used by the Plotting tab and keep plot request construction separate from Python-backed rendering.

Common/PlotOptions.h/.cpp#

Defines the data passed from user selection to rendering:

  • PlotOutputType, PlotStyle, PlotLayout, and AxisScale describe the requested scientific output and its general presentation;

  • DetectorMapXAxis, DetectorMapYAxis, and AlignmentXAxis describe output-specific scientific axis choices;

  • PlotOutputSelection contains the user’s output type and output-specific axis choices;

  • PlotAxis contains the label, unit, and scale for one rendered axis;

  • PlotOptions is the complete rendering configuration derived from the output selection and layout; and

  • PlotRequest combines workspace names, options, figure targeting, and window-parent information for IPlotter.

The implementation provides output-specific option factory functions for reflectivity, detector-map, spin-asymmetry, and alignment plots. They define labels, scales, styles, error bars, markers, and window titles.

Common/IPlotOptionsProvider.h and PlotOptionsProvider.h/.cpp#

Defines:

  • IPlotOptionsProvider, the presenter-facing contract for discovering available plot output types and deriving rendering options; and

  • PlotOptionsProvider, the production implementation that converts a PlotOutputSelection plus PlotLayout into PlotOptions.

Instrument-specific outputs are currently available for POLREF, OFFSPEC, and CRISP; other instruments expose reflectivity curves only.

Common/IPlotter.h and Common/Plotter.h/.cpp#

These files existed before the tab and were extended to support its requests. They define:

  • IPlotter, the presenter-facing contract for inspecting the active figure and plotting a PlotRequest; and

  • Plotter, the production implementation that bridges C++ requests to Mantid’s Python/matplotlib plotting functions.

IPlotter can report whether the active figure belongs to the Reflectometry tab and whether its active axes can be overplotted.

Plotter has three main stages:

  1. Evaluate the request by expanding workspace groups, deriving matplotlib axis properties, finding an eligible active figure, and choosing a plotting route.

  2. Dispatch to colorfill, existing-figure tiled, custom tiled, or standard Mantid plotting.

  3. Apply post-plot processing to the appropriate axes: labels, optional horizontal markers, the Reflectometry figure marker, and transient window parenting.

The distinction between all axes and newly-created axes prevents labels and markers for a tiled addition from modifying plots that were already in the figure.

Integration and Build Files#

Plotting/CMakeLists.txt#

Lists plotting sources, headers, the Qt MOC input, and PlottingWidget.ui, then exports those lists to the enclosing ISISReflectometry CMake configuration.

Batch/BatchPresenter.h/.cpp and BatchPresenterFactory.h#

These existing Batch files integrate the new component. The factory constructs the plotting presenter from the plotting view. BatchPresenter owns it, supplies the parent presenter, forwards instrument and processing state, and calls updatePlottingWorkspaces whenever reduction state or relevant ADS state changes.

Batch/IBatchView.h and Batch/QtBatchView.h/.cpp#

These existing view files expose and construct the QtPlottingView as one of the Batch tab’s child tabs.

Test Files#

The focused test files are:

  • test/Plotting/PlottingWorkspaceTreeTest.h, covering hierarchy and metadata construction from runs-table and ADS state;

  • test/Plotting/PlottingModelTest.h, covering workspace selection and generation for each output type;

  • test/Plotting/PlottingViewStateProviderTest.h, covering plot action enablement and output-specific plotting workspace tree item state;

  • test/Plotting/PlottingPresenterTest.h, covering Batch and view notifications, display-state updates, request construction, and plotting orchestration;

  • test/Plotting/QtPlottingViewTest.h, covering Qt control and plotting workspace tree behavior;

  • test/Common/PlotOptionsProviderTest.h, covering instrument output availability and output-to-options conversion; and

  • test/Common/PlotterTest.h, covering plot route selection and post-plotting behavior through the Python plotting boundary.

TestHelpers/PlottingTestHelpers.h provides readable equality matchers and formatted diagnostics for plotting workspace tree expectations. The test files are registered in test/CMakeLists.txt.

End-to-End Operation#

Construction#

  1. QtBatchView constructs the Plotting tab view.

  2. BatchPresenterFactory asks PlottingPresenterFactory to create the presenter for that view.

  3. PlottingPresenterFactory injects its PlottingModel, PlotOptionsProvider, and Plotter into the presenter. The presenter directly owns its PlottingWorkspaceTree and PlottingViewStateProvider.

  4. The plotting presenter subscribes to the view and to active-figure changes through QtActiveFigureMonitor.

  5. BatchPresenter takes ownership of the plotting presenter and passes itself as the parent coordinator.

Performing a reduction#

  1. The user requests processing from the Runs tab. The Runs presenter forwards the request to BatchPresenter, which coordinates the job manager and algorithm runner.

  2. When a row or group algorithm completes, BatchPresenter::notifyAlgorithmComplete updates reduction state in the job manager and refreshes the Runs view.

  3. The Batch presenter calls updatePlottingWorkspaces. The same refresh is made after an algorithm error, batch load, row or group edits, settings changes, workspace deletion or rename, and ADS clearing.

  4. updatePlottingWorkspaces passes the current model RunsTable to PlottingPresenter::notifyRunsTableChanged.

Updating the plotting workspace tree#

  1. PlottingPresenter asks PlottingWorkspaceTree to rebuild from the runs table.

  2. The tree walks reduction groups and rows that completed successfully and checks each recorded output against the ADS.

  3. Existing ADS workspace groups are expanded. Each selectable leaf is recorded as a PlottingWorkspace with run, containing-group, and period metadata.

  4. The presenter reads the currently selected PlotOutputType and asks PlottingViewStateProvider::plottingWorkspaceTreeItemStates to evaluate the hierarchy using PlotOutputTypeProperties.

  5. The resulting item states are passed to IPlottingView::setPlottingWorkspaceTreeItemStates.

  6. QtPlottingWorkspaceTreeViewAdapter rebuilds its QStandardItemModel, applies muted state and selection modes, and expands the tree.

User interaction#

  1. When the instrument changes, the presenter asks IPlotOptionsProvider::availableTypes for supported plot output types. It then asks PlottingViewStateProvider::outputTypeViewItems to pair those domain values with labels for the plot output selector.

  2. Changing output type clears the current tree selection. The presenter then asks PlottingViewStateProvider to rebuild the plotting workspace tree item states, output-control visibility, and plotting action state.

  3. Clicking a selectable tree row is handled by QtPlottingWorkspaceTreeViewAdapter. Parent selection is propagated only to descendants whose presenter-supplied selection mode permits it.

  4. A selection change notifies PlottingPresenter. The presenter obtains selected leaf names and ADS workspace-group counts from the view and asks PlottingViewStateProvider::plotActionState for a new PlotActionState.

  5. The active-figure monitor causes the same action-state calculation when the current matplotlib figure changes. Add-to-existing is enabled only for a compatible Reflectometry figure and output type. Overplotting additionally requires Mantid to report that the active axes are compatible.

Creating the plot#

  1. Clicking Individual, Overplot, or Tiled sends the corresponding PlotLayout notification to PlottingPresenter.

  2. The presenter resolves selected leaf names through PlottingWorkspaceTree::plottingWorkspacesForNames and reads the current plot output and axis selections from the view.

  3. PlottingModel::workspacesForPlotting returns existing reduced workspace names or creates the derived workspaces required for the selected output.

  4. The presenter passes the view’s PlotOutputSelection and requested layout to IPlotOptionsProvider::optionsFor. The production PlotOptionsProvider returns the axis, style, marker, error-bar, and title configuration as PlotOptions.

  5. For a request of five or more plot items, the view asks the user to confirm.

  6. The presenter creates PlotRequest objects and calls IPlotter::plot. Individual plots are sent separately; overplot and tiled outputs are sent together.

  7. Plotter evaluates and dispatches the request. Colorfill requests use Mantid’s pcolormesh; vertical or workspace-group tiling uses custom tiled axes; tiled additions create axes on the active Reflectometry figure; other line requests use the standard Mantid plotting function.

  8. Post-plot processing labels the correct axes, adds any configured marker, marks the figure as owned by this interface, and assigns the Reflectometry window as its transient parent.

  9. The presenter refreshes active-figure compatibility so the controls reflect the newly created or updated plot, then asks PlottingViewStateProvider for refreshed action state.

Adding a Plot Output Type#

When extending the tab with another output type, update each responsibility at its existing boundary:

  1. Add the scientific selection type and any required controls to PlotOptions.h and the view.

  2. Add selection and action capabilities to PlotOutputTypeProperties.cpp.

  3. Add plot-ready workspace creation or selection to PlottingModel.cpp.

  4. Add rendering options and instrument availability to PlotOptions.cpp and PlotOptionsProvider.cpp.

  5. Add focused model, presenter/state-provider, options-provider, view, and plotter tests for behavior introduced at each boundary.