示例#1
0
def test_convert_tof_to_wavelength_no_scatter():
    # scatter=True and scatter=False only differ in how Ltotal is computed.
    tof = make_test_data(coords=('tof', 'Ltotal'), dataset=True)
    no_scatter = scn.convert(tof,
                             origin='tof',
                             target='wavelength',
                             scatter=False)
    scatter = scn.convert(tof, origin='tof', target='wavelength', scatter=True)
    assert sc.identical(no_scatter, scatter)
示例#2
0
def test_convert_dataset_vs_dataarray(origin, target):
    inputs = make_dataset_in(origin)
    expected = scn.convert(inputs, origin=origin, target=target, scatter=True)
    result = sc.Dataset(
        data={
            name: scn.convert(
                data.copy(), origin=origin, target=target, scatter=True)
            for name, data in inputs.items()
        })
    for name, data in result.items():
        assert sc.identical(data, expected[name])
示例#3
0
def test_convert_binned_convert_slice(target):
    tof = make_test_data(coords=('tof', 'Ltotal', 'two_theta'))['tof',
                                                                0].copy()
    tof.data = make_tof_binned_events()
    original = tof.copy()
    full = scn.convert(tof, origin='tof', target=target, scatter=True)
    sliced = scn.convert(tof['spectrum', 1:2],
                         origin='tof',
                         target=target,
                         scatter=True)
    assert sc.identical(sliced, full['spectrum', 1:2])
    assert sc.identical(tof, original)
def process_event_data(file, lambda_binning):
    """
    Load and reduce event data (used for Vanadium and Empty instrument)

    file: Nexus file to be loaded and its data reduced in this script

    lambda_binning: lambda_min, lamba_max, number_of_bins

    """

    # load nexus file
    event_data = scn.load(file,
                          advanced_geometry=True,
                          load_pulse_times=False,
                          mantid_args={'LoadMonitors': True})

    # ################################
    # Monitor correction
    # extract monitor and convert from tof to wavelength
    mon4_lambda = scn.convert(event_data.attrs['monitor4'].values,
                              'tof',
                              'wavelength',
                              scatter=False)

    mon4_smooth = smooth_data(mon4_lambda, dim='wavelength', NPoints=40)

    del mon4_lambda

    # ################################
    # vana and EC
    # convert to lambda
    event_lambda = scn.convert(event_data, 'tof', 'wavelength', scatter=True)

    # normalize to monitor
    lambda_min, lambda_max, number_bins = lambda_binning

    edges_lambda = sc.Variable(['wavelength'],
                               unit=sc.units.angstrom,
                               values=np.linspace(lambda_min,
                                                  lambda_max,
                                                  num=number_bins))

    mon_rebin = sc.rebin(mon4_smooth, 'wavelength', edges_lambda)

    del mon4_smooth

    event_lambda_norm = event_lambda.bins / sc.lookup(func=mon_rebin,
                                                      dim='wavelength')

    del mon_rebin, event_lambda

    return event_lambda_norm
示例#5
0
def test_convert_coords_vs_attributes():
    with_coords = make_test_data(coords=('tof', 'Ltotal'), dataset=True)
    with_attrs = with_coords.copy()
    with_attrs['counts'].attrs['Ltotal'] = with_attrs.coords.pop('Ltotal')

    from_coords = scn.convert(with_coords,
                              origin='tof',
                              target='wavelength',
                              scatter=True)
    from_attrs = scn.convert(with_attrs,
                             origin='tof',
                             target='wavelength',
                             scatter=True)
    assert sc.identical(from_coords, from_attrs)
示例#6
0
def test_convert_integer_input_elastic(target):
    da_float_coord = make_test_data(coords=('tof', 'L1', 'L2', 'two_theta'))
    da_int_coord = da_float_coord.copy()
    da_int_coord.coords['tof'] = da_float_coord.coords['tof'].astype('int64')

    res = scn.convert(da_int_coord, origin='tof', target=target, scatter=True)
    expected = scn.convert(da_float_coord,
                           origin='tof',
                           target=target,
                           scatter=True)
    assert res.coords[target].dtype == sc.DType.float64
    assert sc.allclose(res.coords[target],
                       expected.coords[target],
                       rtol=1e-15 * sc.units.one)
