erlab.interactive.imagetool.slicer

Helper functions for fast slicing xarray.DataArray objects.

Functions

check_cursors_compatible(old, new)

Check if the cursor positions of the old array can be applied to the new array.

make_dims_uniform(darr)

Ensure that all dimensions of the given DataArray are uniform.

qsel_args_from_indexers(data, indexers, ...)

Build qsel keyword arguments from index selections.

restore_nonuniform_dims(darr)

Undo the effect of make_dims_uniform().

Classes

ArraySlicer(xarray_obj, parent)

Internal class used to slice a xarray.DataArray rapidly.

ArraySlicerState

A dictionary containing the state of cursors in an ArraySlicer.

class erlab.interactive.imagetool.slicer.ArraySlicerState[source]

Bases: TypedDict

A dictionary containing the state of cursors in an ArraySlicer.

dims: tuple[Hashable, ...]
bins: list[list[int]]
indices: list[list[int]]
snap_to_data: bool
twin_coord_names: typing.NotRequired[tuple[Hashable, ...]]
cursor_color_params: typing.NotRequired[tuple[tuple[Hashable, ...], Hashable, str, bool, float, float] | None]
erlab.interactive.imagetool.slicer.check_cursors_compatible(old, new)[source]

Check if the cursor positions of the old array can be applied to the new array.

The two arrays must have the same dimensions, and the coordinate values for each dimension of the old array must be included in the coordinate values of the same dimension in the new array.

Parameters:
erlab.interactive.imagetool.slicer.make_dims_uniform(darr)[source]

Ensure that all dimensions of the given DataArray are uniform.

This function checks each dimension of the input DataArray to determine if its coordinate is evenly spaced. If a dimension is found to be non-uniform, a new coordinate named {dim}_idx is created with indices ranging from 0 to N-1, where N is the length of the original coordinate. The original dimension is then swapped with the new uniform dimension, and is left in the DataArray as a coordinate.

Parameters:

darr (DataArray) – The input DataArray to be processed.

Returns:

DataArray – A new DataArray with all dimensions made uniform.

Return type:

DataArray

erlab.interactive.imagetool.slicer.restore_nonuniform_dims(darr)[source]

Undo the effect of make_dims_uniform().

Restore non-uniform dimensions by swapping dimensions that end with '_idx' with their corresponding coordinates and dropping the uniform dimensions.

Parameters:

darr (DataArray) – The input DataArray with dimensions that may end with '_idx'.

Returns:

DataArray – The DataArray with '_idx' dimensions swapped with their corresponding coordinates and the '_idx' dimensions dropped.

Return type:

DataArray

erlab.interactive.imagetool.slicer.qsel_args_from_indexers(data, indexers, binned_dims)[source]

Build qsel keyword arguments from index selections.

Parameters:
  • data (DataArray) – Data whose current coordinates should be used for the returned qsel values.

  • indexers (Mapping[Hashable, slice | int]) – Dimension names mapped to integer indices or index slices.

  • binned_dims (Sequence[Hashable]) – Dimensions whose index slices should become qsel center and width arguments.

Returns:

dict – Keyword arguments suitable for xarray.DataArray.qsel().

Raises:

ValueError – If a requested dimension is missing or a binned selection cannot be expressed by the current coordinate values.

Return type:

dict[Hashable, float]

class erlab.interactive.imagetool.slicer.ArraySlicer(xarray_obj, parent)[source]

Bases: QObject

Internal class used to slice a xarray.DataArray rapidly.

Computes binned line and image profiles from multiple cursors. This class also stores the data indices and the number of bins for each cursor. Automatic conversion of non-uniform dimensions are also handled here.

Parameters:

xarray_obj (DataArray) – A xarray.DataArray with up to 4 dimensions.

