Ejemplo n.º 1
0
def objFuncSX(pFit, pFull, pFlag, dFunc, dFlag,
              xyo_det, hkls_idx, bMat, vInv, wavelength,
              bVec, eVec, omePeriod,
              simOnly=False, returnScalarValue=returnScalarValue):
    """
    """
    npts   = len(xyo_det)

    refineFlag = np.hstack([pFlag, dFlag])

    # pFull[refineFlag] = pFit/scl[refineFlag]
    pFull[refineFlag] = pFit

    dParams = pFull[-len(dFlag):]
    xy_unwarped = dFunc(xyo_det[:, :2], dParams)

    # detector quantities
    rMat_d = xf.makeDetectorRotMat(pFull[:3])
    tVec_d = pFull[3:6].reshape(3, 1)

    # sample quantities
    chi    = pFull[6]
    tVec_s = pFull[7:10].reshape(3, 1)

    # crystal quantities
    rMat_c = xf.makeRotMatOfExpMap(pFull[10:13])
    tVec_c = pFull[13:16].reshape(3, 1)

    gVec_c = np.dot(bMat, hkls_idx)
    vMat_s = mutil.vecMVToSymm(vInv)                # stretch tensor comp matrix from MV notation in SAMPLE frame
    gVec_s = np.dot(vMat_s, np.dot(rMat_c, gVec_c)) # reciprocal lattice vectors in SAMPLE frame
    gHat_s = mutil.unitVector(gVec_s)               # unit reciprocal lattice vectors in SAMPLE frame
    gHat_c = np.dot(rMat_c.T, gHat_s)               # unit reciprocal lattice vectors in CRYSTAL frame

    match_omes, calc_omes = matchOmegas(xyo_det, hkls_idx, chi, rMat_c, bMat, wavelength,
                                        vInv=vInv, beamVec=bVec, etaVec=eVec, omePeriod=omePeriod)

    calc_xy = np.zeros((npts, 2))
    for i in range(npts):
        rMat_s = xfcapi.makeOscillRotMat([chi, calc_omes[i]])
        calc_xy[i, :] = xfcapi.gvecToDetectorXY(gHat_c[:, i],
                                                rMat_d, rMat_s, rMat_c,
                                                tVec_d, tVec_s, tVec_c,
                                                beamVec=bVec).flatten()
        pass
    if np.any(np.isnan(calc_xy)):
        print "infeasible pFull: may want to scale back finite difference step size"

    # return values
    if simOnly:
        retval = np.hstack([calc_xy, calc_omes.reshape(npts, 1)])
    else:
        diff_vecs_xy = calc_xy - xy_unwarped[:, :2]
        diff_ome     = xf.angularDifference( calc_omes, xyo_det[:, 2] )
        retval = np.hstack([diff_vecs_xy,
                            diff_ome.reshape(npts, 1)
                            ]).flatten()
        if returnScalarValue:
            retval = sum( retval )
    return retval
Ejemplo n.º 2
0
def matchOmegas(xyo_det, hkls_idx, chi, rMat_c, bMat, wavelength,
                vInv=vInv_ref, beamVec=bVec_ref, etaVec=eta_ref,
                omePeriod=None):
    """
    For a given list of (x, y, ome) points, outputs the index into the results from
    oscillAnglesOfHKLs, including the calculated omega values.
    """
    # get omegas for rMat_s calculation
    if omePeriod is not None:
        meas_omes = xf.mapAngle(xyo_det[:, 2], omePeriod)
    else:
        meas_omes = xyo_det[:, 2]

    oangs0, oangs1 = xfcapi.oscillAnglesOfHKLs(hkls_idx.T, chi, rMat_c, bMat, wavelength,
                                               vInv=vInv,
                                               beamVec=beamVec,
                                               etaVec=etaVec)
    if np.any(np.isnan(oangs0)):
        nanIdx = np.where(np.isnan(oangs0[:, 0]))[0]
        errorString = "Infeasible parameters for hkls:\n"
        for i in range(len(nanIdx)):
            errorString += "%d  %d  %d\n" % tuple(hkls_idx[:, nanIdx[i]])
        raise RuntimeError, errorString
    else:
        # CAPI version gives vstacked angles... must be (2, nhkls)
        calc_omes = np.vstack([oangs0[:, 2], oangs1[:, 2]])
    if omePeriod is not None:
        calc_omes  = np.vstack([xf.mapAngle(oangs0[:, 2], omePeriod),
                                xf.mapAngle(oangs1[:, 2], omePeriod)])
    # do angular difference
    diff_omes  = xf.angularDifference(np.tile(meas_omes, (2, 1)), calc_omes)
    match_omes = np.argsort(diff_omes, axis=0) == 0
    calc_omes  = calc_omes.T.flatten()[match_omes.T.flatten()]

    return match_omes, calc_omes
Ejemplo n.º 3
0
def objFuncSX(pFit, pFull, pFlag, dFunc, dFlag,
              xyo_det, hkls_idx, bMat, vInv, wavelength,
              bVec, eVec, omePeriod,
              simOnly=False, returnScalarValue=returnScalarValue):
    """
    """
    npts   = len(xyo_det)

    refineFlag = np.hstack([pFlag, dFlag])

    # pFull[refineFlag] = pFit/scl[refineFlag]
    pFull[refineFlag] = pFit

    dParams = pFull[-len(dFlag):]
    xy_unwarped = dFunc(xyo_det[:, :2], dParams)

    # detector quantities
    rMat_d = xf.makeDetectorRotMat(pFull[:3])
    tVec_d = pFull[3:6].reshape(3, 1)

    # sample quantities
    chi    = pFull[6]
    tVec_s = pFull[7:10].reshape(3, 1)

    # crystal quantities
    rMat_c = xf.makeRotMatOfExpMap(pFull[10:13])
    tVec_c = pFull[13:16].reshape(3, 1)

    gVec_c = np.dot(bMat, hkls_idx)
    vMat_s = mutil.vecMVToSymm(vInv)                # stretch tensor comp matrix from MV notation in SAMPLE frame
    gVec_s = np.dot(vMat_s, np.dot(rMat_c, gVec_c)) # reciprocal lattice vectors in SAMPLE frame
    gHat_s = mutil.unitVector(gVec_s)               # unit reciprocal lattice vectors in SAMPLE frame
    gHat_c = np.dot(rMat_c.T, gHat_s)               # unit reciprocal lattice vectors in CRYSTAL frame

    match_omes, calc_omes = matchOmegas(xyo_det, hkls_idx, chi, rMat_c, bMat, wavelength,
                                        vInv=vInv, beamVec=bVec, etaVec=eVec, omePeriod=omePeriod)

    calc_xy = np.zeros((npts, 2))
    for i in range(npts):
        rMat_s = xfcapi.makeOscillRotMat([chi, calc_omes[i]])
        calc_xy[i, :] = xfcapi.gvecToDetectorXY(gHat_c[:, i],
                                                rMat_d, rMat_s, rMat_c,
                                                tVec_d, tVec_s, tVec_c,
                                                beamVec=bVec).flatten()
        pass
    if np.any(np.isnan(calc_xy)):
        print "infeasible pFull: may want to scale back finite difference step size"

    # return values
    if simOnly:
        retval = np.hstack([calc_xy, calc_omes.reshape(npts, 1)])
    else:
        diff_vecs_xy = calc_xy - xy_unwarped[:, :2]
        diff_ome     = xf.angularDifference( calc_omes, xyo_det[:, 2] )
        retval = np.hstack([diff_vecs_xy,
                            diff_ome.reshape(npts, 1)
                            ]).flatten()
        if returnScalarValue:
            retval = sum( retval )
    return retval
Ejemplo n.º 4
0
def matchOmegas(xyo_det, hkls_idx, chi, rMat_c, bMat, wavelength,
                vInv=vInv_ref, beamVec=bVec_ref, etaVec=eta_ref,
                omePeriod=None):
    """
    For a given list of (x, y, ome) points, outputs the index into the results from
    oscillAnglesOfHKLs, including the calculated omega values.
    """
    # get omegas for rMat_s calculation
    if omePeriod is not None:
        meas_omes = xf.mapAngle(xyo_det[:, 2], omePeriod)
    else:
        meas_omes = xyo_det[:, 2]

    oangs0, oangs1 = xfcapi.oscillAnglesOfHKLs(hkls_idx.T, chi, rMat_c, bMat, wavelength,
                                               vInv=vInv,
                                               beamVec=beamVec,
                                               etaVec=etaVec)
    if np.any(np.isnan(oangs0)):
        nanIdx = np.where(np.isnan(oangs0[:, 0]))[0]
        errorString = "Infeasible parameters for hkls:\n"
        for i in range(len(nanIdx)):
            errorString += "%d  %d  %d\n" % tuple(hkls_idx[:, nanIdx[i]])
        raise RuntimeError, errorString
    else:
        # CAPI version gives vstacked angles... must be (2, nhkls)
        calc_omes = np.vstack([oangs0[:, 2], oangs1[:, 2]])
    if omePeriod is not None:
        calc_omes  = np.vstack([xf.mapAngle(oangs0[:, 2], omePeriod),
                                xf.mapAngle(oangs1[:, 2], omePeriod)])
    # do angular difference
    diff_omes  = xf.angularDifference(np.tile(meas_omes, (2, 1)), calc_omes)
    match_omes = np.argsort(diff_omes, axis=0) == 0
    calc_omes  = calc_omes.T.flatten()[match_omes.T.flatten()]

    return match_omes, calc_omes