示例#7
0
def test_convert_Q_to_wavelength():
    tof = make_test_data(coords=('tof', 'Ltotal', 'two_theta'))
    Q = scn.convert(tof, origin='tof', target='Q', scatter=True)
    del Q.attrs['wavelength']
    wavelength_from_Q = scn.convert(Q,
                                    origin='Q',
                                    target='wavelength',
                                    scatter=True)
    wavelength_from_tof = scn.convert(tof,
                                      origin='tof',
                                      target='wavelength',
                                      scatter=True)
    assert sc.allclose(wavelength_from_Q.coords['wavelength'],
                       wavelength_from_tof.coords['wavelength'],
                       rtol=1e-14 * sc.units.one)
示例#8
0
def test_convert_beam_length_and_angle(target, make_ref):
    original = make_test_data(coords=('incident_beam', 'scattered_beam'))
    converted = scn.convert(original,
                            origin='position',
                            target=target,
                            scatter=True)
    assert sc.identical(converted.meta[target], make_ref())
示例#9
0
    def test_unit_conversion(self):
        import mantid.simpleapi as mantid
        eventWS = self.base_event_ws
        ws = mantid.Rebin(eventWS, 10000, PreserveEvents=False)
        tmp = scn.mantid.convert_Workspace2D_to_data_array(ws)
        target_tof = tmp.coords['tof']
        ws = mantid.ConvertUnits(InputWorkspace=ws,
                                 Target="Wavelength",
                                 EMode="Elastic")
        converted_mantid = scn.mantid.convert_Workspace2D_to_data_array(ws)

        da = scn.mantid.convert_EventWorkspace_to_data_array(
            eventWS, load_pulse_times=False)
        da = sc.histogram(da, bins=target_tof)
        d = sc.Dataset(data={da.name: da})
        converted = scn.convert(d, 'tof', 'wavelength', scatter=True)

        self.assertTrue(
            np.all(np.isclose(converted_mantid.values, converted[""].values)))
        self.assertTrue(
            np.all(
                np.isclose(
                    converted_mantid.coords['wavelength'].values,
                    converted.coords['wavelength'].values,
                )))
示例#10
0
def test_convert_tof_to_dspacing():
    tof = make_test_data(coords=('tof', 'Ltotal', 'two_theta'), dataset=True)
    dspacing = scn.convert(tof, origin='tof', target='dspacing', scatter=True)
    check_tof_conversion_metadata(dspacing, 'dspacing', sc.units.angstrom)

    # Rule of thumb (https://www.psi.ch/niag/neutron-physics):
    # v [m/s] = 3956 / \lambda [ Angstrom ]
    tof_in_seconds = tof.coords['tof'] * 1e-6

    # Spectrum 0 is 11 m from source
    # 2d sin(theta) = n \lambda
    # theta = 45 deg => d = lambda / (2 * 1 / sqrt(2))
    for val, t in zip(dspacing.coords['dspacing']['spectrum', 0].values,
                      tof_in_seconds.values):
        np.testing.assert_almost_equal(val,
                                       3956.0 / (11.0 / t) / math.sqrt(2.0),
                                       val * 1e-3)

    # Spectrum 1
    # sin(2 theta) = 0.1/(L-10)
    L = 10.0 + math.sqrt(1.0 * 1.0 + 0.1 * 0.1)
    lambda_to_d = 1.0 / (2.0 * math.sin(0.5 * math.asin(0.1 / (L - 10.0))))
    for val, t in zip(dspacing.coords['dspacing']['spectrum', 1].values,
                      tof_in_seconds.values):
        np.testing.assert_almost_equal(val, 3956.0 / (L / t) * lambda_to_d,
                                       val * 1e-3)
