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 = xfcapi.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)): # debugging # TODO: remove this import pdb pdb.set_trace() 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([ xfcapi.mapAngle(oangs0[:, 2], omePeriod), xfcapi.mapAngle(oangs1[:, 2], omePeriod) ]) # do angular difference diff_omes = xfcapi.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 cart_to_angles(xys, panel, iviewer): ang_crds, _ = panel.cart_to_angles(xys, tvec_c=iviewer.instr.tvec) ang_crds = np.degrees(ang_crds) ang_crds[:, 1] = mapAngle(ang_crds[:, 1], HexrdConfig().polar_res_eta_period, units='degrees') return ang_crds
def simulate_diffractions(grain_params, experiment, controller): """actual forward simulation of the diffraction""" # use a packed array for the image_stack array_dims = (experiment.nframes, experiment.ncols, ((experiment.nrows - 1) // 8) + 1) image_stack = np.zeros(array_dims, dtype=np.uint8) count = len(grain_params) subprocess = 'simulate diffractions' _project = xrdutil._project_on_detector_plane rD = experiment.rMat_d chi = experiment.chi tD = experiment.tVec_d tS = experiment.tVec_s distortion = experiment.distortion eta_range = [ (-np.pi, np.pi), ] ome_range = experiment.ome_range ome_period = (-np.pi, np.pi) full_hkls = xrdutil._fetch_hkls_from_planedata(experiment.plane_data) bMat = experiment.plane_data.latVecOps['B'] wlen = experiment.plane_data.wavelength controller.start(subprocess, count) for i in range(count): rC = xfcapi.makeRotMatOfExpMap(grain_params[i][0:3]) tC = np.ascontiguousarray(grain_params[i][3:6]) vInv_s = np.ascontiguousarray(grain_params[i][6:12]) ang_list = np.vstack( xfcapi.oscillAnglesOfHKLs(full_hkls[:, 1:], chi, rC, bMat, wlen, vInv=vInv_s)) # hkls not needed here all_angs, _ = xrdutil._filter_hkls_eta_ome(full_hkls, ang_list, eta_range, ome_range) all_angs[:, 2] = xfcapi.mapAngle(all_angs[:, 2], ome_period) proj_pts = _project(all_angs, rD, rC, chi, tD, tC, tS, distortion) det_xy = proj_pts[0] _write_pixels(det_xy, all_angs[:, 2], image_stack, experiment.base, experiment.inv_deltas, experiment.clip_vals) controller.update(i + 1) controller.finish(subprocess) return image_stack
def _normalize_angs_hkls(angs_0, angs_1, omePeriod, symHKLs_ix): # Interleave the two produced oang solutions to simplify later # processing oangs = np.empty((len(angs_0) * 2, 3), dtype=angs_0.dtype) oangs[0::2] = angs_0 oangs[1::2] = angs_1 # Map all of the angles at once oangs[:, 1] = xfcapi.mapAngle(oangs[:, 1]) oangs[:, 2] = xfcapi.mapAngle(oangs[:, 2], omePeriod) # generate array of symHKLs indices symHKLs_ix = symHKLs_ix * 2 hkl_idx = np.empty((symHKLs_ix[-1], ), dtype=int) start = symHKLs_ix[0] idx = 0 for end in symHKLs_ix[1:]: hkl_idx[start:end] = idx start = end idx += 1 return oangs, hkl_idx
def generate_ring_points(self, tths, etas, panel, display_mode): delta_eta_nom = np.degrees(np.median(np.diff(etas))) ring_pts = [] skipped_tth = [] for i, tth in enumerate(tths): # construct ideal angular coords ang_crds = np.vstack([np.tile(tth, len(etas)), etas]).T # !!! must apply offset xys_full = panel.angles_to_cart(ang_crds, tvec_c=self.tvec) # skip if ring not on panel if len(xys_full) == 0: skipped_tth.append(i) continue # clip to detector panel xys, on_panel = panel.clip_to_panel(xys_full, buffer_edges=False) if display_mode == ViewType.polar: # !!! apply offset correction ang_crds, _ = panel.cart_to_angles(xys, tvec_c=self.instrument.tvec) if len(ang_crds) == 0: skipped_tth.append(i) continue # Swap columns, convert to degrees ang_crds[:, [0, 1]] = np.degrees(ang_crds[:, [1, 0]]) # fix eta period ang_crds[:, 0] = xfcapi.mapAngle(ang_crds[:, 0], self.eta_period, units='degrees') # sort points for monotonic eta eidx = np.argsort(ang_crds[:, 0]) ang_crds = ang_crds[eidx, :] # branch cut delta_eta_est = np.median(np.diff(ang_crds[:, 0])) cut_on_panel = bool( xfcapi.angularDifference(np.min(ang_crds[:, 0]), np.max(ang_crds[:, 0]), units='degrees') < 2 * delta_eta_est) if cut_on_panel and len(ang_crds) > 2: split_idx = np.argmax( np.abs(np.diff(ang_crds[:, 0]) - delta_eta_est)) + 1 ang_crds = np.vstack([ ang_crds[:split_idx, :], nans_row, ang_crds[split_idx:, :] ]) # append to list with nan padding ring_pts.append(np.vstack([ang_crds, nans_row])) elif display_mode in [ViewType.raw, ViewType.cartesian]: if display_mode == ViewType.raw: # !!! distortion if panel.distortion is not None: xys = panel.distortion.apply_inverse(xys) # Convert to pixel coordinates # ??? keep in pixels? xys = panel.cartToPixel(xys) diff_tol = np.radians(self.delta_eta) + 1e-4 ring_breaks = np.where( np.abs(np.diff(etas[on_panel])) > diff_tol)[0] + 1 n_segments = len(ring_breaks) + 1 if n_segments == 1: ring_pts.append(np.vstack([xys, nans_row])) else: src_len = sum(on_panel) dst_len = src_len + len(ring_breaks) nxys = np.nan * np.ones((dst_len, 2)) ii = 0 for i in range(n_segments - 1): jj = ring_breaks[i] nxys[ii + i:jj + i, :] = xys[ii:jj, :] ii = jj i = n_segments - 1 nxys[ii + i:, :] = xys[ii:, :] ring_pts.append(np.vstack([nxys, nans_row])) return ring_pts, skipped_tth
def overlay(self, display_mode=ViewType.raw): sim_data = self.instrument.simulate_laue_pattern( self.plane_data, minEnergy=self.min_energy, maxEnergy=self.max_energy, rmat_s=self.sample_rmat, grain_params=[ self.crystal_params, ]) point_groups = {} keys = ['spots', 'ranges', 'hkls'] for det_key, psim in sim_data.items(): point_groups[det_key] = {key: [] for key in keys} # grab panel and split out simulation results # !!! note that the sim results are lists over number of grains # and here we explicitly have one. panel = self.instrument.detectors[det_key] xy_det, hkls_in, angles, dspacing, energy = psim # find valid points idx = ~np.isnan(energy[0]) # there is only one grain here # filter (tth, eta) results xy_data = xy_det[0][idx, :] angles = angles[0][idx, :] # these are in radians point_groups[det_key]['hkls'] = hkls_in[0][:, idx].T angles[:, 1] = xfcapi.mapAngle(angles[:, 1], np.radians(self.eta_period), units='radians') # !!! apply offset corrections to angles # convert to angles in LAB ref angles_corr, _ = xfcapi.detectorXYToGvec( xy_data, panel.rmat, self.sample_rmat, panel.tvec, self.instrument.tvec, constants.zeros_3, beamVec=self.instrument.beam_vector, etaVec=self.instrument.eta_vector) # FIXME modify output to be array angles_corr = np.vstack(angles_corr).T angles_corr[:, 1] = xfcapi.mapAngle(angles_corr[:, 1], np.radians(self.eta_period), units='radians') if display_mode == ViewType.polar: range_corners = self.range_corners(angles_corr) # Save the Laue spots as a list instead of a numpy array, # so that we can predictably get the id() of spots inside. # Numpy arrays do fancy optimizations that break this. spots = np.degrees(angles_corr).tolist() point_groups[det_key]['spots'] = spots point_groups[det_key]['ranges'] = np.degrees(range_corners) elif display_mode in [ViewType.raw, ViewType.cartesian]: # !!! verify this range_corners = self.range_corners(angles) panel = self.instrument.detectors[det_key] data = xy_data if display_mode == ViewType.raw: # Convert to pixel coordinates data = panel.cartToPixel(data) # Swap x and y, they are flipped data[:, [0, 1]] = data[:, [1, 0]] point_groups[det_key]['spots'] = data point_groups[det_key]['ranges'] = self.range_data( range_corners, display_mode, panel) return point_groups
def detector_borders(self, det): panel = self.detectors[det] row_vec, col_vec = panel.row_pixel_vec, panel.col_pixel_vec x_start, x_stop = col_vec[0], col_vec[-1] y_start, y_stop = row_vec[0], row_vec[-1] # Create the borders in Cartesian borders = [[[x, y_start] for x in col_vec], [[x, y_stop] for x in col_vec], [[x_start, y] for y in row_vec], [[x_stop, y] for y in row_vec]] # Convert each border to angles for i, border in enumerate(borders): angles, _ = detectorXYToGvec(border, panel.rmat, ct.identity_3x3, panel.tvec, ct.zeros_3, ct.zeros_3, beamVec=panel.bvec, etaVec=panel.evec) angles = np.array(angles) angles[1:, :] = mapAngle(angles[1:, :], np.radians(self.eta_period), units='radians') # Convert to degrees, and keep them as lists for # easier modification later borders[i] = np.degrees(angles).tolist() # Here, we are going to remove points that are out-of-bounds, # and we are going to insert None in between points that are far # apart (in the y component), so that they are not connected in the # plot. This happens for detectors that are wrapped in the image. x_range = np.degrees((self.tth_min, self.tth_max)) y_range = np.degrees((self.eta_min, self.eta_max)) # "Far apart" is currently defined as half of the y range max_y_distance = abs(y_range[1] - y_range[0]) / 2.0 for j in range(4): border_x, border_y = borders[j][0], borders[j][1] i = 0 # These should be the same length, but just in case... while i < len(border_x) and i < len(border_y): x, y = border_x[i], border_y[i] if (not x_range[0] <= x <= x_range[1] or not y_range[0] <= y <= y_range[1]): # The point is out of bounds, remove it del border_x[i], border_y[i] continue if i != 0 and abs(y - border_y[i - 1]) > max_y_distance: # Points are too far apart. Insert a None border_x.insert(i, None) border_y.insert(i, None) i += 1 i += 1 return borders
def generate_ring_points(self, tths, etas, panel, display_mode): ring_pts = [] for tth in tths: ang_crds = np.vstack([np.tile(tth, len(etas)), etas]).T if display_mode == ViewType.polar: # !!! apply offset correction ang_crds = _convert_angles( ang_crds, panel, identity_3x3, self.tvec, beam_vector=self.instrument.beam_vector, eta_vector=self.instrument.eta_vector ) # Swap columns, convert to degrees ang_crds[:, [0, 1]] = np.degrees(ang_crds[:, [1, 0]]) # fix eta period ang_crds[:, 0] = xfcapi.mapAngle( ang_crds[:, 0], self.eta_period, units='degrees' ) # sort points for monotonic eta eidx = np.argsort(ang_crds[:, 0]) ang_crds = ang_crds[eidx, :] # append to list with nan padding ring_pts.append(np.vstack([ang_crds, nans_row])) elif display_mode in [ViewType.raw, ViewType.cartesian]: # !!! must apply offset xys_full = panel.angles_to_cart(ang_crds, tvec_c=self.tvec) # !!! distortion if panel.distortion is not None: xys_full = panel.distortion.apply_inverse(xys_full) # clip to detector panel xys, on_panel = panel.clip_to_panel( xys_full, buffer_edges=False ) if display_mode == ViewType.raw: # Convert to pixel coordinates # ??? keep in pixels? xys = panel.cartToPixel(xys) diff_tol = np.radians(self.delta_eta) + 1e-4 ring_breaks = np.where( np.abs(np.diff(etas[on_panel])) > diff_tol )[0] + 1 n_segments = len(ring_breaks) + 1 if n_segments == 1: ring_pts.append(np.vstack([xys, nans_row])) else: src_len = sum(on_panel) dst_len = src_len + len(ring_breaks) nxys = np.nan*np.ones((dst_len, 2)) ii = 0 for i in range(n_segments - 1): jj = ring_breaks[i] nxys[ii + i:jj + i, :] = xys[ii:jj, :] ii = jj i = n_segments - 1 nxys[ii + i:, :] = xys[ii:, :] ring_pts.append(np.vstack([nxys, nans_row])) return ring_pts
return np.hstack(resd) # resd # %% det_key = 'ge2' fig, ax = plt.subplots() rid = 0 ii = 0 for ring_data in powder_lines[det_key][rid]: tth_edges = ring_data[0][0] tth_centers = 0.5 * np.sum(np.vstack([tth_edges[:-1], tth_edges[1:]]), axis=0) eta = np.degrees(mapAngle(ring_data[0][1], (0, 2 * np.pi))) intensities = np.sum(np.array(ring_data[1]).squeeze(), axis=0) if ii < 1: iprev = 0 else: iprev = 0.25 * np.max( np.sum(powder_lines[det_key][rid][ii - 1][1], axis=0)) ax.plot(tth_centers, intensities + iprev) ii += 1 p0 = fitpeak.estimate_pk_parms_1d(tth_centers, intensities, pktype) p = fitpeak.fit_pk_parms_1d(p0, tth_centers, intensities, pktype) if pktype == 'pvoigt': fp0 = fitpeak.pkfuncs.pvoigt1d(p0, tth_centers)