Ejemplo n.º 5
0
    def fit_grains(self, grain_id, grain_params):
        """
        Executes lsq fits of grains based on spot files
        
        REFLECTION TABLE
        
        Cols as follows:
            0-6:   ID    PID    H    K    L    sum(int)    max(int)    
            6-9:   pred tth    pred eta    pred ome              
            9-12:  meas tth    meas eta    meas ome              
            12-15: meas X      meas Y      meas ome
        """
        ome_start = self._p['omega_start']
        ome_step = self._p['omega_step']
        ome_stop =  self._p['omega_stop']
        refl_table = np.loadtxt(self._p['spots_stem'] % grain_id)
        valid_refl_ids = refl_table[:, 0] >= 0
        unsat_spots = refl_table[:, 6] < self._p['saturation_level']
        pred_ome = refl_table[:, 9]
        if angularDifference(ome_start, ome_stop, units='degrees') > 0:
            # if here, incomplete have omega range and
            # clip the refelctions very close to the edges to avoid
            # problems with the least squares...
            if np.sign(ome_step) < 0:
                idx_ome = np.logical_and(
                    pred_ome < np.radians(ome_start + 2*ome_step),
                    pred_ome > np.radians(ome_stop - 2*ome_step)
                    )
            else:
                idx_ome = np.logical_and(
                    pred_ome > np.radians(ome_start + 2*ome_step),
                    pred_ome < np.radians(ome_stop - 2*ome_step)
                    )
            idx = np.logical_and(
                valid_refl_ids,
                np.logical_and(unsat_spots, idx_ome)
                )
        else:
            idx = np.logical_and(valid_refl_ids, unsat_spots)

        hkls = refl_table[idx, 2:5].T # must be column vectors
        self._p['hkls'] = hkls
        xyo_det = refl_table[idx, -3:] # these are the cartesian centroids + ome
        xyo_det[:, 2] = mapAngle(xyo_det[:, 2], self._p['omega_period'])
        self._p['xyo_det'] = xyo_det
        if sum(idx) <= 12:
            return grain_params, 0
        grain_params = fitGrain(
            xyo_det, hkls, self._p['bMat'], self._p['wlen'],
            self._p['detector_params'],
            grain_params[:3], grain_params[3:6], grain_params[6:],
            beamVec=bVec_ref, etaVec=eta_ref,
            distortion=self._p['distortion'],
            gFlag=gFlag, gScl=gScl,
            omePeriod=self._p['omega_period']
            )
        completeness = sum(valid_refl_ids)/float(len(valid_refl_ids))
        return grain_params, completeness
Ejemplo n.º 6
0
    def fit_grains(self, grain_id, grain_params, refit_tol=None):
        """
        Executes lsq fits of grains based on spot files
        
        REFLECTION TABLE
        
        Cols as follows:
            0-6:   ID    PID    H    K    L    sum(int)    max(int)    
            6-9:   pred tth    pred eta    pred ome              
            9-12:  meas tth    meas eta    meas ome              
            12-15: meas X      meas Y      meas ome
        """
        ome_start = self._p['omega_start']
        ome_step = self._p['omega_step']
        ome_stop =  self._p['omega_stop']
        refl_table = np.loadtxt(self._p['spots_stem'] % grain_id)
        valid_refl_ids = refl_table[:, 0] >= 0
        unsat_spots = refl_table[:, 6] < self._p['saturation_level']
        pred_ome = refl_table[:, 9]
        if angularDifference(ome_start, ome_stop, units='degrees') > 0:
            # if here, incomplete have omega range and
            # clip the refelctions very close to the edges to avoid
            # problems with the least squares...
            if np.sign(ome_step) < 0:
                idx_ome = np.logical_and(
                    pred_ome < np.radians(ome_start + 2*ome_step),
                    pred_ome > np.radians(ome_stop - 2*ome_step)
                    )
            else:
                idx_ome = np.logical_and(
                    pred_ome > np.radians(ome_start + 2*ome_step),
                    pred_ome < np.radians(ome_stop - 2*ome_step)
                    )
            idx = np.logical_and(
                valid_refl_ids,
                np.logical_and(unsat_spots, idx_ome)
                )
        else:
            idx = np.logical_and(valid_refl_ids, unsat_spots)
            pass # end if edge case

        # if an overlap table has been written, load it and use it
        overlaps = np.zeros(len(refl_table), dtype=bool)
        try:
            ot = np.load(self._p['overlap_table'])
            for key in ot.keys():
                for this_table in ot[key]:
                    these_overlaps = np.where(
                        this_table[:, 0] == grain_id)[0]
                    if len(these_overlaps) > 0:
                        mark_these = np.array(this_table[these_overlaps, 1], dtype=int)
                        overlaps[mark_these] = True
            idx = np.logical_and(idx, ~overlaps)
        except IOError, IndexError:
            #print "no overlap table found"
            pass
Ejemplo n.º 7
0
    def fit_grains(self, grain_id, grain_params, refit_tol=None):
        """
        Executes lsq fits of grains based on spot files
        
        REFLECTION TABLE
        
        Cols as follows:
            0-6:   ID    PID    H    K    L    sum(int)    max(int)    
            6-9:   pred tth    pred eta    pred ome              
            9-12:  meas tth    meas eta    meas ome              
            12-15: meas X      meas Y      meas ome
        """
        ome_start = self._p['omega_start']
        ome_step = self._p['omega_step']
        ome_stop = self._p['omega_stop']
        refl_table = np.loadtxt(self._p['spots_stem'] % grain_id)
        valid_refl_ids = refl_table[:, 0] >= 0
        unsat_spots = refl_table[:, 6] < self._p['saturation_level']
        pred_ome = refl_table[:, 9]
        if angularDifference(ome_start, ome_stop, units='degrees') > 0:
            # if here, incomplete have omega range and
            # clip the refelctions very close to the edges to avoid
            # problems with the least squares...
            if np.sign(ome_step) < 0:
                idx_ome = np.logical_and(
                    pred_ome < np.radians(ome_start + 2 * ome_step),
                    pred_ome > np.radians(ome_stop - 2 * ome_step))
            else:
                idx_ome = np.logical_and(
                    pred_ome > np.radians(ome_start + 2 * ome_step),
                    pred_ome < np.radians(ome_stop - 2 * ome_step))
            idx = np.logical_and(valid_refl_ids,
                                 np.logical_and(unsat_spots, idx_ome))
        else:
            idx = np.logical_and(valid_refl_ids, unsat_spots)
            pass  # end if edge case

        # if an overlap table has been written, load it and use it
        overlaps = np.zeros(len(refl_table), dtype=bool)
        try:
            ot = np.load(self._p['overlap_table'])
            for key in ot.keys():
                for this_table in ot[key]:
                    these_overlaps = np.where(this_table[:, 0] == grain_id)[0]
                    if len(these_overlaps) > 0:
                        mark_these = np.array(this_table[these_overlaps, 1],
                                              dtype=int)
                        overlaps[mark_these] = True
            idx = np.logical_and(idx, ~overlaps)
        except IOError, IndexError:
            #print "no overlap table found"
            pass
Ejemplo n.º 8
0
    def fit_grains(self, grain_id, grain_params):
        ome_start = self._p['omega_start']
        ome_step = self._p['omega_step']
        ome_stop = self._p['omega_stop']
        refl_table = np.loadtxt(self._p['spots_stem'] % grain_id)
        valid_refl_ids = refl_table[:, 0] >= 0
        unsat_spots = refl_table[:, 5] < self._p['saturation_level']
        pred_ome = refl_table[:, 8]
        if angularDifference(ome_start, ome_stop, units='degrees') > 0:
            # if here, incomplete have omega range and
            # clip the refelctions very close to the edges to avoid
            # problems with the least squares...
            if np.sign(ome_step) < 0:
                idx_ome = np.logical_and(
                    pred_ome < np.radians(ome_start + 2 * ome_step),
                    pred_ome > np.radians(ome_stop - 2 * ome_step))
            else:
                idx_ome = np.logical_and(
                    pred_ome > np.radians(ome_start + 2 * ome_step),
                    pred_ome < np.radians(ome_stop - 2 * ome_step))
            idx = np.logical_and(unsat_spots,
                                 np.logical_and(valid_refl_ids, idx_ome))
        else:
            idx = np.logical_and(valid_refl_ids, unsat_spots)

        hkls = refl_table[idx, 1:4].T  # must be column vectors
        self._p['hkls'] = hkls
        xyo_det = refl_table[idx,
                             -3:]  # these are the cartesian centroids + ome
        xyo_det[:, 2] = mapAngle(xyo_det[:, 2], self._p['omega_period'])
        self._p['xyo_det'] = xyo_det
        if sum(idx) <= 12:
            return grain_params, 0
        grain_params = fitGrain(xyo_det,
                                hkls,
                                self._p['bMat'],
                                self._p['wlen'],
                                self._p['detector_params'],
                                grain_params[:3],
                                grain_params[3:6],
                                grain_params[6:],
                                beamVec=bVec_ref,
                                etaVec=eta_ref,
                                distortion=self._p['distortion'],
                                gFlag=gFlag,
                                gScl=gScl,
                                omePeriod=self._p['omega_period'])
        completeness = sum(idx) / float(len(idx))
        return grain_params, completeness