def test_mantid_convert_tof_to_direct_energy_transfer():
    efixed = 1000 * sc.Unit('meV')
    in_ws = make_workspace('tof', emode='Direct', efixed=efixed)
    out_mantid = mantid_convert_units(in_ws,
                                      'energy_transfer',
                                      emode='Direct',
                                      efixed=efixed)

    in_da = scn.mantid.from_mantid(in_ws)
    out_scipp = scn.convert(data=in_da,
                            origin='tof',
                            target='energy_transfer',
                            scatter=True)

    # The conversion consists of multiplications and additions, thus the relative error
    # changes with the inputs. In this case, small tof yields a large error due to
    # the 1/tof**2 factor in the conversion.
    # rtol is chosen to account for linearly changing tof in the input data.
    assert sc.allclose(
        out_scipp.coords['energy_transfer'],
        out_mantid.coords['energy_transfer'],
        rtol=sc.linspace(
            'energy_transfer', 1e-6, 1e-10,
            out_scipp.coords['energy_transfer'].sizes['energy_transfer']))
    assert sc.identical(out_scipp.coords['spectrum'],
                        out_mantid.coords['spectrum'])
示例#12
0
def test_convert_non_tof(origin, target, target_unit, keep_tof):
    tof = make_test_data(coords=('tof', 'Ltotal', 'two_theta'), dataset=True)
    original = scn.convert(tof, origin='tof', target=origin, scatter=True)
    if not keep_tof:
        del original['counts'].attrs['tof']
    converted = scn.convert(original,
                            origin=origin,
                            target=target,
                            scatter=True)
    check_tof_conversion_metadata(converted, target, target_unit)
    converted_from_tof = scn.convert(tof,
                                     origin='tof',
                                     target=target,
                                     scatter=True)
    assert sc.allclose(converted.coords[target],
                       converted_from_tof.coords[target],
                       rtol=1e-14 * sc.units.one)
示例#13
0
def test_convert_beam_length_no_scatter():
    original = make_test_data(coords=('position', 'source_position'))
    converted = scn.convert(original,
                            origin='position',
                            target='Ltotal',
                            scatter=False)
    expected = sc.norm(make_position() - make_source_position())
    assert sc.identical(converted.coords['Ltotal'], expected)
示例#14
0
def test_convert_scattering_conversion_fails_with_noscatter_mode():
    tof = make_test_data(coords=('tof', 'Ltotal', 'two_theta'), dataset=True)
    scn.convert(tof, origin='tof', target='dspacing',
                scatter=True)  # no exception
    with pytest.raises(RuntimeError):
        scn.convert(tof, origin='tof', target='dspacing', scatter=False)

    wavelength = scn.convert(tof,
                             origin='tof',
                             target='wavelength',
                             scatter=True)
    scn.convert(wavelength, origin='wavelength', target='Q', scatter=True)
    with pytest.raises(RuntimeError):
        scn.convert(wavelength, origin='wavelength', target='Q', scatter=False)
示例#15
0
def test_convert_beams(target):
    def check_positions(data):
        assert 'sample_position' not in data.coords
        assert ('source_position'
                in data.coords) == (target == 'scattered_beam')
        assert ('position' in data.coords) == (target == 'incident_beam')

    # A single sample position.
    original = make_test_data(coords=('position', 'sample_position',
                                      'source_position'))
    converted = scn.convert(original,
                            origin='position',
                            target=target,
                            scatter=True)
    check_positions(converted)
    assert sc.identical(
        converted.coords[target],
        make_incident_beam()
        if target == 'incident_beam' else make_scattered_beam())

    # Two sample positions.
    original = make_test_data(coords=('position', 'source_position'))
    original.coords['sample_position'] = sc.vectors(dims=['spectrum'],
                                                    values=[[1.0, 0.0, 0.2],
                                                            [2.1, -0.3, 1.4]],
                                                    unit='m')
    converted = scn.convert(original,
                            origin='position',
                            target=target,
                            scatter=True)
    check_positions(converted)
    if target == 'incident_beam':
        assert sc.allclose(converted.coords['incident_beam'],
                           sc.vectors(dims=['spectrum'],
                                      values=[[1.0, 0.0, 10.2],
                                              [2.1, -0.3, 11.4]],
                                      unit='m'),
                           rtol=1e-14 * sc.units.one)
    if target == 'scattered_beam':
        assert sc.allclose(converted.coords['scattered_beam'],
                           sc.vectors(dims=['spectrum'],
                                      values=[[0.0, 0.0, -0.2],
                                              [-2.0, 0.3, -0.4]],
                                      unit='m'),
                           rtol=1e-14 * sc.units.one)
