Processing NeXus Choppers#

When choppers are loaded from NeXus, they typically contain a number of fields that need to be processed before they can be used for computing wavelength ranges, etc. This guide shows how to extract the relevant data from such a NeXus chopper and create a scippneutron.chopper.DiskChopper object.

[1]:
import matplotlib.pyplot as plt
import scipp as sc

Here, we use fake data which roughly represents what a real chopper loaded from NeXus looks like. ScippNeutron has a function for generating this data:

[2]:
from scippneutron.data import chopper_mockup

chopper = chopper_mockup()
chopper
[2]:
  • scipp
    DataGroup
    (time: 1)
      • value
        scipp
        DataArray
        (time: 1)
        int64
        ns
        3050
  • position
    scipp
    Variable
    ()
    vector3
    m
    [ 0. 0. 60.]
  • radius
    scipp
    Variable
    ()
    float64
    m
    0.35
  • scipp
    DataGroup
    (time: 180)
      • value
        scipp
        DataArray
        (time: 180)
        float64
        Hz
        1.287e-05, 0.359, ..., 0.352, -4.904e-07
  • slit_height
    scipp
    Variable
    ()
    float64
    m
    0.1
  • slit_edges
    scipp
    Variable
    (slit: 4)
    float64
    deg
    30.0, 160.0, 210.0, 280.0
  • slits
    int
    ()
    2
  • scipp
    DataGroup
    (time: 2354)
      • time
        scipp
        Variable
        (time: 2354)
        datetime64
        ns
        2023-01-19T08:11:06.217830400, 2023-01-19T08:11:08.799053824, ..., 2023-01-19T08:14:39.174524416, 2023-01-19T08:14:40.640919296

We can see that there is some information about the slits and geometry of the chopper as well as some timing-related data. Take a look at the NXdisk_chopper documentation for an overview of the fields.

In this case, there already is a position. This typically needs to be computed first, see scippnexus.compute_positions.

Some fields are nested data groups which happens when a NeXus file contains NXlogs. We can extract the relevant arrays from them using extract_chopper_from_nexus:

[3]:
from scippneutron.chopper import extract_chopper_from_nexus

chopper = extract_chopper_from_nexus(chopper)
chopper
[3]:
  • type
    DiskChopperType
    ()
    DiskChopperType.single
  • delay
    scipp
    DataArray
    ()
    int64
    ns
    3050
  • position
    scipp
    Variable
    ()
    vector3
    m
    [ 0. 0. 60.]
  • radius
    scipp
    Variable
    ()
    float64
    m
    0.35
  • rotation_speed
    scipp
    DataArray
    (time: 180)
    float64
    Hz
    1.287e-05, 0.359, ..., 0.352, -4.904e-07
  • slit_height
    scipp
    Variable
    ()
    float64
    m
    0.1
  • slit_edges
    scipp
    Variable
    (slit: 4)
    float64
    deg
    30.0, 160.0, 210.0, 280.0
  • slits
    int
    ()
    2
  • top_dead_center
    scipp
    Variable
    (time: 2354)
    datetime64
    ns
    2023-01-19T08:11:06.217830400, 2023-01-19T08:11:08.799053824, ..., 2023-01-19T08:14:39.174524416, 2023-01-19T08:14:40.640919296

Some data varies with time, which can complicate the data processing. Instead, we compute corresponding time-independent quantities from the raw chopper data.

Identify In-phase Regions#

Frame unwrapping is only feasible when the chopper is in-phase with the neutron source pulses because, otherwise, the wavelength frames vary pulse-by-pulse. To identify regions where the chopper is in-phase, we first find plateaus in the rotation_speed which is the rotation frequency of the chopper.