Ejemplo n.º 9
0
    def fit_grains(self, grain_id, grain_params):
        ome_start = self._p['omega_start']
        ome_step = self._p['omega_step']
        ome_stop =  self._p['omega_stop']
        refl_table = np.loadtxt(self._p['spots_stem'] % grain_id)
        valid_refl_ids = refl_table[:, 0] >= 0
        unsat_spots = refl_table[:, 5] < self._p['saturation_level']
        pred_ome = refl_table[:, 8]
        if angularDifference(ome_start, ome_stop, units='degrees') > 0:
            # if here, incomplete have omega range and
            # clip the refelctions very close to the edges to avoid
            # problems with the least squares...
            if np.sign(ome_step) < 0:
                idx_ome = np.logical_and(
                    pred_ome < np.radians(ome_start + 2*ome_step),
                    pred_ome > np.radians(ome_stop - 2*ome_step)
                    )
            else:
                idx_ome = np.logical_and(
                    pred_ome > np.radians(ome_start + 2*ome_step),
                    pred_ome < np.radians(ome_stop - 2*ome_step)
                    )
            idx = np.logical_and(
                unsat_spots,
                np.logical_and(valid_refl_ids, idx_ome)
                )
        else:
            idx = np.logical_and(valid_refl_ids, unsat_spots)

        hkls = refl_table[idx, 1:4].T # must be column vectors
        self._p['hkls'] = hkls
        xyo_det = refl_table[idx, -3:] # these are the cartesian centroids + ome
        xyo_det[:, 2] = mapAngle(xyo_det[:, 2], self._p['omega_period'])
        self._p['xyo_det'] = xyo_det
        if sum(idx) <= 12:
            return grain_params, 0
        grain_params = fitGrain(
            xyo_det, hkls, self._p['bMat'], self._p['wlen'],
            self._p['detector_params'],
            grain_params[:3], grain_params[3:6], grain_params[6:],
            beamVec=bVec_ref, etaVec=eta_ref,
            distortion=self._p['distortion'],
            gFlag=gFlag, gScl=gScl,
            omePeriod=self._p['omega_period']
            )
        completeness = sum(idx)/float(len(idx))
        return grain_params, completeness
Ejemplo n.º 10
0
def objFuncSX(pFit, pFull, pFlag, dFunc, dFlag,
              xyo_det, hkls_idx, bMat, vInv,
              bVec, eVec, omePeriod,
              simOnly=False, return_value_flag=return_value_flag):
    """
    """
    npts = len(xyo_det)

    refineFlag = np.array(np.hstack([pFlag, dFlag]), dtype=bool)
    print refineFlag

    # pFull[refineFlag] = pFit/scl[refineFlag]
    pFull[refineFlag] = pFit

    if dFunc is not None:
        dParams = pFull[-len(dFlag):]
        xys = dFunc(xyo_det[:, :2], dParams)
    else:
        xys = xyo_det[:, :2]

    # detector quantities
    wavelength = pFull[0]

    rMat_d = xf.makeDetectorRotMat(pFull[1:4])
    tVec_d = pFull[4:7].reshape(3, 1)

    # sample quantities
    chi = pFull[7]
    tVec_s = pFull[8:11].reshape(3, 1)

    # crystal quantities
    rMat_c = xf.makeRotMatOfExpMap(pFull[11:14])
    tVec_c = pFull[14:17].reshape(3, 1)

    # stretch tensor comp matrix from MV notation in SAMPLE frame
    vMat_s = mutil.vecMVToSymm(vInv)

    # g-vectors:
    #   1. calculate full g-vector components in CRYSTAL frame from B
    #   2. rotate into SAMPLE frame and apply stretch
    #   3. rotate back into CRYSTAL frame and normalize to unit magnitude
    # IDEA: make a function for this sequence of operations with option for
    # choosing ouput frame (i.e. CRYSTAL vs SAMPLE vs LAB)
    gVec_c = np.dot(bMat, hkls_idx)
    gVec_s = np.dot(vMat_s, np.dot(rMat_c, gVec_c))
    gHat_c = mutil.unitVector(np.dot(rMat_c.T, gVec_s))

    match_omes, calc_omes = matchOmegas(
            xyo_det, hkls_idx, chi, rMat_c, bMat, wavelength,
            vInv=vInv, beamVec=bVec, etaVec=eVec, omePeriod=omePeriod)

    calc_xy = np.zeros((npts, 2))
    for i in range(npts):
        rMat_s = xfcapi.makeOscillRotMat([chi, calc_omes[i]])
        calc_xy[i, :] = xfcapi.gvecToDetectorXY(gHat_c[:, i],
                                                rMat_d, rMat_s, rMat_c,
                                                tVec_d, tVec_s, tVec_c,
                                                beamVec=bVec).flatten()
        pass
    if np.any(np.isnan(calc_xy)):
        raise RuntimeError(
            "infeasible pFull: may want to scale" +
            "back finite difference step size")

    # return values
    if simOnly:
        # return simulated values
        retval = np.hstack([calc_xy, calc_omes.reshape(npts, 1)])
    else:
        # return residual vector
        # IDEA: try angles instead of xys?
        diff_vecs_xy = calc_xy - xys[:, :2]
        diff_ome = xf.angularDifference(calc_omes, xyo_det[:, 2])
        retval = np.hstack([diff_vecs_xy,
                            diff_ome.reshape(npts, 1)
                            ]).flatten()
        if return_value_flag == 1:
            # return scalar sum of squared residuals
            retval = sum(abs(retval))
        elif return_value_flag == 2:
            # return DOF-normalized chisq
            # TODO: check this calculation
            denom = npts - len(pFit) - 1.
            if denom != 0:
                nu_fac = 1. / denom
            else:
                nu_fac = 1.
            nu_fac = 1 / (npts - len(pFit) - 1.)
            retval = nu_fac * sum(retval**2)
    return retval
Ejemplo n.º 11
0
def objFuncFitGrain(gFit, gFull, gFlag,
                    detectorParams,
                    xyo_det, hkls_idx, bMat, wavelength,
                    bVec, eVec,
                    dFunc, dParams,
                    omePeriod,
                    simOnly=False, returnScalarValue=returnScalarValue):
    """
    gFull[0]  = expMap_c[0]
    gFull[1]  = expMap_c[1]
    gFull[2]  = expMap_c[2]
    gFull[3]  = tVec_c[0]
    gFull[4]  = tVec_c[1]
    gFull[5]  = tVec_c[2]
    gFull[6]  = vInv_MV[0]
    gFull[7]  = vInv_MV[1]
    gFull[8]  = vInv_MV[2]
    gFull[9]  = vInv_MV[3]
    gFull[10] = vInv_MV[4]
    gFull[11] = vInv_MV[5]

    detectorParams[0]  = tiltAngles[0]
    detectorParams[1]  = tiltAngles[1]
    detectorParams[2]  = tiltAngles[2]
    detectorParams[3]  = tVec_d[0]
    detectorParams[4]  = tVec_d[1]
    detectorParams[5]  = tVec_d[2]
    detectorParams[6]  = chi
    detectorParams[7]  = tVec_s[0]
    detectorParams[8]  = tVec_s[1]
    detectorParams[9]  = tVec_s[2]
    """
    npts   = len(xyo_det)

    gFull[gFlag] = gFit

    xy_unwarped = dFunc(xyo_det[:, :2], dParams)

    rMat_d = xfcapi.makeDetectorRotMat(detectorParams[:3])
    tVec_d = detectorParams[3:6].reshape(3, 1)
    chi    = detectorParams[6]
    tVec_s = detectorParams[7:10].reshape(3, 1)

    rMat_c = xfcapi.makeRotMatOfExpMap(gFull[:3])
    tVec_c = gFull[3:6].reshape(3, 1)
    vInv_s = gFull[6:]
    vMat_s = mutil.vecMVToSymm(vInv_s)              # NOTE: Inverse of V from F = V * R

    gVec_c = np.dot(bMat, hkls_idx)                 # gVecs with magnitudes in CRYSTAL frame
    gVec_s = np.dot(vMat_s, np.dot(rMat_c, gVec_c)) # stretched gVecs in SAMPLE frame
    gHat_c = mutil.unitVector(
        np.dot(rMat_c.T, gVec_s)) # unit reciprocal lattice vectors in CRYSTAL frame

    match_omes, calc_omes = matchOmegas(xyo_det, hkls_idx, chi, rMat_c, bMat, wavelength,
                                        vInv=vInv_s, beamVec=bVec, etaVec=eVec,
                                        omePeriod=omePeriod)

    calc_xy = np.zeros((npts, 2))
    for i in range(npts):
        rMat_s = xfcapi.makeOscillRotMat([chi, calc_omes[i]])
        calc_xy[i, :] = xfcapi.gvecToDetectorXY(gHat_c[:, i],
                                                rMat_d, rMat_s, rMat_c,
                                                tVec_d, tVec_s, tVec_c,
                                                beamVec=bVec).flatten()
        pass
    if np.any(np.isnan(calc_xy)):
        print "infeasible pFull"

    # return values
    if simOnly:
        retval = np.hstack([calc_xy, calc_omes.reshape(npts, 1)])
    else:
        diff_vecs_xy = calc_xy - xy_unwarped[:, :2]
        diff_ome     = xf.angularDifference( calc_omes, xyo_det[:, 2] )
        retval = mutil.rowNorm(
            np.hstack([diff_vecs_xy,
                       diff_ome.reshape(npts, 1)
                       ]) ).flatten()
        if returnScalarValue:
            retval = sum( retval )
    return retval