示例#16
0
def test_convert_input_unchanged():
    inputs = make_test_data(coords=('tof', 'Ltotal'), dataset=True)
    original = inputs.copy(deep=True)
    result = scn.convert(inputs,
                         origin='tof',
                         target='wavelength',
                         scatter=True)
    assert not sc.identical(result, original)
    assert sc.identical(inputs, original)
示例#17
0
def test_convert_tof_to_energy_transfer_direct_indirect_are_distinct():
    tof_direct = make_test_data(coords=('tof', 'L1', 'L2'), dataset=True)
    tof_direct.coords['incident_energy'] = 22.0 * sc.units.meV
    direct = scn.convert(tof_direct,
                         origin='tof',
                         target='energy_transfer',
                         scatter=True)

    tof_indirect = make_test_data(coords=('tof', 'L1', 'L2'), dataset=True)
    tof_indirect.coords['final_energy'] = 22.0 * sc.units.meV
    indirect = scn.convert(tof_indirect,
                           origin='tof',
                           target='energy_transfer',
                           scatter=True)
    assert not sc.allclose(direct.coords['energy_transfer'],
                           indirect.coords['energy_transfer'],
                           rtol=0.0 * sc.units.one,
                           atol=1e-11 * sc.units.meV)
示例#18
0
def test_convert_tof_to_energy_transfer_indirect():
    tof = make_test_data(coords=('tof', 'L1', 'L2'), dataset=True)
    with pytest.raises(RuntimeError):
        scn.convert(tof, origin='tof', target='energy_transfer', scatter=True)
    ef = 25.0 * sc.units.meV
    tof.coords['final_energy'] = ef
    indirect = scn.convert(tof,
                           origin='tof',
                           target='energy_transfer',
                           scatter=True)
    check_tof_conversion_metadata(indirect, 'energy_transfer', sc.units.meV)

    t = tof.coords['tof']
    t0 = sc.to_unit(tof.coords['L2'] * sc.sqrt(m_n / 2 / ef), t.unit)
    assert sc.all(t0 < t).value  # only test physical region here
    ref = sc.to_unit(m_n / 2 * (tof.coords['L1'] / (t - t0))**2,
                     ef.unit).rename_dims({'tof': 'energy_transfer'}) - ef
    assert sc.allclose(indirect.coords['energy_transfer'],
                       ref,
                       rtol=sc.scalar(1e-13))
示例#19
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
示例#20
0
def test_convert_tof_to_energy_elastic_fails_if_inelastic_params_present():
    # Note these conversions fail only because they are not implemented.
    # It should definitely be possible to support this.
    tof = make_test_data(coords=('tof', 'L1', 'L2'), dataset=True)
    scn.convert(tof, origin='tof', target='energy', scatter=True)
    tof.coords['incident_energy'] = 2.1 * sc.units.meV
    with pytest.raises(RuntimeError):
        scn.convert(tof, origin='tof', target='energy', scatter=True)

    del tof.coords['incident_energy']
    scn.convert(tof, origin='tof', target='energy', scatter=True)
    tof.coords['final_energy'] = 2.1 * sc.units.meV
    with pytest.raises(RuntimeError):
        scn.convert(tof, origin='tof', target='energy', scatter=True)
