Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"In this notebook, we showcase two tools that can be used to investigate/debug the Loki detectors:\n",
"\n",
"- `LokiBankViewer`: a 2D view of all detector panels with sliders to select straw and layer\n",
"- `InstrumentView`: a 3D view of detector panels with toggle buttons for panel selection"
"- `scippneutron.instrument_view`: a 3D view of the detector panels"
]
},
{
Expand Down Expand Up @@ -110,10 +110,10 @@
"id": "8",
"metadata": {},
"source": [
"## The `InstrumentView`\n",
"## The `scippneutron.instrument_view`\n",
"\n",
"We histogram the data into an additional `event_time_offset` dimension,\n",
"which will be controlled via a slider below the instrument view."
"We histogram the data into an `event_time_offset` dimension, which will be\n",
"controlled via a slider below the instrument view."
]
},
{
Expand All @@ -123,7 +123,14 @@
"metadata": {},
"outputs": [],
"source": [
"dhist = data.hist(event_time_offset=200)"
"time_bins = sc.linspace(\n",
" 'event_time_offset',\n",
" start=0.0,\n",
" stop=1.0 / 14.0,\n",
" num=201,\n",
" unit='s',\n",
").to(unit='ns')\n",
"dhist = data.hist(event_time_offset=time_bins)"
]
},
{
Expand All @@ -146,9 +153,9 @@
"metadata": {},
"outputs": [],
"source": [
"from ess.loki.diagnostics import InstrumentView\n",
"import scippneutron as scn\n",
"\n",
"InstrumentView(dhist, dim='event_time_offset')"
"scn.instrument_view(dhist, dim='event_time_offset')"
]
}
],
Expand All @@ -168,7 +175,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.7"
"version": "3.12.13"
}
},
"nbformat": 4,
Expand Down
139 changes: 0 additions & 139 deletions packages/esssans/src/ess/loki/diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,142 +235,3 @@ def update_node_routing(self, change: dict) -> None:
self.update_cmin({'new': self.cmap_vmin.value})
self._lock = False
self.update_cmax({'new': self.cmap_vmax.value})


def _to_data_group(data: sc.DataArray | sc.DataGroup | dict) -> sc.DataGroup:
if isinstance(data, sc.DataArray):
data = sc.DataGroup({data.name or "data": data})
elif isinstance(data, dict):
data = sc.DataGroup(data)
return data


@pp.node
def _pre_process(da: sc.DataArray, dim: str) -> sc.DataArray:
dims = list(da.dims)
if dim is not None:
dims.remove(dim)
out = da.flatten(dims=dims, to="pixel")
sel = sc.isfinite(out.coords["position"])
return out[sel]


class InstrumentView(ipw.VBox):
"""
Three-dimensional visualization of the Loki instrument.
The instrument view is capable of slicing the input data with a slider widget along
a dimension (e.g. ``tof``) by using the ``dim`` argument.
It will also generate toggle buttons to hide/show the different modules that make up
the Loki detectors.

Parameters
----------
data:
Data to visualize. The data can be a single detector module (``DataArray``),
or a group of detector modules (``dict`` or ``DataGroup``).
The data must contain a ``position`` coordinate.
dim:
Dimension to use for the slider. No slider will be shown if this is None.
pixel_size:
Size of the pixels.
autoscale:
If ``True``, the color scale will be automatically adjusted to the data as it
gets updated. This can be somewhat expensive with many pixels, so it is set to
``False`` by default.
**kwargs:
Additional arguments are forwarded to the scatter3d figure
(see https://scipp.github.io/plopp/generated/plopp.scatter3d.html).
"""

def __init__(
self,
data: sc.DataArray | sc.DataGroup | dict,
dim: str | None = None,
pixel_size: float | sc.Variable | None = None,
**kwargs,
):
from plopp.widgets import SliceWidget, slice_dims

if dim and isinstance(data, sc.DataArray) and dim in data.dims[:-1]:
data = data.transpose([d for d in data.dims if d != dim] + [dim])

if dim and isinstance(data, sc.DataGroup):
data = data.copy(deep=False)
for k, v in data.items():
if dim in v.dims[:-1]:
data[k] = v.transpose([d for d in v.dims if d != dim] + [dim])

self.data = _to_data_group(data)
self.pre_process_nodes = {
key: _pre_process(da, dim) for key, da in self.data.items()
}

self._widgets = []

if dim is not None:
self.slider = SliceWidget(next(iter(self.data.values())), dims=[dim])
self.slider.controls[dim].slider.layout = {"width": "600px"}
self.slider_node = pp.widget_node(self.slider)
self.slice_nodes = {
key: slice_dims(n, self.slider_node)
for key, n in self.pre_process_nodes.items()
}
to_scatter = self.slice_nodes
self._widgets.append(self.slider)
else:
self.slice_nodes = self.pre_process_nodes
to_scatter = self.pre_process_nodes

kwargs.setdefault('cbar', True)
self.fig = pp.scatter3d(
to_scatter,
pos="position",
pixel_size=1.0 * sc.Unit("cm") if pixel_size is None else pixel_size,
**kwargs,
)

self._widgets.insert(0, self.fig)

if len(self.data) > 1:
self._add_module_control()

super().__init__(self._widgets)

def _add_module_control(self):
import ipywidgets as ipw

self.cutting_tool = self.fig.bottom_bar[0]
self._node_backup = list(self.cutting_tool._original_nodes)
self.artist_mapping = dict(
zip(self.data.keys(), self.fig.artists.keys(), strict=True)
)
self.buttons = {
key: ipw.ToggleButton(
value=True, description=f"{i}", layout={"width": "initial"}
)
for i, key in enumerate(self.data)
}

self.modules_widget = ipw.HBox(
[
ipw.HTML(value="Detector banks:     "),
*self.buttons.values(),
]
)
for key, b in self.buttons.items():
b.key = key
b.observe(self._check_visibility, names="value")
self._widgets.insert(0, self.modules_widget)

def _check_visibility(self, _):
active_nodes = [
node_id
for key, node_id in self.artist_mapping.items()
if self.buttons[key].value
]
for n in self._node_backup:
self.fig.artists[n.id].points.visible = n.id in active_nodes
self.cutting_tool._original_nodes = [
n for n in self._node_backup if n.id in active_nodes
]
self.cutting_tool.update_state()
10 changes: 1 addition & 9 deletions packages/esssans/tests/loki/diagnostics_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import pytest
import scipp as sc
from ess import loki
from ess.loki.diagnostics import InstrumentView, LokiBankViewer
from ess.loki.diagnostics import LokiBankViewer
from ess.sans.types import (
BeamCenter,
Filename,
Expand Down Expand Up @@ -88,11 +88,3 @@ def test_loki_bank_viewer_change_bank(histogrammed_loki_data):
viewer.tabs.selected_index = 2
# Change back to all banks
viewer.tabs.selected_index = 0


def test_creat_loki_instrument_view(histogrammed_loki_data):
InstrumentView(histogrammed_loki_data)


def test_creat_loki_instrument_view_with_dim_slider(loki_data):
InstrumentView(loki_data.hist(event_time_offset=10), dim='event_time_offset')
Loading