Signals:
  • sigIndexChanged(int or tuple of int, tuple or None) – Emitted when the cursor index is changed. The first argument is the cursor index, and the second is a tuple containing the changed axes.

  • sigBinChanged(int, tuple) – Emitted when the bin size is changed. The first argument is the cursor index, and the second is a tuple containing the changed axes.

  • sigCursorCountChanged(int) – Emitted when the number of cursors is changed. Emits the new number of cursors.

  • sigShapeChanged() – Emitted when the underlying xarray.DataArray is transposed.

  • sigTwinChanged() – Emitted when the coordinates to be displayed in the twin axes are changed.

Note

The original intent of this class was a xarray accessor. This is why ArraySlicer does not depend on a ImageSlicerArea but rather on the underlying xarray.DataArray. Originally, when loading a different array, a different instance of ArraySlicer had to be created. This was a terrible design choice since it messed up signals every time the instance was replaced. Hence, the behaviour was modified (23/06/19) so that the underlying xarray.DataArray of ArraySlicer could be swapped. As a consequence, each instance of ImageSlicerArea now corresponds to exactly one instance of ArraySlicer, regardless of the data. In the future, ArraySlicer might be changed so that it relies on its one-to-one correspondence with ImageSlicerArea for the signals.

property snap_to_data: bool
property twin_coord_names: set[Hashable]
set_array(xarray_obj, validate=True, reset=False, *, copy_values=True, preserve_dims=None)[source]

Set the DataArray object to be sliced.

Parameters:
  • xarray_obj (DataArray) – The array to slice.

  • validate (bool, default: True) – If True, validate the array before setting it. This flag is intended for internal use where the new array is guaranteed to be valid, such as when transposing an already valid array.

  • reset (bool, default: False) – If True, reset cursors, bins, indices, and values.

  • copy_values (bool, default: True) – If True, copy the underlying array values while validating. Set to False to reuse the current values buffer when the caller already manages ownership.

  • preserve_dims (Sequence[Hashable] | None, default: None) – Dimension order to preserve after validation. This is used when rebuilding the slicer from the public source array without disturbing the current view layout.

Returns:

bool – True if the cursors were reset, False if only the data was updated.

Return type:

bool

property associated_coord_dims: dict[Hashable, tuple[Hashable, ...]]

Numeric non-dimension coordinates that can be plotted with data profiles.

associated_coord_profile(coord_name, cursor, display_axis)[source]

Return a 1D associated-coordinate profile for a profile plot.

associated_coord_point_value(coord_name, cursor, binned=True)[source]

Return an associated-coordinate value at the cursor position.

cursor_color_coord(cursor, coord_dims, coord_name)[source]

Return dims, all values, and cursor value for coordinate-based coloring.

property coords: tuple[ndarray[tuple[Any, ...], dtype[floating]], ...]

Coordinate values of each dimension in the array.

property coords_uniform: tuple[ndarray[tuple[Any, ...], dtype[floating]], ...]

Coordinate values of each dimension in the array.

Non-uniform coordinates are converted to uniform indices.

property incs: tuple[floating, ...]

Increment of each dimension in the array.

Returns the step for each dimension coordinate in the array. Non-uniform dimensions will return the absolute average of all non-zero step sizes.

property incs_uniform: tuple[floating, ...]

Increment size of each dimension in the array.

Non-uniform dimensions will increment by 1.

property lims: tuple[tuple[floating, floating], ...]

Coordinate bounds of each dimension in the array.

property lims_uniform: tuple[tuple[floating, floating], ...]

Coordinate bounds of each dimension in the array.

Non-uniform dimensions are converted to uniform indices.

property uniform_index_params: tuple[tuple[floating, floating, int], ...]

Cached uniform-axis indexing parameters for fast value lookups.

property nanmax: float
property nanmin: float
property display_values_known_safe: bool
property limits: tuple[float, float]

Return the display-safe global minimum and maximum of the data.

property n_cursors: int

The number of cursors.

property state: ArraySlicerState
static validate_array(data, copy_values=True)[source]

Validate a given xarray.DataArray.

