erlab.interactive.imagetool.core

Provides core functionality of ImageTool.

This module contains ImageSlicerArea which handles the core functionality of ImageTool, including the slicing and plotting of data.

Functions

link_slicer([func, indices, steps, color])

Sync decorated methods across multiple ImageSlicerArea instances.

record_history([method])

Log history before calling the decorated method.

suppress_history([method])

Ignore history changes made within the decorated method.

Classes

ColorMapState

A dictionary containing the colormap state of an ImageSlicerArea instance.

ImageSlicerArea(parent, data[, cmap, gamma, ...])

A interactive tool based on pyqtgraph for exploring 3D data.

ImageSlicerState

A dictionary containing the state of an ImageSlicerArea instance.

ItoolColorBar(slicer_area, **cbar_kw)

ItoolColorBarItem(slicer_area, **kwargs)

ItoolCursorLine(*args, **kargs)

A subclass of pyqtgraph.InfiniteLine used in ImageTool.

ItoolCursorSpan(*args, **kargs)

ItoolDisplayObject(axes[, cursor])

Parent class for sliced data.

ItoolGraphicsLayoutWidget(slicer_area, ...)

ItoolImageItem(axes[, cursor])

Display a 2D slice of data as an image.

ItoolPlotDataItem(axes[, cursor, is_vertical])

Display a 1D slice of data in a plot.

ItoolPlotItem(slicer_area, display_axis, ...)

A subclass of pyqtgraph.PlotItem used in ImageTool.

PlotItemState

A dictionary containing the state of a PlotItem instance.

SlicerLinkProxy(*slicers[, link_colors])

Internal class for handling linked ImageSlicerArea s.

class erlab.interactive.imagetool.core.ColorMapState[source]

Bases: TypedDict

A dictionary containing the colormap state of an ImageSlicerArea instance.

cmap: str | ColorMap
gamma: float
reverse: bool
high_contrast: bool
zero_centered: bool
levels_locked: bool
levels: NotRequired[tuple[float, float]]
class erlab.interactive.imagetool.core.PlotItemState[source]

Bases: TypedDict

A dictionary containing the state of a PlotItem instance.

vb_aspect_locked: bool | float
vb_x_inverted: bool
vb_y_inverted: bool
class erlab.interactive.imagetool.core.ImageSlicerState[source]

Bases: TypedDict

A dictionary containing the state of an ImageSlicerArea instance.

color: ColorMapState
slice: ArraySlicerState
current_cursor: int
manual_limits: dict[str, list[float]]
cursor_colors: list[str]
file_path: typing.NotRequired[str | None]
splitter_sizes: typing.NotRequired[list[list[int]]]
plotitem_states: typing.NotRequired[list[PlotItemState]]
class erlab.interactive.imagetool.core.ItoolGraphicsLayoutWidget(slicer_area, display_axis, axis_enabled, image=False, **item_kw)[source]

Bases: PlotWidget

getPlotItem()[source]
erlab.interactive.imagetool.core.suppress_history(method=None)[source]

Ignore history changes made within the decorated method.

erlab.interactive.imagetool.core.record_history(method=None)[source]

Log history before calling the decorated method.

Sync decorated methods across multiple ImageSlicerArea instances.

Parameters:
  • func (Callable | None, default: None) – The method to sync across multiple instances of ImageSlicerArea.

  • indices (bool, default: False) – If True, the input argument named value given to func are interpreted as indices, and will be converted to appropriate values for other instances of ImageSlicerArea. The behavior of this conversion is determined by steps. If True, An input argument named axis of type integer must be present in the decorated method to determine the axis along which the index is to be changed.

  • steps (bool, default: False) – If False, considers value as an absolute index. If True, considers value as a relative value such as the number of steps or bins. See the implementation of SlicerLinkProxy for more information.

  • color (bool, default: False) – Boolean whether the decorated method is related to visualization, such as colormap control.

class erlab.interactive.imagetool.core.SlicerLinkProxy(*slicers, link_colors=True)[source]

Bases: object

Internal class for handling linked ImageSlicerArea s.

Parameters:
  • *slicers (ImageSlicerArea) – The slicers to link.

  • link_colors (bool, default: True) – Whether to sync color related changes, by default True.

property children: WeakSet
property num_children: int
add(slicer_area)[source]
remove(slicer_area)[source]
sync(source, funcname, arguments, indices, steps, color)[source]

Propagate changes across multiple ImageSlicerAreas.

This method is invoked every time a method decorated with link_slicer() in a linked ImageSlicerArea is called.

Parameters:
convert_args(source, target, args, indices, steps)[source]
static convert_index(source, target, axis, index, steps)[source]
class erlab.interactive.imagetool.core.ImageSlicerArea(parent, data, cmap='magma', gamma=0.5, zero_centered=False, rad2deg=False, *, transpose=False, bench=False, state=None, file_path=None, image_cls=None, plotdata_cls=None, _in_manager=False, _disable_reload=False)[source]

Bases: QWidget

A interactive tool based on pyqtgraph for exploring 3D data.

Parameters:
  • parent (QWidget) – Parent widget.

  • data (DataArray or array-like) – Data to display. The data must have 2 to 4 dimensions.

  • cmap (str | ColorMap, default: "magma") – Default colormap of the data.

  • gamma (float, default: 0.5) – Default power law normalization of the colormap.

  • zero_centered (bool, default: False) – If True, the normalization is applied symmetrically from the midpoint of the colormap.

  • rad2deg (bool | Iterable[str], default: False) – If True and data is not None, converts some known angle coordinates to degrees. If an iterable of strings is given, only the coordinates that correspond to the given strings are converted.

  • transpose (bool, default: False) – If True, the main image is transposed before being displayed.

  • bench (bool, default: False) – Prints the fps on Ctrl + drag for debugging purposes.

  • state (ImageSlicerState | None, default: None) – Initial state containing the settings and cursor position.

  • file_path (str | PathLike | None, default: None) – If the data has been loaded from a file, the path to the file. This is used to set the window title.

Signals:
  • sigDataChanged()

  • sigCurrentCursorChanged(index)

  • sigViewOptionChanged()

  • sigHistoryChanged()

  • sigWriteHistory()

  • sigCursorCountChanged(n_cursors) – Inherited from erlab.interactive.slicer.ArraySlicer.

  • sigIndexChanged(cursor, axes) – Inherited from erlab.interactive.slicer.ArraySlicer.

  • sigBinChanged(cursor, axes) – Inherited from erlab.interactive.slicer.ArraySlicer.

  • sigShapeChanged() – Inherited from erlab.interactive.slicer.ArraySlicer.

  • sigTwinChanged() – Inherited from erlab.interactive.slicer.ArraySlicer.

COLORS: tuple[QColor, ...] = (<PyQt6.QtGui.QColor object>, <PyQt6.QtGui.QColor object>, <PyQt6.QtGui.QColor object>, <PyQt6.QtGui.QColor object>, <PyQt6.QtGui.QColor object>, <PyQt6.QtGui.QColor object>, <PyQt6.QtGui.QColor object>)

PySide6.QtGui.QColors for multiple cursors.

TWIN_COLORS: tuple[QColor, ...] = (<PyQt6.QtGui.QColor object>, <PyQt6.QtGui.QColor object>, <PyQt6.QtGui.QColor object>, <PyQt6.QtGui.QColor object>, <PyQt6.QtGui.QColor object>)

PySide6.QtGui.QColors for twin plots.

HORIZ_PAD: int = 45

Reserved space for the x axes in each plot.

VERT_PAD: int = 30

Reserved space for the y axes in each plot.

TICK_FONT_SIZE: float = 11.0

Font size of axis ticks in points.

property parent_title: str
property display_name: str

