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 --> PlottingWorkspaceTreePresenter --> IPlottingWorkspaceTreeView
    |
    +-- owns --> PlottingWorkspaceTree
    |
    +-- owns --> PlottingViewStateProvider --> PlotOutputTypeProperties
    |
    +-- uses --> IPlottingModel (PlottingModel)
    |
    +-- uses --> IPlotOptionsProvider (PlotOptionsProvider)
    |
    +-- uses --> IPlotter (Plotter)
    |
    +-- uses --> IActiveFigureMonitor (QtActiveFigureMonitor)
    |
    `-- updates --> IPlottingView (QtPlottingView)
                                   |
                                   `-- owns --> 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 selection eligibility and muted state. The tree presenter applies filtering and selection rules through IPlottingWorkspaceTreeView; QtPlottingWorkspaceTreeView implements that interface. It receives prepared labels and visual state, keeping tree policy and Qt rendering separate.

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/PlottingWorkspaceTreePresenter.h/.cpp#

PlottingPresenter owns PlottingWorkspaceTreePresenter, which owns the evaluated tree and filter state. It:

  • prepares column labels as std::string values;

  • applies regular-expression and reduced-output filters, retaining the last valid expression while incomplete syntax is edited;

  • propagates selection to visible, eligible descendants; and

  • resolves selected workspace names and ADS workspace-group counts, including complete groups required for spin asymmetry.

Filtering preserves hidden selections. The presenter uses row paths and IPlottingWorkspaceTreeView, with no Qt types.

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 tab control state and output-specific tree eligibility. 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 and through a parent, through a parent only, 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/IPlottingWorkspaceTreeView.h#

Defines the toolkit-independent tree contract and its click/selection notifications. Nodes are identified by row paths. PlottingWorkspaceTreeViewItem contains prepared column labels, children, and muted state. The view renders these values and applies visibility and selection commands.

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;

  • exposes the child tree view and reads filter, output, axes, and layout inputs;

  • owns QtPlottingWorkspaceTreeView; 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/QtPlottingWorkspaceTreeView.h/.cpp#

QtPlottingWorkspaceTreeView implements IPlottingWorkspaceTreeView and owns the QStandardItemModel. It converts prepared strings to QString, creates rows, and reuses palette-aware muted-row styling.

It translates Qt indexes and input events into row paths and presenter notifications using viewportEvent. After handling a selection change, it emits workspaceSelectionChanged, which QtPlottingView forwards to the tab presenter without accessing the selection model.

view/PlottingWidget.ui#

Qt Designer definition for the Plotting tab. It declares the plotting workspace tree; the IvsQBinned, IvsLambda, and IvsQ filters; the Item-column regular-expression filter; the plot output selector; detector-map and alignment axis controls; plotting buttons; vertical-tiling checkbox; shared axis checkboxes; and add-to-existing checkbox.

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/PlottingWorkspaceTreePresenterTest.h, covering prepared labels, filtering, and tree selection rules;

  • test/Plotting/QtPlottingViewTest.h, covering Qt controls, tree rendering, input translation, and selection notifications;

  • 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. test/Plotting/PlottingWorkspaceTreeTestHelpers.h shares tree fixtures between presenter and Qt integration tests.

End-to-End Operation#

Construction#

  1. QtBatchView constructs QtPlottingView, which owns the tree widget.

  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, PlottingViewStateProvider, and PlottingWorkspaceTreePresenter. The tree presenter uses the child view exposed by IPlottingView.

  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 presenter passes the resulting item states to its PlottingWorkspaceTreePresenter, which prepares display labels and passes them to the tree widget.

  6. The widget rebuilds its QStandardItemModel. The tree presenter then applies filters through IPlottingWorkspaceTreeView 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. The tree widget forwards row clicks to PlottingWorkspaceTreePresenter. Parent selection propagates only to visible, eligible descendants. Workspace groups requiring complete selection resolve all required members when read.

  4. Changing a workspace output-type checkbox or the Item-column regular expression notifies PlottingPresenter, which passes the filter inputs to its tree presenter. This reapplies visibility and expands the tree. Hidden rows retain their selection state.

  5. The widget’s workspaceSelectionChanged signal reaches PlottingPresenter through QtPlottingView. The presenter obtains selected leaf names and ADS workspace-group counts from its tree presenter and asks PlottingViewStateProvider::plotActionState for a new PlotActionState.

  6. 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.