Exemple #1
0
def test_illumination_range():
    beam_size = 100.0 * sc.units.m
    sample_size = 10.0 * sc.units.m
    theta = sc.array(values=[15.0, 30.0], unit=sc.units.deg, dims=[''])
    expected_result = sc.array(values=[10., 10.], unit=sc.units.m, dims=[''])
    actual_result = corrections.illumination_of_sample(beam_size, sample_size, theta)
    assert sc.allclose(actual_result, expected_result)
Exemple #2
0
def make_detector_info(ws, spectrum_dim):
    det_info = ws.detectorInfo()
    # det -> spec mapping
    nDet = det_info.size()
    spectrum = np.empty(shape=(nDet, ), dtype=np.int32)
    has_spectrum = np.full((nDet, ), False)
    spec_info = ws.spectrumInfo()
    for i, spec in enumerate(spec_info):
        spec_def = spec.spectrumDefinition
        for j in range(len(spec_def)):
            det, time = spec_def[j]
            if time != 0:
                raise RuntimeError(
                    "Conversion of Mantid Workspace with scanning instrument "
                    "not supported yet.")
            spectrum[det] = i
            has_spectrum[det] = True

    # Store only information about detectors with data (a spectrum). The rest
    # mostly just gets in the way and including it in the default converter
    # is probably not required.
    spectrum = sc.array(dims=['detector'], values=spectrum[has_spectrum])
    detector = sc.array(dims=['detector'],
                        values=det_info.detectorIDs()[has_spectrum])

    # May want to include more information here, such as detector positions,
    # but for now this is not necessary.

    return sc.scalar(
        sc.Dataset(coords={
            'detector': detector,
            spectrum_dim: spectrum
        }))
Exemple #3
0
def _make_simple_dataset(u, v, w):
    data = sc.array(dims=['u', 'v', 'w'], values=np.ones((u, v, w)))
    u = sc.array(dims=['u'], values=np.arange(u))
    v = sc.array(dims=['v'], values=np.arange(v))
    w = sc.array(dims=['w'], values=np.arange(w))
    return sc.Dataset(data={'a': data}, coords={
        'w': w,
        'v': v,
        'u': u,
    })
Exemple #4
0
def test_loads_data_with_coords(nexus_group: Tuple[Callable, LoadFromNexus]):
    resource, loader = nexus_group
    builder = NexusBuilder()
    da = sc.DataArray(
        sc.array(dims=['xx', 'yy'], unit='K', values=[[1.1, 2.2], [3.3, 4.4]]))
    da.coords['xx'] = sc.array(dims=['xx'], unit='m', values=[0.1, 0.2])
    builder.add_detector(
        Detector(detector_numbers=np.array([1, 2, 3, 4]), data=da))
    with resource(builder)() as f:
        detector = nexus.NXroot(f, loader)['entry/detector_0']
        loaded = detector[...]
        assert sc.identical(loaded, da.rename_dims({'yy': 'dim_1'}))
Exemple #5
0
def test_nxobject_monitor(nexus_group: Tuple[Callable, LoadFromNexus]):
    resource, loader = nexus_group
    with resource(builder_with_events_monitor_and_log())() as f:
        monitor = nexus.NXroot(f, loader)['monitor']
        assert monitor.nx_class == nexus.NX_class.NXmonitor
        assert sc.identical(
            monitor[...],
            sc.DataArray(sc.array(dims=['time_of_flight'], values=[1.0]),
                         coords={
                             'time_of_flight':
                             sc.array(dims=['time_of_flight'], values=[1.0])
                         }))
Exemple #6
0
def test_nxobject_log(nexus_group: Tuple[Callable, LoadFromNexus]):
    resource, loader = nexus_group
    with resource(builder_with_events_monitor_and_log())() as f:
        log = nexus.NXroot(f, loader)['entry']['log']
        assert log.nx_class == nexus.NX_class.NXlog
        assert sc.identical(
            log[...],
            sc.DataArray(
                sc.array(dims=['time'], values=[1.1, 2.2, 3.3]),
                coords={
                    'time':
                    sc.epoch(unit='ns') + sc.array(
                        dims=['time'], unit='s', values=[4.4, 5.5, 6.6]).to(
                            unit='ns', dtype='int64')
                }))
