Пример #1
0
    def detector_borders(self, det):
        panel = self.detectors[det]

        row_vec, col_vec = panel.row_pixel_vec, panel.col_pixel_vec
        x_start, x_stop = col_vec[0], col_vec[-1]
        y_start, y_stop = row_vec[0], row_vec[-1]

        # Create the borders in Cartesian
        borders = [[[x, y_start] for x in col_vec],
                   [[x, y_stop] for x in col_vec],
                   [[x_start, y] for y in row_vec],
                   [[x_stop, y] for y in row_vec]]

        # Convert each border to angles
        for i, border in enumerate(borders):
            angles, _ = detectorXYToGvec(border,
                                         panel.rmat,
                                         ct.identity_3x3,
                                         panel.tvec,
                                         ct.zeros_3,
                                         ct.zeros_3,
                                         beamVec=panel.bvec,
                                         etaVec=panel.evec)
            # Convert to degrees, and keep them as lists for
            # easier modification later
            borders[i] = np.degrees(angles).tolist()

        # Here, we are going to remove points that are out-of-bounds,
        # and we are going to insert None in between points that are far
        # apart (in the y component), so that they are not connected in the
        # plot. This happens for detectors that are wrapped in the image.
        x_range = np.degrees((self.tth_min, self.tth_max))
        y_range = np.degrees((self.eta_min, self.eta_max))

        # "Far apart" is currently defined as half of the y range
        max_y_distance = abs(y_range[1] - y_range[0]) / 2.0
        for j in range(4):
            border_x, border_y = borders[j][0], borders[j][1]
            i = 0
            # These should be the same length, but just in case...
            while i < len(border_x) and i < len(border_y):
                x, y = border_x[i], border_y[i]
                if (not x_range[0] <= x <= x_range[1]
                        or not y_range[0] <= y <= y_range[1]):
                    # The point is out of bounds, remove it
                    del border_x[i], border_y[i]
                    continue

                if i != 0 and abs(y - border_y[i - 1]) > max_y_distance:
                    # Points are too far apart. Insert a None
                    border_x.insert(i, None)
                    border_y.insert(i, None)
                    i += 1

                i += 1

        return borders
Пример #2
0
    def angularPixelSize(xy_det,
                         xy_pixelPitch,
                         rMat_d,
                         rMat_s,
                         tVec_d,
                         tVec_s,
                         tVec_c,
                         distortion=None,
                         beamVec=None,
                         etaVec=None):
        """
        Calculate angular pixel sizes on a detector.

        * choices to beam vector and eta vector specs have been supressed
        * assumes xy_det in UNWARPED configuration
        """
        xy_det = np.atleast_2d(xy_det)
        if distortion is not None:  # !!! check this logic
            xy_det = distortion.apply(xy_det)
        if beamVec is None:
            beamVec = xfcapi.bVec_ref
        if etaVec is None:
            etaVec = xfcapi.eta_ref

        xp = np.r_[-0.5, 0.5, 0.5, -0.5] * xy_pixelPitch[0]
        yp = np.r_[-0.5, -0.5, 0.5, 0.5] * xy_pixelPitch[1]

        diffs = np.array([[3, 3, 2, 1], [2, 0, 1, 0]])

        ang_pix = np.zeros((len(xy_det), 2))

        for ipt, xy in enumerate(xy_det):
            xc = xp + xy[0]
            yc = yp + xy[1]

            tth_eta, gHat_l = xfcapi.detectorXYToGvec(np.vstack([xc, yc]).T,
                                                      rMat_d,
                                                      rMat_s,
                                                      tVec_d,
                                                      tVec_s,
                                                      tVec_c,
                                                      beamVec=beamVec,
                                                      etaVec=etaVec)
            delta_tth = np.zeros(4)
            delta_eta = np.zeros(4)
            for j in range(4):
                delta_tth[j] = abs(tth_eta[0][diffs[0, j]] -
                                   tth_eta[0][diffs[1, j]])
                delta_eta[j] = xf.angularDifference(tth_eta[1][diffs[0, j]],
                                                    tth_eta[1][diffs[1, j]])

            ang_pix[ipt, 0] = np.amax(delta_tth)
            ang_pix[ipt, 1] = np.amax(delta_eta)
        return ang_pix
