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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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