예제 #1
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)
예제 #2
0
def _load_pixel_positions(detector_group: Group, detector_ids_size: int,
                          nexus: LoadFromNexus) -> Optional[sc.Variable]:
    offsets_unit = nexus.get_unit(
        nexus.get_dataset_from_group(detector_group, "x_pixel_offset"))
    if offsets_unit == sc.units.dimensionless:
        warn(f"Skipped loading pixel positions as no units found on "
             f"x_pixel_offset dataset in {nexus.get_name(detector_group)}")
        return None

    try:
        x_positions = nexus.load_dataset_from_group_as_numpy_array(
            detector_group, "x_pixel_offset").flatten()
        y_positions = nexus.load_dataset_from_group_as_numpy_array(
            detector_group, "y_pixel_offset").flatten()
    except MissingDataset:
        return None
    try:
        z_positions = nexus.load_dataset_from_group_as_numpy_array(
            detector_group, "z_pixel_offset").flatten()
    except MissingDataset:
        # According to the NeXus standard z offsets are allowed to be
        # missing, in which case use zeros
        z_positions = np.zeros_like(x_positions)

    list_of_sizes = [
        x_positions.size, y_positions.size, z_positions.size, detector_ids_size
    ]
    if list_of_sizes.count(list_of_sizes[0]) != len(list_of_sizes):
        warn(f"Skipped loading pixel positions as pixel offset and id "
             f"dataset sizes do not match in {nexus.get_name(detector_group)}")
        return None

    x_positions = _convert_array_to_metres(x_positions, offsets_unit)
    y_positions = _convert_array_to_metres(y_positions, offsets_unit)
    z_positions = _convert_array_to_metres(z_positions, offsets_unit)

    array = np.array([x_positions, y_positions, z_positions]).T

    data = sc.vectors(dims=[_detector_dimension],
                      values=array,
                      unit=sc.units.m)

    found_depends_on, _ = nexus.dataset_in_group(detector_group, "depends_on")
    if found_depends_on:
        data = (get_full_transformation_matrix(detector_group, nexus) * data)

    if isinstance(data, sc.DataArray):
        return data["time", 0].data
    else:
        return data
예제 #3
0
def get_detector_pos(ws, spectrum_dim):
    nHist = ws.getNumberHistograms()
    pos = np.zeros([nHist, 3])

    spec_info = ws.spectrumInfo()
    for i in range(nHist):
        if spec_info.hasDetectors(i):
            p = spec_info.position(i)
            pos[i, 0] = p.X()
            pos[i, 1] = p.Y()
            pos[i, 2] = p.Z()
        else:
            pos[i, :] = [np.nan, np.nan, np.nan]
    return sc.vectors(dims=[spectrum_dim], values=pos, unit=sc.units.m)
예제 #4
0
def make_dataset_with_beamline():
    positions = [[1, 0, 0], [0, 1, 0], [0, 0, 1], [-1, 0, 0]]
    d = sc.Dataset(
        data={'a': sc.Variable(dims=['position', 'tof'], values=np.random.rand(4, 9))},
        coords={
            'tof':
            sc.Variable(dims=['tof'],
                        values=np.arange(1000.0, 1010.0),
                        unit=sc.units.us),
            'position':
            sc.vectors(dims=['position'], values=positions, unit=sc.units.m)
        })

    d.coords['source_position'] = sc.vector(value=np.array([0, 0, -10]),
                                            unit=sc.units.m)
    d.coords['sample_position'] = sc.vector(value=np.array([0, 0, 0]), unit=sc.units.m)
    return d