示例#21
0
def test_convert_tof_to_Q():
    tof = make_test_data(coords=('tof', 'Ltotal', 'two_theta'), dataset=True)
    wavelength = scn.convert(tof,
                             origin='tof',
                             target='wavelength',
                             scatter=True)
    Q_from_tof = scn.convert(tof, origin='tof', target='Q', scatter=True)
    Q_from_wavelength = scn.convert(wavelength,
                                    origin='wavelength',
                                    target='Q',
                                    scatter=True)
    check_tof_conversion_metadata(Q_from_tof, 'Q',
                                  sc.units.one / sc.units.angstrom)
    check_tof_conversion_metadata(Q_from_wavelength, 'Q',
                                  sc.units.one / sc.units.angstrom)
    # wavelength is intermediate in this case and thus kept but not in the other case.
    assert sc.identical(Q_from_tof, Q_from_wavelength)

    # Rule of thumb (c):
    # v [m/s] = 3956 / \lambda [ Angstrom ]
    tof_in_seconds = tof.coords['tof'] * 1e-6

    # Spectrum 0 is 11 m from source
    # Q = 4pi sin(theta) / lambda
    # theta = 45 deg => Q = 2 sqrt(2) pi / lambda
    for val, t in zip(Q_from_wavelength.coords['Q']['spectrum', 0].values,
                      tof_in_seconds.values):
        np.testing.assert_almost_equal(
            val, 2.0 * math.sqrt(2.0) * math.pi / (3956.0 / (11.0 / t)),
            val * 1e-3)

    # Spectrum 1
    # sin(2 theta) = 0.1/(L-10)
    L = 10.0 + math.sqrt(1.0 * 1.0 + 0.1 * 0.1)
    lambda_to_Q = 4.0 * math.pi * math.sin(math.asin(0.1 / (L - 10.0)) / 2.0)
    for val, t in zip(Q_from_wavelength.coords['Q']['spectrum', 1].values,
                      tof_in_seconds.values):
        np.testing.assert_almost_equal(val, lambda_to_Q / (3956.0 / (L / t)),
                                       val * 1e-3)
示例#22
0
def test_convert_binned_events_converted(target):
    tof = make_test_data(coords=('Ltotal', 'two_theta'), dataset=True)
    del tof['counts']
    tof['events'] = make_tof_binned_events()

    # Construct events with all coords.
    binned_tof = tof['events'].copy()
    for name in ('Ltotal', 'two_theta'):
        binned_tof.bins.coords[name] = sc.bins_like(binned_tof,
                                                    tof.coords[name])
    dense_tof = binned_tof.bins.constituents['data']
    expected = scn.convert(dense_tof,
                           origin='tof',
                           target=target,
                           scatter=True)
    for intermediate in ('Ltotal', 'two_theta'):
        expected.attrs.pop(intermediate, None)
        expected.coords.pop(intermediate, None)
    expected = sc.bins(**{**binned_tof.bins.constituents, 'data': expected})

    res = scn.convert(tof, origin='tof', target=target, scatter=True)
    assert sc.identical(res['events'].data, expected)
示例#23
0
def test_convert_slice(target):
    tof = make_test_data(coords=('tof', 'position', 'sample_position',
                                 'source_position'),
                         dataset=True)
    expected = scn.convert(tof['counts'],
                           origin='tof',
                           target=target,
                           scatter=True)['spectrum', 0].copy()
    assert sc.identical(
        scn.convert(tof['counts']['spectrum', 0].copy(),
                    origin='tof',
                    target=target,
                    scatter=True), expected)
    # Converting slice of item is same as item of converted slice
    assert sc.identical(
        scn.convert(tof['counts']['spectrum', 0].copy(),
                    origin='tof',
                    target=target,
                    scatter=True).data,
        scn.convert(tof['spectrum', 0].copy(),
                    origin='tof',
                    target=target,
                    scatter=True)['counts'].data)