[4]:
rotation_speed = chopper['rotation_speed']
rotation_speed.name = 'rotation_speed'
rotation_speed
[4]:
Show/Hide data repr Show/Hide attributes
scipp.DataArray (3.84 KB)
    • time: 180
    • time
      (time)
      datetime64
      ns
      2023-01-19T08:11:06.205830400, 2023-01-19T08:11:07.412763648, ..., 2023-01-19T08:14:41.039957504, 2023-01-19T08:14:42.246890752
      Values:
      array(['2023-01-19T08:11:06.205830400', '2023-01-19T08:11:07.412763648', '2023-01-19T08:11:08.619696896', '2023-01-19T08:11:09.826630400', '2023-01-19T08:11:11.033563648', '2023-01-19T08:11:12.240496896', '2023-01-19T08:11:13.447430144', '2023-01-19T08:11:14.654363392', '2023-01-19T08:11:15.861296896', '2023-01-19T08:11:17.068230144', '2023-01-19T08:11:18.275163392', '2023-01-19T08:11:19.482096640', '2023-01-19T08:11:20.689029888', '2023-01-19T08:11:21.895963392', '2023-01-19T08:11:23.102896640', '2023-01-19T08:11:24.309829888', '2023-01-19T08:11:25.516763136', '2023-01-19T08:11:26.723696384', '2023-01-19T08:11:27.930629888', '2023-01-19T08:11:29.137563136', '2023-01-19T08:11:30.344496384', '2023-01-19T08:11:31.551429632', '2023-01-19T08:11:32.758362880', '2023-01-19T08:11:33.965296128', '2023-01-19T08:11:35.172229632', '2023-01-19T08:11:36.379162880', '2023-01-19T08:11:37.586096128', '2023-01-19T08:11:38.793029376', '2023-01-19T08:11:39.999962624', '2023-01-19T08:11:41.206896128', '2023-01-19T08:11:42.413829376', '2023-01-19T08:11:43.620762624', '2023-01-19T08:11:44.827695872', '2023-01-19T08:11:46.034629120', '2023-01-19T08:11:47.241562624', '2023-01-19T08:11:48.448495872', '2023-01-19T08:11:49.655429120', '2023-01-19T08:11:50.862362368', '2023-01-19T08:11:52.069295616', '2023-01-19T08:11:53.276229120', '2023-01-19T08:11:54.483162368', '2023-01-19T08:11:55.690095616', '2023-01-19T08:11:56.897028864', '2023-01-19T08:11:58.103962112', '2023-01-19T08:11:59.310895616', '2023-01-19T08:12:00.517828864', '2023-01-19T08:12:01.724762112', '2023-01-19T08:12:02.931695360', '2023-01-19T08:12:04.138628608', '2023-01-19T08:12:05.345562112', '2023-01-19T08:12:06.552495360', '2023-01-19T08:12:07.759428608', '2023-01-19T08:12:08.966361856', '2023-01-19T08:12:10.173295104', '2023-01-19T08:12:11.380228608', '2023-01-19T08:12:12.587161856', '2023-01-19T08:12:13.794095104', '2023-01-19T08:12:15.001028352', '2023-01-19T08:12:16.207961600', '2023-01-19T08:12:17.414895104', '2023-01-19T08:12:18.621828352', '2023-01-19T08:12:19.828761600', '2023-01-19T08:12:21.035694848', '2023-01-19T08:12:22.242628096', '2023-01-19T08:12:23.449561600', '2023-01-19T08:12:24.656494848', '2023-01-19T08:12:25.863428096', '2023-01-19T08:12:27.070361344', '2023-01-19T08:12:28.277294592', '2023-01-19T08:12:29.484227840', '2023-01-19T08:12:30.691161344', '2023-01-19T08:12:31.898094592', '2023-01-19T08:12:33.105027840', '2023-01-19T08:12:34.311961088', '2023-01-19T08:12:35.518894336', '2023-01-19T08:12:36.725827840', '2023-01-19T08:12:37.932761088', '2023-01-19T08:12:39.139694336', '2023-01-19T08:12:40.346627584', '2023-01-19T08:12:41.553560832', '2023-01-19T08:12:42.760494336', '2023-01-19T08:12:43.967427584', '2023-01-19T08:12:45.174360832', '2023-01-19T08:12:46.381294080', '2023-01-19T08:12:47.588227328', '2023-01-19T08:12:48.795160832', '2023-01-19T08:12:50.002094080', '2023-01-19T08:12:51.209027328', '2023-01-19T08:12:52.415960576', '2023-01-19T08:12:53.622893824', '2023-01-19T08:12:54.829827328', '2023-01-19T08:12:56.036760576', '2023-01-19T08:12:57.243693824', '2023-01-19T08:12:58.450627072', '2023-01-19T08:12:59.657560320', '2023-01-19T08:13:00.864493824', '2023-01-19T08:13:02.071427072', '2023-01-19T08:13:03.278360320', '2023-01-19T08:13:04.485293568', '2023-01-19T08:13:05.692226816', '2023-01-19T08:13:06.899160320', '2023-01-19T08:13:08.106093568', '2023-01-19T08:13:09.313026816', '2023-01-19T08:13:10.519960064', '2023-01-19T08:13:11.726893312', '2023-01-19T08:13:12.933826816', '2023-01-19T08:13:14.140760064', '2023-01-19T08:13:15.347693312', '2023-01-19T08:13:16.554626560', '2023-01-19T08:13:17.761559808', '2023-01-19T08:13:18.968493312', '2023-01-19T08:13:20.175426560', '2023-01-19T08:13:21.382359808', '2023-01-19T08:13:22.589293056', '2023-01-19T08:13:23.796226304', '2023-01-19T08:13:25.003159552', '2023-01-19T08:13:26.210093056', '2023-01-19T08:13:27.417026304', '2023-01-19T08:13:28.623959552', '2023-01-19T08:13:29.830892800', '2023-01-19T08:13:31.037826048', '2023-01-19T08:13:32.244759552', '2023-01-19T08:13:33.451692800', '2023-01-19T08:13:34.658626048', '2023-01-19T08:13:35.865559296', '2023-01-19T08:13:37.072492544', '2023-01-19T08:13:38.279426048', '2023-01-19T08:13:39.486359296', '2023-01-19T08:13:40.693292544', '2023-01-19T08:13:41.900225792', '2023-01-19T08:13:43.107159040', '2023-01-19T08:13:44.314092544', '2023-01-19T08:13:45.521025792', '2023-01-19T08:13:46.727959040', '2023-01-19T08:13:47.934892288', '2023-01-19T08:13:49.141825536', '2023-01-19T08:13:50.348759040', '2023-01-19T08:13:51.555692288', '2023-01-19T08:13:52.762625536', '2023-01-19T08:13:53.969558784', '2023-01-19T08:13:55.176492032', '2023-01-19T08:13:56.383425536', '2023-01-19T08:13:57.590358784', '2023-01-19T08:13:58.797292032', '2023-01-19T08:14:00.004225280', '2023-01-19T08:14:01.211158528', '2023-01-19T08:14:02.418092032', '2023-01-19T08:14:03.625025280', '2023-01-19T08:14:04.831958528', '2023-01-19T08:14:06.038891776', '2023-01-19T08:14:07.245825024', '2023-01-19T08:14:08.452758528', '2023-01-19T08:14:09.659691776', '2023-01-19T08:14:10.866625024', '2023-01-19T08:14:12.073558272', '2023-01-19T08:14:13.280491520', '2023-01-19T08:14:14.487425024', '2023-01-19T08:14:15.694358272', '2023-01-19T08:14:16.901291520', '2023-01-19T08:14:18.108224768', '2023-01-19T08:14:19.315158016', '2023-01-19T08:14:20.522091264', '2023-01-19T08:14:21.729024768', '2023-01-19T08:14:22.935958016', '2023-01-19T08:14:24.142891264', '2023-01-19T08:14:25.349824512', '2023-01-19T08:14:26.556757760', '2023-01-19T08:14:27.763691264', '2023-01-19T08:14:28.970624512', '2023-01-19T08:14:30.177557760', '2023-01-19T08:14:31.384491008', '2023-01-19T08:14:32.591424256', '2023-01-19T08:14:33.798357760', '2023-01-19T08:14:35.005291008', '2023-01-19T08:14:36.212224256', '2023-01-19T08:14:37.419157504', '2023-01-19T08:14:38.626090752', '2023-01-19T08:14:39.833024256', '2023-01-19T08:14:41.039957504', '2023-01-19T08:14:42.246890752'], dtype='datetime64[ns]')
    • (time)
      float64
      Hz
      1.287e-05, 0.359, ..., 0.352, -4.904e-07
      Values:
      array([ 1.28712703e-05, 3.58958178e-01, 7.17866971e-01, 1.07691359e+00, 1.43591746e+00, 1.79487320e+00, 2.15385369e+00, 2.51281987e+00, 2.87187121e+00, 3.23081226e+00, 3.58981891e+00, 3.94870842e+00, 4.30769912e+00, 4.66666365e+00, 5.02562219e+00, 5.38460756e+00, 5.74358259e+00, 6.10256219e+00, 6.46145332e+00, 6.82052313e+00, 7.17950960e+00, 7.53843141e+00, 7.89749324e+00, 8.25639496e+00, 8.61538232e+00, 8.97432454e+00, 9.33327696e+00, 9.69229285e+00, 1.00513025e+01, 1.04102649e+01, 1.07692595e+01, 1.11281847e+01, 1.14871807e+01, 1.18461841e+01, 1.22050969e+01, 1.25640798e+01, 1.29231327e+01, 1.32820439e+01, 1.36409727e+01, 1.40000353e+01, 1.40783218e+01, 1.40743732e+01, 1.40368964e+01, 1.39993821e+01, 1.39790818e+01, 1.39768099e+01, 1.39851619e+01, 1.39956710e+01, 1.40030625e+01, 1.40059890e+01, 1.40054666e+01, 1.40033109e+01, 1.40010291e+01, 1.39994742e+01, 1.39987127e+01, 1.39987323e+01, 1.39990919e+01, 1.39995409e+01, 1.39998985e+01, 1.40000804e+01, 1.40002122e+01, 1.40001767e+01, 1.40002364e+01, 1.40000597e+01, 1.40001066e+01, 1.40000218e+01, 1.40000392e+01, 1.39999286e+01, 1.40000235e+01, 1.40000074e+01, 1.39999709e+01, 1.39999340e+01, 1.39999981e+01, 1.40000250e+01, 1.40000138e+01, 1.39999544e+01, 1.40000262e+01, 1.39999248e+01, 1.39999959e+01, 1.40000356e+01, 1.39999859e+01, 1.40000064e+01, 1.40000152e+01, 1.39999306e+01, 1.40000103e+01, 1.40000394e+01, 1.40000453e+01, 1.39999621e+01, 1.39999829e+01, 1.40000255e+01, 1.40000156e+01, 1.40001212e+01, 1.40000104e+01, 1.40000177e+01, 1.40000035e+01, 1.40000708e+01, 1.39999885e+01, 1.40000239e+01, 1.39999674e+01, 1.39999966e+01, 1.40000941e+01, 1.39999697e+01, 1.40000485e+01, 1.39999898e+01, 1.39999805e+01, 1.40000370e+01, 1.39999218e+01, 1.39999741e+01, 1.40000058e+01, 1.40000634e+01, 1.39999932e+01, 1.40000127e+01, 1.39999972e+01, 1.40000141e+01, 1.40000016e+01, 1.39999793e+01, 1.39999465e+01, 1.39997833e+01, 1.39994304e+01, 1.39975883e+01, 1.39909586e+01, 1.39679657e+01, 1.39066992e+01, 1.38161344e+01, 1.37547382e+01, 1.37317718e+01, 1.37251129e+01, 1.37233104e+01, 1.37229065e+01, 1.37227973e+01, 1.37227971e+01, 1.37227141e+01, 1.37227334e+01, 1.37227890e+01, 1.37228152e+01, 1.37227866e+01, 1.37227864e+01, 1.37227676e+01, 1.37227788e+01, 1.37227187e+01, 1.37227271e+01, 1.33708923e+01, 1.30189700e+01, 1.26671450e+01, 1.23152892e+01, 1.19635346e+01, 1.16115960e+01, 1.12596457e+01, 1.09078860e+01, 1.05559769e+01, 1.02041706e+01, 9.85215034e+00, 9.50041097e+00, 9.14844059e+00, 8.79657999e+00, 8.44471935e+00, 8.09286946e+00, 7.74101219e+00, 7.38913836e+00, 7.03729080e+00, 6.68543505e+00, 6.33355645e+00, 5.98173710e+00, 5.62985157e+00, 5.27793131e+00, 4.92608422e+00, 4.57427248e+00, 4.22239068e+00, 3.87061422e+00, 3.51868112e+00, 3.16675315e+00, 2.81483757e+00, 2.46306945e+00, 2.11123897e+00, 1.75938373e+00, 1.40747555e+00, 1.05549357e+00, 7.03716252e-01, 3.51902452e-01, -4.90383720e-07])