Generate a display name for the slicer.

Depending on the source of the data and the ‘name’ attribute of the underlying DataArray, the display name is generated differently.

If nothing can be inferred, an empty string is returned.

property colormap_properties: ColorMapState
property state: ImageSlicerState
property splitter_sizes: list[list[int]]
property is_linked: bool
property linked_slicers: WeakSet
property colormap: str | ColorMap
property levels_locked: bool
property levels: tuple[float, float]
property slices: tuple[ItoolPlotItem, ...]
property profiles: tuple[ItoolPlotItem, ...]
property main_image: ItoolPlotItem

Return the main PlotItem.

property images: tuple[ItoolPlotItem, ...]
property axes: tuple[ItoolPlotItem, ...]

Currently valid subset of self._plots.

property array_slicer: ArraySlicer
property n_cursors: int
property current_indices: list[int]
property current_values: list[float]
property current_values_uniform: list[float]
property data: DataArray
property undoable: bool
property redoable: bool
history_suppressed()[source]
on_close()[source]
write_state()[source]
flush_history()[source]

Clear the undo and redo history.

undo()[source]

Undo the most recent action.

redo()[source]

Redo the most recently undone action.

initialize_actions()[source]

Initialize QtWidgets.QAction instances.

refresh_actions_enabled()[source]

Refresh the enabled state of miscellaneous actions.

This slot is triggered from the parent widget when the menubar containing the actions is about to be shown.

connect_axes_signals()[source]
disconnect_axes_signals()[source]
connect_signals()[source]
get_current_index(axis)[source]
get_current_value(axis, uniform=False)[source]
get_axes_widget(index)[source]
get_axes(index)[source]
close_associated_windows()[source]
refresh_all(axes=None, only_plots=False)[source]
refresh_current(axes=None)[source]
refresh(cursor, axes=None)[source]
view_all()[source]
center_all_cursors()[source]
center_cursor()[source]
set_current_cursor(cursor, update=True)[source]
set_data(data, rad2deg=False, file_path=None)[source]

Set the data to be displayed.

Parameters:
  • data (DataArray | ndarray[Any, dtype[TypeVar(_ScalarType_co, bound= generic, covariant=True)]]) – The data to be displayed. If a xarray.DataArray is given, the dimensions and coordinates are used to determine the axes of the plots. If a xarray.Dataset is given, the first data variable is used. If a numpy.ndarray is given, it is converted to a xarray.DataArray with default dimensions.

  • rad2deg (bool | Iterable[str], default: False) – If True, converts coords along dimensions that have angle-like names to degrees. If an iterable of strings is given, coordinates for dimensions that correspond to the given strings are converted.

  • file_path (str | PathLike | None, default: None) – Path to the file from which the data was loaded. If given, the file path is used to set the window title.

property reloadable: bool

Check if the data can be reloaded from the file.

The data can be reloaded if the data was loaded from a file that still exists and the data loader name is stored in the data attributes.

Returns:

boolTrue if the data can be reloaded, False otherwise.

reload()[source]

Reload the data from the file it was loaded from, using the same loader.

Silently fails if the data cannot be reloaded. If an error occurs while reloading the data, a message is shown to the user.

See also

reloadable

update_values(values, update=True)[source]

Update only the values of the data.

The coords and shape of the data array are not changed.

Parameters:
  • values (ndarray[Any, dtype[TypeVar(_ScalarType_co, bound= generic, covariant=True)]] | DataArray) – The new values to be set. If a xarray.DataArray is given, the dimensions must match the current data array. If a numpy.ndarray is given, the shape must match the current data array. Note that if the user has transposed the current data array, passing a numpy.ndarray with the original shape will fail.

  • update (bool, default: True) – If True, the plots are updated after setting the new values.

Note

This method only checks for matching dimension name and shape, and does not check for equal coordinate values.

apply_func(func, update=True)[source]

Apply a function to the data.