Ejemplo n.º 12
0
class FitGrainsWorker(object):
    def __init__(self, jobs, results, reader, pkwargs, **kwargs):
        self._jobs = jobs
        self._results = results
        self._reader = reader
        # a dict containing the rest of the parameters
        self._p = pkwargs

        # lets make a couple shortcuts:
        self._p['bMat'] = np.ascontiguousarray(
            self._p['plane_data'].latVecOps['B']
        )  # is it still necessary to re-cast?
        self._p['wlen'] = self._p['plane_data'].wavelength
        self._pbar = kwargs.get('progressbar', None)

    def pull_spots(self, grain_id, grain_params, iteration):
        # need to calc panel dims on the fly
        xdim = self._p['pixel_pitch'][1] * self._p['ncols']
        ydim = self._p['pixel_pitch'][0] * self._p['nrows']
        panel_dims = [(-0.5 * xdim, -0.5 * ydim), (0.5 * xdim, 0.5 * ydim)]
        return pullSpots(
            self._p['plane_data'],
            self._p['detector_params'],
            grain_params,
            self._reader,
            distortion=self._p['distortion'],
            eta_range=self._p['eta_range'],
            ome_period=self._p['omega_period'],
            eta_tol=self._p['eta_tol'][iteration],
            ome_tol=self._p['omega_tol'][iteration],
            tth_tol=self._p['tth_tol'][iteration],
            pixel_pitch=self._p['pixel_pitch'],
            panel_dims=panel_dims,
            panel_buff=self._p['panel_buffer'],
            npdiv=self._p['npdiv'],
            threshold=self._p['threshold'],
            doClipping=False,
            filename=self._p['spots_stem'] % grain_id,
        )

    def fit_grains(self, grain_id, grain_params, refit_tol=None):
        """
        Executes lsq fits of grains based on spot files
        
        REFLECTION TABLE
        
        Cols as follows:
            0-6:   ID    PID    H    K    L    sum(int)    max(int)    
            6-9:   pred tth    pred eta    pred ome              
            9-12:  meas tth    meas eta    meas ome              
            12-15: meas X      meas Y      meas ome
        """
        ome_start = self._p['omega_start']
        ome_step = self._p['omega_step']
        ome_stop = self._p['omega_stop']
        refl_table = np.loadtxt(self._p['spots_stem'] % grain_id)
        valid_refl_ids = refl_table[:, 0] >= 0
        unsat_spots = refl_table[:, 6] < self._p['saturation_level']
        pred_ome = refl_table[:, 9]
        if angularDifference(ome_start, ome_stop, units='degrees') > 0:
            # if here, incomplete have omega range and
            # clip the refelctions very close to the edges to avoid
            # problems with the least squares...
            if np.sign(ome_step) < 0:
                idx_ome = np.logical_and(
                    pred_ome < np.radians(ome_start + 2 * ome_step),
                    pred_ome > np.radians(ome_stop - 2 * ome_step))
            else:
                idx_ome = np.logical_and(
                    pred_ome > np.radians(ome_start + 2 * ome_step),
                    pred_ome < np.radians(ome_stop - 2 * ome_step))
            idx = np.logical_and(valid_refl_ids,
                                 np.logical_and(unsat_spots, idx_ome))
        else:
            idx = np.logical_and(valid_refl_ids, unsat_spots)
            pass  # end if edge case

        # if an overlap table has been written, load it and use it
        overlaps = np.zeros(len(refl_table), dtype=bool)
        try:
            ot = np.load(self._p['overlap_table'])
            for key in ot.keys():
                for this_table in ot[key]:
                    these_overlaps = np.where(this_table[:, 0] == grain_id)[0]
                    if len(these_overlaps) > 0:
                        mark_these = np.array(this_table[these_overlaps, 1],
                                              dtype=int)
                        overlaps[mark_these] = True
            idx = np.logical_and(idx, ~overlaps)
        except IOError, IndexError:
            #print "no overlap table found"
            pass

        # completeness from pullspots only; incl saturated and overlaps
        completeness = sum(valid_refl_ids) / float(len(valid_refl_ids))

        # extract data from grain table
        hkls = refl_table[idx, 2:5].T  # must be column vectors
        xyo_det = refl_table[idx,
                             -3:]  # these are the cartesian centroids + ome

        # set in parameter attribute
        self._p['hkls'] = hkls
        self._p['xyo_det'] = xyo_det

        if sum(idx) <= 12:  # not enough reflections to fit... exit
            completeness = 0.
        else:
            grain_params = fitGrain(xyo_det,
                                    hkls,
                                    self._p['bMat'],
                                    self._p['wlen'],
                                    self._p['detector_params'],
                                    grain_params[:3],
                                    grain_params[3:6],
                                    grain_params[6:],
                                    beamVec=bVec_ref,
                                    etaVec=eta_ref,
                                    distortion=self._p['distortion'],
                                    gFlag=gFlag,
                                    gScl=gScl,
                                    omePeriod=self._p['omega_period'])
            if refit_tol is not None:
                xpix_tol = refit_tol[0] * self._p['pixel_pitch'][1]
                ypix_tol = refit_tol[0] * self._p['pixel_pitch'][0]
                fome_tol = refit_tol[1] * self._p['omega_step']

                xyo_det_fit = objFuncFitGrain(grain_params[gFlag],
                                              grain_params,
                                              gFlag,
                                              self._p['detector_params'],
                                              xyo_det,
                                              hkls,
                                              self._p['bMat'],
                                              self._p['wlen'],
                                              bVec_ref,
                                              eta_ref,
                                              self._p['distortion'][0],
                                              self._p['distortion'][1],
                                              self._p['omega_period'],
                                              simOnly=True)

                # define difference vectors for spot fits
                x_diff = abs(xyo_det[:, 0] - xyo_det_fit[:, 0])
                y_diff = abs(xyo_det[:, 1] - xyo_det_fit[:, 1])
                ome_diff = np.degrees(
                    angularDifference(xyo_det[:, 2], xyo_det_fit[:, 2]))

                # filter out reflections with centroids more than
                # a pixel and delta omega away from predicted value
                idx_1 = np.logical_and(
                    x_diff <= xpix_tol,
                    np.logical_and(y_diff <= ypix_tol, ome_diff <= fome_tol))
                idx_new = np.zeros_like(idx, dtype=bool)
                idx_new[np.where(idx == 1)[0][idx_1]] = True

                if sum(idx_new) > 12 and (sum(idx_new) > 0.5 * sum(idx)):
                    # have enough reflections left
                    #   ** the check that we have more than half of what
                    #      we started with is a hueristic
                    hkls = refl_table[idx_new, 2:5].T
                    xyo_det = refl_table[idx_new, -3:]

                    # set in parameter attribute
                    self._p['hkls'] = hkls
                    self._p['xyo_det'] = xyo_det

                    # do fit
                    grain_params = fitGrain(xyo_det,
                                            hkls,
                                            self._p['bMat'],
                                            self._p['wlen'],
                                            self._p['detector_params'],
                                            grain_params[:3],
                                            grain_params[3:6],
                                            grain_params[6:],
                                            beamVec=bVec_ref,
                                            etaVec=eta_ref,
                                            distortion=self._p['distortion'],
                                            gFlag=gFlag,
                                            gScl=gScl,
                                            omePeriod=self._p['omega_period'])
                    pass  # end check on num of refit refls
                pass  # end refit loop
            pass  # end on num of refls
        return grain_params, completeness
Ejemplo n.º 13
0
    def fit_grains(self, grain_id, grain_params, refit_tol=None):
        """
        Executes lsq fits of grains based on spot files
        
        REFLECTION TABLE
        
        Cols as follows:
            0-6:   ID    PID    H    K    L    sum(int)    max(int)    
            6-9:   pred tth    pred eta    pred ome              
            9-12:  meas tth    meas eta    meas ome              
            12-15: meas X      meas Y      meas ome
        """
        ome_start = self._p['omega_start']
        ome_step = self._p['omega_step']
        ome_stop =  self._p['omega_stop']
        refl_table = np.loadtxt(self._p['spots_stem'] % grain_id)
        valid_refl_ids = refl_table[:, 0] >= 0
        unsat_spots = refl_table[:, 6] < self._p['saturation_level']
        pred_ome = refl_table[:, 9]
        if angularDifference(ome_start, ome_stop, units='degrees') > 0:
            # if here, incomplete have omega range and
            # clip the refelctions very close to the edges to avoid
            # problems with the least squares...
            if np.sign(ome_step) < 0:
                idx_ome = np.logical_and(
                    pred_ome < np.radians(ome_start + 2*ome_step),
                    pred_ome > np.radians(ome_stop - 2*ome_step)
                    )
            else:
                idx_ome = np.logical_and(
                    pred_ome > np.radians(ome_start + 2*ome_step),
                    pred_ome < np.radians(ome_stop - 2*ome_step)
                    )
            idx = np.logical_and(
                valid_refl_ids,
                np.logical_and(unsat_spots, idx_ome)
                )
        else:
            idx = np.logical_and(valid_refl_ids, unsat_spots)
            pass # end if edge case

        # completeness from pullspots only; incl saturated
        completeness = sum(valid_refl_ids)/float(len(valid_refl_ids))

        # extract data from grain table
        hkls = refl_table[idx, 2:5].T # must be column vectors
        xyo_det = refl_table[idx, -3:] # these are the cartesian centroids + ome

        # set in parameter attribute
        self._p['hkls'] = hkls
        self._p['xyo_det'] = xyo_det
        
        if sum(idx) <= 12: # not enough reflections to fit... exit
            completeness = 0.
        else:
            grain_params = fitGrain(
                xyo_det, hkls, self._p['bMat'], self._p['wlen'],
                self._p['detector_params'],
                grain_params[:3], grain_params[3:6], grain_params[6:],
                beamVec=bVec_ref, etaVec=eta_ref,
                distortion=self._p['distortion'],
                gFlag=gFlag, gScl=gScl,
                omePeriod=self._p['omega_period']
                )
            if refit_tol is not None:
                xpix_tol = refit_tol[0]*self._p['pixel_pitch'][1]
                ypix_tol = refit_tol[0]*self._p['pixel_pitch'][0]
                fome_tol = refit_tol[1]*self._p['omega_step']
                
                xyo_det_fit = objFuncFitGrain(
                    grain_params[gFlag], grain_params, gFlag,
                    self._p['detector_params'],
                    xyo_det, hkls, self._p['bMat'], self._p['wlen'],
                    bVec_ref, eta_ref,
                    self._p['distortion'][0], self._p['distortion'][1],
                    self._p['omega_period'], simOnly=True
                    )

                # define difference vectors for spot fits
                x_diff = abs(xyo_det[:, 0] - xyo_det_fit[:, 0])
                y_diff = abs(xyo_det[:, 1] - xyo_det_fit[:, 1])
                ome_diff = np.degrees(
                    angularDifference(xyo_det[:, 2], xyo_det_fit[:, 2])
                    )

                # filter out reflections with centroids more than 
                # a pixel and delta omega away from predicted value
                idx_1 = np.logical_and(
                    x_diff <= xpix_tol,
                    np.logical_and(y_diff <= ypix_tol,
                                   ome_diff <= fome_tol)
                                   )
                idx_new = np.zeros_like(idx, dtype=bool)
                idx_new[np.where(idx == 1)[0][idx_1]] = True

                if sum(idx_new) > 12 and (sum(idx_new) > 0.5*sum(idx)):
                    # have enough reflections left
                    #   ** the check that we have more than half of what
                    #      we started with is a hueristic
                    hkls = refl_table[idx_new, 2:5].T
                    xyo_det = refl_table[idx_new, -3:]

                    # set in parameter attribute
                    self._p['hkls'] = hkls
                    self._p['xyo_det'] = xyo_det

                    # do fit
                    grain_params = fitGrain(
                        xyo_det, hkls,
                        self._p['bMat'], self._p['wlen'],
                        self._p['detector_params'],
                        grain_params[:3], grain_params[3:6], grain_params[6:],
                        beamVec=bVec_ref, etaVec=eta_ref,
                        distortion=self._p['distortion'],
                        gFlag=gFlag, gScl=gScl,
                        omePeriod=self._p['omega_period']
                        )
                    pass # end check on num of refit refls
                pass # end refit loop
            pass # end on num of refls
        return grain_params, completeness