Пример #3
0
    def angularPixelSize(xy_det,
                         xy_pixelPitch,
                         rMat_d,
                         rMat_s,
                         tVec_d,
                         tVec_s,
                         tVec_c,
                         distortion=None,
                         beamVec=None,
                         etaVec=None):
        """
        Calculate angular pixel sizes on a detector.

        * choices to beam vector and eta vector specs have been supressed
        * assumes xy_det in UNWARPED configuration
        """
        xy_det = np.atleast_2d(xy_det)
        if distortion is not None:  # !!! check this logic
            xy_det = distortion.apply(xy_det)
        if beamVec is None:
            beamVec = xfcapi.bVec_ref
        if etaVec is None:
            etaVec = xfcapi.eta_ref

        xy_expanded = np.empty((len(xy_det) * 4, 2), dtype=xy_det.dtype)
        xy_expanded = _expand_pixels(xy_det, xy_pixelPitch[0],
                                     xy_pixelPitch[1], xy_expanded)
        gvec_space, _ = xfcapi.detectorXYToGvec(xy_expanded,
                                                rMat_d,
                                                rMat_s,
                                                tVec_d,
                                                tVec_s,
                                                tVec_c,
                                                beamVec=beamVec,
                                                etaVec=etaVec)
        result = np.empty_like(xy_det)
        return _compute_max(gvec_space[0], gvec_space[1], result)
Пример #4
0
    def overlay(self, display_mode=ViewType.raw):
        sim_data = self.instrument.simulate_laue_pattern(
            self.plane_data,
            minEnergy=self.min_energy,
            maxEnergy=self.max_energy,
            rmat_s=self.sample_rmat,
            grain_params=[
                self.crystal_params,
            ])

        point_groups = {}
        keys = ['spots', 'ranges', 'hkls']
        for det_key, psim in sim_data.items():
            point_groups[det_key] = {key: [] for key in keys}

            # grab panel and split out simulation results
            # !!! note that the sim results are lists over number of grains
            #     and here we explicitly have one.
            panel = self.instrument.detectors[det_key]
            xy_det, hkls_in, angles, dspacing, energy = psim

            # find valid points
            idx = ~np.isnan(energy[0])  # there is only one grain here

            # filter (tth, eta) results
            xy_data = xy_det[0][idx, :]
            angles = angles[0][idx, :]  # these are in radians
            point_groups[det_key]['hkls'] = hkls_in[0][:, idx].T
            angles[:, 1] = xfcapi.mapAngle(angles[:, 1],
                                           np.radians(self.eta_period),
                                           units='radians')

            # !!! apply offset corrections to angles
            # convert to angles in LAB ref
            angles_corr, _ = xfcapi.detectorXYToGvec(
                xy_data,
                panel.rmat,
                self.sample_rmat,
                panel.tvec,
                self.instrument.tvec,
                constants.zeros_3,
                beamVec=self.instrument.beam_vector,
                etaVec=self.instrument.eta_vector)
            # FIXME modify output to be array
            angles_corr = np.vstack(angles_corr).T
            angles_corr[:, 1] = xfcapi.mapAngle(angles_corr[:, 1],
                                                np.radians(self.eta_period),
                                                units='radians')

            if display_mode == ViewType.polar:
                range_corners = self.range_corners(angles_corr)
                # Save the Laue spots as a list instead of a numpy array,
                # so that we can predictably get the id() of spots inside.
                # Numpy arrays do fancy optimizations that break this.
                spots = np.degrees(angles_corr).tolist()
                point_groups[det_key]['spots'] = spots
                point_groups[det_key]['ranges'] = np.degrees(range_corners)
            elif display_mode in [ViewType.raw, ViewType.cartesian]:
                # !!! verify this
                range_corners = self.range_corners(angles)
                panel = self.instrument.detectors[det_key]
                data = xy_data
                if display_mode == ViewType.raw:
                    # Convert to pixel coordinates
                    data = panel.cartToPixel(data)
                    # Swap x and y, they are flipped
                    data[:, [0, 1]] = data[:, [1, 0]]

                point_groups[det_key]['spots'] = data
                point_groups[det_key]['ranges'] = self.range_data(
                    range_corners, display_mode, panel)

        return point_groups