The function must accept the data as the first argument and return a new DataArray. The returned DataArray must have the same dimensions and coordinates as the original data.

This action is not recorded in the history, and the data is not affected. Only one function can be applied at a time.

Parameters:
  • func (Callable[[DataArray], DataArray] | None) – The function to apply to the data. if None, the data is restored.

  • update (bool, default: True) – If True, the plots are updated after setting the new values.

set_manual_limits(manual_limits)[source]

Set manual limits for the axes.

Replaces the current manual limits with the given limits dictionary and updates all child axes accordingly.

propagate_limit_change(axes)[source]

Propagate manual limits changes to all linked slicers.

Called when the limits of a child axes are changed by the user.

This method first propagates the limits to all linked slicers (if any), and then triggers the update of the manual limits for all other axes. This ensures that all plots share the same limits for a given dimension.

swap_axes(ax1, ax2)[source]
transpose_main_image()[source]
set_index(axis, value, update=True, cursor=None)[source]
step_index(axis, value, update=True, cursor=None)[source]
step_index_all(axis, value, update=True)[source]
set_value(axis, value, update=True, uniform=False, cursor=None)[source]
set_bin(axis, value, update=True, cursor=None)[source]
set_bin_all(axis, value, update=True)[source]
make_cursors(n, colors)[source]
add_cursor(color=None)[source]
remove_cursor(index)[source]
remove_current_cursor()[source]
gen_cursor_color(index)[source]
gen_cursor_colors(index)[source]
set_colormap(cmap=None, gamma=None, reverse=None, high_contrast=None, zero_centered=None, levels_locked=None, levels=None, update=True)[source]
refresh_colormap()[source]
lock_levels(lock)[source]
add_tool_window(widget)[source]

Save a reference to an additional window widget.

This is mainly used for handling tool windows such as goldtool and dtool.

The tool window is cleared from memory immediately when it is closed. Closing the main window will close all associated tool windows.

Only pass widgets that are not associated with a parent widget.

If the parent ImageTool is in the manager, the widget is transferred to the manager instead.

Parameters:

widget (QWidget) – The widget to add.

open_in_ktool()[source]

Open the interactive momentum conversion tool.

adjust_layout(r=(1.2, 1.5, 3.0, 1.0))[source]

Determine the padding and aspect ratios.

Parameters:
  • horiz_pad – Reserved space for the x and y axes.

  • vert_pad – Reserved space for the x and y axes.

  • font_size – Font size of axis ticks in points.

  • r (tuple[float, float, float, float], default: (1.2, 1.5, 3.0, 1.0)) – 4 numbers that determine the aspect ratio of the layout. See notes.

Notes

Axes indices and layout parameters.

     ┌───────────┬───────────┐
r[0] │     1     │     6     │
     │           ├───────────┤
     ├───────────┤     3     │
r[1] │     4     ├───────────┤
     │           │     7     │
     │───────────┼───────┬───┤
     │           │       │   │
r[2] │     0     │   5   │ 2 │
     │           │       │   │
     └───────────┴───────┴───┘
      r[3] * r[2]
toggle_snap(value=None)[source]
changeEvent(evt)[source]
class erlab.interactive.imagetool.core.ItoolCursorLine(*args, **kargs)[source]

Bases: InfiniteLine

A subclass of pyqtgraph.InfiniteLine used in ImageTool.

property plotItem: ItoolPlotItem
setBounds(bounds, value=None)[source]
value()[source]
mouseDragEvent(ev)[source]
mouseClickEvent(ev)[source]
hoverEvent(ev)[source]
class erlab.interactive.imagetool.core.ItoolCursorSpan(*args, **kargs)[source]

Bases: LinearRegionItem

setRegion(rgn)[source]
class erlab.interactive.imagetool.core.ItoolDisplayObject(axes, cursor=None)[source]

Bases: object

Parent class for sliced data.

Stores the axes and cursor index for the object, and retrieves the sliced data from erlab.interactive.imagetool.slicer.ArraySlicer when needed.