Exemple #7
0
def test_make_chopper_bad_close_angles(params):
    dim = 'frame'
    with pytest.raises(ValueError) as e_info:
        _ = ch.make_chopper(
            frequency=params['frequency'],
            phase=params['phase'],
            position=params['position'],
            cutout_angles_begin=sc.array(dims=[dim],
                                         values=[0.0, 1.0, 2.0],
                                         unit='rad'),
            cutout_angles_end=sc.array(dims=[dim],
                                       values=[4.0, 3.0, 5.0],
                                       unit='rad'),
            kind=params['kind'])
    assert str(e_info.value) == "Chopper end cutout angles are not monotonic."
Exemple #8
0
def test_load_component_info_to_2d_geometry(geom_file):
    geometry = mantid.load_component_info_to_2d(geom_file,
                                                sizes={
                                                    'x': 10,
                                                    'y': 10
                                                })
    assert geometry["position"].sizes == {'x': 10, 'y': 10}
    assert sc.identical(
        geometry["x"],
        sc.DataArray(data=sc.array(
            dims=["x"], values=np.arange(0.0, 0.1, 0.01), unit=sc.units.m)))
    assert sc.identical(
        geometry["y"],
        sc.DataArray(data=sc.array(
            dims=["y"], values=np.arange(0.0, 0.1, 0.01), unit=sc.units.m)))
Exemple #9
0
def _create_empty_events_data_array(
        tof_dtype: Any = np.int64,
        tof_unit: Union[str, sc.Unit] = "ns",
        detector_id_dtype: Any = np.int32) -> sc.DataArray:
    data = sc.DataArray(data=sc.empty(dims=[_event_dimension],
                                      shape=[0],
                                      unit='counts',
                                      with_variances=True,
                                      dtype=np.float32),
                        coords={
                            _time_of_flight:
                            sc.empty(dims=[_event_dimension],
                                     shape=[0],
                                     dtype=tof_dtype,
                                     unit=tof_unit),
                            _detector_dimension:
                            sc.empty(dims=[_event_dimension],
                                     shape=[0],
                                     dtype=detector_id_dtype),
                        })
    indices = sc.array(dims=[_pulse_dimension], values=[], dtype='int64')
    return sc.DataArray(data=sc.bins(begin=indices,
                                     end=indices,
                                     dim=_event_dimension,
                                     data=data),
                        coords={
                            'pulse_time':
                            sc.zeros(dims=[_pulse_dimension],
                                     shape=[0],
                                     dtype='datetime64',
                                     unit='ns')
                        })
Exemple #10
0
    def load_dataset(
        self,
        group: Dict,
        dataset_name: str,
        dimensions: Optional[List[str]] = [],
        dtype: Optional[Any] = None,
        index=tuple()) -> sc.Variable:
        """
        Load a dataset into a Scipp Variable (array or scalar)
        :param group: Group containing dataset to load
        :param dataset_name: Name of the dataset to load
        :param dimensions: Dimensions for the output Variable. If empty, yields scalar.
        :param dtype: Cast to this dtype during load,
          otherwise retain dataset dtype
        """
        dataset = self.get_dataset_from_group(group, dataset_name)
        if dataset is None:
            raise MissingDataset()

        if dtype is None:
            dtype = self.get_dtype(dataset)

        try:
            units = _get_attribute_value(dataset, _nexus_units)
        except MissingAttribute:
            units = sc.units.dimensionless

        return sc.array(dims=dimensions,
                        values=np.asarray(dataset[_nexus_values])[index],
                        dtype=dtype,
                        unit=units)
Exemple #11
0
def test_illumination_correction_no_spill():
    beam_size = 1.0 * sc.units.m
    sample_size = 10.0 * sc.units.m
    theta = sc.array(values=[30.0], unit=sc.units.deg, dims=['event'])
    expected_result = sc.scalar(1.0)
    actual_result = corrections.illumination_correction(beam_size, sample_size, theta)
    assert sc.allclose(actual_result, expected_result)