If data has two momentum axes (kx and ky), set them (and eV if exists) as the first two (or three) dimensions. Then, checks the data for non-uniform coordinates, which are converted to indices. Finally, converts the coordinates to C-contiguous arrays.

If input data values are neither float32 nor float64, a conversion to float64 is attempted.

Parameters:
  • data (DataArray) – Input array with at least two dimensions.

  • copy_values (bool, default: True) – If True, copy the underlying values while validating. Set to False when the caller intentionally wants the validated array to share the same values buffer as the source array.

Returns:

xarray.DataArray – The converted data. Non-uniform dimensions are converted to be dependent on uniform index dimensions, suffixed with '_idx'.

Return type:

DataArray

clear_dim_cache()[source]

Clear cached properties related to dimensions.

This method clears cached coordinate values, increments, limits, and the small argument-keyed memo tables derived from the current dimension layout.

clear_val_cache()[source]

Clear cached properties related to data values.

This method clears the cached properties that depend on the data values, such as the global minima and maxima.

clear_cache()[source]

Clear all cached properties.

values_of_dim(dim)[source]

Fast equivalent of self._obj[dim].values.

Returns the cached pointer of the underlying coordinate array, achieving a ~80x speedup. This should work most of the time since we only assume floating point values, but does require further testing. May break for future versions of pandas or xarray. See Notes.

Parameters:

dim (Hashable) – Name of the dimension to get the values from.

Returns:

numpy.ndarray

Return type:

ndarray[tuple[Any, …], dtype[floating]]

Notes

Looking at the implementation, I think this may return a pandas array in some cases, but I’m not sure so I’ll just leave it this way. When something breaks, replacing with self._obj._coords[dim]._data.array.array._ndarray may do the trick.

get_significant(axis, uniform=False)[source]

Return the number of significant digits for a given axis.

add_cursor(like_cursor=-1, update=True)[source]
remove_cursor(index, update=True)[source]
center_cursor(cursor, update=True)[source]
get_bins(cursor)[source]
get_bin_values(cursor)[source]
set_bins(cursor, value, update=True)[source]
set_bin(cursor, axis, value, update=True)[source]
get_binned(cursor)[source]

Return whether each axis is binned for the given cursor.

is_binned(cursor)[source]

Return whether any axis is binned for the given cursor.

get_indices(cursor)[source]
get_index(cursor, axis)[source]
set_indices(cursor, value, update=True)[source]
set_index(cursor, axis, value, update=True)[source]
step_index(cursor, axis, value, update=True)[source]
get_values(cursor, uniform=False)[source]
get_value(cursor, axis, uniform=False)[source]
set_values(cursor, values, update=True)[source]
set_value(cursor, axis, value, update=True, uniform=False)[source]
point_value(cursor, binned=True)[source]
swap_axes(ax1, ax2)[source]
array_rect(i=None, j=None)[source]
value_of_index(axis, value, uniform=False)[source]

Get the value of the coordinate at the given index.

Parameters:
  • axis (int) – The axis to index into.

  • value (int) – The index to get the value from.

  • uniform (bool, default: False) – This flag is only applied when the given axis corresponds to a non-uniform coordinate. If True, an index is returned. If False, the coordinate value at the given index is returned.

index_of_value(axis, value, uniform=False)[source]

Get the index of the coordinate closest to the given value.

Parameters:
  • axis (int) – The axis to search.

  • value (float) – The value to search for.

  • uniform (bool, default: False) – This flag is only applied when the given axis corresponds to a non-uniform coordinate. If True, value is treated as an index. If False, the index corresponding to the coordinate with the closest value to value is returned.

isel_args(cursor, disp, int_if_one=False, uniform=False)[source]
qsel_args(cursor, disp)[source]
qsel_code(cursor, disp)[source]
isel_code(cursor, disp)[source]
xslice(cursor, disp)[source]
slice_with_coord(cursor, disp)[source]
extract_avg_slice(cursor, axis)[source]
span_bounds(cursor, axis)[source]