The chopper has a long region of near-constant rotation speed surrounded by spin-up and spin-down regions:

[5]:
rotation_speed.plot(markersize=2)
[5]:
../../_images/user-guide_chopper_processing-nexus-choppers_9_0.svg

We use find_plateaus and collapse_plateaus to find those plateaus. Note the atol and min_n_points parameters, they need to be tuned for the specific input data.

Warning

find_plateaus can potentially falsely identify regions with a small but steady slope as a plateau. See the function’s documentation for details.

[6]:
from scippneutron.chopper import collapse_plateaus, find_plateaus

plateaus = find_plateaus(rotation_speed, atol=sc.scalar(1e-3, unit='Hz / s'), min_n_points=10)
plateaus = collapse_plateaus(plateaus)
plateaus
[6]:
Show/Hide data repr Show/Hide attributes
scipp.DataArray (1.34 KB)
    • plateau: 2
    • plateau
      (plateau)
      int64
      0, 1
      Values:
      array([0, 1])
    • time
      (plateau, time [bin-edge])
      datetime64
      ns
      2023-01-19T08:12:10.173295104, 2023-01-19T08:13:28.623959553, 2023-01-19T08:13:39.486359296, 2023-01-19T08:13:55.176492033
      Values:
      array([['2023-01-19T08:12:10.173295104', '2023-01-19T08:13:28.623959553'], ['2023-01-19T08:13:39.486359296', '2023-01-19T08:13:55.176492033']], dtype='datetime64[ns]')
    • (plateau)
      float64
      Hz
      14.000, 13.723
      Values:
      array([13.99993461, 13.7228163 ])