Exemple #12
0
    def _bin_events(data: DetectorData):
        if not bin_by_pixel:
            # If loading "raw" data, leave binned by pulse.
            return data.event_data
        if data.detector_ids is None:
            # If detector ids were not found in an associated detector group
            # we will just have to bin according to whatever
            # ids we have a events for (pixels with no recorded events
            # will not have a bin)
            event_id = data.event_data.bins.constituents['data'].coords[
                _detector_dimension]
            data.detector_ids = sc.array(dims=[_detector_dimension],
                                         values=np.unique(event_id.values))

        # Events in the NeXus file are effectively binned by pulse
        # (because they are recorded chronologically)
        # but for reduction it is more useful to bin by detector id
        # Broadcast pulse times to events
        data.event_data.bins.coords['pulse_time'] = sc.bins_like(
            data.event_data, fill_value=data.event_data.coords['pulse_time'])
        # TODO Look into using `erase=[_pulse_dimension]` instead of binning
        # underlying buffer. Must prove that performance can be unaffected.
        da = sc.bin(data.event_data.bins.constituents['data'],
                    groups=[data.detector_ids])
        # Add a single time-of-flight bin
        da = sc.DataArray(data=sc.broadcast(da.data,
                                            dims=da.dims + [_time_of_flight],
                                            shape=da.shape + [1]),
                          coords={_detector_dimension: data.detector_ids})
        if pixel_positions_loaded:
            # TODO: the name 'position' should probably not be hard-coded but moved
            # to a variable that cah be changed in a single place.
            da.coords['position'] = data.pixel_positions
        return da
Exemple #13
0
def test_basic_stitching():
    frames = sc.Dataset()
    shift = -5.0
    frames['time_min'] = sc.array(dims=['frame'],
                                  values=[0.0],
                                  unit=sc.units.us)
    frames['time_max'] = sc.array(dims=['frame'],
                                  values=[10.0],
                                  unit=sc.units.us)
    frames['time_correction'] = sc.array(dims=['frame'],
                                         values=[shift],
                                         unit=sc.units.us)
    frames["wfm_chopper_mid_point"] = sc.vector(value=[0., 0., 2.0], unit='m')

    data = sc.DataArray(data=sc.ones(dims=['t'],
                                     shape=[100],
                                     unit=sc.units.counts),
                        coords={
                            't':
                            sc.linspace(dim='t',
                                        start=0.0,
                                        stop=10.0,
                                        num=101,
                                        unit=sc.units.us),
                            'source_position':
                            sc.vector(value=[0., 0., 0.], unit='m')
                        })

    nbins = 10
    stitched = wfm.stitch(data=data, dim='t', frames=frames, bins=nbins)
    # Note dimension change to TOF as well as shift
    assert sc.identical(
        sc.values(stitched),
        sc.DataArray(
            data=sc.ones(dims=['tof'], shape=[nbins], unit=sc.units.counts) *
            nbins,
            coords={
                'tof':
                sc.linspace(dim='tof',
                            start=0.0 - shift,
                            stop=10.0 - shift,
                            num=nbins + 1,
                            unit=sc.units.us),
                'source_position':
                sc.vector(value=[0., 0., 2.], unit='m')
            }))
Exemple #14
0
def make_unphysical_tof(t0, da):
    # 0 < t < t0, t < 0, t > t0
    tof = sc.concat([t0 - t0 / 2, sc.full_like(t0, -2), 2 * t0], 'tof')
    is_unphysical = sc.array(dims=['energy_transfer'],
                             values=[True, True, False]).broadcast(
                                 ['energy_transfer', 'spectrum'],
                                 [3, da.sizes['spectrum']])
    return tof, is_unphysical
Exemple #15
0
def test_simple_case_any_naming():
    ds = _make_simple_dataset(u=2, v=10, w=10)
    grouped = groupby2D(ds, nx_target=5, ny_target=5, x='w', y='v', z='u')
    assert grouped['a'].shape == [2, 5, 5]
    projection = sc.array(dims=['v', 'w'], values=np.ones((5, 5))) * 4
    expected_data = sc.concat([projection, projection], dim='u')
    assert sc.all(
        sc.isclose(grouped['a'].data, expected_data,
                   atol=1e-14 * sc.units.one)).value
