def _check_against_reference(ds, frames): reference = _frames_from_slopes(ds) for key in frames: assert sc.allclose(reference[key].data, frames[key].data) for i in range(frames.sizes['frame'] - 1): assert sc.allclose(frames["delta_time_max"]["frame", i].data, frames["delta_time_min"]["frame", i + 1].data)
def test_cutout_angles_from_centers_widths(params): chopper = ch.make_chopper(**params) assert sc.allclose( ch.cutout_angles_begin(chopper), params["cutout_angles_center"] - 0.5 * params["cutout_angles_width"]) assert sc.allclose( ch.cutout_angles_end(chopper), params["cutout_angles_center"] + 0.5 * params["cutout_angles_width"])
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)
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'])
def test_illumination_of_sample_off_angle(): beam_size = 1.0 * sc.units.m sample_size = 10.0 * sc.units.m theta = 30.0 * sc.units.deg expected_result = 2.0 * sc.units.m actual_result = corrections.illumination_of_sample(beam_size, sample_size, theta) assert sc.allclose(actual_result, expected_result)
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)
def test_linlogspace_log(): q_log = tools.linlogspace(dim='qz', edges=[0.008, 0.08], unit='1/angstrom', scale='log', num=50) expected = sc.geomspace(dim='qz', start=0.008, stop=0.08, num=50, unit='1/angstrom') assert sc.allclose(q_log, expected)
def test_linlogspace_linear(): q_lin = tools.linlogspace(dim='qz', edges=[0.008, 0.08], scale='linear', num=50, unit='1/angstrom') expected = sc.linspace(dim='qz', start=0.008, stop=0.08, num=50, unit='1/angstrom') assert sc.allclose(q_lin, expected)
def test_beamline_compute_l1(in_ws, in_da): out_mantid = in_ws.detectorInfo().l1() * sc.Unit('m') in_da = scn.mantid.from_mantid(in_ws) out_scipp = scn.L1(in_da) assert sc.allclose(out_scipp, out_mantid, rtol=1e-15 * sc.units.one, atol=1e-15 * out_scipp.unit)
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)
def test_linlogspace_log_linear(): q_loglin = tools.linlogspace(dim='qz', edges=[0.008, 0.03, 0.08], unit='1/angstrom', scale=['log', 'linear'], num=[16, 20]) exp_log = sc.geomspace(dim='qz', start=0.008, stop=0.03, num=16, unit='1/angstrom') exp_lin = sc.linspace(dim='qz', start=0.03, stop=0.08, num=21, unit='1/angstrom') expected = sc.concat([exp_log, exp_lin['qz', 1:]], 'qz') assert sc.allclose(q_loglin, expected)
def test_cutout_angles_from_begin_end(params): dim = 'frame' del params['cutout_angles_center'] del params['cutout_angles_width'] params["cutout_angles_begin"] = sc.linspace(dim=dim, start=0.0, stop=1.5 * np.pi, num=6, unit='rad') params["cutout_angles_end"] = sc.linspace(dim=dim, start=0.1, stop=2.0 * np.pi, num=6, unit='rad') chopper = ch.make_chopper(**params) assert sc.allclose( ch.cutout_angles_width(chopper), params["cutout_angles_end"] - params["cutout_angles_begin"]) assert sc.allclose( ch.cutout_angles_center(chopper), 0.5 * (params["cutout_angles_begin"] + params["cutout_angles_end"]))
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)
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)
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'))
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)
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'])
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)
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)
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'])
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))
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)