示例#24
0
def test_convert_integer_input_inelastic(input_energy, input_dtypes):
    da_float_coord = make_test_data(coords=('tof', 'L1', 'L2', 'two_theta'))
    da_float_coord.coords[input_energy] = sc.scalar(35,
                                                    dtype=sc.DType.float64,
                                                    unit=sc.units.meV)

    da_int_coord = da_float_coord.copy()
    for i, name in enumerate(('tof', input_energy)):
        da_int_coord.coords[name] = da_float_coord.coords[name].astype(
            input_dtypes[i])

    res = scn.convert(da_int_coord,
                      origin='tof',
                      target='energy_transfer',
                      scatter=True)
    expected = scn.convert(da_float_coord,
                           origin='tof',
                           target='energy_transfer',
                           scatter=True)
    assert res.coords['energy_transfer'].dtype == sc.DType.float64
    assert sc.allclose(res.coords['energy_transfer'],
                       expected.coords['energy_transfer'],
                       rtol=1e-14 * sc.units.one)
示例#25
0
def test_convert_tof_to_energy_transfer_indirect_unphysical():
    tof = make_test_data(coords=('tof', 'L1', 'L2'), dataset=True)
    ef = 25.0 * sc.units.meV
    tof.coords['final_energy'] = ef
    t0 = sc.to_unit(tof.coords['L2'] * sc.sqrt(m_n / ef), sc.units.s)
    coord, is_unphysical = make_unphysical_tof(t0, tof)
    tof.coords['tof'] = coord

    result = scn.convert(tof,
                         origin='tof',
                         target='energy_transfer',
                         scatter=True)
    assert sc.identical(sc.isnan(result.coords['energy_transfer']),
                        is_unphysical)
def test_mantid_convert_tof_to_dspacing():
    in_ws = make_workspace('tof')
    out_mantid = mantid_convert_units(in_ws, 'dspacing')

    in_da = scn.mantid.from_mantid(in_ws)
    out_scipp = scn.convert(data=in_da,
                            origin='tof',
                            target='dspacing',
                            scatter=True)

    assert sc.allclose(out_scipp.coords['dspacing'],
                       out_mantid.coords['dspacing'],
                       rtol=1e-8 * sc.units.one)
    assert sc.identical(out_scipp.coords['spectrum'],
                        out_mantid.coords['spectrum'])
示例#27
0
 def test_inelastic_unit_conversion(self):
     import mantid.simpleapi as mantid
     eventWS = self.base_event_ws
     ws_deltaE = mantid.ConvertUnits(eventWS,
                                     Target='DeltaE',
                                     EMode='Direct',
                                     EFixed=3)
     ref = scn.from_mantid(ws_deltaE)
     da = scn.from_mantid(eventWS)
     # Boost and Mantid use CODATA 2006. This test passes if we manually
     # change the implementation to use the old constants. Alternatively
     # we can correct for this by scaling L1^2 or L2^2, and this was also
     # confirmed in C++. Unfortunately only positions are accessible to
     # correct for this here, and due to precision issues with
     # dot/norm/sqrt this doesn't actually fix the test. We additionally
     # exclude low TOF region, and bump relative and absolute accepted
     # errors from 1e-8 to 1e-5.
     m_n_2006 = 1.674927211
     m_n_2018 = 1.67492749804
     e_2006 = 1.602176487
     e_2018 = 1.602176634
     scale = (m_n_2006 / m_n_2018) / (e_2006 / e_2018)
     da.coords['source_position'] *= np.sqrt(scale)
     da.coords['position'] *= np.sqrt(scale)
     low_tof = da.bins.constituents['data'].coords[
         'tof'] < 49000.0 * sc.units.us
     da.coords['incident_energy'] = 3.0 * sc.units.meV
     da = scn.convert(da, 'tof', 'energy_transfer', scatter=True)
     assert sc.all(
         sc.isnan(da.coords['energy_transfer'])
         | sc.isclose(da.coords['energy_transfer'],
                      ref.coords['energy_transfer'],
                      atol=1e-8 * sc.units.meV,
                      rtol=1e-8 * sc.units.one)).value
     assert sc.all(
         low_tof
         | sc.isnan(da.bins.constituents['data'].coords['energy_transfer'])
         | sc.isclose(
             da.bins.constituents['data'].coords['energy_transfer'],
             ref.bins.constituents['data'].coords['energy_transfer'],
             atol=1e-5 * sc.units.meV,
             rtol=1e-5 * sc.units.one)).value