Exemple #16
0
def make_tof_binned_events():
    buffer = sc.DataArray(sc.zeros(dims=['event'], shape=[7], dtype=float),
                          coords={
                              'tof':
                              sc.array(dims=['event'],
                                       values=[
                                           1000.0, 3000.0, 2000.0, 4000.0,
                                           5000.0, 6000.0, 3000.0
                                       ],
                                       unit='us')
                          })
    return sc.bins(data=buffer,
                   dim='event',
                   begin=sc.array(dims=['spectrum'],
                                  values=[0, 4],
                                  dtype='int64'),
                   end=sc.array(dims=['spectrum'],
                                values=[4, 7],
                                dtype='int64'))
Exemple #17
0
def test_groupby2d_simple_case_neutron_specific():
    data = sc.array(dims=['wavelength', 'y', 'x'],
                    values=np.arange(100.0).reshape(1, 10, 10))
    wav = sc.scalar(value=1.0)
    x = sc.array(dims=['x'], values=np.arange(10))
    y = sc.array(dims=['y'], values=np.arange(10))
    source_position = sc.vector(value=[0, 0, -10])
    ds = sc.Dataset(data={'a': data},
                    coords={
                        'y': y,
                        'x': x,
                        'wavelength': wav,
                        'source_position': source_position
                    })
    grouped = groupby2D(ds, 5, 5)
    assert grouped['a'].shape == [1, 5, 5]
    grouped = groupby2D(ds, 1, 1)
    assert grouped['a'].shape == [1, 1, 1]
    assert 'source_position' in grouped['a'].meta
Exemple #18
0
def test_stitching_on_beamline(event_mode, dim):
    wavelengths = sc.array(dims=['event'],
                           values=[1.75, 3.2, 4.5, 6.0, 7.0, 8.25],
                           unit='angstrom')
    stitched, dlambda_over_lambda = _do_stitching_on_beamline(
        wavelengths, dim=dim, event_mode=event_mode)

    for i in range(len(wavelengths)):
        _check_lambda_inside_resolution(wavelengths['event', i],
                                        dlambda_over_lambda,
                                        stitched,
                                        event_mode=event_mode)
Exemple #19
0
def test_beamline_compute_two_theta(in_ws, in_da):
    out_mantid = sc.array(dims=['spectrum'],
                          unit='rad',
                          values=[
                              in_ws.detectorInfo().twoTheta(i)
                              for i in range(in_ws.detectorInfo().size())
                          ])
    in_da = scn.mantid.from_mantid(in_ws)
    out_scipp = scn.two_theta(in_da)
    assert sc.allclose(out_scipp,
                       out_mantid,
                       rtol=1e-13 * sc.units.one,
                       atol=1e-13 * out_scipp.unit)
Exemple #20
0
def _check_lambda_inside_resolution(lam,
                                    dlam_over_lam,
                                    data,
                                    event_mode=False,
                                    check_value=True):
    dlam = 0.5 * dlam_over_lam * lam
    if event_mode:
        sum_in_range = sc.bin(data,
                              edges=[
                                  sc.array(dims=['wavelength'],
                                           values=[(lam - dlam).value,
                                                   (lam + dlam).value],
                                           unit=lam.unit)
                              ]).bins.sum().data['wavelength', 0]
    else:
        sum_in_range = sc.sum(data['wavelength', lam - dlam:lam + dlam]).data
    assert sc.isclose(sum_in_range, 1.0 * sc.units.counts).value is check_value
Exemple #21
0
def test_array_creates_correct_variable():
    dims = ['x']
    values = [1, 2, 3]
    variances = [4, 5, 6]
    unit = sc.units.m
    dtype = sc.dtype.float64
    var = sc.array(dims=dims,
                   values=values,
                   variances=variances,
                   unit=unit,
                   dtype=dtype)
    expected = sc.Variable(dims=dims,
                           values=values,
                           variances=variances,
                           unit=unit,
                           dtype=dtype)

    comparison = var == expected
    assert comparison.values.all()