find_plateaus found two plateaus that we can plot with the following helper function:

[7]:
def plot_plateaus(raw_data: sc.DataArray, plateaus: sc.DataArray) -> None:
    fig, ax = plt.subplots(1)
    raw_data.plot(ax=ax, markersize=2)
    for plateau in plateaus:
        i = plateau.coords['plateau'].value
        da = sc.DataArray(
            plateau.data.broadcast(dims=['time'], shape=[2]),
            coords={'time': plateau.coords['time']},
            name=f'Plateau {i}')
        da.plot(ax=ax, ls='-', marker='|', c=f'C{i + 1}')
[8]:
plot_plateaus(rotation_speed, plateaus)
../../_images/user-guide_chopper_processing-nexus-choppers_14_0.png

In this case, the source has a frequency of 14Hz which means that plateau 0 is in phase. But plateau 1 is not, it is a short region where the chopper slowed down before fully stopping.

We can use filter_in_phase to remove all out-of-phase plateaus:

[9]:
pulse_frequency = sc.scalar(14.0, unit='Hz')
[10]:
from scippneutron.chopper import filter_in_phase

frequency_in_phase = filter_in_phase(
    plateaus,
    reference=pulse_frequency,
    rtol=sc.scalar(1e-3))
frequency_in_phase
[10]:
Show/Hide data repr Show/Hide attributes
scipp.DataArray (1.31 KB)
    • plateau: 1
    • plateau
      (plateau)
      int64
      0
      Values:
      array([0])
    • time
      (plateau, time [bin-edge])
      datetime64
      ns
      2023-01-19T08:12:10.173295104, 2023-01-19T08:13:28.623959553
      Values:
      array([['2023-01-19T08:12:10.173295104', '2023-01-19T08:13:28.623959553']], dtype='datetime64[ns]')
    • (plateau)
      float64
      Hz
      14.000
      Values:
      array([13.99993461])