def test_mantid_convert_tof_to_energy():
    in_ws = make_workspace('tof')
    out_mantid = mantid_convert_units(in_ws, 'energy')

    in_da = scn.mantid.from_mantid(in_ws)
    out_scipp = scn.convert(data=in_da,
                            origin='tof',
                            target='energy',
                            scatter=True)

    # Mantid reverses the order of the energy dim.
    mantid_energy = sc.empty_like(out_mantid.coords['energy'])
    assert mantid_energy.dims[1] == 'energy'
    mantid_energy.values = out_mantid.coords['energy'].values[..., ::-1]

    assert sc.allclose(out_scipp.coords['energy'],
                       mantid_energy,
                       rtol=1e-7 * sc.units.one)
    assert sc.identical(out_scipp.coords['spectrum'],
                        out_mantid.coords['spectrum'])
示例#29
0
def test_convert_tof_to_wavelength():
    tof = make_test_data(coords=('tof', 'Ltotal'), dataset=True)
    wavelength = scn.convert(tof,
                             origin='tof',
                             target='wavelength',
                             scatter=True)
    check_tof_conversion_metadata(wavelength, 'wavelength', sc.units.angstrom)

    # Rule of thumb (https://www.psi.ch/niag/neutron-physics):
    # v [m/s] = 3956 / \lambda [ Angstrom ]
    tof_in_seconds = tof.coords['tof'] * 1e-6

    # Spectrum 0 is 11 m from source
    for val, t in zip(wavelength.coords['wavelength']['spectrum', 0].values,
                      tof_in_seconds.values):
        np.testing.assert_almost_equal(val, 3956.0 / (11.0 / t), val * 1e-3)
    # Spectrum 1
    L = 10.0 + math.sqrt(1.0 * 1.0 + 0.1 * 0.1)
    for val, t in zip(wavelength.coords['wavelength']['spectrum', 1].values,
                      tof_in_seconds.values):
        np.testing.assert_almost_equal(val, 3956.0 / (L / t), val * 1e-3)
示例#30
0
def test_convert_tof_to_energy_elastic():
    tof = make_test_data(coords=('tof', 'Ltotal'), dataset=True)
    energy = scn.convert(tof, origin='tof', target='energy', scatter=True)
    check_tof_conversion_metadata(energy, 'energy', sc.units.meV)

    tof_in_seconds = sc.to_unit(tof.coords['tof'], 's')
    # e [J] = 1/2 m(n) [kg] (l [m] / tof [s])^2
    joule_to_mev = sc.to_unit(1.0 * sc.Unit('J'), sc.units.meV).value
    neutron_mass = sc.to_unit(m_n, sc.units.kg).value

    # Spectrum 0 is 11 m from source
    for val, t in zip(energy.coords['energy']['spectrum', 0].values,
                      tof_in_seconds.values):
        np.testing.assert_almost_equal(
            val, joule_to_mev * neutron_mass / 2 * (11 / t)**2, val * 1e-3)
    # Spectrum 1
    L = 10.0 + math.sqrt(1.0 * 1.0 + 0.1 * 0.1)
    for val, t in zip(energy.coords['energy']['spectrum', 1].values,
                      tof_in_seconds.values):
        np.testing.assert_almost_equal(
            val, joule_to_mev * 0.5 * neutron_mass * (L / t)**2, val * 1e-3)