Exemple #22
0
def test_raises_if_data_and_event_data_found(
        nexus_group: Tuple[Callable, LoadFromNexus]):
    resource, loader = nexus_group
    da = sc.DataArray(
        sc.array(dims=['xx', 'yy'], values=[[1.1, 2.2], [3.3, 4.4]]))
    event_data = EventData(
        event_id=np.array([1, 2, 4, 1, 2, 2]),
        event_time_offset=np.array([456, 743, 347, 345, 632, 23]),
        event_time_zero=np.array([1, 2, 3, 4]),
        event_index=np.array([0, 3, 3, 5]),
    )
    builder = NexusBuilder()
    builder.add_detector(
        Detector(detector_numbers=np.array([1, 2, 3, 4]),
                 data=da,
                 event_data=event_data))
    with resource(builder)() as f:
        detector = nexus.NXroot(f, loader)['entry/detector_0']
        with pytest.raises(nexus.NexusStructureError):
            detector[...]
Exemple #23
0
def test_convert_with_factor_type_promotion():
    tof = make_test_data(coords=('tof', 'L1', 'L2', 'two_theta'))
    tof.coords['tof'] = sc.array(dims=['tof'],
                                 values=[4000, 5000, 6100, 7300],
                                 unit='us',
                                 dtype='float32')
    for target in TOF_TARGET_DIMS:
        res = scn.convert(tof, origin='tof', target=target, scatter=True)
        assert res.coords[target].dtype == sc.DType.float32

    for key in ('incident_energy', 'final_energy'):
        inelastic = tof.copy()
        inelastic.coords[key] = sc.scalar(35,
                                          dtype=sc.DType.float32,
                                          unit=sc.units.meV)
        res = scn.convert(inelastic,
                          origin='tof',
                          target='energy_transfer',
                          scatter=True)
        assert res.coords['energy_transfer'].dtype == sc.DType.float32
Exemple #24
0
def test_stitching_on_beamline_bad_wavelength(event_mode, dim):
    # Create 6 neutrons. The first wavelength is in this case too short to pass through
    # the WFM choppers.
    wavelengths = sc.array(dims=['event'],
                           values=[1.5, 3.2, 4.5, 6.0, 7.0, 8.25],
                           unit='angstrom')
    stitched, dlambda_over_lambda = _do_stitching_on_beamline(
        wavelengths, dim=dim, event_mode=event_mode)

    # The first wavelength should fail the check, since anything not passing through
    # the choppers won't satisfy the dlambda/lambda condition.
    _check_lambda_inside_resolution(wavelengths['event', 0],
                                    dlambda_over_lambda,
                                    stitched,
                                    check_value=False,
                                    event_mode=event_mode)
    for i in range(1, len(wavelengths)):
        _check_lambda_inside_resolution(wavelengths['event', i],
                                        dlambda_over_lambda,
                                        stitched,
                                        event_mode=event_mode)
Exemple #25
0
    def load_dataset(
        self,
        group: h5py.Group,
        dataset_name: str,
        dimensions: Optional[List[str]] = [],
        dtype: Optional[Any] = None,
        index=tuple()) -> sc.Variable:
        """
        Load an HDF5 dataset into a Scipp Variable (array or scalar)
        :param group: Group containing dataset to load
        :param dataset_name: Name of the dataset to load
        :param dimensions: Dimensions for the output Variable. Empty for reading scalars
        :param dtype: Cast to this dtype during load,
          otherwise retain dataset dtype
        """
        try:
            dataset = group[dataset_name]
        except KeyError:
            raise MissingDataset()

        if self.is_group(dataset):
            raise MissingDataset(f"Attempted to load a group "
                                 f"({dataset_name}) as a dataset.")

        if dtype is None:
            dtype = _ensure_supported_int_type(dataset.dtype.type)
        if index == tuple():
            variable = sc.empty(dims=dimensions,
                                shape=dataset.shape,
                                dtype=dtype,
                                unit=self.get_unit(dataset))
            if variable.values.flags[
                    "C_CONTIGUOUS"] and variable.values.size > 0:
                dataset.read_direct(variable.values)
            else:
                variable.values = dataset
            return variable
        return sc.array(dims=dimensions,
                        unit=self.get_unit(dataset),
                        values=dataset[index].astype(dtype))