Пример #5
0
def simulateLauePattern(hkls,
                        bMat,
                        rmat_d,
                        tvec_d,
                        panel_dims,
                        panel_buffer=5,
                        minEnergy=8,
                        maxEnergy=24,
                        rmat_s=np.eye(3),
                        grain_params=None,
                        distortion=None,
                        beamVec=None):

    if beamVec is None:
        beamVec = xfcapi.bVec_ref

    # parse energy ranges
    multipleEnergyRanges = False
    if hasattr(maxEnergy, '__len__'):
        assert len(maxEnergy) == len(minEnergy), \
            'energy cutoff ranges must have the same length'
        multipleEnergyRanges = True
        lmin = []
        lmax = []
        for i in range(len(maxEnergy)):
            lmin.append(processWavelength(maxEnergy[i]))
            lmax.append(processWavelength(minEnergy[i]))
    else:
        lmin = processWavelength(maxEnergy)
        lmax = processWavelength(minEnergy)

    # process crystal rmats and inverse stretches
    if grain_params is None:
        grain_params = np.atleast_2d(
            [0., 0., 0., 0., 0., 0., 1., 1., 1., 0., 0., 0.])

    n_grains = len(grain_params)

    # dummy translation vector... make input
    tvec_s = np.zeros((3, 1))

    # number of hkls
    nhkls_tot = hkls.shape[1]

    # unit G-vectors in crystal frame
    ghat_c = mutil.unitVector(np.dot(bMat, hkls))

    # pre-allocate output arrays
    xy_det = np.nan * np.ones((n_grains, nhkls_tot, 2))
    hkls_in = np.nan * np.ones((n_grains, 3, nhkls_tot))
    angles = np.nan * np.ones((n_grains, nhkls_tot, 2))
    dspacing = np.nan * np.ones((n_grains, nhkls_tot))
    energy = np.nan * np.ones((n_grains, nhkls_tot))
    """
    LOOP OVER GRAINS
    """

    for iG, gp in enumerate(grain_params):
        rmat_c = xfcapi.makeRotMatOfExpMap(gp[:3])
        tvec_c = gp[3:6].reshape(3, 1)
        vInv_s = mutil.vecMVToSymm(gp[6:].reshape(6, 1))

        # stretch them: V^(-1) * R * Gc
        ghat_s_str = mutil.unitVector(np.dot(vInv_s, np.dot(rmat_c, ghat_c)))
        ghat_c_str = np.dot(rmat_c.T, ghat_s_str)

        # project
        dpts = xfcapi.gvecToDetectorXY(ghat_c_str.T,
                                       rmat_d,
                                       rmat_s,
                                       rmat_c,
                                       tvec_d,
                                       tvec_s,
                                       tvec_c,
                                       beamVec=beamVec).T

        # check intersections with detector plane
        canIntersect = ~np.isnan(dpts[0, :])
        npts_in = sum(canIntersect)

        if np.any(canIntersect):
            dpts = dpts[:, canIntersect].reshape(2, npts_in)
            dhkl = hkls[:, canIntersect].reshape(3, npts_in)

            # back to angles
            tth_eta, gvec_l = xfcapi.detectorXYToGvec(dpts.T,
                                                      rmat_d,
                                                      rmat_s,
                                                      tvec_d,
                                                      tvec_s,
                                                      tvec_c,
                                                      beamVec=beamVec)
            tth_eta = np.vstack(tth_eta).T

            # warp measured points
            if distortion is not None:
                dpts = distortion.apply_inverse(dpts)

            # plane spacings and energies
            dsp = 1. / mutil.columnNorm(np.dot(bMat, dhkl))
            wlen = 2 * dsp * np.sin(0.5 * tth_eta[:, 0])

            # find on spatial extent of detector
            xTest = np.logical_and(
                dpts[0, :] >= -0.5 * panel_dims[1] + panel_buffer,
                dpts[0, :] <= 0.5 * panel_dims[1] - panel_buffer)
            yTest = np.logical_and(
                dpts[1, :] >= -0.5 * panel_dims[0] + panel_buffer,
                dpts[1, :] <= 0.5 * panel_dims[0] - panel_buffer)

            onDetector = np.logical_and(xTest, yTest)
            if multipleEnergyRanges:
                validEnergy = np.zeros(len(wlen), dtype=bool)
                for i in range(len(lmin)):
                    validEnergy = validEnergy | \
                        np.logical_and(wlen >= lmin[i], wlen <= lmax[i])
                    pass
            else:
                validEnergy = np.logical_and(wlen >= lmin, wlen <= lmax)
                pass

            # index for valid reflections
            keepers = np.where(np.logical_and(onDetector, validEnergy))[0]

            # assign output arrays
            xy_det[iG][keepers, :] = dpts[:, keepers].T
            hkls_in[iG][:, keepers] = dhkl[:, keepers]
            angles[iG][keepers, :] = tth_eta[keepers, :]
            dspacing[iG, keepers] = dsp[keepers]
            energy[iG, keepers] = processWavelength(wlen[keepers])
            pass
        pass
    return xy_det, hkls_in, angles, dspacing, energy