예제 #5
0
def get_detector_properties(ws,
                            source_pos,
                            sample_pos,
                            spectrum_dim,
                            advanced_geometry=False):
    if not advanced_geometry:
        return (get_detector_pos(ws, spectrum_dim), None, None)
    spec_info = ws.spectrumInfo()
    det_info = ws.detectorInfo()
    comp_info = ws.componentInfo()
    nspec = len(spec_info)
    det_rot = np.zeros([nspec, 3, 3])
    det_bbox = np.zeros([nspec, 3])

    if sample_pos is not None and source_pos is not None:
        total_detectors = spec_info.detectorCount()
        act_beam = (sample_pos - source_pos)
        rot = _rot_from_vectors(act_beam, sc.vector(value=[0, 0, 1]))
        inv_rot = _rot_from_vectors(sc.vector(value=[0, 0, 1]), act_beam)

        pos_d = sc.Dataset()
        # Create empty to hold position info for all spectra detectors
        pos_d["x"] = sc.zeros(dims=["detector"],
                              shape=[total_detectors],
                              unit=sc.units.m)
        pos_d["y"] = sc.zeros_like(pos_d["x"])
        pos_d["z"] = sc.zeros_like(pos_d["x"])
        pos_d.coords[spectrum_dim] = sc.array(dims=["detector"],
                                              values=np.empty(total_detectors))

        spectrum_values = pos_d.coords[spectrum_dim].values

        x_values = pos_d["x"].values
        y_values = pos_d["y"].values
        z_values = pos_d["z"].values

        idx = 0
        for i, spec in enumerate(spec_info):
            if spec.hasDetectors:
                definition = spec_info.getSpectrumDefinition(i)
                n_dets = len(definition)
                quats = []
                bboxes = []
                for j in range(n_dets):
                    det_idx = definition[j][0]
                    p = det_info.position(det_idx)
                    r = det_info.rotation(det_idx)
                    spectrum_values[idx] = i
                    x_values[idx] = p.X()
                    y_values[idx] = p.Y()
                    z_values[idx] = p.Z()
                    idx += 1
                    quats.append(
                        np.array([r.imagI(),
                                  r.imagJ(),
                                  r.imagK(),
                                  r.real()]))
                    if comp_info.hasValidShape(det_idx):
                        s = comp_info.shape(det_idx)
                        bboxes.append(s.getBoundingBox().width())
                det_rot[
                    i, :] = sc.geometry.rotation_matrix_from_quaternion_coeffs(
                        np.mean(quats, axis=0))
                det_bbox[i, :] = np.sum(bboxes, axis=0)

        rot_pos = rot * sc.geometry.position(pos_d["x"].data, pos_d["y"].data,
                                             pos_d["z"].data)

        _to_spherical(rot_pos, pos_d)

        averaged = sc.groupby(pos_d,
                              spectrum_dim,
                              bins=sc.Variable(dims=[spectrum_dim],
                                               values=np.arange(
                                                   -0.5,
                                                   len(spec_info) + 0.5,
                                                   1.0))).mean("detector")

        sign = averaged["p-sign"].data / sc.abs(averaged["p-sign"].data)
        averaged["p"] = sign * (
            (np.pi * sc.units.rad) - averaged["p-delta"].data)
        averaged["x"] = averaged["r"].data * sc.sin(
            averaged["t"].data) * sc.cos(averaged["p"].data)
        averaged["y"] = averaged["r"].data * sc.sin(
            averaged["t"].data) * sc.sin(averaged["p"].data)
        averaged["z"] = averaged["r"].data * sc.cos(averaged["t"].data)

        pos = sc.geometry.position(averaged["x"].data, averaged["y"].data,
                                   averaged["z"].data)

        return (inv_rot * pos,
                sc.spatial.linear_transforms(dims=[spectrum_dim],
                                             values=det_rot),
                sc.vectors(dims=[spectrum_dim],
                           values=det_bbox,
                           unit=sc.units.m))
    else:
        pos = np.zeros([nspec, 3])

        for i, spec in enumerate(spec_info):
            if spec.hasDetectors:
                definition = spec_info.getSpectrumDefinition(i)
                n_dets = len(definition)
                vec3s = []
                quats = []
                bboxes = []
                for j in range(n_dets):
                    det_idx = definition[j][0]
                    p = det_info.position(det_idx)
                    r = det_info.rotation(det_idx)
                    vec3s.append([p.X(), p.Y(), p.Z()])
                    quats.append(
                        np.array([r.imagI(),
                                  r.imagJ(),
                                  r.imagK(),
                                  r.real()]))
                    if comp_info.hasValidShape(det_idx):
                        s = comp_info.shape(det_idx)
                        bboxes.append(s.getBoundingBox().width())
                pos[i, :] = np.mean(vec3s, axis=0)
                det_rot[
                    i, :] = sc.geometry.rotation_matrix_from_quaternion_coeffs(
                        np.mean(quats, axis=0))
                det_bbox[i, :] = np.sum(bboxes, axis=0)
            else:
                pos[i, :] = [np.nan, np.nan, np.nan]
                det_rot[i, :] = [np.nan, np.nan, np.nan, np.nan]
                det_bbox[i, :] = [np.nan, np.nan, np.nan]
        return (sc.vectors(dims=[spectrum_dim], values=pos, unit=sc.units.m),
                sc.spatial.linear_transforms(dims=[spectrum_dim],
                                             values=det_rot),
                sc.vectors(
                    dims=[spectrum_dim],
                    values=det_bbox,
                    unit=sc.units.m,
                ))
예제 #6
0
def make_scattered_beam():
    return sc.vectors(dims=['spectrum'],
                      values=[[1.0, 0.0, 0.0], [0.1, 0.0, 1.0]],
                      unit='m')
예제 #7
0
def make_position():
    return sc.vectors(dims=['spectrum'],
                      values=[[1.0, 0.0, 0.0], [0.1, 0.0, 1.0]],
                      unit='m')