Exemple #26
0
def test_loading_event_data_creates_automatic_detector_numbers_if_not_present_in_file(
        nexus_group: Tuple[Callable, LoadFromNexus]):
    event_time_offsets = np.array([456, 743, 347, 345, 632, 23])
    event_data = EventData(
        event_id=np.array([1, 2, 4, 1, 2, 2]),
        event_time_offset=event_time_offsets,
        event_time_zero=np.array([1, 2, 3]),
        event_index=np.array([0, 3, 5]),
    )
    builder = NexusBuilder()
    builder.add_detector(Detector(event_data=event_data))
    resource, loader = nexus_group
    with resource(builder)() as f:
        detector = nexus.NXroot(f, loader)['entry/detector_0']
        assert detector.dims == ['detector_number']
        with pytest.raises(nexus.NexusStructureError):
            assert detector.shape == (4, )
        loaded = detector[...]
        assert sc.identical(
            loaded.bins.size().data,
            sc.array(dims=['detector_number'],
                     dtype='int64',
                     values=[2, 3, 0, 1]))
Exemple #27
0
def test_loads_event_data_mapped_to_detector_numbers_based_on_their_event_id(
        nexus_group: Tuple[Callable, LoadFromNexus]):
    event_time_offsets = np.array([456, 743, 347, 345, 632, 23])
    event_data = EventData(
        event_id=np.array([1, 2, 3, 1, 2, 2]),
        event_time_offset=event_time_offsets,
        event_time_zero=np.array([1, 2, 3, 4]),
        event_index=np.array([0, 3, 3, 5]),
    )
    builder = NexusBuilder()
    builder.add_detector(
        Detector(detector_numbers=np.array([1, 2, 3, 4]),
                 event_data=event_data))
    resource, loader = nexus_group
    with resource(builder)() as f:
        detector = nexus.NXroot(f, loader)['entry/detector_0']
        assert detector.dims == ['detector_number']
        assert detector.shape == (4, )
        loaded = detector[...]
        assert sc.identical(
            loaded.bins.size().data,
            sc.array(dims=['detector_number'],
                     dtype='int64',
                     values=[2, 3, 1, 0]))
Exemple #28
0
def test_time_open_closed(params):
    dim = 'frame'
    chopper = ch.make_chopper(
        frequency=sc.scalar(0.5, unit=sc.units.one / sc.units.s),
        phase=sc.scalar(0., unit='rad'),
        position=params['position'],
        cutout_angles_begin=sc.array(dims=[dim],
                                     values=np.pi * np.array([0.0, 0.5, 1.0]),
                                     unit='rad'),
        cutout_angles_end=sc.array(dims=[dim],
                                   values=np.pi * np.array([0.5, 1.0, 1.5]),
                                   unit='rad'),
        kind=params['kind'])

    assert sc.allclose(
        ch.time_open(chopper),
        sc.to_unit(sc.array(dims=[dim], values=[0.0, 0.5, 1.0], unit='s'),
                   'us'))
    assert sc.allclose(
        ch.time_closed(chopper),
        sc.to_unit(sc.array(dims=[dim], values=[0.5, 1.0, 1.5], unit='s'),
                   'us'))

    chopper["phase"] = sc.scalar(2.0 * np.pi / 3.0, unit='rad')
    assert sc.allclose(
        ch.time_open(chopper),
        sc.to_unit(
            sc.array(dims=[dim],
                     values=np.array([0.0, 0.5, 1.0]) + 2.0 / 3.0,
                     unit='s'), 'us'))
    assert sc.allclose(
        ch.time_closed(chopper),
        sc.to_unit(
            sc.array(dims=[dim],
                     values=np.array([0.5, 1.0, 1.5]) + 2.0 / 3.0,
                     unit='s'), 'us'))