Ejemplo n.º 14
0
def check_indexing_plots(cfg_filename,
                         plot_trials=False,
                         plot_from_grains=False):
    cfg = config.open(cfg_filename)[0]  # use first block, like indexing

    working_dir = cfg.working_dir
    analysis_dir = os.path.join(working_dir, cfg.analysis_name)

    #instrument parameters
    icfg = get_instrument_parameters(cfg)
    chi = icfg['oscillation_stage']['chi']

    # load maps that were used
    oem = cPickle.load(open(cfg.find_orientations.orientation_maps.file, 'r'))
    nmaps = len(oem.dataStore)
    omeEdges = np.degrees(oem.omeEdges)
    nome = len(omeEdges) - 1
    etaEdges = np.degrees(oem.etaEdges)
    neta = len(etaEdges) - 1
    delta_ome = abs(omeEdges[1] - omeEdges[0])

    full_ome_range = xf.angularDifference(omeEdges[0], omeEdges[-1]) == 0
    full_eta_range = xf.angularDifference(etaEdges[0], etaEdges[-1]) == 0

    # grab plane data and figure out IDs of map HKLS
    pd = oem.planeData
    gvids = [
        pd.hklDataList[i]['hklID']
        for i in np.where(pd.exclusions == False)[0].tolist()
    ]

    # load orientations
    quats = np.atleast_2d(
        np.loadtxt(os.path.join(working_dir, 'accepted_orientations.dat')))
    if plot_trials:
        scored_trials = np.load(
            os.path.join(working_dir, 'scored_orientations.dat'))
        quats = scored_orientations[:4, scored_orientations[
            -1, :] >= cfg.find_orientations.clustering.completeness]
        pass
    expMaps = np.tile(2. * np.arccos(quats[:, 0]),
                      (3, 1)) * unitVector(quats[:, 1:].T)

    ##########################################
    #      SPECIAL CASE FOR FIT GRAINS       #
    ##########################################
    if plot_from_grains:
        distortion = (GE_41RT, icfg['detector']['distortion']['parameters'])
        #
        grain_table = np.atleast_2d(
            np.loadtxt(os.path.join(analysis_dir, 'grains.out')))
        ngrains = len(grain_table)
        #
        expMaps = grain_table[:, 3:6]
        tVec_c = grain_table[:, 6:9]
        vInv = grain_table[:, 6:12]
        #
        rMat_d = xf.makeDetectorRotMat(
            icfg['detector']['transform']['tilt_angles'])
        tVec_d = np.vstack(icfg['detector']['transform']['t_vec_d'])
        #
        chi = icfg['oscillation_stage']['chi']
        tVec_s = np.vstack(icfg['oscillation_stage']['t_vec_s'])
        #
        oes = np.zeros(oem.dataStore.shape)
        for i_grn in range(ngrains):
            spots_table = np.loadtxt(
                os.path.join(analysis_dir, 'spots_%05d.out' % i_grn))
            idx_m = spots_table[:, 0] >= 0
            for i_map in range(nmaps):
                idx_g = spots_table[:, 1] == gvids[i_map]
                idx = np.logical_and(idx_m, idx_g)
                nrefl = sum(idx)

                omes_fit = xf.mapAngle(spots_table[idx, 9],
                                       np.radians(
                                           cfg.find_orientations.omega.period),
                                       units='radians')
                xy_det = spots_table[idx, -3:]
                xy_det[:, 2] = np.zeros(nrefl)

                rMat_s_array = xfcapi.makeOscillRotMatArray(chi, omes_fit)

                # form in-plane vectors for detector points list in DETECTOR FRAME
                P2_d = xy_det.T

                # in LAB FRAME
                P2_l = np.dot(rMat_d, P2_d) + tVec_d  # point on detector
                P0_l = np.hstack([
                    tVec_s +
                    np.dot(rMat_s_array[j], tVec_c[i_grn, :].reshape(3, 1))
                    for j in range(nrefl)
                ])  # origin of CRYSTAL FRAME

                # diffraction unit vector components in LAB FRAME
                dHat_l = unitVector(P2_l - P0_l)
                P2_l = np.dot(rMat_d, xy_det.T) + tVec_d

                # angles for reference frame
                dHat_ref_l = unitVector(P2_l)

                # append etas and omes
                etas_fit = np.arctan2(dHat_ref_l[1, :],
                                      dHat_ref_l[0, :]).flatten()

                # find indices, then truncate or wrap
                i_ome = cellIndices(oem.omeEdges, omes_fit)
                if full_ome_range:
                    i_ome[i_ome < 0] = np.mod(i_ome, nome) + 1
                    i_ome[i_ome >= nome] = np.mod(i_ome, nome)
                else:
                    incl = np.logical_or(i_ome >= 0, i_ome < nome)
                    i_ome = i_ome[incl]
                j_eta = cellIndices(oem.etaEdges, etas_fit)
                if full_eta_range:
                    j_eta[j_eta < 0] = np.mod(j_eta, neta) + 1
                    j_eta[j_eta >= neta] = np.mod(j_eta, neta)
                else:
                    incl = np.logical_or(j_eta >= 0, j_eta < neta)
                    j_eta = j_eta[incl]

                #if np.max(i_ome) >= nome or np.min(i_ome) < 0 or np.max(j_eta) >= neta or np.min(j_eta) < 0:
                #    import pdb; pdb.set_trace()
                # add to map
                oes[i_map][i_ome, j_eta] = 1
            pass
        pass

    # simulate quaternion points
    if not plot_from_grains:
        oes = simulateOmeEtaMaps(omeEdges,
                                 etaEdges,
                                 pd,
                                 expMaps,
                                 chi=chi,
                                 etaTol=0.01,
                                 omeTol=0.01,
                                 etaRanges=None,
                                 omeRanges=None,
                                 bVec=xf.bVec_ref,
                                 eVec=xf.eta_ref,
                                 vInv=xf.vInv_ref)

    # tick labling
    omes = np.degrees(oem.omeEdges)
    etas = np.degrees(oem.etaEdges)
    num_ticks = 7
    xmin = np.amin(etas)
    xmax = np.amax(etas)
    dx = (xmax - xmin) / (num_ticks - 1.)
    dx1 = (len(etas) - 1) / (num_ticks - 1.)
    xtlab = ["%.0f" % (xmin + i * dx) for i in range(num_ticks)]
    xtloc = np.array([i * dx1 for i in range(num_ticks)]) - 0.5
    ymin = np.amin(omes)
    ymax = np.amax(omes)
    dy = (ymax - ymin) / (num_ticks - 1.)
    dy1 = (len(omes) - 1) / (num_ticks - 1.)
    ytlab = ["%.0f" % (ymin + i * dy) for i in range(num_ticks)]
    ytloc = np.array([i * dy1 for i in range(num_ticks)]) - 0.5

    # Plot the three kernel density estimates
    n_maps = len(oem.iHKLList)

    fig_list = [plt.figure(num=i + 1) for i in range(n_maps)]
    ax_list = [fig_list[i].gca() for i in range(n_maps)]
    for i_map in range(n_maps):
        y, x = np.where(oes[i_map] > 0)
        ax_list[i_map].hold(True)
        ax_list[i_map].imshow(oem.dataStore[i_map] > 0.1, cmap=cm.bone)
        ax_list[i_map].set_title(r'Map for $\{%d %d %d\}$' %
                                 tuple(pd.hkls[:, i_map]))
        ax_list[i_map].set_xlabel(
            r'Azimuth channel, $\eta$; $\Delta\eta=%.3f$' % delta_ome)
        ax_list[i_map].set_ylabel(
            r'Rotation channel, $\omega$; $\Delta\omega=%.3f$' % delta_ome)
        ax_list[i_map].plot(x, y, 'c+')
        ax_list[i_map].xaxis.set_ticks(xtloc)
        ax_list[i_map].xaxis.set_ticklabels(xtlab)
        ax_list[i_map].yaxis.set_ticks(ytloc)
        ax_list[i_map].yaxis.set_ticklabels(ytlab)
        ax_list[i_map].axis('tight')
    plt.show()
    return fig_list, oes