property display_axis
property slicer_area: ImageSlicerArea
property array_slicer: ArraySlicer
property cursor_index
property sliced_data: DataArray
refresh_data()[source]
class erlab.interactive.imagetool.core.ItoolPlotDataItem(axes, cursor=None, is_vertical=False, **kargs)[source]

Bases: ItoolDisplayObject, PlotDataItem

Display a 1D slice of data in a plot.

refresh_data()[source]
class erlab.interactive.imagetool.core.ItoolImageItem(axes, cursor=None, **kargs)[source]

Bases: ItoolDisplayObject, BetterImageItem

Display a 2D slice of data as an image.

updateImage(*args, **kargs)[source]
refresh_data()[source]
mouseDragEvent(ev)[source]
mouseClickEvent(ev)[source]
class erlab.interactive.imagetool.core.ItoolPlotItem(slicer_area, display_axis, axis_enabled, image=False, image_cls=None, plotdata_cls=None, **item_kw)[source]

Bases: PlotItem

A subclass of pyqtgraph.PlotItem used in ImageTool.

This class tracks axes and cursors for the data displayed in the plot, and provides context menu actions for interacting with the data.

connect_signals()[source]
disconnect_signals()[source]
setup_twin()[source]
property twin_axes_location: Literal['top', 'bottom', 'left', 'right']
property twin_visible: bool
enableAutoRange(axis=None, enable=True, x=None, y=None)[source]
update_twin_range(autorange=True)[source]
update_twin_plots()[source]
property axis_dims: tuple[str | None, str | None]
property axis_dims_uniform: tuple[str | None, str | None]
property is_independent: bool
property current_data: DataArray
property selection_code: str
property is_guidelines_visible: bool
set_normalize(normalize)[source]

Toggle normalization for 1D plots.

open_in_new_window()[source]

Open the current data in a new window. Only available for 2D data.

open_in_goldtool()[source]
open_in_restool()[source]
open_in_dtool()[source]
range_changed_manually()[source]

Propagate manual range changes to other plots.

This slot propagates the limit change to related other plots in the same slicer area, and to other linked slicer areas.

refresh_manual_range()[source]

Store manual limit changes in the parent slicer area.

This slot ensures that the manual limits stored in the parent slicer area are always up to date with the current view range.

When a user manually changes the view range, this slot is called before range_changed_manually is called.

update_manual_range()[source]

Update view range from values stored in the parent slicer area.

set_range_from(limits, **kwargs)[source]
toggle_aspect_equal()[source]
getMenu()[source]
getViewBox()[source]
mouseDragEvent(ev)[source]
process_drag(sig)[source]
add_cursor(update=True)[source]
index_of_line(line)[source]
line_click(line)[source]
line_drag(line, value, axis)[source]
remove_cursor(index)[source]
refresh_cursor(cursor)[source]
set_guidelines(n)[source]

Show rotating crosshairs for alignment.

remove_guidelines()[source]

Hide rotating crosshairs.

refresh_items_data(cursor, axes=None)[source]
refresh_labels()[source]
set_active_cursor(index)[source]
save_current_data()[source]
copy_selection_code()[source]
property display_axis: tuple[int, ...]
property slicer_area: ImageSlicerArea
property array_slicer: ArraySlicer
changeEvent(evt)[source]
class erlab.interactive.imagetool.core.ItoolColorBarItem(slicer_area, **kwargs)[source]

Bases: BetterColorBarItem

property slicer_area: ImageSlicerArea
property images
property primary_image
setImageItem(*args, **kwargs)[source]
class erlab.interactive.imagetool.core.ItoolColorBar(slicer_area, **cbar_kw)[source]

Bases: PlotWidget

property cb: ItoolColorBarItem
set_dimensions(width=30, horiz_pad=None, vert_pad=None, font_size=11.0)[source]
setVisible(visible)[source]