Exemple #29
0
def make_beamline() -> dict:
    """
    ODIN chopper cascade and component positions.
    Chopper opening angles taken from Schmakat et al. (2020)
    https://www.sciencedirect.com/science/article/pii/S0168900220308640

    Note that the values listed in the paper for the FOC1 opening angles are wrong.
    The correct values are used here.
    """

    dim = 'frame'

    beamline = {
        "source_pulse_length": sc.scalar(2.86e+03, unit='us'),
        "source_pulse_t_0": sc.scalar(130.0, unit='us'),
        "source_position": sc.vector(value=[0.0, 0.0, 0.0], unit='m')
    }

    beamline["chopper_wfm_1"] = sc.scalar(
        make_chopper(frequency=sc.scalar(56.0, unit="Hz"),
                     phase=sc.scalar(0.0, unit='deg'),
                     position=sc.vector(value=[0, 0, 6.775], unit='m'),
                     cutout_angles_center=sc.array(dims=[dim],
                                                   values=[
                                                       91.93, 142.23, 189.40,
                                                       233.63, 275.10, 313.99
                                                   ],
                                                   unit='deg'),
                     cutout_angles_width=sc.array(
                         dims=[dim],
                         values=[5.74, 8.98, 12.01, 14.85, 17.52, 20.02],
                         unit='deg'),
                     kind="wfm"))

    beamline["chopper_wfm_2"] = sc.scalar(
        make_chopper(frequency=sc.scalar(56.0, unit="Hz"),
                     phase=sc.scalar(0.0, unit='deg'),
                     position=sc.vector(value=[0, 0, 7.225], unit='m'),
                     cutout_angles_center=sc.array(dims=[dim],
                                                   values=[
                                                       97.67, 151.21, 201.41,
                                                       248.48, 292.62, 334.01
                                                   ],
                                                   unit='deg'),
                     cutout_angles_width=sc.array(
                         dims=[dim],
                         values=[5.74, 8.98, 12.01, 14.85, 17.52, 20.02],
                         unit='deg'),
                     kind="wfm"))

    beamline["chopper_foc_1"] = sc.scalar(
        make_chopper(frequency=sc.scalar(42.0, unit="Hz"),
                     phase=sc.scalar(0.0, unit='deg'),
                     position=sc.vector(value=[0, 0, 8.4], unit='m'),
                     cutout_angles_center=sc.array(dims=[dim],
                                                   values=[
                                                       81.12, 127.82, 171.60,
                                                       212.66, 251.16, 288.85
                                                   ],
                                                   unit='deg'),
                     cutout_angles_width=sc.array(
                         dims=[dim],
                         values=[11.06, 13.06, 14.94, 16.70, 18.36, 19.91],
                         unit='deg'),
                     kind="frame_overlap"))

    beamline["chopper_foc_2"] = sc.scalar(
        make_chopper(frequency=sc.scalar(42.0, unit="Hz"),
                     phase=sc.scalar(0.0, unit='deg'),
                     position=sc.vector(value=[0, 0, 12.20], unit='m'),
                     cutout_angles_center=sc.array(dims=[dim],
                                                   values=[
                                                       106.57, 174.42, 238.04,
                                                       297.53, 353.48,
                                                       46.65 + 360.0
                                                   ],
                                                   unit='deg'),
                     cutout_angles_width=sc.array(
                         dims=[dim],
                         values=[32.90, 33.54, 34.15, 34.71, 35.24, 35.74],
                         unit='deg'),
                     kind="frame_overlap"))

    beamline["chopper_foc_3"] = sc.scalar(
        make_chopper(frequency=sc.scalar(28.0, unit="Hz"),
                     phase=sc.scalar(0.0, unit='deg'),
                     position=sc.vector(value=[0, 0, 17.0], unit='m'),
                     cutout_angles_center=sc.array(dims=[dim],
                                                   values=[
                                                       92.47, 155.52, 214.65,
                                                       270.09, 322.08,
                                                       11.39 + 360.0
                                                   ],
                                                   unit='deg'),
                     cutout_angles_width=sc.array(
                         dims=[dim],
                         values=[40.32, 39.61, 38.94, 38.31, 37.72, 37.16],
                         unit='deg'),
                     kind="frame_overlap"))

    beamline["chopper_foc_4"] = sc.scalar(
        make_chopper(frequency=sc.scalar(14.0, unit="Hz"),
                     phase=sc.scalar(0.0, unit='deg'),
                     position=sc.vector(value=[0, 0, 23.69], unit='m'),
                     cutout_angles_center=sc.array(dims=[dim],
                                                   values=[
                                                       61.17, 105.11, 146.32,
                                                       184.96, 221.19, 255.72
                                                   ],
                                                   unit='deg'),
                     cutout_angles_width=sc.array(
                         dims=[dim],
                         values=[32.98, 31.82, 30.74, 29.72, 28.77, 27.87],
                         unit='deg'),
                     kind="frame_overlap"))

    beamline["chopper_foc_5"] = sc.scalar(
        make_chopper(frequency=sc.scalar(14.0, unit="Hz"),
                     phase=sc.scalar(0.0, unit='deg'),
                     position=sc.vector(value=[0, 0, 33.0], unit='m'),
                     cutout_angles_center=sc.array(dims=[dim],
                                                   values=[
                                                       82.20, 143.05, 200.44,
                                                       254.19, 304.68, 353.46
                                                   ],
                                                   unit='deg'),
                     cutout_angles_width=sc.array(
                         dims=[dim],
                         values=[50.81, 48.55, 46.42, 44.43, 42.56, 40.80],
                         unit='deg'),
                     kind="frame_overlap"))

    return beamline
