Instrument view#

Overview#

A simple version of the Mantid instrument view is available in scippneutron. It currently does not support detector ‘picking’ and manual drawing of masks, nor does it render the actual shape of the detectors (currently it represents them as 2-D squares), but basic functionalities such as spatial slicing, as well as navigation through the time-of-flight dimension via a slider, are provided.

Note

The file used in this notebook is from the Mantid training course data.

Warning

While you can interact with the 3D view of the instrument, the buttons and sliders will have no effect in the documentation pages, as there is no kernel to perform the operations. These will only work inside a Jupyter notebook.

We load a file containing a position coordinate:

[1]:
import numpy as np
import scipp as sc
import scippneutron as scn
import scippneutron.data
[2]:
sample = scn.data.powder_sample()['data'].hist()
sample
FrameworkManager-[Notice] Welcome to Mantid 6.10.0
FrameworkManager-[Notice] Please cite: http://dx.doi.org/10.1016/j.nima.2014.07.029 and this release: http://dx.doi.org/10.5286/Software/Mantid6.10
CheckMantidVersion-[Notice] A new version of Mantid(6.11.0) is available for download from https://download.mantidproject.org
DownloadInstrument-[Notice] All instrument definitions up to date
Load-[Notice] Load started
Load-[Notice] Load successful, Duration 1.45 seconds
DeleteWorkspace-[Notice] DeleteWorkspace started
DeleteWorkspace-[Notice] DeleteWorkspace successful, Duration 0.00 seconds
[2]:
Show/Hide data repr Show/Hide attributes
scipp.DataArray (873.92 KB)
    • spectrum: 24794
    • tof: 1
    • position
      (spectrum)
      vector3
      m
      [ 1.17451004 -1.01106149 -2.03796699], [ 1.18147634 -0.95946649 -2.05334117], ..., [1.81428985 0.09565841 3.84338287], [1.81375055 0.1499371 3.84269584]
      Values:
      array([[ 1.17451004, -1.01106149, -2.03796699], [ 1.18147634, -0.95946649, -2.05334117], [ 1.18844265, -0.90787149, -2.06871534], ..., [ 1.81482915, 0.04137972, 3.8440699 ], [ 1.81428985, 0.09565841, 3.84338287], [ 1.81375055, 0.1499371 , 3.84269584]])
    • sample_position
      ()
      vector3
      m
      [0. 0. 0.]
      Values:
      array([0., 0., 0.])
    • source_position
      ()
      vector3
      m
      [ 0. 0. -60.]
      Values:
      array([ 0., 0., -60.])
    • spectrum
      (spectrum)
      int32
      1, 2, ..., 24793, 24794
      Values:
      array([ 1, 2, 3, ..., 24792, 24793, 24794], dtype=int32)
    • tof
      (tof [bin-edge])
      float64
      µs
      19.0, 1.669e+04
      Values:
      array([ 19. , 16694.30078125])
    • (spectrum, tof)
      float32
      counts
      0.0, 0.0, ..., 0.0, 0.0
      σ = 0.0, 0.0, ..., 0.0, 0.0
      Values:
      array([[0.], [0.], [0.], ..., [0.], [0.], [0.]], dtype=float32)

      Variances (σ²):
      array([[0.], [0.], [0.], ..., [0.], [0.], [0.]], dtype=float32)

The instrument_view function can now be used to display a 3-D representation:

[3]:
scn.instrument_view(sample)
[3]:

The 31b84014c9e94f6493995b2299dacb90 button in the toolbar activates a tool that lets you can create spatial cuts to slice your data in 3D.

It is possible to customize the figure using the usual arguments, as well as adjusting the pixel size, e.g.

[4]:
scn.instrument_view(
    sample, cmap="magma", vmax=2000.0 * sc.units.counts, norm="log", pixel_size=0.03
)
[4]:

Displaying additional components#

Additional beamline components can be displayed in the instrument view by providing a dict of component settings. As we can see above, the loaded data array also contains source_position and sample_position stored as 3-D vector coordinates. This is in addition to the position coordinate, which defines only the positions of detector pixels.

Apart from position, the instrument_view does not require data arrays to follow a pre-defined naming convention for additional components. Instead it relies on the aforementioned dict of components, which can be customized, e.g., for a particular beamline.

The dict key of the component is used as the text label. Component settings are given in the form of a dictionary defining, e.g., color, size, and type. We can pick from a limited number of types including cylinder, disk and box:

[5]:
sample_settings = {
    'center': sample.meta['sample_position'],
    'color': '#000000',
    'wireframe': True,
    'size': sc.vector(value=[0.3, 0.3, 0.3], unit=sc.units.m),
    'type': 'box',
}
source_settings = {
    'center': sample.meta['source_position'],
    'color': '#FFC133',
    'size': sc.vector(value=[1000, 2000, 1000], unit=sc.units.mm),
    'type': 'cylinder',
}
scn.instrument_view(
    sample, components={'sample': sample_settings, 'source': source_settings}
)
sc.DataArray.attrs has been deprecated and will be removed in Scipp v24.12.0. The deprecation includes sc.DataArray.meta and sc.DataArray.drop_attrs. For unaligned coords, use sc.DataArray.coords and unset the alignment flag. For other attributes, use a higher-level data structure.
sc.DataArray.attrs has been deprecated and will be removed in Scipp v24.12.0. The deprecation includes sc.DataArray.meta and sc.DataArray.drop_attrs. For unaligned coords, use sc.DataArray.coords and unset the alignment flag. For other attributes, use a higher-level data structure.
[5]:

Defining detector positions#

If data comes without pre-defined detector-positions, e.g., when they are not contained in the original file, they can be defined by simply adding a position coordinate to a data array:

[6]:
nx, ny = (10, 10)
points_x = np.linspace(0, 1, nx)
points_y = np.linspace(0, 1, ny)
xv, yv = np.meshgrid(points_x, points_y)

_x = sc.array(dims=['spectrum'], values=xv.ravel())
_y = sc.array(dims=['spectrum'], values=yv.ravel())
_z = sc.array(dims=['spectrum'], values=np.zeros(100))

data = sc.arange('spectrum', 100.0, unit='counts')
da = sc.DataArray(data)
da.coords['position'] = sc.spatial.as_vectors(_x, _y, _z)
da.coords['spectrum'] = sc.arange('spectrum', 100)

scn.instrument_view(da, pixel_size=0.1)
[6]: