def Dobs(t, sc, fc, omega, pars): """ Compute tth0, eta0 and derivatives given: t = (tx,ty,tz) grain position sc,fc = pixel positions of spots omega = sample rotation angle pars = ImageD11 parameters (dict) with wavelength, distance, tilts, etc returns tth, eta, dtth, deta """ mypars = pars.parameters.copy() mypars['t_x'] = t[0] mypars['t_y'] = t[1] mypars['t_z'] = t[2] # tth, eta for the spots tth0, eta0 = transform.compute_tth_eta((sc, fc), omega=omega, **mypars) # arrays for dtth/dt_{xyz} and deta/dt_{xyz} dtth = np.zeros((3, len(sc))) deta = np.zeros((3, len(sc))) # Step size for numerical derivative s = 1.0 for i, p in enumerate(("t_x", "t_y", "t_z")): # reset mypars['t_x'] = t[0] mypars['t_y'] = t[1] mypars['t_z'] = t[2] # shift + and - mypars[p] = t[i] + s / 2.0 tth1, eta1 = transform.compute_tth_eta((sc, fc), omega=omega, **mypars) mypars[p] = t[i] - s / 2.0 tth2, eta2 = transform.compute_tth_eta((sc, fc), omega=omega, **mypars) dtth[i] = (tth1 - tth2) / s deta[i] = angmod(eta1 - eta2) / s return tth0, eta0, dtth, deta
def get_hkl(self, event): # canvas x and y take the screen coords from the event and translate # them into the coordinate system of the canvas object xpos = self.canvasObject.canvasx(event.x) / self.zoom ypos = self.canvasObject.canvasy(event.y) / self.zoom print "xpos,ypos", xpos, ypos from ImageD11 import transform tth, eta = transform.compute_tth_eta(np.array([[xpos], [ypos]]), **self.parameters) print "omega:", self.omega, type(self.omega) om = np.array([float(self.omega)]) print "tth,eta,om", tth, eta, om self.gv = transform.compute_g_vectors( tth, eta, om, float(self.parameters['wavelength']), self.parameters['wedge']) self.gv = np.transpose(self.gv) s = "" i = 0 for ubi in self.ubisread: h = np.dot(ubi, self.gv.T) print "i=%d" % (i), "hkl= %.2f %.2f %.2f" % tuple(h) i += 1 s += "grain %3d\n h = %.2f k=%.2f l = %.2f\n" % (i, h[0], h[1], h[2]) showinfo( "Right clicked", "You click at %f %f, tth=%f eta=%f omega=%f\n %s" % (xpos, ypos, tth, eta, om, s))
def make_powder_mask( parfile, ndeg = 1, splinefile=None, dims=(2048, 2048) ): """ Compute a two theta and azimuth image """ pars = parameters.parameters() pars.loadparameters( parfile ) if splinefile is None: spatial = blobcorrector.perfect() else: spatial = blobcorrector.correctorclass( splinefile ) xim, yim = spatial.make_pixel_lut ( dims ) peaks = [ np.ravel( xim ) , np.ravel( yim ) ] tth , eta = transform.compute_tth_eta( peaks , **pars.get_parameters() ) tth.shape = dims eta.shape = dims # Assume a circle geometry for now # tth * eta ~ length on detector # lim = tth * eta # need some idea how to cut it up... # degree bins m = (eta.astype(np.int) % 2)==0 return m
def make_k_vecs(self): """ Generate the k vectors from the experiment parameters given in constructor """ xim, yim = self.spatial.make_pixel_lut(self.dims) peaks = [numpy.ravel(xim), numpy.ravel(yim)] # First, x, is the slow pixel direction, should not change # when raveled #for i in range(10): # print "slow, fast" # print peaks[0][i],peaks[1][i] assert abs(peaks[0][10] - peaks[0][0]) < 3 # Second, y, is the fast, should change by ~ 1 pixel per pixel assert abs(peaks[1][10] - peaks[1][0] - 10) < 3 tth, eta = transform.compute_tth_eta(peaks, **self.pars.get_parameters()) self.k = transform.compute_k_vectors(tth, eta, self.pars.get('wavelength')) # FIXME # This should be something like domega/dk where # dk [ k(omega=0) - k(omega=1) ] self.lorfac = numpy.ones(self.dims[0] * self.dims[1], numpy.float32)
def test_xyz_from_tth_eta(self): # Check the compute_xyz_from_tth_eta works # mm yc = 1032. ys = 0.05 ty = 0.001 zc = 1024. zs = 0.047 tz = -0.002 dist = 112.345 omega = np.ones(len(self.peaks[0])) tth, eta = transform.compute_tth_eta(self.peaks, y_center=yc, y_size=ys, tilt_y=ty, z_center=zc, z_size=zs, tilt_z=tz, distance=dist) fc, sc = transform.compute_xyz_from_tth_eta(tth, eta, omega, y_center=yc, y_size=ys, tilt_y=ty, z_center=zc, z_size=zs, tilt_z=tz, distance=dist) self.assertAlmostEqual(np.abs(sc - self.peaks[0]).sum(), 0, 5) self.assertAlmostEqual(np.abs(fc - self.peaks[1]).sum(), 0, 5)
def compute_gv(self,g): """ Makes self.gv refer be g-vectors computed for this grain in this scan """ try: xc = self.scantitles.index("xc") except: print(self.scantitles) raise # print self.scandata[scanname].shape x = self.scandata[:,xc] yc = self.scantitles.index("yc") y = self.scandata[:,yc] om = self.scantitles.index("omega") om = self.scandata[:,om] tth,eta = transform.compute_tth_eta( np.array([x, y]) , self.parameters['y-center'], self.parameters['y-size'], self.parameters['tilt-y'], self.parameters['z-center'], self.parameters['z-size'], self.parameters['tilt-z'], self.parameters['distance']*1.0e3, crystal_translation = g.translation, omega = om, axis_orientation1 = self.parameters['wedge'], axis_orientation2 = self.parameters['chi']) self.gv = transform.compute_g_vectors(tth,eta,om, float(self.parameters['wavelength']), self.parameters['wedge']) self.gv = np.transpose(self.gv)
def tth_ds_max(pars, detector_size): # tth of the four corners. corners = [(0, 0, detector_size[0], detector_size[0]), (0, detector_size[1], detector_size[1], 0)] tth_c, eta_c = transform.compute_tth_eta(corners, **pars.parameters) tthmax = tth_c.max() dsmax = 2 * np.sin(np.radians(tthmax / 2)) / pars.get("wavelength") return tthmax, dsmax
def compute_tth_eta_lut(splinefile, pars, dims): """ Computes look up values of tth, eta for each pixel """ c = blobcorrector.correctorclass(splinefile) p = parameters.read_par_file(pars) xp, yp = c.make_pixel_lut(dims) t, e = transform.compute_tth_eta((xp.ravel(), yp.ravel()), **p.parameters) t.shape = dims e.shape = dims return t, e
def readimage(self, image): from ImageD11 import transform from fabio import openimage self.imageobj = openimage.openimage(image) # map from 2048x2048 to 1024x1024 d = self.imageobj.data.astype(numpy.float32) mi = d.mean() - d.std() * 2 mx = d.mean() * d.std() * 2 shape = self.imageobj.data.shape d = numpy.reshape(numpy.clip(self.imageobj.data, mi, mx), shape) # makes a clipped copy d = (255. * (d - mi) / (mx - mi)) # scale intensity print d.min(), d.max(), d.mean() self.image = numpy.zeros((1024, 1024), numpy.uint8) if d.shape == (2048, 2048): # rebin 2x2 im = (d[::2, ::2] + d[::2, 1::2] + d[1::2, ::2] + d[1::2, 1::2]) / 4 self.image = (255 - im).astype(numpy.uint8).tostring() self.imageWidth = 1024 self.imageHeight = 1024 # make a 2D array of x,y p = [] pk = [] step = 64 r = [[0, 0], [0, step], [step, step], [step, 0]] for i in range(0, 1024, step): for j in range(0, 1024, step): # i,j 1024x1024 texture coords # x,y spatially corrected for v in r: pk.append([i + v[0], j + v[1]]) x, y = self.corrector.correct((i + v[0]) * 2, (j + v[1]) * 2) # corrected p.append([x, y]) p = numpy.array(p).T pk = numpy.array(pk).T omega = float(self.imageobj.header['Omega']) self.pars['distance'] = float(self.pars['distance']) * 1000 tth, eta = transform.compute_tth_eta(p, **self.pars) gve = transform.compute_g_vectors(tth, eta, omega * self.pars['omegasign'], self.pars['wavelength']) self.pts = [] print "Setting up image mapping", p.shape, gve.shape for i in range(pk.shape[1]): self.pts.append([ pk[1, i] / 1024., pk[0, i] / 1024., gve[0, i], gve[1, i], gve[2, i] ]) #for p in self.pts: # print p self.setupTexture()
def find_vol(self, border, omegarange): """ find limiting volume The four image corners over 360 degrees np is the number of pixels per hkl returns (RSV, NR) RSV min/max in reciprocal space (np*ubi).gv NR number of points == 1+RSV[i][1]-RSV[i][0] """ # Note that ImageD11 peaks are [slow, fast] # 1 2 3 # 4 5 6 # 7 8 9 p1 = [ -border, self.dims[0] / 2, self.dims[0] + border, self.dims[0] / 2, self.dims[0] + border, -border, self.dims[0] + border, -border, self.dims[0] / 2 ] p2 = [ -border, self.dims[1] / 2, self.dims[1] + border, -border, self.dims[1] / 2, self.dims[1] + border, -border, self.dims[1] / 2, self.dims[1] + border ] for i in range(9): p1[i], p2[i] = self.spatial.correct(p1[i], p2[i]) peaks = [p1 * len(omegarange), p2 * len(omegarange)] om = numpy.array(list(omegarange) * 9, numpy.float32) tth, eta = transform.compute_tth_eta(peaks, **self.pars.get_parameters()) #print "tth",tth.min(),tth.max() #print "eta",eta.min(),eta.max() assert om.shape == tth.shape gv = transform.compute_g_vectors(tth, eta, om, self.pars.get('wavelength'), float(self.pars.get('wedge')), float(self.pars.get('chi'))) # Rotate g-vectors into target volume hkls = numpy.dot(self.uspace, gv) # print "Ranges for RSV" bounds = numpy.zeros((3, 2)) npv = numpy.zeros(3) for i in range(3): bounds[i][0] = numpy.floor(hkls[i].min()) bounds[i][1] = numpy.ceil(hkls[i].max()) npv[i] = (bounds[i][1] - bounds[i][0]) + 1 self.bounds = bounds self.rsv = rsv.rsv(npv, bounds=bounds, np=self.np) # Cross your fingers and.... self.rsv.allocate_vol()
def test_compute_tth_eta1(self): # Check translation of 0,0,0 has no effect yc = 49. ; ys=0.05 ; ty = 0.001 zc = 51. ; zs=0.04 ; tz =-0.002 dist = 112.345 not_trans = transform.compute_tth_eta(self.peaks, y_center=yc, y_size=ys, tilt_y=ty, z_center=zc, z_size=zs, tilt_z=tz, distance=dist) om = np.ones(self.peaks.shape[1], np.float) trans = transform.compute_tth_eta(self.peaks, y_center=yc, y_size=ys, tilt_y=ty, z_center=zc, z_size=zs, tilt_z=tz, distance=dist, t_x=0.,t_y=0.,t_z=0., omega=om, wedge=10., chi=-11.) diff = not_trans[0] - trans[0] self.assertAlmostEqual(np.sum(diff*diff), 0, 5 ) diff = not_trans[1] - trans[1] self.assertAlmostEqual(np.sum(diff*diff), 0, 5 )
def calccolumns(p, c, g, pks=None): """ p = parameters c = columnfile g = grain pks = selection of which peaks to use for the grain. If none we do all. """ t = g.translation p.set('t_x', t[0]) p.set('t_y', t[1]) p.set('t_z', t[2]) # tth, eta of the spots given this origin position if pks is None: pks = ~np.isnan(c.sc) tth, eta = transform.compute_tth_eta([c.sc[pks], c.fc[pks]], omega=c.omega[pks], **p.parameters) # g-vectors given this origin gve = transform.compute_g_vectors(tth, eta, c.omega[pks], p.get("wavelength"), p.get("wedge"), p.get("chi")) # Find hkl indices hklo = np.dot(g.ubi, gve) hkli = np.round(hklo) diff = hklo - hkli # Now uncompute to get ideal spot positions in each case: gcalc = np.dot(g.ub, hkli) tthcalc, etacalc, omegacalc = transform.uncompute_g_vectors( gcalc, p.get("wavelength"), p.get("wedge"), p.get("chi")) # which eta to choose - there are two possibilities # ... eta should always be in -180, 180 as it is arctan2 smatch = np.sign(eta) == np.sign(etacalc[0]) etachosen = np.where(smatch, etacalc[0], etacalc[1]) omegachosen = np.where(smatch, omegacalc[0], omegacalc[1]) # deal with the mod360 for omega omegachosen = mod360(omegachosen, c.omega[pks]) fcc, scc = transform.compute_xyz_from_tth_eta(tthcalc, etachosen, omegachosen, **p.parameters) # how close to reciprocal lattice point (could throw out some peaks here...) drlv = np.sqrt((diff * diff).sum(axis=0)) # save arrays to colfile: c.drlv[pks] = drlv c.tth_per_grain[pks] = tth c.eta_per_grain[pks] = eta c.tthcalc[pks] = tthcalc c.etacalc[pks] = etachosen c.omegacalc[pks] = omegachosen c.sccalc[pks] = scc c.fccalc[pks] = fcc return c
def test_xyz_from_tth_eta_trans(self): # Check the compute_xyz_from_tth_eta works # mm yc = 1032. ys = 0.05 ty = 0.001 zc = 1024. zs = 0.047 tz = -0.002 t_x = 0.1 t_y = 0.2 t_z = 0.3 dist = 112.345 omega = np.linspace(-720, 720, len(self.peaks[0])) # With translation tth, eta = transform.compute_tth_eta(self.peaks, omega=omega, t_x=t_x, t_y=t_y, t_z=t_z, y_center=yc, y_size=ys, tilt_y=ty, z_center=zc, z_size=zs, tilt_z=tz, distance=dist) fc, sc = transform.compute_xyz_from_tth_eta(tth, eta, omega, t_x=t_x, t_y=t_y, t_z=t_z, y_center=yc, y_size=ys, tilt_y=ty, z_center=zc, z_size=zs, tilt_z=tz, distance=dist) self.assertAlmostEqual(np.abs(sc - self.peaks[0]).sum(), 0, 5) self.assertAlmostEqual(np.abs(fc - self.peaks[1]).sum(), 0, 5)
def compute_tth_eta(self, dims): """ Find the twotheta and azimuth images """ assert len(dims) == 2 xim, yim = self.spatial.make_pixel_lut(dims) self.dims = dims peaks = [numpy.ravel(xim), numpy.ravel(yim)] tth, eta = transform.compute_tth_eta(peaks, **self.pars.get_parameters()) assert len(tth) == dims[0] * dims[1] assert len(eta) == dims[0] * dims[1] # Now we have the twotheta and azimuth images in memory # they are in degrees self.tth = numpy.reshape(tth, dims) # self.eta = numpy.mod(numpy.reshape( eta, dims ), 360)-180 self.eta = numpy.reshape(eta, dims) - eta.mean() self.compute_rad_arc()
def update_cols( flt, pars, OMSLOP ): """ update the twotheta, eta, g-vector columns to be sure they are right fill in some weighting estimates for fitting """ tth, eta = transform.compute_tth_eta( [flt.sc, flt.fc], **pars.parameters ) gve = transform.compute_g_vectors( tth, eta, flt.omega, pars.get('wavelength'), wedge=pars.get('wedge'), chi=pars.get('chi') ) flt.addcolumn( tth , "tth" ) flt.addcolumn( eta , "eta" ) # Compute the relative tth, eta, omega errors ... wtth, weta, womega = estimate_weights( pars, flt, OMSLOP ) flt.addcolumn( wtth, "wtth" ) flt.addcolumn( weta, "weta" ) flt.addcolumn( womega, "womega" ) flt.addcolumn( gve[0], "gx" ) flt.addcolumn( gve[1], "gy" ) flt.addcolumn( gve[2], "gz" ) return tth, eta, gve
import pylab as pl # put parfile, npeaks and tol and this would be general purpose! c = columnfile(sys.argv[1]) p = read_par_file(sys.argv[2]) tol = float(sys.argv[3]) tthmax = float(sys.argv[4]) outfile = sys.argv[5] npx = int(sys.argv[6]) top = int(sys.argv[7]) c.filter(c.Number_of_pixels > npx) u = unitcell_from_parameters(p) w = p.get("wavelength") tth, eta = compute_tth_eta((c.sc, c.fc), **p.parameters) dsmax = 2 * np.sin(1.03 * tth.max() * np.pi / 360) / w u.makerings(dsmax) mask = np.zeros(c.nrows, dtype=np.bool) for d in u.ringds: tthc = np.arcsin(w * d / 2) * 360 / np.pi M = len(u.ringhkls[d]) print("hkl", u.ringhkls[d][-1], M, end=" ") sel = abs(tth - tthc) < tol nring = sel.sum() print(nring, end=" ") if nring == 0: print() continue
def getPlotData(self, grainnumber, whattoplot): grain = self.grains[grainnumber] peaks = grain.getPeaks() npeaks = len(peaks) # Will hold predicted peak positions, ttheta, eta, omega tthetaPred = numpy.zeros(npeaks) etaPred = numpy.zeros(npeaks) omegaPred = numpy.zeros(npeaks) # Will hold measured peak positions, f, s, and omega fsmeasured = numpy.zeros([2, npeaks]) omegaexp = numpy.zeros([npeaks]) # Filling up the array i = 0 for peak in peaks: tthetaPred[i] = peak.getTThetaPred() etaPred[i] = peak.getEtaPred() omegaPred[i] = peak.getOmegaPred() try: index = self.idlist.index(peak.getPeakID()) fsmeasured[1, i] = self.peaksflt[index]['fc'] fsmeasured[0, i] = self.peaksflt[index]['sc'] omegaexp[i] = self.peaksflt[index]['omega'] except IndexError: print( "Failed to locate peak ID %d which was found in grain %s" % (peak.getPeakID(), grain.getName())) return i += 1 # eta vs 2 theta if (whattoplot == "etavsttheta"): # Calculating 2theta and eta for experimental peaks (tthetaexp, etaexp) = transform.compute_tth_eta( fsmeasured, **self.imageD11Pars.parameters) # Bringing eta into 0-360 range instead of -180-180 etaexp = etaexp % 360 # Preparing information to add diffraction rings ringstth = numpy.unique(tthetaPred) rings = [] for tth in ringstth: eta = numpy.array([0., 180., 360.]) ttheta = numpy.full((len(eta)), tth) omega = numpy.full((len(eta)), 0.) rings.append([eta, ttheta]) # Ready to plot return [ "Grain %s" % (grainnumber + 1), '2theta (degrees)', 'eta (degrees)', tthetaexp, etaexp, tthetaPred, etaPred, rings ] # omega vs 2 theta elif (whattoplot == "omegavsttheta"): # Calculating 2theta and eta for experimental peaks (tthetaexp, etaexp) = transform.compute_tth_eta( fsmeasured, **self.imageD11Pars.parameters) # Bringing eta into 0-360 range instead of -180-180 etaexp = etaexp % 360 # Preparing information to add diffraction rings ringstth = numpy.unique(tthetaPred) rings = [] omegam = min(min(omegaexp), min(omegaPred)) omegaM = max(max(omegaexp), max(omegaPred)) for tth in ringstth: omega = numpy.array([omegam - 1., omegaM + 1.]) ttheta = numpy.full((len(omega)), tth) rings.append([omega, ttheta]) # Ready to plot, using multithreading to be able to have multiple plots, did not work!! return [ "Grain %s" % (grainnumber + 1), '2theta (degrees)', 'omega (degrees)', tthetaexp, omegaexp, tthetaPred, omegaPred, rings ] # s vs f (as on detector) else: # Calculating predicted peak positions from angles (fpred, spred) = transform.compute_xyz_from_tth_eta( tthetaPred, etaPred, omegaPred, **self.imageD11Pars.parameters) # Preparing information to add diffraction rings ringstth = numpy.unique(tthetaPred) rings = [] for tth in ringstth: eta = numpy.arange(0., 362., 2.) ttheta = numpy.full((len(eta)), tth) omega = numpy.full((len(eta)), 0.) rings.append( transform.compute_xyz_from_tth_eta( ttheta, eta, omega, **self.imageD11Pars.parameters)) # Ready to plot return [ "Grain %s" % (grainnumber + 1), 'f (pixels)', 's (pixels)', fsmeasured[0, :], fsmeasured[1, :], spred, fpred, rings ]