[11]:
plot_plateaus(rotation_speed, frequency_in_phase)
../../_images/user-guide_chopper_processing-nexus-choppers_18_0.png

Extract Plateau#

Since there is only one plateau left, we can simply index into it to get the chopper frequency:

[12]:
frequency = frequency_in_phase['plateau', 0]
frequency
[12]:
Show/Hide data repr Show/Hide attributes
scipp.DataArray (1.31 KB)
      • plateau
        ()
        int64
        0
        Values:
        array(0)
      • time
        (time [bin-edge])
        datetime64
        ns
        2023-01-19T08:12:10.173295104, 2023-01-19T08:13:28.623959553
        Values:
        array(['2023-01-19T08:12:10.173295104', '2023-01-19T08:13:28.623959553'], dtype='datetime64[ns]')
      • ()
        float64
        Hz
        13.999934613725587
        Values:
        array(13.99993461)

    Next, we need the TDC timestamps for the in-phase region:

    [13]:
    
    tdc = chopper['top_dead_center']
    tdc
    
    [13]:
    
    Show/Hide data repr Show/Hide attributes
    scipp.Variable (18.64 KB)
      • (time: 2354)
        datetime64
        ns
        2023-01-19T08:11:06.217830400, 2023-01-19T08:11:08.799053824, ..., 2023-01-19T08:14:39.174524416, 2023-01-19T08:14:40.640919296
        Values:
        array(['2023-01-19T08:11:06.217830400', '2023-01-19T08:11:08.799053824', '2023-01-19T08:11:09.873177088', ..., '2023-01-19T08:14:38.209520640', '2023-01-19T08:14:39.174524416', '2023-01-19T08:14:40.640919296'], dtype='datetime64[ns]')
    [14]:
    
    low = frequency.coords['time'][0]
    high = frequency.coords['time'][1]
    tdc_in_phase = tdc[(tdc > low) & (tdc < high)]
    tdc_in_phase
    
    [14]:
    
    Show/Hide data repr Show/Hide attributes
    scipp.Variable (8.83 KB)
      • (time: 1098)
        datetime64
        ns
        2023-01-19T08:12:10.228627200, 2023-01-19T08:12:10.300058880, ..., 2023-01-19T08:13:28.514769152, 2023-01-19T08:13:28.586200832
        Values:
        array(['2023-01-19T08:12:10.228627200', '2023-01-19T08:12:10.300058880', '2023-01-19T08:12:10.371490560', ..., '2023-01-19T08:13:28.443337984', '2023-01-19T08:13:28.514769152', '2023-01-19T08:13:28.586200832'], dtype='datetime64[ns]')

    We can check that the rate at which the TDC triggers is indeed close to 14Hz.

    [15]:
    
    diff = tdc_in_phase[1:] - tdc_in_phase[:-1]
    rate = 1 / diff.to(unit='s', dtype='float64')
    rate.min(), rate.max()
    
    [15]:
    
    (<scipp.Variable> ()    float64             [Hz]  13.9986,
     <scipp.Variable> ()    float64             [Hz]  14.0002)
    

    Compute Chopper Phase#

    DiskChopper does not use TDC directly for time calculations but instead the chopper phase \(\phi\). According to the disk chopper docs, the phase is defined as

    \[\phi = \omega (t_0 + \delta_t - T_0),\]

    where \(t_0\) is a TDC timestamp and \(T_0\) a pulse time.

    We already determined the TDC timestamps above. In practice, we would get \(T_0\) from the input NeXus file, but here, we simply make one up:

    [16]:
    
    pulse_time = sc.datetime('2023-01-19T08:12:03.442912915', unit='ns')
    

    Note

    The pulse time is typically an array of timestamps and it can be difficult to determine which pulse goes with which chopper period. While the choice is technically arbitrary, the times calculated by DiskChopper are relative to the chosen pulse time.

    If the chopper rotates at the pulse frequency or an integer multiple of it, we can select any pulse time and TDC timestamp and simply use phase = phase % (2 * sc.constants.pi) below. This corresponds to selecting the pulse and TDC times that are closest to each other.

    (We multiply by 1 rad to get the proper rad*Hz unit in omega.)

    [17]:
    
    omega = 2*sc.constants.pi * frequency.data * sc.scalar(1, unit='rad')
    phase = omega * (tdc_in_phase[0] + chopper['delay'].data - pulse_time)
    phase = phase.to(unit='rad')
    phase
    
    [17]:
    
    Show/Hide data repr Show/Hide attributes
    scipp.Variable (264 Bytes)
      • ()
        float64
        rad
        596.900084607312
        Values:
        array(596.90008461)

    Build DiskChopper#

    Finally, we can assemble all data into a scippneutron.chopper.DiskChopper object.

    The rotation speed gets rounded (resulting in 14Hz) because DiskChopper requires it to be a near exact integer multiple of the pulse frequency or vice versa:

    • rotation_speed = N * pulse_frequency

    • rotation_speed = pulse_frequency / N

    where N is an integer number.

    [18]:
    
    processed = chopper.copy()
    processed['rotation_speed'] = sc.round(frequency.data)
    processed['phase'] = phase
    

    The input data does not contain a beam position (the angle between the beam and TDC). This probably means that it is 0. But since DiskChopper does not make that assumption we have to be explicit:

    [19]:
    
    processed['beam_position'] = sc.scalar(0.0, unit='rad')
    
    [20]:
    
    from scippneutron.chopper import DiskChopper
    
    disk_chopper = DiskChopper.from_nexus(processed)
    disk_chopper
    
    [20]:
    
    • axle_position
      scipp
      Variable
      ()
      vector3
      m
      [ 0. 0. 60.]
    • frequency
      scipp
      Variable
      ()
      float64
      Hz
      14.0
    • beam_angle
      scipp
      Variable
      ()
      float64
      rad
      0.0
    • phase
      scipp
      Variable
      ()
      float64
      rad
      596.900084607312
    • slit_begin
      scipp
      Variable
      (slit: 2)
      float64
      deg
      30.0, 210.0
    • slit_end
      scipp
      Variable
      (slit: 2)
      float64
      deg
      160.0, 280.0
    • slit_height
      scipp
      Variable
      (slit: 2)
      float64
      m
      0.1, 0.1
    • radius
      scipp
      Variable
      ()
      float64
      m
      0.35
    begin0 end0 begin1 end1 TDC beam position