Ejemplo n.º 15
0
def check_indexing_plots(cfg_filename, plot_trials=False, plot_from_grains=False):
    cfg = config.open(cfg_filename)[0]    # use first block, like indexing

    working_dir = cfg.working_dir
    analysis_dir = os.path.join(working_dir, cfg.analysis_name)
    
    #instrument parameters
    icfg = get_instrument_parameters(cfg)
    chi = icfg['oscillation_stage']['chi']

    # load maps that were used
    oem = cPickle.load(
        open(cfg.find_orientations.orientation_maps.file, 'r')
        )
    nmaps = len(oem.dataStore)
    omeEdges = np.degrees(oem.omeEdges); nome = len(omeEdges) - 1
    etaEdges = np.degrees(oem.etaEdges); neta = len(etaEdges) - 1
    delta_ome = abs(omeEdges[1]-omeEdges[0])

    full_ome_range = xf.angularDifference(omeEdges[0], omeEdges[-1]) == 0
    full_eta_range = xf.angularDifference(etaEdges[0], etaEdges[-1]) == 0
    
    # grab plane data and figure out IDs of map HKLS
    pd = oem.planeData
    gvids = [pd.hklDataList[i]['hklID'] for i in np.where(pd.exclusions == False)[0].tolist()]

    # load orientations
    quats = np.atleast_2d(np.loadtxt(os.path.join(working_dir, 'accepted_orientations.dat')))
    if plot_trials:
        scored_trials = np.load(os.path.join(working_dir, 'scored_orientations.dat'))
        quats = scored_orientations[:4, scored_orientations[-1, :] >= cfg.find_orientations.clustering.completeness]
        pass
    expMaps = np.tile(2. * np.arccos(quats[:, 0]), (3, 1))*unitVector(quats[:, 1:].T)

    ##########################################
    #      SPECIAL CASE FOR FIT GRAINS       #
    ##########################################
    if plot_from_grains:
        distortion = (GE_41RT, icfg['detector']['distortion']['parameters'])
        #
        grain_table = np.atleast_2d(np.loadtxt(os.path.join(analysis_dir, 'grains.out')))
        ngrains = len(grain_table)
        #
        expMaps = grain_table[:, 3:6]
        tVec_c = grain_table[:, 6:9]
        vInv = grain_table[:, 6:12]
        #
        rMat_d = xf.makeDetectorRotMat(icfg['detector']['transform']['tilt_angles'])
        tVec_d = np.vstack(icfg['detector']['transform']['t_vec_d'])
        #
        chi = icfg['oscillation_stage']['chi']
        tVec_s = np.vstack(icfg['oscillation_stage']['t_vec_s'])
        #
        oes = np.zeros(oem.dataStore.shape)
        for i_grn in range(ngrains):
            spots_table = np.loadtxt(os.path.join(analysis_dir, 'spots_%05d.out' %i_grn))
            idx_m = spots_table[:, 0] >= 0
            for i_map in range(nmaps):
                idx_g = spots_table[:, 1] == gvids[i_map]
                idx = np.logical_and(idx_m, idx_g)
                nrefl = sum(idx)
                
                omes_fit = xf.mapAngle(spots_table[idx, 9], np.radians(cfg.find_orientations.omega.period), units='radians')
                xy_det = spots_table[idx, -3:]
                xy_det[:, 2] = np.zeros(nrefl)
                
                rMat_s_array = xfcapi.makeOscillRotMatArray(chi, omes_fit)
                
                # form in-plane vectors for detector points list in DETECTOR FRAME
                P2_d = xy_det.T
                
                # in LAB FRAME
                P2_l = np.dot(rMat_d, P2_d) + tVec_d # point on detector
                P0_l = np.hstack(
                    [tVec_s + np.dot(rMat_s_array[j], tVec_c[i_grn, :].reshape(3, 1)) for j in range(nrefl)]
                ) # origin of CRYSTAL FRAME

                # diffraction unit vector components in LAB FRAME
                dHat_l = unitVector(P2_l - P0_l)
                P2_l = np.dot(rMat_d, xy_det.T) + tVec_d
                
                # angles for reference frame
                dHat_ref_l = unitVector(P2_l)
    
                # append etas and omes
                etas_fit = np.arctan2(dHat_ref_l[1, :], dHat_ref_l[0, :]).flatten()
           
                # find indices, then truncate or wrap
                i_ome = cellIndices(oem.omeEdges, omes_fit)
                if full_ome_range:
                    i_ome[i_ome < 0] = np.mod(i_ome, nome) + 1
                    i_ome[i_ome >= nome] = np.mod(i_ome, nome)
                else:
                    incl = np.logical_or(i_ome >= 0, i_ome < nome)
                    i_ome = i_ome[incl]
                j_eta = cellIndices(oem.etaEdges, etas_fit)
                if full_eta_range:
                    j_eta[j_eta < 0] = np.mod(j_eta, neta) + 1
                    j_eta[j_eta >= neta] = np.mod(j_eta, neta)
                else:
                    incl = np.logical_or(j_eta >= 0, j_eta < neta)
                    j_eta = j_eta[incl]

                #if np.max(i_ome) >= nome or np.min(i_ome) < 0 or np.max(j_eta) >= neta or np.min(j_eta) < 0:
                #    import pdb; pdb.set_trace()
                # add to map
                oes[i_map][i_ome, j_eta] = 1
            pass
        pass
    
    # simulate quaternion points
    if not plot_from_grains:
        oes = simulateOmeEtaMaps(omeEdges, etaEdges, pd,
                                 expMaps,
                                 chi=chi,
                                 etaTol=0.01, omeTol=0.01,
                                 etaRanges=None, omeRanges=None,
                                 bVec=xf.bVec_ref, eVec=xf.eta_ref, vInv=xf.vInv_ref)
    
    # tick labling
    omes = np.degrees(oem.omeEdges)
    etas = np.degrees(oem.etaEdges)
    num_ticks = 7
    xmin = np.amin(etas); xmax = np.amax(etas)
    dx = (xmax - xmin) / (num_ticks - 1.); dx1 = (len(etas) - 1) / (num_ticks - 1.)
    xtlab = ["%.0f" % (xmin + i*dx) for i in range(num_ticks)]
    xtloc = np.array([i*dx1 for i in range(num_ticks)]) - 0.5
    ymin = np.amin(omes); ymax = np.amax(omes)
    dy = (ymax - ymin) / (num_ticks - 1.); dy1 = (len(omes) - 1) / (num_ticks - 1.)
    ytlab = ["%.0f" % (ymin + i*dy) for i in range(num_ticks)]
    ytloc = np.array([i*dy1 for i in range(num_ticks)]) - 0.5
    
    # Plot the three kernel density estimates
    n_maps = len(oem.iHKLList)
    
    fig_list =[plt.figure(num=i+1) for i in range(n_maps)]
    ax_list = [fig_list[i].gca() for i in range(n_maps)]
    for i_map in range(n_maps):
        y, x = np.where(oes[i_map] > 0)
        ax_list[i_map].hold(True)
        ax_list[i_map].imshow(oem.dataStore[i_map] > 0.1, cmap=cm.bone)
        ax_list[i_map].set_title(r'Map for $\{%d %d %d\}$' %tuple(pd.hkls[:, i_map]))
        ax_list[i_map].set_xlabel(r'Azimuth channel, $\eta$; $\Delta\eta=%.3f$' %delta_ome)
        ax_list[i_map].set_ylabel(r'Rotation channel, $\omega$; $\Delta\omega=%.3f$' %delta_ome)
        ax_list[i_map].plot(x, y, 'c+')
        ax_list[i_map].xaxis.set_ticks(xtloc)
        ax_list[i_map].xaxis.set_ticklabels(xtlab)
        ax_list[i_map].yaxis.set_ticks(ytloc)
        ax_list[i_map].yaxis.set_ticklabels(ytlab)
        ax_list[i_map].axis('tight')
    plt.show()
    return fig_list, oes