Exemple #30
0
def _load_event_group(group: Group,
                      nexus: LoadFromNexus,
                      quiet: bool,
                      select=tuple()) -> DetectorData:
    _check_for_missing_fields(group, nexus)
    index = to_plain_index([_pulse_dimension], select)

    def shape(name):
        return nexus.get_shape(nexus.get_dataset_from_group(group, name))

    max_index = shape("event_index")[0]
    single = False
    if index is Ellipsis or index == tuple():
        last_loaded = False
    else:
        if isinstance(index, int):
            single = True
            start, stop, _ = slice(index, None).indices(max_index)
            if start == stop:
                raise IndexError('Index {start} is out of range')
            index = slice(start, start + 1)
        start, stop, stride = index.indices(max_index)
        if stop + stride > max_index:
            last_loaded = False
        else:
            stop += stride
            last_loaded = True
        index = slice(start, stop, stride)

    event_index = nexus.load_dataset_from_group_as_numpy_array(
        group, "event_index", index)
    event_time_zero = _load_event_time_zero(group, nexus, index)

    num_event = shape("event_time_offset")[0]
    # Some files contain uint64 "max" indices, which turn into negatives during
    # conversion to int64. This is a hack to get arround this.
    event_index[event_index < 0] = num_event

    if len(event_index) > 0:
        event_select = slice(event_index[0],
                             event_index[-1] if last_loaded else num_event)
    else:
        event_select = slice(None)

    if nexus.dataset_in_group(group, "event_id")[0]:
        event_id = nexus.load_dataset(group,
                                      "event_id", [_event_dimension],
                                      index=event_select)
    else:
        event_id = None

    event_time_offset = nexus.load_dataset(group,
                                           "event_time_offset",
                                           [_event_dimension],
                                           index=event_select)

    # Weights are not stored in NeXus, so use 1s
    weights = sc.ones(dims=[_event_dimension],
                      shape=event_time_offset.shape,
                      unit='counts',
                      dtype=np.float32,
                      with_variances=True)

    events = sc.DataArray(data=weights,
                          coords={'event_time_offset': event_time_offset})
    if event_id is not None:
        events.coords['event_id'] = event_id

    if not last_loaded:
        event_index = np.append(event_index, num_event)
    else:
        # Not a bin-edge coord, all events in bin are associated with same (previous)
        # pulse time value
        event_time_zero = event_time_zero[:-1]

    event_index = sc.array(dims=[_pulse_dimension],
                           values=event_index,
                           dtype=sc.DType.int64)

    event_index -= event_index.min()

    # There is some variation in the last recorded event_index in files from different
    # institutions. We try to make sure here that it is what would be the first index of
    # the next pulse. In other words, ensure that event_index includes the bin edge for
    # the last pulse.
    if single:
        begins = event_index[_pulse_dimension, 0]
        ends = event_index[_pulse_dimension, 1]
        event_time_zero = event_time_zero[_pulse_dimension, 0]
    else:
        begins = event_index[_pulse_dimension, :-1]
        ends = event_index[_pulse_dimension, 1:]

    try:
        binned = sc.bins(data=events,
                         dim=_event_dimension,
                         begin=begins,
                         end=ends)
    except sc.SliceError:
        raise BadSource(
            f"Event index in NXEvent at {group.name}/event_index was not"
            f" ordered. The index must be ordered to load pulse times.")

    if not quiet:
        print(f"Loaded {len(event_time_offset)} events from "
              f"{nexus.get_name(group)} containing {num_event} events")

    return sc.DataArray(data=binned,
                        coords={'event_time_zero': event_time_zero})