Пример #6
0
def _convert_angles(tth_eta,
                    detector,
                    rmat_s,
                    tvec_s,
                    tvec_c,
                    beam_vector=constants.beam_vec,
                    eta_vector=constants.eta_vec):
    """
    Coverts frame-local angles to effective angles in the LAB reference frame.

    Operates on a detector instance in lieu of instrument.

    Parameters
    ----------
    tth_eta : TYPE
        DESCRIPTION.
    detector : TYPE
        DESCRIPTION.
    rmat_s : TYPE
        DESCRIPTION.
    tvec_c : TYPE
        DESCRIPTION.
    beam_vector : TYPE, optional
        DESCRIPTION. The default is constants.beam_vec.
    eta_vector : TYPE, optional
        DESCRIPTION. The default is constants.eta_vec.

    Returns
    -------
    tth_eta_ref : TYPE
        DESCRIPTION.

    Notes
    -----
    FIXME: This API won't work for rotation series data
    """

    tth_eta = np.atleast_2d(tth_eta)

    chi = np.arctan2(rmat_s[2, 1], rmat_s[1, 1])
    ome = np.arctan2(rmat_s[0, 2], rmat_s[0, 0])

    # !!! reform rmat_s to be consistent with def in geometric model
    rmat_s = xfcapi.makeOscillRotMat(np.r_[chi, ome])
    rmat_c = constants.identity_3x3
    # tvec_s = constants.zeros_3
    tvec_c_ref = constants.zeros_3

    # FIXME: doesn't work for rotation series with different ome yet.
    full_angs = np.hstack([tth_eta, ome * np.ones((len(tth_eta), 1))])

    # convert to gvectors using trivial crystal frame
    gvec_s = xfcapi.anglesToGVec(full_angs,
                                 bHat_l=beam_vector,
                                 eHat_l=eta_vector,
                                 chi=chi)

    # convert to detector points
    det_xys = xfcapi.gvecToDetectorXY(gvec_s,
                                      detector.rmat,
                                      rmat_s,
                                      rmat_c,
                                      detector.tvec,
                                      tvec_s,
                                      tvec_c,
                                      beamVec=beam_vector)

    # convert to angles in LAB ref
    tth_eta_ref, _ = xfcapi.detectorXYToGvec(det_xys,
                                             detector.rmat,
                                             rmat_s,
                                             detector.tvec,
                                             tvec_s,
                                             tvec_c_ref,
                                             beamVec=beam_vector,
                                             etaVec=eta_vector)

    return np.vstack(tth_eta_ref).T