Ejemplo n.º 16
0
def objFuncFitGrain(gFit,
                    gFull,
                    gFlag,
                    instrument,
                    reflections_dict,
                    bMat,
                    wavelength,
                    omePeriod,
                    simOnly=False,
                    return_value_flag=return_value_flag):
    """
    gFull[0]  = expMap_c[0]
    gFull[1]  = expMap_c[1]
    gFull[2]  = expMap_c[2]
    gFull[3]  = tVec_c[0]
    gFull[4]  = tVec_c[1]
    gFull[5]  = tVec_c[2]
    gFull[6]  = vInv_MV[0]
    gFull[7]  = vInv_MV[1]
    gFull[8]  = vInv_MV[2]
    gFull[9]  = vInv_MV[3]
    gFull[10] = vInv_MV[4]
    gFull[11] = vInv_MV[5]

    OLD CALL
    objFuncFitGrain(gFit, gFull, gFlag,
                    detectorParams,
                    xyo_det, hkls_idx, bMat, wavelength,
                    bVec, eVec,
                    dFunc, dParams,
                    omePeriod,
                    simOnly=False, return_value_flag=return_value_flag)
    """

    bVec = instrument.beam_vector
    eVec = instrument.eta_vector

    # fill out parameters
    gFull[gFlag] = gFit

    # map parameters to functional arrays
    rMat_c = xfcapi.makeRotMatOfExpMap(gFull[:3])
    tVec_c = gFull[3:6].reshape(3, 1)
    vInv_s = gFull[6:]
    vMat_s = mutil.vecMVToSymm(vInv_s)  # NOTE: Inverse of V from F = V * R

    # loop over instrument panels
    # CAVEAT: keeping track of key ordering in the "detectors" attribute of
    # instrument here because I am not sure if instatiating them using
    # dict.fromkeys() preserves the same order if using iteration...
    # <JVB 2017-10-31>
    calc_omes_dict = dict.fromkeys(instrument.detectors, [])
    calc_xy_dict = dict.fromkeys(instrument.detectors)
    meas_xyo_all = []
    det_keys_ordered = []
    for det_key, panel in instrument.detectors.iteritems():
        det_keys_ordered.append(det_key)

        # extract transformation quantities
        rMat_d = instrument.detectors[det_key].rmat
        tVec_d = instrument.detectors[det_key].tvec
        chi = instrument.chi
        tVec_s = instrument.tvec

        results = reflections_dict[det_key]
        if len(results) == 0:
            continue
        """
        extract data from results list
        fields:
          refl_id, gvec_id, hkl, sum_int, max_int, pred_ang, meas_ang, meas_xy
        """

        # WARNING: hkls and derived vectors below must be columnwise;
        # strictly necessary??? change affected APIs instead?
        # <JVB 2017-03-26>
        hkls = np.atleast_2d(np.vstack([x[2] for x in results])).T

        meas_xyo = np.atleast_2d(
            np.vstack([np.r_[x[7], x[6][-1]] for x in results]))

        # FIXME: distortion handling must change to class-based
        if panel.distortion is not None:
            meas_omes = meas_xyo[:, 2]
            xy_unwarped = panel.distortion[0](meas_xyo[:, :2],
                                              panel.distortion[1])
            meas_xyo = np.vstack([xy_unwarped.T, meas_omes]).T
            pass

        # append to meas_omes
        meas_xyo_all.append(meas_xyo)

        # G-vectors:
        #   1. calculate full g-vector components in CRYSTAL frame from B
        #   2. rotate into SAMPLE frame and apply stretch
        #   3. rotate back into CRYSTAL frame and normalize to unit magnitude
        # IDEA: make a function for this sequence of operations with option for
        # choosing ouput frame (i.e. CRYSTAL vs SAMPLE vs LAB)
        gVec_c = np.dot(bMat, hkls)
        gVec_s = np.dot(vMat_s, np.dot(rMat_c, gVec_c))
        gHat_c = mutil.unitVector(np.dot(rMat_c.T, gVec_s))

        # !!!: check that this operates on UNWARPED xy
        match_omes, calc_omes = matchOmegas(meas_xyo,
                                            hkls,
                                            chi,
                                            rMat_c,
                                            bMat,
                                            wavelength,
                                            vInv=vInv_s,
                                            beamVec=bVec,
                                            etaVec=eVec,
                                            omePeriod=omePeriod)

        # append to omes dict
        calc_omes_dict[det_key] = calc_omes

        # TODO: try Numba implementations
        rMat_s = xfcapi.makeOscillRotMatArray(chi, calc_omes)
        calc_xy = xfcapi.gvecToDetectorXYArray(gHat_c.T,
                                               rMat_d,
                                               rMat_s,
                                               rMat_c,
                                               tVec_d,
                                               tVec_s,
                                               tVec_c,
                                               beamVec=bVec)

        # append to xy dict
        calc_xy_dict[det_key] = calc_xy
        pass

    # stack results to concatenated arrays
    calc_omes_all = np.hstack([calc_omes_dict[k] for k in det_keys_ordered])
    tmp = []
    for k in det_keys_ordered:
        if calc_xy_dict[k] is not None:
            tmp.append(calc_xy_dict[k])
    calc_xy_all = np.vstack(tmp)
    meas_xyo_all = np.vstack(meas_xyo_all)

    npts = len(meas_xyo_all)
    if np.any(np.isnan(calc_xy)):
        raise RuntimeError("infeasible pFull: may want to scale" +
                           "back finite difference step size")

    # return values
    if simOnly:
        # return simulated values
        if return_value_flag in [None, 1]:
            retval = np.hstack([calc_xy_all, calc_omes_all.reshape(npts, 1)])
        else:
            rd = dict.fromkeys(det_keys_ordered)
            for det_key in det_keys_ordered:
                rd[det_key] = {
                    'calc_xy': calc_xy_dict[det_key],
                    'calc_omes': calc_omes_dict[det_key]
                }
            retval = rd
    else:
        # return residual vector
        # IDEA: try angles instead of xys?
        diff_vecs_xy = calc_xy_all - meas_xyo_all[:, :2]
        diff_ome = xf.angularDifference(calc_omes_all, meas_xyo_all[:, 2])
        retval = np.hstack([diff_vecs_xy, diff_ome.reshape(npts, 1)]).flatten()
        if return_value_flag == 1:
            # return scalar sum of squared residuals
            retval = sum(abs(retval))
        elif return_value_flag == 2:
            # return DOF-normalized chisq
            # TODO: check this calculation
            denom = 3 * npts - len(gFit) - 1.
            if denom != 0:
                nu_fac = 1. / denom
            else:
                nu_fac = 1.
            retval = nu_fac * sum(retval**2)
    return retval
Ejemplo n.º 17
0
def objFuncSX(pFit,
              pFull,
              pFlag,
              dFunc,
              dFlag,
              xyo_det,
              hkls_idx,
              bMat,
              vInv,
              bVec,
              eVec,
              omePeriod,
              simOnly=False,
              return_value_flag=return_value_flag):
    """
    """
    npts = len(xyo_det)

    refineFlag = np.array(np.hstack([pFlag, dFlag]), dtype=bool)
    print refineFlag

    # pFull[refineFlag] = pFit/scl[refineFlag]
    pFull[refineFlag] = pFit

    if dFunc is not None:
        dParams = pFull[-len(dFlag):]
        xys = dFunc(xyo_det[:, :2], dParams)
    else:
        xys = xyo_det[:, :2]

    # detector quantities
    wavelength = pFull[0]

    rMat_d = xf.makeDetectorRotMat(pFull[1:4])
    tVec_d = pFull[4:7].reshape(3, 1)

    # sample quantities
    chi = pFull[7]
    tVec_s = pFull[8:11].reshape(3, 1)

    # crystal quantities
    rMat_c = xf.makeRotMatOfExpMap(pFull[11:14])
    tVec_c = pFull[14:17].reshape(3, 1)

    # stretch tensor comp matrix from MV notation in SAMPLE frame
    vMat_s = mutil.vecMVToSymm(vInv)

    # g-vectors:
    #   1. calculate full g-vector components in CRYSTAL frame from B
    #   2. rotate into SAMPLE frame and apply stretch
    #   3. rotate back into CRYSTAL frame and normalize to unit magnitude
    # IDEA: make a function for this sequence of operations with option for
    # choosing ouput frame (i.e. CRYSTAL vs SAMPLE vs LAB)
    gVec_c = np.dot(bMat, hkls_idx)
    gVec_s = np.dot(vMat_s, np.dot(rMat_c, gVec_c))
    gHat_c = mutil.unitVector(np.dot(rMat_c.T, gVec_s))

    match_omes, calc_omes = matchOmegas(xyo_det,
                                        hkls_idx,
                                        chi,
                                        rMat_c,
                                        bMat,
                                        wavelength,
                                        vInv=vInv,
                                        beamVec=bVec,
                                        etaVec=eVec,
                                        omePeriod=omePeriod)

    calc_xy = np.zeros((npts, 2))
    for i in range(npts):
        rMat_s = xfcapi.makeOscillRotMat([chi, calc_omes[i]])
        calc_xy[i, :] = xfcapi.gvecToDetectorXY(gHat_c[:, i],
                                                rMat_d,
                                                rMat_s,
                                                rMat_c,
                                                tVec_d,
                                                tVec_s,
                                                tVec_c,
                                                beamVec=bVec).flatten()
        pass
    if np.any(np.isnan(calc_xy)):
        raise RuntimeError("infeasible pFull: may want to scale" +
                           "back finite difference step size")

    # return values
    if simOnly:
        # return simulated values
        retval = np.hstack([calc_xy, calc_omes.reshape(npts, 1)])
    else:
        # return residual vector
        # IDEA: try angles instead of xys?
        diff_vecs_xy = calc_xy - xys[:, :2]
        diff_ome = xf.angularDifference(calc_omes, xyo_det[:, 2])
        retval = np.hstack([diff_vecs_xy, diff_ome.reshape(npts, 1)]).flatten()
        if return_value_flag == 1:
            # return scalar sum of squared residuals
            retval = sum(abs(retval))
        elif return_value_flag == 2:
            # return DOF-normalized chisq
            # TODO: check this calculation
            denom = npts - len(pFit) - 1.
            if denom != 0:
                nu_fac = 1. / denom
            else:
                nu_fac = 1.
            nu_fac = 1 / (npts - len(pFit) - 1.)
            retval = nu_fac * sum(retval**2)
    return retval
