def make_indices(self): arshape = self.dims[0] / 2 + 1, self.dims[1] nv = (arshape[0] - 1) * 2 nh = arshape[0] print("NV,NH", nv, nh) self.ftimshape = (nv, nh) self.ftimlen = nv * nh n1 = (self.dims[0] / 2 + 1) * self.dims[1] xv = numpy.arange(0, self.dims[0] / 2 + 1, 1, dtype=numpy.float32) # dimensions? cth = numpy.cos(self.theta) # 1D sth = numpy.sin(self.theta) # 1D ia = numpy.round(numpy.outer(cth, xv)).astype(numpy.int).ravel() ja = numpy.round(numpy.outer(sth, xv)).astype(numpy.int).ravel() on = numpy.ones(ja.shape, numpy.float32) jm = numpy.where(ja < 0, -on, on) numpy.multiply(ia, jm, ia) # if j<0: i=-i numpy.multiply(ja, jm, ja) # if j<0: j=-j # if j<0: f=f.conj() ia = numpy.where(ia < 0, nv + ia, ia) inds = (ia * nh + ja).ravel() self.conjer = jm self.inds = inds nim = numpy.zeros((nv * nh), numpy.float32) wons = numpy.ones((len(inds)), dtype=numpy.float32) # This is now more dense - bincount? cImageD11.put_incr(nim, inds, wons) nim = nim.astype(numpy.int) self.nim_div = nim + (nim == 0)
def test_put(self): data = np.zeros(10, np.float32) ind = np.arange(10).astype(np.intp) vals = np.ones(10, np.float32) cImageD11.put_incr(data, ind, vals) assert (data == vals).all() cImageD11.put_incr(data, ind, vals) assert (data == 2 * vals).all()
def test_as_flat(self): data = np.zeros((10, 10), np.float32) ind = np.ones(10, np.intp) * 50 vals = np.ones(10, np.float32) cImageD11.put_incr(np.ravel(data), ind, vals) assert (np.ravel(data)[50] == 10) assert (np.ravel(data)[49] == 0) assert (np.ravel(data)[51] == 0)
def test_put_twice(self): data = np.zeros(10, np.float32) ind = np.ones(10, np.intp) vals = np.ones(10, np.float32) cImageD11.put_incr(data, ind, vals) assert (data == np.array([0, 10] + [0] * 8, np.float)).all() cImageD11.put_incr(data, ind, vals) assert (data == np.array([0, 20] + [0] * 8, np.float)).all()
def gv_to_grid_new(self, gv): """ Put gvectors into our grid gv - ImageD11.indexing gvectors """ # Compute hkl indices in the fft unit cell logging.info("Gridding data") self.gv = gv hrkrlr = self.cell_size * gv hkl = np.round(hrkrlr).astype(int) # Filter to have the peaks in asym unit # ... do we need to do this? What about wrapping? hmx = hkl.max(axis=1) < (self.npx / 2. - 2.) hmn = hkl.min(axis=1) > (2. - self.npx / 2.) my_g = np.compress(hmx & hmn, gv, axis=0) # Compute hkl indices in the fft unit cell using filtered peaks hrkrlr = self.cell_size * my_g # Integer part of hkl (eg 1.0 from 1.9) hkl = np.floor(hrkrlr).astype(int) # Fractional part of indices ( eg 0.9 from 1.9) remain = hrkrlr - hkl grid = self.grid start = time.time() # Loop over corners with respect to floor corner ng = grid.shape[0] * grid.shape[1] * grid.shape[2] flatgrid = grid.reshape(ng) for cor in [ (0, 0, 0), #1 (1, 0, 0), #2 (0, 1, 0), #3 (0, 0, 1), #4 (1, 1, 0), #5 (1, 0, 1), #6 (0, 1, 1), #7 (1, 1, 1) ]: #8 # The corner thkl = hkl + cor fac = 1 - abs(remain - cor) vol = abs(fac[:, 0] * fac[:, 1] * fac[:, 2]).astype(np.float32) thkl = np.where(thkl < 0, self.npx + thkl, thkl) ind = thkl[:,0]*grid.shape[1]*grid.shape[2] + \ thkl[:,1]*grid.shape[1] + \ thkl[:,2] cImageD11.put_incr(flatgrid, ind.astype(np.intp), vol) logging.info("Grid filling loop takes " + str(time.time() - start) + " /s")
def moments(self, spline=None): titles = "1 I fI sI".split() # for now npx = cImageD11.s2D_1 I = cImageD11.s2D_I sI = cImageD11.s2D_sI fI = cImageD11.s2D_fI # results c = { '1': np.zeros(self.ncomp, 'f'), 'I': np.zeros(self.ncomp, 'f'), 'sI': np.zeros(self.ncomp, 'f'), 'fI': np.zeros(self.ncomp, 'f'), 'oI': np.zeros(self.ncomp, 'f'), } for i, f in enumerate(self.frames): m = sparseframe.sparse_moments(f, 'intensity', 'localmax') # data , ind, vals : data[ind] += vals inds = self.labels[self.cpks[i]:self.cpks[i + 1]] cImageD11.put_incr(c['1'], inds, m[:, npx]) cImageD11.put_incr(c['I'], inds, m[:, I]) cImageD11.put_incr(c['sI'], inds, m[:, sI]) cImageD11.put_incr(c['fI'], inds, m[:, fI]) cImageD11.put_incr(c['oI'], inds, m[:, I] * self.omega[i]) s_raw = c['sI'] / c['I'] f_raw = c['fI'] / c['I'] omega = c['oI'] / c['I'] if spline is not None: sc, fc = spatial_correct(s_raw, f_raw, spline) else: sc, fc = s_raw, f_raw results = { 'sc': sc, 'fc': fc, 'omega': omega, 'Number_of_pixels': c['1'], 'avg_intensity': c['I'] / c['1'], 's_raw': s_raw, 'f_raw': f_raw, 'sum_intensity': c['I'], } return results
def process_sinogram(self, sinogram, do_interpolation=False): """ sinogram is from the data dimensions [npixels, nangles] do_interp - tries to fill in some of the missing data in fourier space returns the radon transform """ assert sinogram.shape == self.dims ar = numpy.fft.rfft(sinogram, axis=0) faprojr = (ar.T.real.astype(numpy.float32)).ravel() faprojc = (ar.T.imag.astype(numpy.float32)).ravel() numpy.multiply(faprojc, self.conjer, faprojc) fimr = numpy.zeros(self.ftimlen, numpy.float32) fimc = numpy.zeros(self.ftimlen, numpy.float32) cImageD11.put_incr(fimr, self.inds, faprojr) cImageD11.put_incr(fimc, self.inds, faprojc) fim = fimr + fimc * 1j fim = numpy.divide(fimr + fimc * 1j, self.nim_div) fim.shape = self.ftimshape return fim
def add_image(self, om, data): """ RSV = bounds of reciprocal space vol NR = dims of RSV k = scattering vector for image at om == 0 data = 2D image (dims == k.dims) SIG = signal MON = monitor """ dat = numpy.ravel(data).astype(numpy.float32) assert len(dat) == len(self.k[0]), "dimensioning issue" # hkl = ubi.( gtok. k ) gvm = transform.compute_g_from_k( numpy.eye(3), # this transform module sucks om * float(self.pars.get('omegasign')), wedge=float(self.pars.get('wedge')), chi=float(self.pars.get('chi'))) tmat = numpy.dot(self.uspace, gvm) hkls = numpy.dot(tmat, self.k) # Find a way to test if we are doing the transform OK # Bounds checks # for i in range(3): # assert hkls[i].min() > self.bounds[i][0], \ # "%d %s %s"%(i, str(hkls[i].min()),str( self.bounds[i][0])) # assert hkls[i].max() < self.bounds[i][1], \ # "%d %s %s"%(i, str(hkls[i].max()),str( self.bounds[i][1])) NR = self.rsv.NR # hkls[0] is the slowest index. integer steps of NR[1]*NR[2] ind = numpy.floor(hkls[0] + 0.5 - self.bounds[0][0]).astype(numpy.intp) numpy.multiply(ind, NR[1] * NR[2], ind) assert ind.dtype == numpy.intp # hkls[1] is faster. Steps by NR[2] only numpy.add( ind, NR[2] * numpy.floor(hkls[1] + 0.5 - self.bounds[1][0]).astype(numpy.int32), ind) numpy.add( ind, numpy.floor(hkls[2] + 0.5 - self.bounds[2][0]).astype(numpy.int32), ind) # # # if self.maxpix is not None: msk = numpy.where(dat > self.maxpix, 0, 1).astype(numpy.uint8) else: msk = None if self.mask is not None: # This excludes saturated pixels if msk is None: msk = self.mask else: numpy.multiply(msk, numpy.ravel(self.mask), msk) # cases: # maxpix only == msk # mask only == msk # maxpix and mask == msk # neither if msk is not None: numpy.multiply(dat, msk, dat) cImageD11.put_incr(self.rsv.SIG, ind, dat) cImageD11.put_incr(self.rsv.MON, ind, self.lorfac * msk) else: cImageD11.put_incr(self.rsv.SIG, ind, dat) cImageD11.put_incr(self.rsv.MON, ind, self.lorfac) return
def update_wtd(recon, proj, angle, msk, dbg=True): """ recon is the current reconstruction proj is a projection at angle (degrees) the middle pixel of proj matches the middle pixel of recon TODO: angle + offset as more general geometric term """ assert len(recon.shape) == 2 assert len(proj.shape) == 1 rads = angle * np.pi / 180.0 cth = np.cos(rads).astype(np.float32) sth = np.sin(rads).astype(np.float32) # For each pixel in recon, compute the array index in proj nx = recon.shape[0] ny = recon.shape[1] x, y = np.mgrid[-nx / 2:nx / 2, -ny / 2:ny / 2] # pos is a 2D array of positions in reconstruction pos = np.zeros(x.shape, np.float32).ravel() np.add(x.ravel() * cth, y.ravel() * sth, pos) # Lower & upper pixel: idx_lo = np.floor(pos).astype(np.int) idx_hi = idx_lo + 1 # idx will go from -xxx to xxx mn = idx_lo.min() mx = idx_hi.max() + 1 # Weights: wt_lo = np.subtract(idx_hi, pos, np.zeros(pos.shape, np.float32)) wt_hi = np.subtract(pos, idx_lo, np.zeros(pos.shape, np.float32)) wt_lo = np.where(msk.ravel(), wt_lo, 0) wt_hi = np.where(msk.ravel(), wt_hi, 0) # wtc = wt_lo + wt_hi calc_proj = np.zeros((mx - mn), np.float32) r = recon.ravel() np.subtract(idx_lo, mn, idx_lo) # Move these to offsets in calc_proj np.subtract(idx_hi, mn, idx_hi) cImageD11.put_incr(calc_proj, idx_lo, r * wt_lo) cImageD11.put_incr(calc_proj, idx_hi, r * wt_hi) error = np.zeros(calc_proj.shape, np.float32) start = (len(calc_proj) - len(proj)) / 2 error[start:start + len(proj)] = proj error = error - calc_proj npcalc_proj = np.zeros((mx - mn), np.float32) cImageD11.put_incr(npcalc_proj, idx_hi, wt_hi) cImageD11.put_incr(npcalc_proj, idx_lo, wt_lo) npcalc_proj = np.where(npcalc_proj > 0, npcalc_proj, 1) # update = np.zeros( r.shape, np.float32) update = wt_hi * np.take(error / npcalc_proj, idx_hi) update += wt_lo * np.take(error / npcalc_proj, idx_lo) # Now make calc_proj align with the supplied proj. # Convention will be to make the central pixel of our image # match the central pixel of proj. Logically this is the central # pixel of calc_proj too... # Now take this error off of recon according to the weights #tot = np.zeros( (mx-mn), np.float32 ) #cImageD11.put_incr( tot, idx_hi, wt_hi) #cImageD11.put_incr( tot, idx_lo, wt_lo) #pl.imshow(np.reshape(update,recon.shape)) #pl.colorbar() #pl.show() # update = update update.shape = recon.shape print(update.sum(), error.sum(), end=' ') if dbg: pl.figure() pl.imshow(np.reshape(update, recon.shape)) pl.colorbar() # pl.show() return update
def main(): """ A CLI user interface """ import sys, time, os, logging start = time.time() root = logging.getLogger('') root.setLevel(logging.WARNING) try: from optparse import OptionParser parser = OptionParser() parser = get_options(parser) options, args = parser.parse_args() except SystemExit: raise except: parser.print_help() print("\nProblem with your options:") raise if options.mask is not None: fit2dmask = (1 - openimage(options.mask).data).ravel() else: fit2dmask = 1.0 first_image = True imagefiles = ImageD11_file_series.get_series_from_options(options, args) tthvals = numpy.load(options.lookup + "_tth.npy") try: for fim in imagefiles: dataim = fim.data print(fim.filename) if first_image: # allocate volume, compute k etc first_image = False dxim = openimage(options.lookup + "_dx.edf").data dyim = openimage(options.lookup + "_dy.edf").data outsum = numpy.ravel(numpy.zeros(dataim.shape, numpy.float32)) outnp = numpy.ravel(numpy.zeros(dataim.shape, numpy.float32)) e = edfimage() # C code from rsv_mapper (not intended to be obfuscated) o = blobcorrector.perfect() idealx, idealy = o.make_pixel_lut(dataim.shape) destx, desty = idealx + dxim, idealy + dyim assert destx.min() >= 0 assert destx.max() < dataim.shape[1] assert desty.min() >= 0 assert desty.max() < dataim.shape[1] imageshape = dataim.shape indices = numpy.ravel(destx).astype(numpy.intp) numpy.multiply(indices, dataim.shape[1], indices) numpy.add(indices, numpy.ravel(desty).astype(numpy.intp), indices) assert indices.min() >= 0 assert indices.max() < dataim.shape[0] * dataim.shape[1] on = numpy.ones(len(outnp), numpy.float32) if fit2dmask is not None: on = on * fit2dmask # Number of pixels and mask are constant cImageD11.put_incr(outnp, indices, on) mask = outnp < 0.1 scalar = (1.0 - mask) / (outnp + mask) flatshape = outsum.shape # arsorted = mask.copy() outmask = mask.copy() outmask = outmask * 1e6 outmask.shape = imageshape arsorted.shape = imageshape arsorted.sort(axis=1) minds = numpy.array([l.searchsorted(0.5) for l in arsorted]) # ENDIF firstimage start = time.time() numpy.multiply(outsum, 0, outsum) outsum.shape = flatshape dm = (dataim.ravel() * fit2dmask).astype(numpy.float32) cImageD11.put_incr(outsum, indices, dm) # outsum = outsum.reshape( dataim.shape ) # outnp = outnp.reshape( dataim.shape ).astype(numpy.int32) # Normalise numpy.multiply(outsum, scalar, outsum) print(dataim.max(), dataim.min(), end=' ') print(scalar.max(), scalar.min(), outsum.min(), outsum.max()) outsum.shape = imageshape # saving edf e.data = outsum e.write("r_" + fim.filename, force_type=numpy.float32) print(time.time() - start) except: raise