Ejemplo n.º 18
0
def objFuncFitGrain(gFit,
                    gFull,
                    gFlag,
                    detectorParams,
                    xyo_det,
                    hkls_idx,
                    bMat,
                    wavelength,
                    bVec,
                    eVec,
                    dFunc,
                    dParams,
                    omePeriod,
                    simOnly=False,
                    return_value_flag=return_value_flag):
    """
    gFull[0]  = expMap_c[0]
    gFull[1]  = expMap_c[1]
    gFull[2]  = expMap_c[2]
    gFull[3]  = tVec_c[0]
    gFull[4]  = tVec_c[1]
    gFull[5]  = tVec_c[2]
    gFull[6]  = vInv_MV[0]
    gFull[7]  = vInv_MV[1]
    gFull[8]  = vInv_MV[2]
    gFull[9]  = vInv_MV[3]
    gFull[10] = vInv_MV[4]
    gFull[11] = vInv_MV[5]

    detectorParams[0]  = tiltAngles[0]
    detectorParams[1]  = tiltAngles[1]
    detectorParams[2]  = tiltAngles[2]
    detectorParams[3]  = tVec_d[0]
    detectorParams[4]  = tVec_d[1]
    detectorParams[5]  = tVec_d[2]
    detectorParams[6]  = chi
    detectorParams[7]  = tVec_s[0]
    detectorParams[8]  = tVec_s[1]
    detectorParams[9]  = tVec_s[2]
    """
    npts = len(xyo_det)

    gFull[gFlag] = gFit

    xy_unwarped = dFunc(xyo_det[:, :2], dParams)

    rMat_d = xfcapi.makeDetectorRotMat(detectorParams[:3])
    tVec_d = detectorParams[3:6].reshape(3, 1)
    chi = detectorParams[6]
    tVec_s = detectorParams[7:10].reshape(3, 1)

    rMat_c = xfcapi.makeRotMatOfExpMap(gFull[:3])
    tVec_c = gFull[3:6].reshape(3, 1)
    vInv_s = gFull[6:]
    vMat_s = mutil.vecMVToSymm(vInv_s)  # NOTE: Inverse of V from F = V * R

    gVec_c = np.dot(bMat, hkls_idx)  # gVecs with magnitudes in CRYSTAL frame
    gVec_s = np.dot(vMat_s, np.dot(rMat_c,
                                   gVec_c))  # stretched gVecs in SAMPLE frame
    gHat_c = mutil.unitVector(np.dot(
        rMat_c.T, gVec_s))  # unit reciprocal lattice vectors in CRYSTAL frame

    match_omes, calc_omes = matchOmegas(xyo_det,
                                        hkls_idx,
                                        chi,
                                        rMat_c,
                                        bMat,
                                        wavelength,
                                        vInv=vInv_s,
                                        beamVec=bVec,
                                        etaVec=eVec,
                                        omePeriod=omePeriod)

    rMat_s = xfcapi.makeOscillRotMatArray(chi, calc_omes)
    calc_xy = xfcapi.gvecToDetectorXYArray(gHat_c.T,
                                           rMat_d,
                                           rMat_s,
                                           rMat_c,
                                           tVec_d,
                                           tVec_s,
                                           tVec_c,
                                           beamVec=bVec)

    if np.any(np.isnan(calc_xy)):
        print "infeasible pFull"

    # return values
    if simOnly:
        retval = np.hstack([calc_xy, calc_omes.reshape(npts, 1)])
    else:
        diff_vecs_xy = calc_xy - xy_unwarped[:, :2]
        diff_ome = xf.angularDifference(calc_omes, xyo_det[:, 2])
        retval = np.hstack([diff_vecs_xy, diff_ome.reshape(npts, 1)]).flatten()
        if return_value_flag == 1:
            retval = sum(abs(retval))
        elif return_value_flag == 2:
            denom = npts - len(gFit) - 1.
            if denom != 0:
                nu_fac = 1. / denom
            else:
                nu_fac = 1.
            retval = nu_fac * sum(retval**2 / abs(
                np.hstack([calc_xy, calc_omes.reshape(npts, 1)]).flatten()))
    return retval
Ejemplo n.º 19
0
def objFuncFitGrain(gFit, gFull, gFlag,
                    instrument,
                    reflections_dict,
                    bMat, wavelength,
                    omePeriod,
                    simOnly=False,
                    return_value_flag=return_value_flag):
    """
    gFull[0]  = expMap_c[0]
    gFull[1]  = expMap_c[1]
    gFull[2]  = expMap_c[2]
    gFull[3]  = tVec_c[0]
    gFull[4]  = tVec_c[1]
    gFull[5]  = tVec_c[2]
    gFull[6]  = vInv_MV[0]
    gFull[7]  = vInv_MV[1]
    gFull[8]  = vInv_MV[2]
    gFull[9]  = vInv_MV[3]
    gFull[10] = vInv_MV[4]
    gFull[11] = vInv_MV[5]

    OLD CALL
    objFuncFitGrain(gFit, gFull, gFlag,
                    detectorParams,
                    xyo_det, hkls_idx, bMat, wavelength,
                    bVec, eVec,
                    dFunc, dParams,
                    omePeriod,
                    simOnly=False, return_value_flag=return_value_flag)
    """

    bVec = instrument.beam_vector
    eVec = instrument.eta_vector

    # fill out parameters
    gFull[gFlag] = gFit

    # map parameters to functional arrays
    rMat_c = xfcapi.makeRotMatOfExpMap(gFull[:3])
    tVec_c = gFull[3:6].reshape(3, 1)
    vInv_s = gFull[6:]
    vMat_s = mutil.vecMVToSymm(vInv_s)  # NOTE: Inverse of V from F = V * R

    # loop over instrument panels
    # CAVEAT: keeping track of key ordering in the "detectors" attribute of
    # instrument here because I am not sure if instatiating them using
    # dict.fromkeys() preserves the same order if using iteration...
    # <JVB 2017-10-31>
    calc_omes_dict = dict.fromkeys(instrument.detectors, [])
    calc_xy_dict = dict.fromkeys(instrument.detectors)
    meas_xyo_all = []
    det_keys_ordered = []
    for det_key, panel in instrument.detectors.iteritems():
        det_keys_ordered.append(det_key)

        rMat_d, tVec_d, chi, tVec_s = extract_detector_transformation(
            instrument.detector_parameters[det_key])

        results = reflections_dict[det_key]
        if len(results) == 0:
            continue

        """
        extract data from results list fields:
          refl_id, gvec_id, hkl, sum_int, max_int, pred_ang, meas_ang, meas_xy

        or array from spots tables:
          0:5    ID    PID    H    K    L       
          5:7    sum(int)    max(int)      
          7:10   pred tth    pred eta    pred ome                 
          10:13  meas tth    meas eta    meas ome                 
          13:15  pred X    pred Y                   
          15:17  meas X    meas Y                 
        """
        if isinstance(results, list):
            # WARNING: hkls and derived vectors below must be columnwise;
            # strictly necessary??? change affected APIs instead?
            # <JVB 2017-03-26>
            hkls = np.atleast_2d(
                np.vstack([x[2] for x in results])
            ).T
            
            meas_xyo = np.atleast_2d(
                np.vstack([np.r_[x[7], x[6][-1]] for x in results])
            )
        elif isinstance(results, np.ndarray):
            hkls = np.atleast_2d(results[:, 2:5]).T
            meas_xyo = np.atleast_2d(results[:, [15, 16, 12]])

        # FIXME: distortion handling must change to class-based
        if panel.distortion is not None:
            meas_omes = meas_xyo[:, 2]
            xy_unwarped = panel.distortion[0](
                    meas_xyo[:, :2], panel.distortion[1])
            meas_xyo = np.vstack([xy_unwarped.T, meas_omes]).T
            pass

        # append to meas_omes
        meas_xyo_all.append(meas_xyo)

        # G-vectors:
        #   1. calculate full g-vector components in CRYSTAL frame from B
        #   2. rotate into SAMPLE frame and apply stretch
        #   3. rotate back into CRYSTAL frame and normalize to unit magnitude
        # IDEA: make a function for this sequence of operations with option for
        # choosing ouput frame (i.e. CRYSTAL vs SAMPLE vs LAB)
        gVec_c = np.dot(bMat, hkls)
        gVec_s = np.dot(vMat_s, np.dot(rMat_c, gVec_c))
        gHat_c = mutil.unitVector(np.dot(rMat_c.T, gVec_s))

        # !!!: check that this operates on UNWARPED xy
        match_omes, calc_omes = matchOmegas(
            meas_xyo, hkls, chi, rMat_c, bMat, wavelength,
            vInv=vInv_s, beamVec=bVec, etaVec=eVec,
            omePeriod=omePeriod)

        # append to omes dict
        calc_omes_dict[det_key] = calc_omes

        # TODO: try Numba implementations
        rMat_s = xfcapi.makeOscillRotMatArray(chi, calc_omes)
        calc_xy = xfcapi.gvecToDetectorXYArray(gHat_c.T,
                                               rMat_d, rMat_s, rMat_c,
                                               tVec_d, tVec_s, tVec_c,
                                               beamVec=bVec)

        # append to xy dict
        calc_xy_dict[det_key] = calc_xy
        pass

    # stack results to concatenated arrays
    calc_omes_all = np.hstack([calc_omes_dict[k] for k in det_keys_ordered])
    tmp = []
    for k in det_keys_ordered:
        if calc_xy_dict[k] is not None:
            tmp.append(calc_xy_dict[k])
    calc_xy_all = np.vstack(tmp)
    meas_xyo_all = np.vstack(meas_xyo_all)

    npts = len(meas_xyo_all)
    if np.any(np.isnan(calc_xy)):
        raise RuntimeError(
            "infeasible pFull: may want to scale" +
            "back finite difference step size")

    # return values
    if simOnly:
        # return simulated values
        if return_value_flag in [None, 1]:
            retval = np.hstack([calc_xy_all, calc_omes_all.reshape(npts, 1)])
        else:
            rd = dict.fromkeys(det_keys_ordered)
            for det_key in det_keys_ordered:
                rd[det_key] = {'calc_xy': calc_xy_dict[det_key],
                               'calc_omes': calc_omes_dict[det_key]}
            retval = rd
    else:
        # return residual vector
        # IDEA: try angles instead of xys?
        diff_vecs_xy = calc_xy_all - meas_xyo_all[:, :2]
        diff_ome = xf.angularDifference(calc_omes_all, meas_xyo_all[:, 2])
        retval = np.hstack([diff_vecs_xy,
                            diff_ome.reshape(npts, 1)
                            ]).flatten()
        if return_value_flag == 1:
            # return scalar sum of squared residuals
            retval = sum(abs(retval))
        elif return_value_flag == 2:
            # return DOF-normalized chisq
            # TODO: check this calculation
            denom = 3*npts - len(gFit) - 1.
            if denom != 0:
                nu_fac = 1. / denom
            else:
                nu_fac = 1.
            retval = nu_fac * sum(retval**2)
    return retval