def interpolate(h, hnext, filter): """ interpolate h into hnext, this needs a lot of memory(full mesh of the lower level) """ # round down exbot = (hnext['Offset'] * h['Nmesh']) // hnext['Nmesh'] # round up extop = ((hnext['Offset'] + hnext['Size']) * h['Nmesh'] + h['Nmesh'] - 1)// hnext['Nmesh'] print h['Nmesh'], 'box', exbot, extop overlay = joinchunks(h, exbot, extop) src = overlay.reshape(*(extop-exbot)) if filter >= 2: src['delta'] = spline_filter(src['delta'], order=filter) for d in range(3): src['disp'][:, d] = spline_filter(src['disp'][:, d], order=filter) for fn in list(yieldfilename(hnext, lookfor='delta1')): # read in the current level displacement chunk = readchunk(hnext, fn, None, None, extra='1') ipos = chunk['ipos'] ipos = 1.0 * ipos * h['Nmesh'] / hnext['Nmesh'] - exbot chunk['delta'] += map_coordinates(src['delta'], ipos.T, order=filter, prefilter=False) for d in range(3): chunk['disp'][:, d] += map_coordinates(src['disp'][..., d], ipos.T, order=filter, prefilter=False) # write to the full displacement writechunk(hnext, fn, chunk)
def xy2lonlat(self, x, y): """Calculate x,y in own projection from given lon,lat (scalars/arrays). """ if self.projected is True: if self.proj.is_latlong(): return x, y else: if 'ob_tran' in self.proj4: logging.info('NB: Converting degrees to radians ' + 'due to ob_tran srs') x = np.radians(np.array(x)) y = np.radians(np.array(y)) return self.proj(x, y, inverse=True) else: np.seterr(invalid='ignore') # Disable warnings for nan-values y = np.atleast_1d(np.array(y)) x = np.atleast_1d(np.array(x)) # NB: mask coordinates outside domain x[x < self.xmin] = np.nan x[x > self.xmax] = np.nan y[y < self.ymin] = np.nan y[y < self.ymin] = np.nan lon = map_coordinates(self.lon, [y, x], order=1, cval=np.nan, mode='nearest') lat = map_coordinates(self.lat, [y, x], order=1, cval=np.nan, mode='nearest') return (lon, lat)
def test_map_coordinates_dts(): # check that ndimage accepts different data types for interpolation data = np.array([[4, 1, 3, 2], [7, 6, 8, 5], [3, 5, 3, 6]]) shifted_data = np.array([[0, 0, 0, 0], [0, 4, 1, 3], [0, 7, 6, 8]]) idx = np.indices(data.shape) dts = (np.uint8, np.uint16, np.uint32, np.uint64, np.int8, np.int16, np.int32, np.int64, np.intp, np.uintp, np.float32, np.float64) for order in range(0, 6): for data_dt in dts: these_data = data.astype(data_dt) for coord_dt in dts: # affine mapping mat = np.eye(2, dtype=coord_dt) off = np.zeros((2,), dtype=coord_dt) out = ndimage.affine_transform(these_data, mat, off) assert_array_almost_equal(these_data, out) # map coordinates coords_m1 = idx.astype(coord_dt) - 1 coords_p10 = idx.astype(coord_dt) + 10 out = ndimage.map_coordinates(these_data, coords_m1, order=order) assert_array_almost_equal(out, shifted_data) # check constant fill works out = ndimage.map_coordinates(these_data, coords_p10, order=order) assert_array_almost_equal(out, np.zeros((3,4))) # check shift and zoom out = ndimage.shift(these_data, 1) assert_array_almost_equal(out, shifted_data) out = ndimage.zoom(these_data, 1) assert_array_almost_equal(these_data, out)
def eval_volume_at_3d_coordinates(volume, coords): """ Evaluates the volume data at the given coordinates using trilinear interpolation. Parameters ---------- volume : 3D array or 4D array Data volume. coords : ndarray of shape (N, 3) 3D coordinates where to evaluate the volume data. Returns ------- output : 2D array Values from volume. """ if volume.ndim <= 2 or volume.ndim >= 5: raise ValueError("Volume must be 3D or 4D!") if volume.ndim == 3: return map_coordinates(volume, coords.T, order=1, mode="nearest") if volume.ndim == 4: values_4d = [] for i in range(volume.shape[-1]): values_tmp = map_coordinates(volume[..., i], coords.T, order=1, mode="nearest") values_4d.append(values_tmp) return np.ascontiguousarray(np.array(values_4d).T)
def __call__( self, X, out=None ): """ query_values = Intergrid(...) ( query_points npt x dim ) """ X = np.asanyarray(X) assert X.shape[-1] == self.dim, ("the query array must have %d columns, " "but its shape is %s" % (self.dim, X.shape) ) Xdim = X.ndim if Xdim == 1: X = np.asarray([X]) # in a single point -> out scalar if self.copy: X = X.copy() assert X.ndim == 2, X.shape npt = X.shape[0] if out is None: out = np.empty( npt, dtype=self.griddata.dtype ) t0 = time() self._map_to_uniform_grid( X ) # X inplace #............................................................................... map_coordinates( self.griddata, X.T, order=self.order, prefilter=self.prefilter, mode="nearest", # outside -> edge # test: mode="constant", cval=np.NaN, output=out ) if self.verbose: print "Intergrid: %.3g msec %d points in a %s grid %d maps order %d" % ( (time() - t0) * 1000, npt, self.griddata.shape, self.nmap, self.order ) return out if Xdim == 2 else out[0]
def resample(self, source, deformation, warped): """ Resample the source image in the space of target. Parameters: :param source: The source image. :param deformation: The deformation field :param warped: Warped image. Should be allocated in the space of target and must have the same number of time points as the source image. """ assert source.time_points == warped.time_points # Matrix to go from world to voxel space ijk_2_voxel = source.mm_2_voxel vol_ext = warped.vol_ext def_data = [deformation.data[..., i].reshape(vol_ext, order='F') for i in range(deformation.data.shape[-1])] # Create the sampling grid in which the source image will be evaluated. def_data = [ijk_2_voxel[i][3] + sum(ijk_2_voxel[i][k] * def_data[k] for k in range(len(def_data))) for i in range(len(vol_ext))] if source.time_points == 1: ndimage.map_coordinates(source.data, def_data, warped.data, order=self.order, prefilter=self.prefilter) else: for i in range(source.time_points): ndimage.map_coordinates(source.data[i], def_data, warped.data[i], order=self.order, prefilter=self.prefilter)
def radiance(ref,cosb,t_setx,height,r_setx,sang): if isinstance(t_setx,(int,float)): ttmp=[t_setx/dtau] else: ttmp=t_setx/dtau if isinstance(height,(int,float)): htmp=[height/dheight] else: htmp=height/dheight if isinstance(sang,(int,float)): stmp=[sang-smin] else: stmp=sang-smin path=ndimage.map_coordinates(path_rad,[ttmp,htmp,stmp]) back=ndimage.map_coordinates(back_rad,[ttmp,htmp,stmp]) pixel=ndimage.map_coordinates(pixel_rad,[ttmp,htmp,stmp]) dir=ndimage.map_coordinates(dir_irad,[ttmp,htmp,stmp]) sky=ndimage.map_coordinates(sky_irad,[ttmp,htmp,stmp]) env=ndimage.map_coordinates(env_irad,[ttmp,htmp,stmp]) sph=ndimage.map_coordinates(sph_alb,[ttmp,htmp,stmp]) rayl=ndimage.map_coordinates(tau_rayl,[ttmp,htmp,stmp]) aero=ndimage.map_coordinates(tau_aero,[ttmp,htmp,stmp]) minor=ndimage.map_coordinates(tau_minor,[ttmp,htmp,stmp]) dir=dir*cosb/cosb0 #print dir back=back*(1-r_set0*sph)*r_setx/(1-r_setx*sph)/r_set0 #print back env=env*(1-r_set0*sph)*r_setx/(1-r_setx*sph)/r_set0 odep=rayl+aero+minor S=np.cos(np.pi*sang/180) rad=path+back+ref*(dir+sky+env)/np.exp(odep/S)/np.pi return rad
def compose(self, left, right, result): """ Compose deformations. Parameters: ----------- :param left: Outer field. :param right: Inner field. :param result: Resulting field after composition. Must be valid and allocated. Order of composition: left(right(x)) """ ijk_2_voxel = right.mm_2_voxel vol_ext = right.vol_ext[:right.data.shape[-1]] right_data = [right.data[..., i].reshape(vol_ext, order='F') for i in range(right.data.shape[-1])] right_data = [ijk_2_voxel[i][3] + sum(ijk_2_voxel[i][k] * right_data[k] for k in range(len(right_data))) for i in range(len(vol_ext))] data = np.squeeze(result.data) for i in range(data.shape[-1]): ndimage.map_coordinates(np.squeeze(left.data[..., i]), right_data, data[..., i], mode='reflect', order=self.order, prefilter=False)
def smooth_with_spline(img, nx, ny, order=3): """Smooth an image with a spline. It returns the fitted spline. arguments: img - Two-dimensional image. If img is complex, abs(img) is calculated. nx - number of control points in x (columns). ny - number control points in y (rows). order - order of splines. Defaults to 3. returns: spline - The fit of the image with the same dimension as img. """ from scipy.ndimage import map_coordinates assert img.ndim == 2, "image must be two dimensional" assert (type(nx), type(ny)) == (int,int), "nx and ny must be int" assert order in range(0,6), "Spline interpolation order must be betwen 0-5." order = int(order) j = complex(0,1) (ys, xs) = img.shape # reduce image down to (ny, nx) shape new_idx = np.mgrid[0:ys-1:ny*j, 0:xs-1:nx*j] # take absolute value if complex. map_coordinates doen't work # for some reason, map_coordinates crashes even if np.iscomplex().any() is false. img = np.abs(img) reduced = map_coordinates(img, new_idx, order=order) # blow image back up to img.shape (rys, rxs) = reduced.shape out_idx = np.mgrid[0:rys-1:ys*j, 0:rxs-1:xs*j] return map_coordinates(reduced, out_idx, order=order)
def el_field(self, X, Q, gamma, nxyz): if self.random_seed != None: np.random.seed(self.random_seed) N = X.shape[0] X[:, 2] = X[:, 2]*gamma XX = np.max(X, axis=0)-np.min(X, axis=0) #XX = XX*np.random.uniform(low=1.0, high=1.1) if self.debug: print( 'mesh steps:', XX) # here we use a fast 3D "near-point" interpolation # we need a stand-alone module with 1D,2D,3D parricles-to-grid functions steps = XX/(nxyz-3) X = X/steps X_min = np.min(X, axis=0) X_mid = np.dot(Q, X)/np.sum(Q) X_off = np.floor(X_min-X_mid) + X_mid X = X - X_off nx = nxyz[0] ny = nxyz[1] nz = nxyz[2] nzny = nz*ny Xi = np.int_(np.floor(X)+1) inds = np.int_(Xi[:, 0]*nzny+Xi[:, 1]*nz+Xi[:, 2]) # 3d -> 1d q = np.bincount(inds, Q, nzny*nx).reshape(nxyz) p = self.potential(q, steps) Ex = np.zeros(p.shape) Ey = np.zeros(p.shape) Ez = np.zeros(p.shape) Ex[:nx-1, :, :] = (p[:nx-1, :, :] - p[1:nx, :, :])/steps[0] Ey[:, :ny-1, :] = (p[:, :ny-1, :] - p[:, 1:ny, :])/steps[1] Ez[:, :, :nz-1] = (p[:, :, :nz-1] - p[:, :, 1:nz])/steps[2] Exyz = np.zeros((N, 3)) Exyz[:, 0] = ndimage.map_coordinates(Ex, np.c_[X[:, 0], X[:, 1]+0.5, X[:, 2]+0.5].T, order=1)*gamma Exyz[:, 1] = ndimage.map_coordinates(Ey, np.c_[X[:, 0]+0.5, X[:, 1], X[:, 2]+0.5].T, order=1)*gamma Exyz[:, 2] = ndimage.map_coordinates(Ez, np.c_[X[:, 0]+0.5, X[:, 1]+0.5, X[:, 2]].T, order=1) return Exyz
def tract_map_image(tractography, image, quantity_name, file_output): from os import path from scipy import ndimage image = nibabel.load(image) ijk_points = tract_in_ijk(image, tractography) image_data = image.get_data() if image_data.ndim > 3: output_name, ext = path.splitext(file_output) output_name = output_name + '_%04d' + ext for i, image in enumerate(image_data): new_scalar_data = ndimage.map_coordinates( image.T, ijk_points.T )[:, None] tractography.original_tracts_data()[ quantity_name] = new_scalar_data tractography_to_file(output_name % i, Tractography( tractography.original_tracts(), tractography.original_tracts_data())) else: new_scalar_data_flat = ndimage.map_coordinates( image_data.T, ijk_points.T )[:, None] start = 0 new_scalar_data = [] for tract in tractography.original_tracts(): new_scalar_data.append( new_scalar_data_flat[start: start + len(tract)]) start += len(tract) tractography.original_tracts_data()[quantity_name] = new_scalar_data return Tractography( tractography.original_tracts(), tractography.original_tracts_data() )
def interp3(x, y, z, v, xi, yi, zi, **kwargs): """Sample a 3D array "v" with pixel corner locations at "x","y","z" at the points in "xi", "yi", "zi" using linear interpolation. Additional kwargs are passed on to ``scipy.ndimage.map_coordinates``.""" import numpy as np from scipy.ndimage import map_coordinates if v.shape != (x.size,y.size,z.size): print 'size mismatch in interp3' raise ValueError def index_coords(corner_locs, interp_locs): index = np.arange(len(corner_locs)) if np.all(np.diff(corner_locs) < 0): corner_locs, index = corner_locs[::-1], index[::-1] return np.interp(interp_locs, corner_locs, index) orig_shape = np.asarray(xi).shape xi, yi, zi = np.atleast_1d(xi, yi, zi) for arr in [xi, yi, zi]: arr.shape = -1 output = np.empty(xi.shape, dtype=float) coords = [index_coords(*item) for item in zip([x, y, z], [xi, yi, zi])] map_coordinates(v, coords, order=3, output=output, **kwargs) return output.reshape(orig_shape)
def minimize_psf(p, im1, im2, box_size, nudgexy, offset): """ Simply minimize residuals Args: scale - scale factor ave_dm - average dm for a given slice ave_sat - average sat for a given slice return: residuals for ave_dm and ave_sat """ if nudgexy is False: if offset is True: return np.nansum(np.abs(((p[0]*im1) - (im2-p[1])))) else: return np.nansum(np.abs(((p*im1) - im2))) else: if offset is True: #Don't worry about this part - not actually useful! x, y = gen_xy(box_size + 4) x += p[1] y += p[2] shifted_im1 = ndimage.map_coordinates(im1, (y, x), cval = np.nan) return np.nansum(np.abs(((p[0]*shifted_im1) - (im2-p[3])))) else: #Don't worry about this part - not actually useful! x, y = gen_xy(box_size + 4) x += p[1] y += p[2] shifted_im1 = ndimage.map_coordinates(im1, (y, x), cval = np.nan) return np.nansum(np.abs(((p[0]*shifted_im1) - im2)))
def profile_line(img, src, dst, linewidth=1, order=1, mode='constant', cval=0.0): """Return the intensity profile of an image measured along a scan line. Parameters ---------- img : numeric array, shape (M, N[, C]) The image, either grayscale (2D array) or multichannel (3D array, where the final axis contains the channel information). src : 2-tuple of numeric scalar (float or int) The start point of the scan line. dst : 2-tuple of numeric scalar (float or int) The end point of the scan line. linewidth : int, optional Width of the scan, perpendicular to the line order : int in {0, 1, 2, 3, 4, 5}, optional The order of the spline interpolation to compute image values at non-integer coordinates. 0 means nearest-neighbor interpolation. mode : string, one of {'constant', 'nearest', 'reflect', 'wrap'}, optional How to compute any values falling outside of the image. cval : float, optional If `mode` is 'constant', what constant value to use outside the image. Returns ------- return_value : array The intensity profile along the scan line. The length of the profile is the ceil of the computed length of the scan line. Examples -------- >>> x = np.array([[1, 1, 1, 2, 2, 2]]) >>> img = np.vstack([np.zeros_like(x), x, x, x, np.zeros_like(x)]) >>> img array([[0, 0, 0, 0, 0, 0], [1, 1, 1, 2, 2, 2], [1, 1, 1, 2, 2, 2], [1, 1, 1, 2, 2, 2], [0, 0, 0, 0, 0, 0]]) >>> profile_line(img, (2, 1), (2, 4)) array([ 1., 1., 2., 2.]) Notes ----- The destination point is included in the profile, in contrast to standard numpy indexing. """ perp_lines = _line_profile_coordinates(src, dst, linewidth=linewidth) if img.ndim == 3: pixels = [ndi.map_coordinates(img[..., i], perp_lines, order=order, mode=mode, cval=cval) for i in range(img.shape[2])] pixels = np.transpose(np.asarray(pixels), (1, 2, 0)) else: pixels = ndi.map_coordinates(img, perp_lines, order=order, mode=mode, cval=cval) intensities = pixels.mean(axis=1) return intensities
def compose(self, left, right): """ Compose position fields. Parameters: ----------- :param left: Outer field. :param right: Inner field Order of composition: left(right(x)) :return The composed position field """ d = np.zeros(left.data.shape) result = Image.from_data(d, header=left.get_header()) vol_ext = left.vol_ext[:left.data.shape[-1]] left_data = [left.data[..., i].reshape(vol_ext, order='F') for i in range(left.data.shape[-1])] data = np.squeeze(result.data) for i in range(data.shape[-1]): # todo: Incorrect behaviour at boundary # This is an issue we need to revisit. # Nearest mode is not good when we are dealing with fields. # Unfortunately map_coordinates does not allow for leaving the value # as is and we will need to implement this at some point. ndimage.map_coordinates(np.squeeze(right.data[..., i]), left_data, data[..., i], mode='nearest', order=self.order, prefilter=True) return result
def compose_with_position_field(self, left, right_pos): """ Compose displacement fields. Parameters: ----------- :param left: Outer displacement field. :param right_pos: Inner position field. Order of composition: left(right_pos(x)) :return Return the composed displacement field """ d = np.zeros(right_pos.data.shape) result = Image.from_data(d, header=right_pos.get_header()) vol_ext = right_pos.vol_ext[:right_pos.data.shape[-1]] right_data = [right_pos.data[..., i].reshape(vol_ext, order='F') for i in range(right_pos.data.shape[-1])] data = np.squeeze(result.data) for i in range(data.shape[-1]): ndimage.map_coordinates(np.squeeze(left.data[..., i]), right_data, data[..., i], mode='nearest', order=self.order, prefilter=True) return result
def EField(X,Q,gamma,kern,steps): N=X.shape[0]; X[:,2]=X[:,2]*gamma X=X/steps X_min=np.min(X,axis=0) X_mid=np.dot(Q,X)/np.sum(Q); X_off=np.floor(X_min-X_mid)+X_mid; X=X-X_off nx,ny,nz=np.int_(3+np.floor(np.max(X,axis=0))) nzny=nz*ny Xi=np.int_(np.floor(X)+1) inds=np.int_(Xi[:,0]*nzny+Xi[:,1]*nz+Xi[:,2]) # 3d -> 1d q=np.bincount(inds,Q,nzny*nx) print len(q), nx*ny*nz q=q.reshape(nx,ny,nz) #t0=time.time() print q.shape, steps p,kern=Phi(q,kern,steps) #t1=time.time(); print t1-t0 Ex=np.zeros(p.shape);Ey=np.zeros(p.shape);Ez=np.zeros(p.shape); Ex[:nx-1,:,:]=(p[:nx-1,:,:]-p[1:nx,:,:])/steps[0] Ey[:,:ny-1,:]=(p[:,:ny-1,:]-p[:,1:ny,:])/steps[1] Ez[:,:,:nz-1]=(p[:,:,:nz-1]-p[:,:,1:nz])/steps[2] Exyz=np.zeros((N,3)) Exyz[:,0]=ndimage.map_coordinates(Ex,np.c_[X[:,0],X[:,1]+0.5,X[:,2]+0.5].T,order=1)*gamma Exyz[:,1]=ndimage.map_coordinates(Ey,np.c_[X[:,0]+0.5,X[:,1],X[:,2]+0.5].T,order=1)*gamma Exyz[:,2]=ndimage.map_coordinates(Ez,np.c_[X[:,0]+0.5,X[:,1]+0.5,X[:,2]].T,order=1) #t1=time.time(); print t1-t0 return Exyz
def EField(X,Q,gamma,nxyz): N=X.shape[0]; X[:,2]=X[:,2]*gamma XX=np.max(X,axis=0)-np.min(X,axis=0) XX=XX*np.random.uniform(low=1.0,high=1.1) print 'mesh steps:', XX steps=XX/(nxyz-3) X=X/steps X_min=np.min(X,axis=0) X_mid=np.dot(Q,X)/np.sum(Q); X_off=np.floor(X_min-X_mid)+X_mid; X=X-X_off nx=nxyz[0];ny=nxyz[1];nz=nxyz[2];nzny=nz*ny Xi=np.int_(np.floor(X)+1) inds=np.int_(Xi[:,0]*nzny+Xi[:,1]*nz+Xi[:,2]) # 3d -> 1d print inds.shape, nxyz q=np.bincount(inds,Q,nzny*nx).reshape(nxyz) p=Phi(q,steps) Ex=np.zeros(p.shape);Ey=np.zeros(p.shape);Ez=np.zeros(p.shape); Ex[:nx-1,:,:]=(p[:nx-1,:,:]-p[1:nx,:,:])/steps[0] Ey[:,:ny-1,:]=(p[:,:ny-1,:]-p[:,1:ny,:])/steps[1] Ez[:,:,:nz-1]=(p[:,:,:nz-1]-p[:,:,1:nz])/steps[2] Exyz=np.zeros((N,3)) Exyz[:,0]=ndimage.map_coordinates(Ex,np.c_[X[:,0],X[:,1]+0.5,X[:,2]+0.5].T,order=1)*gamma Exyz[:,1]=ndimage.map_coordinates(Ey,np.c_[X[:,0]+0.5,X[:,1],X[:,2]+0.5].T,order=1)*gamma Exyz[:,2]=ndimage.map_coordinates(Ez,np.c_[X[:,0]+0.5,X[:,1]+0.5,X[:,2]].T,order=1) return Exyz
def map_coordinates_3d_4d(input_array, indices): """ Evaluate the input_array data at the given indices using trilinear interpolation Parameters ---------- input_array : ndarray, 3D or 4D array indices : ndarray Returns ------- output : ndarray 1D or 2D array """ if input_array.ndim <= 2 or input_array.ndim >= 5: raise ValueError("Input array can only be 3d or 4d") if input_array.ndim == 3: return map_coordinates(input_array, indices.T, order=1) if input_array.ndim == 4: values_4d = [] for i in range(input_array.shape[-1]): values_tmp = map_coordinates(input_array[..., i], indices.T, order=1) values_4d.append(values_tmp) return np.ascontiguousarray(np.array(values_4d).T)
def interp6(x, y, z, w, q, qq, v, xi, yi, zi, wi, qi, qqi, **kwargs): """Sample a 5D array "v". Additional kwargs are passed on to ``scipy.ndimage.map_coordinates``.""" import numpy as np from scipy.ndimage import map_coordinates if v.shape != (x.size,y.size,z.size, w.size, q.size, qq.size): print 'size mismatch in interp3' raise ValueError def index_coords(corner_locs, interp_locs): index = np.arange(len(corner_locs)) if np.all(np.diff(corner_locs) < 0): corner_locs, index = corner_locs[::-1], index[::-1] return np.interp(interp_locs, corner_locs, index) orig_shape = np.asarray(xi).shape xi, yi, zi, wi, qi, qqi = np.atleast_1d(xi, yi, zi, wi, qi, qqi) for arr in [xi, yi, zi, wi, qi, qqi]: arr.shape = -1 output = np.empty(xi.shape, dtype=float) coords = [index_coords(*item) for item in zip([x, y, z, w, q, qq], [xi, yi, zi, wi, qi, qqi])] map_coordinates(v, coords, order=3, output=output, **kwargs) return output.reshape(orig_shape)
def query(self, l, b, order=1): l = np.asarray(l) b = np.asarray(b) if l.shape != b.shape: raise ValueError('l.shape must equal b.shape') out = np.zeros_like(l, dtype='f4') for pole in ['ngp', 'sgp']: m = (b >= 0) if pole == 'ngp' else b < 0 if np.any(m): header, data = self.data[pole] wcs = pywcs.WCS(header) if not m.shape: # Support for 0-dimensional arrays (scalars). Otherwise it barfs on l[m], b[m] x, y = wcs.wcs_world2pix(l, b, 0) out = map_coordinates(data, [[y], [x]], order=order, mode='nearest')[0] continue x, y = wcs.wcs_world2pix(l[m], b[m], 0) out[m] = map_coordinates(data, [y, x], order=order, mode='nearest') return out
def ginterpolate (im, X, Y=None, output_type=None, order=1, mode='constant', cval=0.0, q=False) : """ Emulate the IDL interface to the intepolate function using the ndimage.map_coordinates call @type im: 2-D image buffer @type X: 2-D index array with the x-location for which interpolation is desired. @type Y: 2-D index array with the y-location for which interpolation is desired. @type order: Default:1. Order of interpolation. The default for map_coordinates is 3 @type q: Default False. If True, there is only X and we use only the upper left quarter of the symmetric X (w/r to the array center). NOTE: Currently it is slower to use this option. For more information see help ndimage.map_coordinates """ dim = np.size(np.shape(im)) szx = np.size(np.shape(X)) X = np.array(X) if Y != None: Y = np.array(Y) if dim == 1: if szx == 1: X = X.reshape([1,np.size(X)]) z = nd.map_coordinates(im,X, output=output_type, order=order, mode=mode, cval=cval) elif szx == 2: lim = np.size(im) limy,limx = lim,lim if Y == None: Y = X coords = np.array([X,Y]) if q: nx,ny = np.shape(X) nx,ny=nx/2,ny/2 coords = np.array([X[:ny,:nx],X[:ny,:nx]]) limy,limx = lim/2,lim else: coords = np.array([X,Y]) z = nd.map_coordinates(np.resize(im,[limy,limx]),coords, output=output_type, order=order, mode=mode, cval=cval) elif dim == 2: if szx == 1 and Y != None: z = nd.map_coordinates(im,[X,Y],output=output_type, order=order, mode=mode, cval=cval) elif szx == 2: if Y == None: Y = X z = nd.map_coordinates(im,[X,Y],output=output_type, order=order, mode=mode, cval=cval) else: print 'ERROR, dimension of input buffer not supported: ',len return return z
def vect(coord, t): x = [coord[0]] y = [coord[1]] z = [coord[2]] ux = ndimage.map_coordinates(vel[:, :, :, 0, :], [x, y, z, [t]], order=3) uy = ndimage.map_coordinates(vel[:, :, :, 1, :], [x, y, z, [t]], order=3) uz = ndimage.map_coordinates(vel[:, :, :, 2, :], [x, y, z, [t]], order=3) return [ux[0], uy[0], uz[0]]
def polarSlice2Cube (Slice, zaxis=1, size=None, mode='nearest'): s=max(Slice.shape) if not(size): size=s g=x,y,z=np.mgrid[-s:s:size*1j,-s:s:size*1j,-s:s:size*1j] R=np.sqrt(x*x+y*y) if zaxis==1: return ndimage.map_coordinates(Slice, (R,abs(z)), mode=mode, order=1) else : return ndimage.map_coordinates(Slice, (abs(z),R), mode=mode, order=1)
def lin2loglog (grid, low=-3, shape=[], order=3): xmax,ymax=grid.shape if not(shape): shape=grid.shape oxmax,oymax=shape out=np.zeros(shape) x,y=np.mgrid[low:0:oxmax*1j, low:0:oymax*1j] ndimage.map_coordinates(grid, [10**x*xmax,10**y*ymax], output=out, mode='nearest', order=order) return out
def extract_line_slice(cube, x, y, order=3, respect_nan=True): """ Given an array with shape (z, y, x), extract a (z, n) slice by interpolating at n (x, y) points. All units are in *pixels*. .. note:: If there are NaNs in the cube, they will be treated as zeros when using spline interpolation. Parameters ---------- cube : `~numpy.ndarray` The data cube to extract the slice from curve : list or tuple A list or tuple of (x, y) pairs, with minimum length 2 order : int, optional Spline interpolation order. Set to ``0`` for nearest-neighbor interpolation. Returns ------- slice : `numpy.ndarray` The (z, d) slice """ if order == 0: slice = np.zeros([cube.shape[0], len(x)]) + np.nan x = np.round(x) y = np.round(y) ok = (x > 0) & (y > 0) & (x < cube.shape[2]) & (y < cube.shape[1]) slice[:,ok] = cube[:, y[ok].astype(int), x[ok].astype(int)] elif order > 0 and order == int(order): nx = len(x) nz = cube.shape[0] zi = np.outer(np.arange(nz, dtype=int), np.ones(nx)) xi = np.outer(np.ones(nz), x) yi = np.outer(np.ones(nz), y) slice = map_coordinates(np.nan_to_num(cube), [zi,yi,xi], order=order, cval=np.nan) if respect_nan: slice_bad = map_coordinates(np.nan_to_num(np.isnan(cube).astype(int)), [zi,yi,xi], order=order) slice[np.nonzero(slice_bad)] = np.nan else: raise TypeError("order should be a positive integer") return slice
def ebv(coordinate, order=1): """ Return SFD E(B-V) at the input coordinate(s). Parameters ---------- coordinate : :class:`~astropy.coordinates.SkyCoord`, :class:`~astropy.coordinates.BaseCoordinateFrame` The coordinate(s) to compute extinction at. order : int (optional) Passed to :func:`~scipy.ndimage.map_coordinates`. Returns ------- EBV : :class:`~numpy.ndarray` Extinction at each input coordinate. Example ------- TODO h, w = 1000, 4000 b, l = numpy.mgrid[0:h,0:w] l = 180.-(l+0.5) / float(w) * 360. b = 90. - (b+0.5) / float(h) * 180. ebv = dust.getval(l, b) imshow(ebv, aspect='auto', norm=matplotlib.colors.LogNorm()) """ ngp_filename = get_pkg_data_filename("data/SFD_dust_4096_ngp.fits") sgp_filename = get_pkg_data_filename("data/SFD_dust_4096_sgp.fits") # convert input coordinate to Galactic frame gal = coordinate.transform_to(coord.Galactic) l = gal.l.wrap_at(180*u.degree).degree b = gal.b.degree # output extinctions EBV = np.zeros_like(l, dtype='f4') + np.nan b_gtr_zero = b >= 0. b_les_zero = np.logical_not(b_gtr_zero) if np.any(b_gtr_zero): # north hdulist = fits.open(ngp_filename) w = wcs.WCS(hdulist[0].header) x, y = w.wcs_world2pix(l[b_gtr_zero], b[b_gtr_zero], 0) EBV[b_gtr_zero] = map_coordinates(hdulist[0].data, [y, x], order=order, mode='nearest') hdulist.close() if np.any(b_les_zero): # south hdulist = fits.open(sgp_filename) w = wcs.WCS(hdulist[0].header) x, y = w.wcs_world2pix(l[b_les_zero], b[b_les_zero], 0) EBV[b_les_zero] = map_coordinates(hdulist[0].data, [y, x], order=order, mode='nearest') hdulist.close() return EBV
def sample_colors(image, sample_points): r""" Sample RGB colour values from an image of shape (w, h, 3) at floating point (x, y) sample points. """ r = map_coordinates(image[..., 0], sample_points.T) g = map_coordinates(image[..., 1], sample_points.T) b = map_coordinates(image[..., 2], sample_points.T) return np.vstack((r, g, b)).T
def values_in_world(self, x, y, z, interpolation_order=3): """ Return the values of the data at the world-space positions given by x, y, z Parameters ---------- x : number or ndarray x positions in world space, in other words milimeters y : number or ndarray y positions in world space, in other words milimeters. The shape of y should match the shape of x z : number or ndarray z positions in world space, in other words milimeters. The shape of z should match the shape of x interpolation_order : int, optional Order of the spline interplation. If 0, nearest neighboor interpolation is performed. Returns ------- values : number or ndarray Data values interpolated at the given world position. This is a number or an ndarray, depending on the shape of the input coordinate. """ x = np.atleast_1d(x) y = np.atleast_1d(y) z = np.atleast_1d(z) shape = x.shape if not ((x.shape == y.shape) and (x.shape == z.shape)): raise ValueError('x, y and z shapes should be equal') x = x.ravel() y = y.ravel() z = z.ravel() xyz = np.c_[x, y, z] world_to_voxel = self.xyz_transform.inverse() ijk = world_to_voxel(xyz) data = self.get_data() if self.ndim == 3: values = map_coordinates(data, ijk.T, order=interpolation_order) values = np.reshape(values, shape) elif self.ndim == 4: values = np.empty(shape + (self.shape[3],)) for i in range(self.shape[3]): tmp_values = map_coordinates(data[...,i], ijk.T, order=interpolation_order) tmp_values = np.reshape(tmp_values, shape) values[...,i] = tmp_values return values
def OnButton(self, evt): '''Handle button click event''' # Get title of clicked button label = evt.GetEventObject().GetLabel() if label == "Get Atmospheric Factors": # Calculate try: sampleLat = float(self.lat.GetValue()) sampleLon = float(self.lon.GetValue()) NCEP = load(self.repo.GetClimateDataPath()) Temperature = NCEP[0:73,:];seaLevelPress = NCEP[73:146,:]; LapseRate = NCEP[146:219,:];topo = NCEP[219:292,:] Temperature = NCEP[73:0:-1,:];seaLevelPress = NCEP[146:73:-1,:]; LapseRate = NCEP[219:146:-1,:];topo = NCEP[292:73:-1,:] lat = arange(90,-91,-2.5);lon = arange(0, 361,2.5) #localCoords is the site coordinates relative to the NCEP data coords #For interpolation the field is considered to bound 1 -> nx-1 , 1 -> ny-1 xfac = len(lat) - 1 yfac = len(lon) - 1 localX = (max(lat) - sampleLat) * xfac / (max(lat) - min(lat)) + 1 localY = sampleLon / max(lon) * yfac + 1 localCoords = array([[ localX],[ localY ]]) AnnualMeanSLP = ndimage.map_coordinates(seaLevelPress, localCoords) AnnualMeanTemp = ndimage.map_coordinates(Temperature, localCoords) AnnualMeanLapse = ndimage.map_coordinates(LapseRate, localCoords) sltempVal = "%3.1f" % (float(AnnualMeanTemp)) slprecVal = "%3.1f" % (float(AnnualMeanSLP)) LapseRate = "%3.1f" % (float(AnnualMeanLapse*-1)) # Ignore empty calculation #if not compute.strip(): if not sltempVal: return # Calculate result # result = eval(compute) # Add to history self.sltemp.Insert(str(sltempVal), 0) self.slprec.Insert(str(slprecVal), 0) self.lapse.Insert(str(LapseRate), 0) # Show result #self.display.SetValue(str(result)) self.sltemp.SetValue(str(sltempVal)) self.slprec.SetValue(str(slprecVal)) self.lapse.SetValue(str(LapseRate)) #self.slprec.SetValue(str(slprecVal)) except Exception, e: wx.LogError(str(e)) return
def calc_offset(psflets, image, offsets, dx=64, maxcpus=multiprocessing.cpu_count()): """ Function calc_offset: compute the position-dependent sub-pixel shift in the PSFlet spot grid using cross-correlation. Inputs: 1. psflets: ndarray, (nlam, ny, Nx), with Nx = upsamp*nx, i.e. oversampled by a factor upsamp in the last dimension (perpendicular to the CHARIS dispersion direction). 2. image: ndarray, (ny, nx) 3. offsets: ndarray, integer offsets at which to compute cross-correlation, shifting psflets by upsamp with respect to image. Optional inputs: 1. dx: integer, (dx,dx) size of chunks on which to compute cross-correlation. Default 64 (so that 32x32 offsets are computed for a 2048x2048 image). 2. maxcpus: number of threads for OpenMP parallelization of cython code. Default multiprocessing.cpu_count(). Output: 1. psflets: ndarray, (nlam, ny, nx), PSFlet templates shifted by a position-dependent value to maximize the cross-correlation with the input image. """ mask = (image.ivar > 0).astype(np.uint16) if psflets.dtype != 'float32': # Ensure correct dtype, native byte order psflets2 = np.empty(psflets.shape, np.float32) psflets2[:] = psflets psflets = psflets2 ##################################################################### # Calculate the cross-correlation of the PSFlet images and the # actual data at the specified offsets. Do this in dim/dx # subregions of the image to get a position-dependent shift. ##################################################################### ny, nx = image.data.shape shiftarr = np.zeros( (int(np.ceil(ny * 1. / dx)), int(np.ceil(nx * 1. / dx)))) outarr = np.zeros((psflets.shape[0], ny, nx)) for i in range(0, nx, dx): corrvals_all = matutils.crosscorr(psflets, image.data, image.ivar, offsets, maxproc=maxcpus, m1=i, m2=i + dx) for j in range(0, ny, dx): corrvals = np.sum(corrvals_all[:, j:j + dx], axis=1) ############################################################# # Calculate offset to maximize the cross-correlation by # fitting a parabola to the five points bracketing the # best value ############################################################# icen = np.arange( offsets.shape[0])[np.where(corrvals == np.amax(corrvals))] imin = int(max(0, icen - 2)) imax = int(min(offsets.shape[0], icen + 3)) corrvals = corrvals[imin:imax] arr = np.ones((imax - imin, 3)) arr[:, 1] = offsets[imin:imax] arr[:, 2] = offsets[imin:imax]**2 coef = linalg.lstsq(arr, corrvals)[0] shift = -coef[1] / (2 * coef[2]) shiftarr[j // dx, i // dx] = shift ##################################################################### # Return the interpolated array at the requested offset ##################################################################### if shiftarr.shape[0] >= 3: shiftarr[1:-1, 1:-1] = signal.medfilt2d(shiftarr, 3)[1:-1, 1:-1] shiftarr[0, 1:-1] = signal.medfilt(shiftarr[0], 3)[1:-1] shiftarr[-1, 1:-1] = signal.medfilt(shiftarr[-1], 3)[1:-1] shiftarr[1:-1, 0] = signal.medfilt(shiftarr[:, 0], 3)[1:-1] shiftarr[1:-1, -1] = signal.medfilt(shiftarr[:, -1], 3)[1:-1] x = (1. * np.arange(ny)) / dx - 0.5 x *= x > 0 x[np.where(x > shiftarr.shape[0] - 1)] = shiftarr.shape[0] - 1 x, y = np.meshgrid(x, x) fullshiftarr = ndimage.map_coordinates(shiftarr, [y, x], order=3) psflets = matutils.interpcal(psflets, image.data, mask, fullshiftarr, maxproc=maxcpus) return psflets
def run_on_image_setting(self, workspace, image): assert isinstance(workspace, cpw.Workspace) image_set = workspace.image_set measurements = workspace.measurements im = image_set.get_image(image.image_name.value, must_be_grayscale=True) # # Downsample the image and mask # new_shape = np.array(im.pixel_data.shape) if image.subsample_size.value < 1: new_shape = new_shape * image.subsample_size.value i, j = (np.mgrid[0:new_shape[0], 0:new_shape[1]].astype(float) / image.subsample_size.value) pixels = scind.map_coordinates(im.pixel_data, (i, j), order=1) mask = scind.map_coordinates(im.mask.astype(float), (i, j)) > .9 else: pixels = im.pixel_data mask = im.mask # # Remove background pixels using a greyscale tophat filter # if image.image_sample_size.value < 1: back_shape = new_shape * image.image_sample_size.value i, j = (np.mgrid[0:back_shape[0], 0:back_shape[1]].astype(float) / image.image_sample_size.value) back_pixels = scind.map_coordinates(pixels, (i, j), order=1) back_mask = scind.map_coordinates(mask.astype(float), (i, j)) > .9 else: back_pixels = pixels back_mask = mask radius = image.element_size.value back_pixels = morph.grey_erosion(back_pixels, radius, back_mask) back_pixels = morph.grey_dilation(back_pixels, radius, back_mask) if image.image_sample_size.value < 1: i, j = np.mgrid[0:new_shape[0], 0:new_shape[1]].astype(float) # # Make sure the mapping only references the index range of # back_pixels. # i *= float(back_shape[0] - 1) / float(new_shape[0] - 1) j *= float(back_shape[1] - 1) / float(new_shape[1] - 1) back_pixels = scind.map_coordinates(back_pixels, (i, j), order=1) pixels -= back_pixels pixels[pixels < 0] = 0 # # For each object, build a little record # class ObjectRecord(object): def __init__(self, name): self.name = name self.labels = workspace.object_set.get_objects(name).segmented self.nobjects = np.max(self.labels) if self.nobjects != 0: self.range = np.arange(1, np.max(self.labels) + 1) self.labels = self.labels.copy() self.labels[~im.mask] = 0 self.current_mean = fix( scind.mean(im.pixel_data, self.labels, self.range)) self.start_mean = np.maximum(self.current_mean, np.finfo(float).eps) object_records = [ ObjectRecord(ob.objects_name.value) for ob in image.objects ] # # Transcribed from the Matlab module: granspectr function # # CALCULATES GRANULAR SPECTRUM, ALSO KNOWN AS SIZE DISTRIBUTION, # GRANULOMETRY, AND PATTERN SPECTRUM, SEE REF.: # J.Serra, Image Analysis and Mathematical Morphology, Vol. 1. Academic Press, London, 1989 # Maragos,P. "Pattern spectrum and multiscale shape representation", IEEE Transactions on Pattern Analysis and Machine Intelligence, 11, N 7, pp. 701-716, 1989 # L.Vincent "Granulometries and Opening Trees", Fundamenta Informaticae, 41, No. 1-2, pp. 57-90, IOS Press, 2000. # L.Vincent "Morphological Area Opening and Closing for Grayscale Images", Proc. NATO Shape in Picture Workshop, Driebergen, The Netherlands, pp. 197-208, 1992. # I.Ravkin, V.Temov "Bit representation techniques and image processing", Applied Informatics, v.14, pp. 41-90, Finances and Statistics, Moskow, 1988 (in Russian) # THIS IMPLEMENTATION INSTEAD OF OPENING USES EROSION FOLLOWED BY RECONSTRUCTION # ng = image.granular_spectrum_length.value startmean = np.mean(pixels[mask]) ero = pixels.copy() # Mask the test image so that masked pixels will have no effect # during reconstruction # ero[~mask] = 0 currentmean = startmean startmean = max(startmean, np.finfo(float).eps) footprint = np.array([[False, True, False], [True, True, True], [False, True, False]]) statistics = [image.image_name.value] for i in range(1, ng + 1): prevmean = currentmean ero = morph.grey_erosion(ero, mask=mask, footprint=footprint) rec = morph.grey_reconstruction(ero, pixels, footprint) currentmean = np.mean(rec[mask]) gs = (prevmean - currentmean) * 100 / startmean statistics += ["%.2f" % gs] feature = image.granularity_feature(i) measurements.add_image_measurement(feature, gs) # # Restore the reconstructed image to the shape of the # original image so we can match against object labels # orig_shape = im.pixel_data.shape i, j = np.mgrid[0:orig_shape[0], 0:orig_shape[1]].astype(float) # # Make sure the mapping only references the index range of # back_pixels. # i *= float(new_shape[0] - 1) / float(orig_shape[0] - 1) j *= float(new_shape[1] - 1) / float(orig_shape[1] - 1) rec = scind.map_coordinates(rec, (i, j), order=1) # # Calculate the means for the objects # for object_record in object_records: assert isinstance(object_record, ObjectRecord) if object_record.nobjects > 0: new_mean = fix( scind.mean(rec, object_record.labels, object_record.range)) gss = ((object_record.current_mean - new_mean) * 100 / object_record.start_mean) object_record.current_mean = new_mean else: gss = np.zeros((0, )) measurements.add_measurement(object_record.name, feature, gss) return statistics
def get_profile(x, y, f, xi, yi, mode='nearest', order=3): """ Interpolate regular data. Parameters ---------- x : two dimensional np.ndarray an array for the :math:`x` coordinates y : two dimensional np.ndarray an array for the :math:`y` coordinates f : two dimensional np.ndarray an array with the value of the function to be interpolated at :math:`x,y` coordinates. xi : one dimension np.ndarray the :math:`x` coordinates of the point where we want the function to be interpolated. yi : one dimension np.ndarray the :math:`y` coordinates of the point where we want the function to be interpolated. order : int the order of the bivariate spline interpolation Returns ------- fi : one dimension np.ndarray the value of the interpolating spline at :math:`xi,yi` Examples -------- >>> import numpy as np >>> from oceans.ocfis import get_profile >>> x, y = np.meshgrid(range(360), range(91)) >>> f = np.array(range(91 * 360)).reshape((91, 360)) >>> Paris = [2.4, 48.9] >>> Rome = [12.5, 41.9] >>> Greenwich = [0, 51.5] >>> xi = Paris[0], Rome[0], Greenwich[0] >>> yi = Paris[1], Rome[1], Greenwich[1] >>> get_profile(x, y, f, xi, yi, order=3) array([17606, 15096, 18540]) """ from scipy.ndimage import map_coordinates x, y, f, xi, yi = list(map(np.asanyarray, (x, y, f, xi, yi))) conditions = np.array([xi.min() < x.min(), xi.max() > x.max(), yi.min() < y.min(), yi.max() > y.max()]) if conditions.any(): warnings.warn('Warning! Extrapolation!!') dx = x[0, 1] - x[0, 0] dy = y[1, 0] - y[0, 0] jvals = (xi - x[0, 0]) / dx ivals = (yi - y[0, 0]) / dy coords = np.array([ivals, jvals]) return map_coordinates(f, coords, mode=mode, order=order)
def frontalization(self, img_, facebb, p2d_): #we rescale the face region (twice as big as the detected face) before applying frontalisation #the rescaled size is WD x HT WD = 250 HT = 250 ACC_CONST = 800 facebb = [facebb.left(), facebb.top(), facebb.width(), facebb.height()] w = facebb[2] h = facebb[3] fb_ = np.clip([[facebb[0] - w, facebb[1] - h], [facebb[0] + 2 * w, facebb[1] + 2 * h]], [0, 0], [img_.shape[1], img_.shape[0]]) img = img_[fb_[0][1]:fb_[1][1], fb_[0][0]:fb_[1][0], :] p2d = copy.deepcopy(p2d_) p2d[:, 0] = (p2d_[:, 0] - fb_[0][0]) * float(WD) / float(img.shape[1]) p2d[:, 1] = (p2d_[:, 1] - fb_[0][1]) * float(HT) / float(img.shape[0]) img = cv2.resize(img, (WD, HT)) #finished rescaling tem3d = np.reshape(self.refU, (-1, 3), order='F') bgids = tem3d[:, 1] < 0 # excluding background 3d points # plot3d(tem3d) # print tem3d.shape ref3dface = np.insert(tem3d, 3, np.ones(len(tem3d)), axis=1).T ProjM = self.get_headpose(p2d)[2] proj3d = ProjM.dot(ref3dface) proj3d[0] /= proj3d[2] proj3d[1] /= proj3d[2] proj2dtmp = proj3d[0:2] #The 3D reference is projected to the 2D region by the estimated pose #The check the projection lies in the image or not vlids = np.logical_and( np.logical_and(proj2dtmp[0] > 0, proj2dtmp[1] > 0), np.logical_and(proj2dtmp[0] < img.shape[1] - 1, proj2dtmp[1] < img.shape[0] - 1)) vlids = np.logical_and(vlids, bgids) proj2d_valid = proj2dtmp[:, vlids] sp_ = self.refU.shape[0:2] synth_front = np.zeros(sp_, np.float) inds = np.ravel_multi_index(np.round(proj2d_valid).astype(int), (img.shape[1], img.shape[0]), order='F') unqeles, unqinds, inverids, conts = np.unique(inds, return_index=True, return_inverse=True, return_counts=True) tmp_ = synth_front.flatten() tmp_[vlids] = conts[inverids].astype(np.float) synth_front = tmp_.reshape(synth_front.shape, order='F') synth_front = cv2.GaussianBlur(synth_front, (17, 17), 30).astype(np.float) rawfrontal = np.zeros((self.refU.shape[0], self.refU.shape[1], 3)) for k in range(3): z = img[:, :, k] intervalues = ndimage.map_coordinates(img[:, :, k].T, proj2d_valid, order=3, mode='nearest') tmp_ = rawfrontal[:, :, k].flatten() tmp_[vlids] = intervalues rawfrontal[:, :, k] = tmp_.reshape(self.refU.shape[0:2], order='F') mline = synth_front.shape[1] / 2 sumleft = np.sum(synth_front[:, 0:mline]) sumright = np.sum(synth_front[:, mline:]) sum_diff = sumleft - sumright #print sum_diff if np.abs(sum_diff) > ACC_CONST: weights = np.zeros(sp_) if sum_diff > ACC_CONST: weights[:, mline:] = 1. else: weights[:, 0:mline] = 1. weights = cv2.GaussianBlur(weights, (33, 33), 60.5).astype(np.float) synth_front /= np.max(synth_front) weight_take_from_org = 1 / np.exp(1 + synth_front) weight_take_from_sym = 1 - weight_take_from_org weight_take_from_org = weight_take_from_org * np.fliplr(weights) weight_take_from_sym = weight_take_from_sym * np.fliplr(weights) weights = np.tile(weights, (1, 3)).reshape( (weights.shape[0], weights.shape[1], 3), order='F') weight_take_from_org = np.tile( weight_take_from_org, (1, 3)).reshape( (weight_take_from_org.shape[0], weight_take_from_org.shape[1], 3), order='F') weight_take_from_sym = np.tile( weight_take_from_sym, (1, 3)).reshape( (weight_take_from_sym.shape[0], weight_take_from_sym.shape[1], 3), order='F') denominator = weights + weight_take_from_org + weight_take_from_sym frontal_sym = ( rawfrontal * weights + rawfrontal * weight_take_from_org + np.fliplr(rawfrontal) * weight_take_from_sym) / denominator else: frontal_sym = rawfrontal return rawfrontal, frontal_sym, np.round(frontal_sym).astype(np.uint8)
linename = 'NaClv=2_26-25' linename = 'NaClv=1_18-17' # use this to compute the continuum in the spectral extraction region naclfn = paths.dpath( 'moments/Orion{1}_{0}_robust{robust}.maskedclarkclean10000_medsub_K_peak.fits' ).format(linename, sourcename, robust=robust) nacldata = fits.getdata(naclfn) ww = wcs.WCS(fits.getheader(naclfn)) pixscale = wcs.utils.proj_plane_pixel_scales(ww)[0] yy, xx = np.indices(np.array(nacldata.shape) * 2) - np.array([0, 101])[:, None, None] rotcoords = np.dot( np.array([yy, xx]).T, [[np.cos(-38 * u.deg), -np.sin(-38 * u.deg)], [np.sin(-38 * u.deg), np.cos(-38 * u.deg)]]) rslt = map_coordinates(nacldata, rotcoords.T) mn, mid, std = stats.sigma_clipped_stats(nacldata) pl.clf() pl.imshow(rslt, origin='lower') pl.colorbar() xslice = slice(36, 110) # truncate the disk edges xslice = slice(55,95) yslice = slice(100, 128) naclcutout = rslt[xslice, yslice] naclmask = naclcutout > (std * 2 + mn) naclcutout[~naclmask] = np.nan fig = pl.gcf() pl.clf()
def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1, mode='constant', cval=0., clip=True): """Warp an image according to a given coordinate transformation. Parameters ---------- image : ndarray Input image. inverse_map : transformation object, callable ``cr = f(cr, **kwargs)``, or ndarray Inverse coordinate map, which transforms coordinates in the output images into their corresponding coordinates in the input image. There are a number of different options to define this map, depending on the dimensionality of the input image. A 2-D image can have 2 dimensions for gray-scale images, or 3 dimensions with color information. - For 2-D images, you can directly pass a transformation object, e.g. `skimage.transform.SimilarityTransform`, or its inverse. - For 2-D images, you can pass a ``(3, 3)`` homogeneous transformation matrix, e.g. `skimage.transform.SimilarityTransform.params`. - For 2-D images, a function that transforms a ``(M, 2)`` array of ``(col, row)`` coordinates in the output image to their corresponding coordinates in the input image. Extra parameters to the function can be specified through `map_args`. - For N-D images, you can directly pass an array of coordinates. The first dimension specifies the coordinates in the input image, while the subsequent dimensions determine the position in the output image. E.g. in case of 2-D images, you need to pass an array of shape ``(2, rows, cols)``, where `rows` and `cols` determine the shape of the output image, and the first dimension contains the ``(row, col)`` coordinate in the input image. See `scipy.ndimage.map_coordinates` for further documentation. Note, that a ``(3, 3)`` matrix is interpreted as a homogeneous transformation matrix, so you cannot interpolate values from a 3-D input, if the output is of shape ``(3,)``. See example section for usage. map_args : dict, optional Keyword arguments passed to `inverse_map`. output_shape : tuple (rows, cols), optional Shape of the output image generated. By default the shape of the input image is preserved. Note that, even for multi-band images, only rows and columns need to be specified. order : int, optional The order of interpolation. The order has to be in the range 0-5: - 0: Nearest-neighbor - 1: Bi-linear (default) - 2: Bi-quadratic - 3: Bi-cubic - 4: Bi-quartic - 5: Bi-quintic mode : string, optional Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). cval : float, optional Used in conjunction with mode 'constant', the value outside the image boundaries. clip : bool, optional Whether to clip the output to the float range of ``[0, 1]``, or ``[-1, 1]`` for input images with negative values. This is enabled by default, since higher order interpolation may produce values outside the given input range. Notes ----- In case of a `SimilarityTransform`, `AffineTransform` and `ProjectiveTransform` and `order` in [0, 3] this function uses the underlying transformation matrix to warp the image with a much faster routine. Examples -------- >>> from skimage.transform import warp >>> from skimage import data >>> image = data.camera() The following image warps are all equal but differ substantially in execution time. The image is shifted to the bottom. Use a geometric transform to warp an image (fast): >>> from skimage.transform import SimilarityTransform >>> tform = SimilarityTransform(translation=(0, -10)) >>> warped = warp(image, tform) Use a callable (slow): >>> def shift_down(xy): ... xy[:, 1] -= 10 ... return xy >>> warped = warp(image, shift_down) Use a transformation matrix to warp an image (fast): >>> matrix = np.array([[1, 0, 0], [0, 1, -10], [0, 0, 1]]) >>> warped = warp(image, matrix) >>> from skimage.transform import ProjectiveTransform >>> warped = warp(image, ProjectiveTransform(matrix=matrix)) You can also use the inverse of a geometric transformation (fast): >>> warped = warp(image, tform.inverse) For N-D images you can pass a coordinate array, that specifies the coordinates in the input image for every element in the output image. E.g. if you want to rescale a 3-D cube, you can do: >>> cube_shape = np.array([30, 30, 30]) >>> cube = np.random.rand(*cube_shape) Setup the coordinate array, that defines the scaling: >>> scale = 0.1 >>> output_shape = (scale * cube_shape).astype(int) >>> coords0, coords1, coords2 = \ ... np.mgrid[:output_shape[0], :output_shape[1], :output_shape[2]] >>> coords = np.array([coords0, coords1, coords2]) Assume that the cube contains spatial data, where the first array element center is at coordinate (0.5, 0.5, 0.5) in real space, i.e. we have to account for this extra offset when scaling the image: >>> coords = (coords + 0.5) / scale - 0.5 >>> warped = warp(cube, coords) """ image = img_as_float(image) input_shape = np.array(image.shape) if output_shape is None: output_shape = input_shape else: output_shape = safe_as_int(output_shape) out = None if order in range(4) and not map_args: # use fast Cython version for specific interpolation orders and input matrix = None if isinstance(inverse_map, np.ndarray) and inverse_map.shape == (3, 3): # inverse_map is a transformation matrix as numpy array matrix = inverse_map elif isinstance(inverse_map, HOMOGRAPHY_TRANSFORMS): # inverse_map is a homography matrix = inverse_map.params elif (hasattr(inverse_map, '__name__') and inverse_map.__name__ == 'inverse' and get_bound_method_class(inverse_map) \ in HOMOGRAPHY_TRANSFORMS): # inverse_map is the inverse of a homography matrix = np.linalg.inv(six.get_method_self(inverse_map).params) if matrix is not None: matrix = matrix.astype(np.double) if image.ndim == 2: out = _warp_fast(image, matrix, output_shape=output_shape, order=order, mode=mode, cval=cval) elif image.ndim == 3: dims = [] for dim in range(image.shape[2]): dims.append( _warp_fast(image[..., dim], matrix, output_shape=output_shape, order=order, mode=mode, cval=cval)) out = np.dstack(dims) if out is None: # use ndimage.map_coordinates if (isinstance(inverse_map, np.ndarray) and inverse_map.shape == (3, 3)): # inverse_map is a transformation matrix as numpy array, # this is only used for order >= 4. inverse_map = ProjectiveTransform(matrix=inverse_map) if isinstance(inverse_map, np.ndarray): # inverse_map is directly given as coordinates coords = inverse_map else: # inverse_map is given as function, that transforms (N, 2) # destination coordinates to their corresponding source # coordinates. This is only supported for 2(+1)-D images. if image.ndim < 2 or image.ndim > 3: raise ValueError("Only 2-D images (grayscale or color) are " "supported, when providing a callable " "`inverse_map`.") def coord_map(*args): return inverse_map(*args, **map_args) if len(input_shape) == 3 and len(output_shape) == 2: # Input image is 2D and has color channel, but output_shape is # given for 2-D images. Automatically add the color channel # dimensionality. output_shape = (output_shape[0], output_shape[1], input_shape[2]) coords = warp_coords(coord_map, output_shape) # Pre-filtering not necessary for order 0, 1 interpolation prefilter = order > 1 out = ndimage.map_coordinates(image, coords, prefilter=prefilter, mode=mode, order=order, cval=cval) if clip: # The spline filters sometimes return results outside [0, 1], # so clip to ensure valid data if np.min(image) < 0: min_val = -1 else: min_val = 0 max_val = 1 clipped = np.clip(out, min_val, max_val) if mode == 'constant' and not (0 <= cval <= 1): clipped[out == cval] = cval out = clipped return out
def frontalization(self, img_, facebb, p2d_): #we rescale the face region (twice as big as the detected face) before applying frontalisation ACC_CONST = 0 img, p2d, TransM = resize(img_, facebb, p2d_) tem3d = np.reshape(self.refU, (-1, 3), order='F') bgids = tem3d[:, 1] < 0 # excluding background 3d points # plot3d(tem3d) # print tem3d.shape ref3dface = np.insert(tem3d, 3, np.ones(len(tem3d)), axis=1).T # homogeneous coordinates _, _, ProjM = self.get_headpose(p2d) proj3d = ProjM.dot(ref3dface) proj3d[0] /= proj3d[2] # homogeneous normalization proj3d[1] /= proj3d[2] # homogeneous normalization proj2dtmp = proj3d[0:2] #The 3D reference is projected to the 2D region by the estimated pose #Then check the projection lies in the image or not vlids = np.logical_and( np.logical_and(proj2dtmp[0] > 0, proj2dtmp[1] > 0), np.logical_and(proj2dtmp[0] < img.shape[1] - 1, proj2dtmp[1] < img.shape[0] - 1)) vlids = np.logical_and(vlids, bgids) proj2d_valid = proj2dtmp[:, vlids] # totally vlids points can be projected into the query image sp_ = self.refU.shape[0:2] synth_front = np.zeros(sp_, np.float) # 320 * 320 inds = np.ravel_multi_index(np.round(proj2d_valid).astype(int), (img.shape[1], img.shape[0]), order='F') unqeles, unqinds, inverids, conts = np.unique(inds, return_index=True, return_inverse=True, return_counts=True) tmp_ = synth_front.flatten() tmp_[vlids] = conts[inverids].astype(np.float) synth_front = tmp_.reshape(synth_front.shape, order='F') synth_front = cv2.GaussianBlur(synth_front, (17, 17), 30).astype(np.float) # color all the valid projected 2d points according to the query image rawfrontal = np.zeros((self.refU.shape[0], self.refU.shape[1], 3)) for k in range(3): intervalues = ndimage.map_coordinates(img[:, :, k].T, proj2d_valid, order=3, mode='nearest') tmp_ = rawfrontal[:, :, k].flatten() tmp_[vlids] = intervalues rawfrontal[:, :, k] = tmp_.reshape(self.refU.shape[0:2], order='F') mline = synth_front.shape[1] // 2 sumleft = np.sum(synth_front[:, 0:mline]) sumright = np.sum(synth_front[:, mline:]) sum_diff = sumleft - sumright # print(sum_diff) if np.abs(sum_diff) > ACC_CONST: weights = np.zeros(sp_) if sum_diff > ACC_CONST: # sumleft > sumright => face to left weights[:, mline:] = 1. else: # sumright > sumleft => face to right weights[:, 0:mline] = 1. weights = cv2.GaussianBlur(weights, (33, 33), 60.5).astype(np.float) synth_front /= np.max(synth_front) weight_take_from_org = 1 / np.exp(1 + synth_front) weight_take_from_sym = 1 - weight_take_from_org weight_take_from_org = weight_take_from_org * np.fliplr(weights) weight_take_from_sym = weight_take_from_sym * np.fliplr(weights) weights = np.tile(weights, (1, 3)).reshape( (weights.shape[0], weights.shape[1], 3), order='F') weight_take_from_org = np.tile( weight_take_from_org, (1, 3)).reshape( (weight_take_from_org.shape[0], weight_take_from_org.shape[1], 3), order='F') weight_take_from_sym = np.tile( weight_take_from_sym, (1, 3)).reshape( (weight_take_from_sym.shape[0], weight_take_from_sym.shape[1], 3), order='F') denominator = weights + weight_take_from_org + weight_take_from_sym frontal_sym = ( rawfrontal * weights + rawfrontal * weight_take_from_org + np.fliplr(rawfrontal) * weight_take_from_sym) / denominator else: frontal_sym = rawfrontal return rawfrontal, frontal_sym, ProjM, TransM
def correlate_img_to_ref_q4(node_coordss, img, ref, settings): # Instantiate empty arrays node_coords = node_coordss.copy() img = nd.spline_filter(img, order=settings.interpolation_order) pix_cord_local = [ np.zeros((2, ref.Nref_stack[elm_nr].shape[0]), dtype=np.float64) for elm_nr in range(settings.mesh.n_elms) ] n_nodes = settings.mesh.n_nodes n_nodes_elm = settings.mesh.element_def.n_nodes di = np.zeros(n_nodes_elm * 2, dtype=np.float64) dnod = np.zeros(n_nodes * 2, dtype=np.float64) C = np.zeros(n_nodes * 2, dtype=np.float64) # Find borders of the elements borders = find_elm_borders_mesh(node_coords, settings.mesh, settings.mesh.n_elms) # Extract image within element borders with padding img_frames = [ img[borders[2, el].astype(int) - settings.pad:borders[3, el].astype(int) + settings.pad, borders[0, el].astype(int) - settings.pad:borders[1, el].astype(int) + settings.pad] for el in range(settings.mesh.n_elms) ] # Normalize image frame flux if False: img_frames = map(normalized_zero_mean, img_frames) # Element loop # TODO: This implementation does handle errors very pretty... for it in range(settings.maxit): C[:] = 0.0 for el in range(settings.mesh.n_elms): Ic = np.zeros_like(ref.I0_stack[el], dtype=np.float64) # Find current coordinates element within the elm_frame np.dot(ref.Nref_stack[el], node_coords[0, settings.mesh.ele[:, el]] - borders[0, el] + settings.pad, out=pix_cord_local[el][1]) np.dot(ref.Nref_stack[el], node_coords[1, settings.mesh.ele[:, el]] - borders[2, el] + settings.pad, out=pix_cord_local[el][0]) # Determine greyscale value at XYc nd.map_coordinates(img_frames[el], pix_cord_local[el], order=settings.interpolation_order, prefilter=False, output=Ic, mode="nearest") # Calculate B^T * dIK np.dot(ref.B_stack[el], (ref.I0_stack[el] - Ic), out=di) # TODO: This shape is awkvard # Order di to match format of K C[(settings.mesh.ele[:, el] + 1) * 2 - 2] += di[:settings.elm.n_nodes] C[(settings.mesh.ele[:, el] + 1) * 2 - 1] += di[settings.elm.n_nodes:] # Calculate position increment as (B^T B)^-1 * (B^T*dIk) "Least squares solution" np.dot(ref.K, C, out=dnod) # Add increment to nodal positions node_coords[0, :] += dnod[::2] node_coords[1, :] += dnod[1::2] # Check for convergence if np.max(np.abs(dnod)) < settings.tol: logging.info('Converged in %s iterations' % it) return node_coords, Ic, True logging.info( 'Did not converged in %s iterations last increment was %0.4f' % (it, np.max(np.abs(dnod)))) return node_coords, Ic, False
def correlate_frames(node_pos, mesh, img, ref, settings): """ Parameters ---------- node_pos : ndarray The position of the nodes mesh : Mesh The mesh object img : ndarray 2d array containing the image frame ref : Reference The reference object settings : DICInput The settings which will be used during the analysis Returns ------- updated node positions, current pixel values """ logger = logging.getLogger(__name__) node_pos = np.copy(node_pos).astype(settings.precision) # Declare empty arrays pixel_pos = np.zeros((2, ref.n_pixels), dtype=settings.precision) dnod_x = np.zeros(mesh.n_nodes * 2) image_filtered = nd.spline_filter( img, order=settings.interpolation_order).transpose() for it in range(settings.maxit): # Find nodal positions within ROI np.dot(node_pos, ref.Nref_stack, out=pixel_pos) # Find pixel values for current coordinates. Use edge values if out of bounds. Ic = nd.map_coordinates(image_filtered, pixel_pos, order=settings.interpolation_order, prefilter=False, mode="nearest") # Calculate position increment as (B^T B)^-1 * (B^T*dIk) "Least squares solution" dnod = np.dot(ref.K, ref.I0_stack - Ic) # Add increment to nodal positions node_pos[0, :] += dnod[:mesh.n_nodes] node_pos[1, :] += dnod[mesh.n_nodes:] dnod_x += dnod # Check for convergence if np.max(np.abs(dnod)) < settings.tol: logger.info('Frame converged in %s iterations', it) return np.array( (dnod_x[:mesh.n_nodes], dnod_x[mesh.n_nodes:])), Ic, True # Reset array values logger.info("Frame did not converge. Largest increment was %f pixels" % np.max(dnod)) return np.array((dnod_x[:mesh.n_nodes], dnod_x[mesh.n_nodes:])), Ic, False
def summarise(image, *, spacing=1, using_height=False): """Compute statistics for every disjoint skeleton in `image`. **Note: this function is deprecated. Prefer** :func:`.summarize`. Parameters ---------- image : array, shape (M, N, ..., P) N-dimensional array, where nonzero entries correspond to an object's single-pixel-wide skeleton. If the image is of type 'float', the values are taken to be the height at that pixel, which is used to compute the skeleton distances. spacing : float, or array-like of float, shape `(skel.ndim,)` A value indicating the distance between adjacent pixels. This can either be a single value if the data has the same resolution along all axes, or it can be an array of the same shape as `skel` to indicate spacing along each axis. using_height : bool, optional If `True`, the pixel value at each point of the skeleton will be considered to be a height measurement, and this height will be incorporated into skeleton branch lengths, endpoint coordinates, and euclidean distances. Used for analysis of atomic force microscopy (AFM) images. Returns ------- df : pandas DataFrame A data frame summarising the statistics of the skeletons in `image`. """ ndim = image.ndim spacing = np.ones(ndim, dtype=float) * spacing g, coords_img, degrees = skeleton_to_csgraph(image, spacing=spacing, value_is_height=using_height) num_skeletons, skeleton_ids = csgraph.connected_components(g, directed=False) if np.issubdtype(image.dtype, np.float_) and not using_height: pixel_values = ndi.map_coordinates(image, coords_img.T, order=3) value_columns = ['mean pixel value'] value_column_types = [float] else: pixel_values = None value_columns = [] value_column_types = [] stats = branch_statistics(g, pixel_values) indices0 = stats[:, 0].astype(int) indices1 = stats[:, 1].astype(int) coords_img0 = coords_img[indices0] coords_img1 = coords_img[indices1] coords_real0 = coords_img0 * spacing coords_real1 = coords_img1 * spacing if using_height: height_coords0 = ndi.map_coordinates(image, coords_img0.T, order=3) coords_real0 = np.column_stack((height_coords0, coords_real0)) height_coords1 = ndi.map_coordinates(image, coords_img1.T, order=3) coords_real1 = np.column_stack((height_coords1, coords_real1)) distances = np.sqrt(np.sum((coords_real0 - coords_real1)**2, axis=1)) skeleton_id = skeleton_ids[stats[:, 0].astype(int)] table = np.column_stack((skeleton_id, stats, coords_img0, coords_img1, coords_real0, coords_real1, distances)) height_ndim = ndim if not using_height else (ndim + 1) columns = ([ 'skeleton-id', 'node-id-0', 'node-id-1', 'branch-distance', 'branch-type' ] + value_columns + ['image-coord-src-%i' % i for i in range(ndim)] + ['image-coord-dst-%i' % i for i in range(ndim)] + ['coord-src-%i' % i for i in range(height_ndim)] + ['coord-dst-%i' % i for i in range(height_ndim)] + ['euclidean-distance']) column_types = ([int, int, int, float, int] + value_column_types + 2 * ndim * [int] + 2 * height_ndim * [float] + [float]) data_dict = { col: dat.astype(dtype) for col, dat, dtype in zip(columns, table.T, column_types) } df = pd.DataFrame(data_dict) return df
final_map[ind] = 0 # do this so I can FFT it uv = NP.fft.fftshift(NP.fft.fft2(NP.fft.fftshift(final_map.copy()))) #load previously calculated LWA PSF and convolve with open('/data2/beards/instr_data/lwa_uv_psf.pickle') as f: lwa_uv_psf, gridu, gridv = pickle.load(f) du = gridu[0, 1] - gridu[0, 0] dv = gridv[1, 0] - gridv[0, 0] # interpolate to GSM defined grid gridu_gsm, gridv_gsm = NP.meshgrid( 0.5 * (NP.arange(uv.shape[1]) - uv.shape[1] / 2), 0.5 * (NP.arange(uv.shape[0]) - uv.shape[0] / 2)) # map_coordinates uses pixel coordinates... need to remap ucoords = (gridu_gsm - gridu.min()) / du vcoords = (gridv_gsm - gridv.min()) / dv psf_matched = ndimage.map_coordinates(lwa_uv_psf, [ucoords, vcoords]) psf_image = NP.fft.fftshift(NP.real(NP.fft.ifft2( NP.fft.fftshift(psf_matched)))) norm_factor = NP.sum(psf_image[where( abs(psf_image) > 0.05 * psf_image.max())]) # normalize the PSF psf_matched = psf_matched / norm_factor uv_convolved = psf_matched * uv final_map = NP.fft.fftshift( NP.real(NP.fft.ifft2(NP.fft.fftshift(uv_convolved)))) final_map[ind] = -inf # reset to -inf to plot it as white clf() imshow(final_map, aspect='equal',
def cal_trans_data(pc_dict, cnt=-1): posfile = pc_dict[0] pointcloud = pc_dict[1] pointcloud = np.hstack([pointcloud, np.ones((pointcloud.shape[0], 1))]) imgpos = {} with open(posfile) as imgpos_file: for line in imgpos_file: pos = [x for x in line.split(' ')] for i in range(len(pos) - 2): pos[i + 1] = float(pos[i + 1]) imgpos[pos[0]] = np.reshape(np.array(pos[1:-1]), [4, 4]) #translate pointcloud to image coordinate pointcloud = np.dot(np.linalg.inv(imgpos["stereo_centre"]), pointcloud.T) pointcloud = np.dot(G_CAMERA_POSESOURCE, pointcloud) uv = CAMERA_MODEL.project(pointcloud, [1280, 960]) #print(CAMERA_MODEL.bilinear_lut[:, 1::-1].shape) lut = CAMERA_MODEL.bilinear_lut[:, 1::-1].T.reshape((2, 960, 1280)) lut = np.swapaxes(lut, 2, 1) u = map_coordinates(lut[0, :, :], uv, order=1) v = map_coordinates(lut[1, :, :], uv, order=1) uv = np.array([u, v]) zero0 = np.where(uv[1, :] == 0) zero1 = np.where(uv[0, :] == 0) zero_01 = np.intersect1d(zero0, zero1) nozero = np.setdiff1d(np.arange(4096), zero_01) uv = np.delete(uv, zero_01.tolist(), axis=1) #print(max(uv[0,:]),max(uv[1,:])) if cnt == 0: uv_show = uv / 4 plt.scatter(np.ravel(uv_show[1, :]), np.ravel(uv_show[0, :]), s=5, edgecolors='none', cmap='jet') plt.xlim(0, 320) plt.ylim(240, 0) plt.xticks([]) plt.yticks([]) plt.savefig("test.png") plt.cla() transform_matrix = np.zeros([80 * 4096, 1]) u = np.floor(uv[0, :] / 120) v = np.floor(uv[1, :] / 128) row = u * 10 + v #print(min(u),min(v),min(row)) #print(max(u),max(v),max(row)) row1 = (row * 4096 + nozero).astype(int).tolist() transform_matrix[row1] = 1 transform_matrix = transform_matrix.reshape([80, 4096]) ''' aa = np.sum(transform_matrix,1).reshape([8,10]) print(np.sum(aa)) plt.figure(2) plt.imshow(aa) plt.show() input() exit() ''' return transform_matrix
def resample(moving, transform=None, reference=None, mov_voxel_coords=False, ref_voxel_coords=False, dtype=None, interp_order=INTERP_ORDER): """ Resample `movimg` into voxel space of `reference` using `transform` Apply a transformation to the image considered as 'moving' to bring it into the same grid as a given `reference` image. The transformation usually maps world space in `reference` to world space in `movimg`, but can also be a voxel to voxel mapping (see parameters below). This function uses scipy.ndimage except for the case `interp_order==3`, where a fast cubic spline implementation is used. Parameters ---------- moving: nipy-like image Image to be resampled. transform: transform object or None Represents a transform that goes from the `reference` image to the `moving` image. None means an identity transform. Otherwise, it should have either an `apply` method, or an `as_affine` method. By default, `transform` maps between the output (world) space of `reference` and the output (world) space of `moving`. If `mov_voxel_coords` is True, maps to the *voxel* space of `moving` and if `ref_vox_coords` is True, maps from the *voxel* space of `reference`. reference : None or nipy-like image or tuple, optional The reference image defines the image dimensions and xyz affine to which to resample. It can be input as a nipy-like image or as a tuple (shape, affine). If None, use `movimg` to define these. mov_voxel_coords : boolean, optional True if the transform maps to voxel coordinates, False if it maps to world coordinates. ref_voxel_coords : boolean, optional True if the transform maps from voxel coordinates, False if it maps from world coordinates. interp_order: int, optional Spline interpolation order, defaults to 3. Returns ------- aligned_img : Image Image resliced to `reference` with reference-to-movimg transform `transform` """ # Function assumes xyz_affine for inputs moving = as_xyz_image(moving) mov_aff = xyz_affine(moving) if reference == None: reference = moving if isinstance(reference, (tuple, list)): ref_shape, ref_aff = reference else: # Expecting image. Must be an image that can make an xyz_affine reference = as_xyz_image(reference) ref_shape = reference.shape ref_aff = xyz_affine(reference) if not len(ref_shape) == 3 or not ref_aff.shape == (4, 4): raise ValueError('Input image should be 3D') data = moving.get_data() if dtype == None: dtype = data.dtype # Assume identity transform by default if transform == None: transform = Affine() # Case: affine transform if hasattr(transform, 'as_affine'): Tv = transform.as_affine() if not ref_voxel_coords: Tv = np.dot(Tv, ref_aff) if not mov_voxel_coords: Tv = np.dot(inverse_affine(mov_aff), Tv) if interp_order == 3: output = _cspline_resample3d(data, ref_shape, Tv, dtype=dtype) output = output.astype(dtype) else: output = np.zeros(ref_shape, dtype=dtype) affine_transform(data, Tv[0:3, 0:3], offset=Tv[0:3, 3], order=interp_order, cval=0, output_shape=ref_shape, output=output) # Case: non-affine transform else: Tv = transform if not ref_voxel_coords: Tv = Tv.compose(Affine(ref_aff)) if not mov_voxel_coords: Tv = Affine(inverse_affine(mov_aff)).compose(Tv) coords = np.indices(ref_shape).transpose((1, 2, 3, 0)) coords = np.reshape(coords, (np.prod(ref_shape), 3)) coords = Tv.apply(coords).T if interp_order == 3: cbspline = _cspline_transform(data) output = np.zeros(ref_shape, dtype='double') output = _cspline_sample3d(output, cbspline, *coords) output = output.astype(dtype) else: output = map_coordinates(data, coords, order=interp_order, cval=0, output=dtype) return make_xyz_image(output, ref_aff, 'scanner')
def profile_line(img, src, dst, axes, linewidth=1, order=1, mode='constant', cval=0.0): """Return the intensity profile of an image measured along a scan line. Parameters ---------- img : numeric array, shape (M, N[, C]) The image, either grayscale (2D array) or multichannel (3D array, where the final axis contains the channel information). src : 2-tuple of numeric scalar (float or int) The start point of the scan line. dst : 2-tuple of numeric scalar (float or int) The end point of the scan line. linewidth : int, optional Width of the scan, perpendicular to the line order : int in {0, 1, 2, 3, 4, 5}, optional The order of the spline interpolation to compute image values at non-integer coordinates. 0 means nearest-neighbor interpolation. mode : string, one of {'constant', 'nearest', 'reflect', 'wrap'}, optional How to compute any values falling outside of the image. cval : float, optional If `mode` is 'constant', what constant value to use outside the image. Returns ------- return_value : array The intensity profile along the scan line. The length of the profile is the ceil of the computed length of the scan line. Examples -------- >>> x = np.array([[1, 1, 1, 2, 2, 2]]) >>> img = np.vstack([np.zeros_like(x), x, x, x, np.zeros_like(x)]) >>> img array([[0, 0, 0, 0, 0, 0], [1, 1, 1, 2, 2, 2], [1, 1, 1, 2, 2, 2], [1, 1, 1, 2, 2, 2], [0, 0, 0, 0, 0, 0]]) >>> profile_line(img, (2, 1), (2, 4)) array([ 1., 1., 2., 2.]) Notes ----- The destination point is included in the profile, in contrast to standard numpy indexing. """ import scipy.ndimage as nd p0 = ((src[0] - axes[0].offset) / axes[0].scale, (src[1] - axes[1].offset) / axes[1].scale) p1 = ((dst[0] - axes[0].offset) / axes[0].scale, (dst[1] - axes[1].offset) / axes[1].scale) perp_lines = Line2DROI._line_profile_coordinates(p0, p1, linewidth=linewidth) if img.ndim > 2: idx = [ax.index_in_array for ax in axes] if idx[0] < idx[1]: img = np.rollaxis(img, idx[0], 0) img = np.rollaxis(img, idx[1], 1) else: img = np.rollaxis(img, idx[1], 0) img = np.rollaxis(img, idx[0], 0) orig_shape = img.shape img = np.reshape(img, orig_shape[0:2] + (np.product(orig_shape[2:]), )) pixels = [ nd.map_coordinates(img[..., i].T, perp_lines, order=order, mode=mode, cval=cval) for i in range(img.shape[2]) ] i0 = min(axes[0].index_in_array, axes[1].index_in_array) pixels = np.transpose(np.asarray(pixels), (1, 2, 0)) intensities = pixels.mean(axis=1) intensities = np.rollaxis( np.reshape(intensities, intensities.shape[0:1] + orig_shape[2:]), 0, i0 + 1) else: pixels = nd.map_coordinates(img, perp_lines, order=order, mode=mode, cval=cval) intensities = pixels.mean(axis=1) return intensities
def handle_interaction(self, pixel_data): '''Run a UI that gets an angle from the user''' import wx if pixel_data.ndim == 2: # make a color matrix for consistency pixel_data = np.dstack((pixel_data, pixel_data, pixel_data)) pd_min = np.min(pixel_data) pd_max = np.max(pixel_data) if pd_min == pd_max: pixel_data[:, :, :] = 0 else: pixel_data = ((pixel_data - pd_min) * 255.0 / (pd_max - pd_min)) # # Make a 100 x 100 image so it's manageable # isize = 200 i, j, k = np.mgrid[0:isize, 0:int(isize * pixel_data.shape[1] / pixel_data.shape[0]), 0:3].astype(float) i *= float(pixel_data.shape[0]) / float(isize) j *= float(pixel_data.shape[0]) / float(isize) pixel_data = scind.map_coordinates(pixel_data, (i, j, k)) # # Make a dialog box that contains the image # dialog = wx.Dialog(None, title="Rotate image") sizer = wx.BoxSizer(wx.VERTICAL) dialog.SetSizer(sizer) sizer.Add( wx.StaticText(dialog, label="Drag image to rotate, hit OK to continue"), 0, wx.ALIGN_CENTER_HORIZONTAL) canvas = wx.StaticBitmap(dialog) canvas.SetDoubleBuffered(True) canvas.BackgroundColour = wx.Colour(0, 0, 0, wx.ALPHA_TRANSPARENT) sizer.Add( canvas, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) angle = [0] angle_text = wx.StaticText(dialog, label="Angle: %d" % angle[0]) sizer.Add(angle_text, 0, wx.ALIGN_CENTER_HORIZONTAL) def imshow(): angle_text.Label = "Angle: %d" % int(angle[0]) angle_text.Refresh() my_angle = -angle[0] * np.pi / 180.0 transform = np.array([[np.cos(my_angle), -np.sin(my_angle)], [np.sin(my_angle), np.cos(my_angle)]]) # Make it rotate about the center offset = affine_offset(pixel_data.shape, transform) x = np.dstack((scind.affine_transform(pixel_data[:, :, 0], transform, offset, order=0), scind.affine_transform(pixel_data[:, :, 1], transform, offset, order=0), scind.affine_transform(pixel_data[:, :, 2], transform, offset, order=0))) buff = x.astype(np.uint8).tostring() bitmap = wx.BitmapFromBuffer(x.shape[1], x.shape[0], buff) canvas.SetBitmap(bitmap) imshow() # # Install handlers for mouse down, mouse move and mouse up # dragging = [False] initial_angle = [0] hand_cursor = wx.StockCursor(wx.CURSOR_HAND) arrow_cursor = wx.StockCursor(wx.CURSOR_ARROW) def get_angle(event): center = np.array(canvas.Size) / 2 point = np.array(event.GetPositionTuple()) offset = point - center return -np.arctan2(offset[1], offset[0]) * 180.0 / np.pi def on_mouse_down(event): canvas.Cursor = hand_cursor dragging[0] = True initial_angle[0] = get_angle(event) - angle[0] canvas.CaptureMouse() wx.EVT_LEFT_DOWN(canvas, on_mouse_down) def on_mouse_up(event): if dragging[0]: canvas.ReleaseMouse() dragging[0] = False canvas.Cursor = arrow_cursor wx.EVT_LEFT_UP(canvas, on_mouse_up) def on_mouse_lost(event): dragging[0] = False canvas.Cursor = arrow_cursor wx.EVT_MOUSE_CAPTURE_LOST(canvas, on_mouse_lost) def on_mouse_move(event): if dragging[0]: angle[0] = get_angle(event) - initial_angle[0] imshow() canvas.Refresh(eraseBackground=False) wx.EVT_MOTION(canvas, on_mouse_move) # # Put the OK and Cancel buttons on the bottom # btnsizer = wx.StdDialogButtonSizer() btn = wx.Button(dialog, wx.ID_OK) btn.SetDefault() btnsizer.AddButton(btn) btn = wx.Button(dialog, wx.ID_CANCEL) btnsizer.AddButton(btn) btnsizer.Realize() sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5) dialog.Fit() result = dialog.ShowModal() dialog.Destroy() if result == wx.ID_OK: return angle[0] raise ValueError("Canceled by user in FlipAndRotate")
x_step = x_res_deg, x_shift = x0_conv, y_step = y_res_deg, y_shift = y0_conv, z_step = 1, z_shift = 1.5) s1_xyz = np.array(s1_xyz) s1_xyz[0:2,:] = s1_xyz[0:2,:] - clip_len comp_list = ['zz', 'xy', 'xz', 'yz', 'xx', 'yy'] print 'interpolating stresses to fault points' for comp in comp_list: print 'doing {}'.format(comp) stress_vol = (stress_db['{}_MPa'.format(comp)][clip_len:clip_dist, clip_len:clip_dist,:]) s1['{}_stress'.format(comp)] = nd.map_coordinates( stress_vol, [s1_xyz[1], s1_xyz[0], s1_xyz[2]], order=interp_order) del stress_vol stress_db.close() print 'calculating shear and normal stresses' s1['tau_dd_1'] = 0. s1['tau_ss_1'] = 0. s1['sig_nn_1'] = 0. s1['tau_dd_2'] = 0. s1['tau_ss_2'] = 0. s1['sig_nn_2'] = 0. stress_tens_xyz = {}
def get_pars_fr(wavst, flxst, model_patht='../../data/COELHO2014/', npools=4, fixG=1.0): for order in range(len(flxst)): flxst[order] = clean_strong_lines(wavst[order], flxst[order], mode=1) t0 = time.time() global wavs, flxs global model_path wavs, flxs = wavst.copy(), flxst.copy() model_path = model_patht gt = np.array([6000, 7000, 8000, 9000, 10000]) gg = np.array([2.5, 3.0, 3.5, 4.0, 4.5]) if fixG != -1: gg = np.array([fixG]) gz = np.array([-1, -0.5, 0.0, 0.2]) gr = np.array([10., 50., 100., 150., 200., 250., 300.]) #""" tr = np.tile(gr, len(gt) * len(gg) * len(gz)) tg = np.repeat(np.tile(gg, len(gt)), len(gr) * len(gz)) tz = np.repeat(np.tile(gz, len(gt) * len(gg)), len(gr)) tt = np.repeat(gt, len(gg) * len(gr) * len(gz)) tot = np.vstack((tt, tg, tz, tr)).T #for pars in tot: # pars = [8000,4.0,-0.5,40.0] # print pars, multiccf(pars) p = Pool(npools) vals = np.array((p.map(multiccf, list(tot)))) p.terminate() I = np.argmin(vals) best_vals = tot[I] bt, bg, bz, br = best_vals[0], best_vals[1], best_vals[2], best_vals[3] #""" t1 = time.time() print(bt, bg, bz, br, (t1 - t0) / 60., 'mins') #bt,bg,bz,br = 7000.,4.5, 0.2, 100.0 gt = np.arange(bt - 1000, bt + 1001, 250) I = np.where((gt >= 6000) & (gt <= 10000))[0] gt = gt[I] gr = np.arange(br - 60., br + 61., 20.) I = np.where(gr >= 10)[0] gr = gr[I] tr = np.tile(gr, len(gt) * len(gg) * len(gz)) tg = np.repeat(np.tile(gg, len(gt)), len(gr) * len(gz)) tz = np.repeat(np.tile(gz, len(gt) * len(gg)), len(gr)) tt = np.repeat(gt, len(gg) * len(gr) * len(gz)) tot = np.vstack((tt, tg, tz, tr)).T p = Pool(npools) vals = np.array((p.map(multiccf, list(tot)))) p.terminate() I = np.argmin(vals) best_vals = tot[I] bt, bg, bz, br = best_vals[0], best_vals[1], best_vals[2], best_vals[3] t2 = time.time() print(bt, bg, bz, br, (t2 - t1) / 60., 'mins') #np.savetxt('temp_grid.txt',vals) if fixG == -1: grid = np.reshape(vals, (len(gt), len(gg), len(gz), len(gr))) tckt = interpolate.splrep(gt, np.arange(len(gt)), k=1) tckg = interpolate.splrep(gg, np.arange(len(gg)), k=1) tckz = interpolate.splrep(gz, np.arange(len(gz)), k=1) tckr = interpolate.splrep(gr, np.arange(len(gr)), k=1) itckt = interpolate.splrep(np.arange(len(gt)), gt, k=1) itckg = interpolate.splrep(np.arange(len(gg)), gg, k=1) itckz = interpolate.splrep(np.arange(len(gz)), gz, k=1) itckr = interpolate.splrep(np.arange(len(gr)), gr, k=1) st = np.arange(gt[0], gt[-1] + 1, 10.) sg = np.arange(gg[0], gg[-1] + 0.01, 0.1) sz = np.arange(gz[0], gz[-1] + 0.01, 0.1) sr = np.arange(gr[0], gr[-1] + 1., 5.) st = interpolate.splev(st, tckt) sg = interpolate.splev(sg, tckg) sz = interpolate.splev(sz, tckz) sr = interpolate.splev(sr, tckr) tr2 = np.tile(sr, len(st) * len(sg) * len(sz)) tg2 = np.repeat(np.tile(sg, len(st)), len(sr) * len(sz)) tz2 = np.repeat(np.tile(sz, len(st) * len(sg)), len(sr)) tt2 = np.repeat(st, len(sg) * len(sr) * len(sz)) tot2 = np.vstack((tt2, tg2, tz2, tr2)) zi = ndimage.map_coordinates(grid, tot2, order=3, mode='nearest') I = np.argmin(zi) minval = tot2[:, I] mint = interpolate.splev(minval[0], itckt) ming = interpolate.splev(minval[1], itckg) minz = interpolate.splev(minval[2], itckz) minr = interpolate.splev(minval[3], itckr) else: grid = np.reshape(vals, (len(gt), len(gz), len(gr))) tckt = interpolate.splrep(gt, np.arange(len(gt)), k=1) tckz = interpolate.splrep(gz, np.arange(len(gz)), k=1) tckr = interpolate.splrep(gr, np.arange(len(gr)), k=1) itckt = interpolate.splrep(np.arange(len(gt)), gt, k=1) itckz = interpolate.splrep(np.arange(len(gz)), gz, k=1) itckr = interpolate.splrep(np.arange(len(gr)), gr, k=1) st = np.arange(gt[0], gt[-1] + 1, 10.) sz = np.arange(gz[0], gz[-1] + 0.01, 0.1) sr = np.arange(gr[0], gr[-1] + 1., 5.) st = interpolate.splev(st, tckt) sz = interpolate.splev(sz, tckz) sr = interpolate.splev(sr, tckr) tr2 = np.tile(sr, len(st) * len(sz)) tz2 = np.repeat(np.tile(sz, len(st)), len(sr)) tt2 = np.repeat(st, len(sr) * len(sz)) tot2 = np.vstack((tt2, tz2, tr2)) zi = ndimage.map_coordinates(grid, tot2, order=3, mode='nearest') I = np.argmin(zi) minval = tot2[:, I] mint = interpolate.splev(minval[0], itckt) ming = fixG minz = interpolate.splev(minval[1], itckz) minr = interpolate.splev(minval[2], itckr) #d = {'grid':grid, 'zi':zi, 'tot2':tot2, 'gt':gt, 'gg':gg, 'gz':gz, 'gr':gr} #pickle.dump(d,open('temp_dict.pkl')) return float(mint), float(ming), float(minz), float(minr)
def _correct_mesh_orientation(volume, actual_verts, faces, spacing=(1., 1., 1.), gradient_direction='descent'): """ Correct orientations of mesh faces. Parameters ---------- volume : (M, N, P) array of doubles Input data volume to find isosurfaces. Will be cast to `np.float64`. actual_verts : (F, 3, 3) array of floats Array with (face, vertex, coords) index coordinates. faces : (F, 3) array of ints List of length-3 lists of integers, referencing vertex coordinates as provided in `verts`. spacing : length-3 tuple of floats Voxel spacing in spatial dimensions corresponding to numpy array indexing dimensions (M, N, P) as in `volume`. gradient_direction : string Controls if the mesh was generated from an isosurface with gradient descent toward objects of interest (the default), or the opposite. The two options are: * descent : Object was greater than exterior * ascent : Exterior was greater than object Returns ------- faces_corrected (F, 3) array of ints Corrected list of faces referencing vertex coordinates in `verts`. Notes ----- Certain applications and mesh processing algorithms require all faces to be oriented in a consistent way. Generally, this means a normal vector points "out" of the meshed shapes. This algorithm corrects the output from `skimage.measure.marching_cubes_classic` by flipping the orientation of mis-oriented faces. Because marching cubes could be used to find isosurfaces either on gradient descent (where the desired object has greater values than the exterior) or ascent (where the desired object has lower values than the exterior), the ``gradient_direction`` kwarg allows the user to inform this algorithm which is correct. If the resulting mesh appears to be oriented completely incorrectly, try changing this option. The arguments expected by this function are the exact outputs from `skimage.measure.marching_cubes_classic` except `actual_verts`, which is an uncorrected version of the fancy indexing operation `verts[faces]`. Only `faces` is corrected and returned as the vertices do not change, only the order in which they are referenced. This algorithm assumes ``faces`` provided are exclusively triangles. See Also -------- skimage.measure.marching_cubes_classic skimage.measure.mesh_surface_area """ # Calculate gradient of `volume`, then interpolate to vertices in `verts` grad_x, grad_y, grad_z = np.gradient(volume) a = actual_verts[:, 0, :] - actual_verts[:, 1, :] b = actual_verts[:, 0, :] - actual_verts[:, 2, :] # Find triangle centroids centroids = (actual_verts.sum(axis=1) / 3.).T del actual_verts # Interpolate face centroids into each gradient axis grad_centroids_x = ndi.map_coordinates(grad_x, centroids) grad_centroids_y = ndi.map_coordinates(grad_y, centroids) grad_centroids_z = ndi.map_coordinates(grad_z, centroids) # Combine and normalize interpolated gradients grad_centroids = np.c_[grad_centroids_x, grad_centroids_y, grad_centroids_z] grad_centroids = (grad_centroids / (np.sum(grad_centroids**2, axis=1)**0.5)[:, np.newaxis]) # Find normal vectors for each face via cross product crosses = np.cross(a, b) crosses = crosses / (np.sum(crosses**2, axis=1)**(0.5))[:, np.newaxis] # Take dot product dotproducts = (grad_centroids * crosses).sum(axis=1) # Find mis-oriented faces if 'descent' in gradient_direction: # Faces with incorrect orientations have dot product < 0 indices = (dotproducts < 0).nonzero()[0] elif 'ascent' in gradient_direction: # Faces with incorrection orientation have dot product > 0 indices = (dotproducts > 0).nonzero()[0] else: raise ValueError("Incorrect input %s in `gradient_direction`, see " "docstring." % (gradient_direction)) # Correct orientation and return, without modifying original data faces_corrected = faces.copy() faces_corrected[indices] = faces_corrected[indices, ::-1] return faces_corrected
def test_warp_coords_example(): image = astronaut().astype(np.float32) assert 3 == image.shape[2] tform = SimilarityTransform(translation=(0, -10)) coords = warp_coords(tform, (30, 30, 3)) map_coordinates(image[:, :, 0], coords[:2])
def make(self, key): from scipy.spatial import distance import bisect # Set some params min_distance = 40 max_height = 100 # Create list of units units = [] # stands for matched units for field in stack.Registration & key: # Edge case: when two channels are registered, we don't know which to use if len(stack.Registration.proj(ignore='scan_channel') & field) > 1: msg = ('More than one channel was registered for {animal_id}-' '{scan_session}-{scan_idx} field {field}'.format(**field)) raise PipelineException(msg) # Get registered grid field_key = {'animal_id': field['animal_id'], 'session': field['scan_session'], 'scan_idx': field['scan_idx'], 'field': field['field']} um_per_px = (meso.ScanInfo.Field & field_key).microns_per_pixel grid = (stack.Registration & field).get_grid(type='affine', desired_res=um_per_px) # Create cell objects for channel_key in (meso.ScanSet & field_key & {'segmentation_method': key['segmentation_method']}): # * field_masks = meso.ScanSet.Unit & channel_key unit_keys, xs, ys = (meso.ScanSet.UnitInfo & field_masks).fetch('KEY', 'px_x', 'px_y') px_coords = np.stack([ys, xs]) xs, ys, zs = [ndimage.map_coordinates(grid[..., i], px_coords, order=1) for i in range(3)] units += [StackMatching.MatchedUnit(*args, key_hash(channel_key)) for args in zip(unit_keys, xs, ys, zs)] # * Separating masks per channel allows masks in diff channels to be matched print(len(units), 'initial units') def find_close_units(centroid, centroids, min_distance): """ Finds centroids that are closer than min_distance to centroid. """ dists = distance.cdist(np.expand_dims(centroid, 0), centroids) indices = np.flatnonzero(dists < min_distance) return indices, dists[0, indices] def is_valid(unit1, unit2, max_height): """ Checks that units belong to different fields and that the resulting unit would not be bigger than 20 microns.""" different_fields = len(set(unit1.plane_ids) & set(unit2.plane_ids)) == 0 acceptable_height = (max(unit1.zs + unit2.zs) - min( unit1.zs + unit2.zs)) < max_height return different_fields and acceptable_height # Create distance matrix # For memory efficiency we use an adjacency list with only the units at less than 10 microns centroids = np.stack([u.centroid for u in units]) distance_list = [] # list of triples (distance, unit1, unit2) for i in range(len(units)): indices, distances = find_close_units(centroids[i], centroids[i + 1:], min_distance) for dist, j in zip(distances, i + 1 + indices): if is_valid(units[i], units[j], max_height): bisect.insort(distance_list, (dist, units[i], units[j])) print(len(distance_list), 'possible pairings') # Join units while (len(distance_list) > 0): # Get next pair of units d, unit1, unit2 = distance_list.pop(0) # Remove them from lists units.remove(unit1) units.remove(unit2) f = lambda x: (unit1 not in x[1:]) and (unit2 not in x[1:]) distance_list = list(filter(f, distance_list)) # Join them unit1.join_with(unit2) # Recalculate distances centroids = [u.centroid for u in units] indices, distances = find_close_units(unit1.centroid, centroids, min_distance) for dist, j in zip(distances, indices): if is_valid(unit1, units[j], max_height): bisect.insort(distance_list, (d, unit1, units[j])) # Insert new unit units.append(unit1) print(len(units), 'number of final masks') # Insert self.insert1({**key, 'min_distance': min_distance, 'max_height': max_height}) for munit_id, munit in zip(itertools.count(start=1), units): new_unit = {**key, 'munit_id': munit_id, 'munit_x': munit.centroid[0], 'munit_y': munit.centroid[1], 'munit_z': munit.centroid[2]} self.Unit().insert1(new_unit) for subunit_key in munit.keys: new_match = {**key, 'munit_id': munit_id, **subunit_key, 'scan_session': subunit_key['session']} self.Match().insert1(new_match, ignore_extra_fields=True)
def properties2d(image, resolution=None, verbose=1): label_img = measure.label(np.transpose(image)) regions = measure.regionprops(label_img) areas = [r.area for r in regions] ix = np.argsort(areas) if len(regions) != 0: sc_region = regions[ix[-1]] try: ratio_minor_major = sc_region.minor_axis_length / sc_region.major_axis_length except ZeroDivisionError: ratio_minor_major = 0.0 area = sc_region.area diameter = sc_region.equivalent_diameter major_l = sc_region.major_axis_length minor_l = sc_region.minor_axis_length if resolution is not None: area *= resolution[0] * resolution[1] # TODO: compute length depending on resolution. Here it assume the patch has the same X and Y resolution diameter *= resolution[0] major_l *= resolution[0] minor_l *= resolution[0] size_grid = 8.0 / resolution[0] # assuming the maximum spinal cord radius is 8 mm else: size_grid = int(2.4 * sc_region.major_axis_length) """ import matplotlib.pyplot as plt plt.imshow(label_img) plt.text(1, 1, sc_region.orientation, color='white') plt.show() """ y0, x0 = sc_region.centroid orientation = sc_region.orientation resolution_grid = 0.25 x_grid, y_grid = np.mgrid[-size_grid:size_grid:resolution_grid, -size_grid:size_grid:resolution_grid] coordinates_grid = np.array(zip(x_grid.ravel(), y_grid.ravel())) coordinates_grid_image = np.array([[x0 + math.cos(orientation) * coordinates_grid[i, 0], y0 - math.sin(orientation) * coordinates_grid[i, 1]] for i in range(coordinates_grid.shape[0])]) from scipy.ndimage import map_coordinates square = map_coordinates(image, coordinates_grid_image.T, output=np.float32, order=0, mode='constant', cval=0.0) square_image = square.reshape((len(x_grid), len(x_grid))) size_half = square_image.shape[1] / 2 left_image = square_image[:, :size_half] right_image = np.fliplr(square_image[:, size_half:]) dice_symmetry = np.sum(left_image[right_image == 1]) * 2.0 / (np.sum(left_image) + np.sum(right_image)) """ import matplotlib.pyplot as plt plt.imshow(square_image) plt.text(3, 3, dice, color='white') plt.show() """ sc_properties = {'area': area, 'bbox': sc_region.bbox, 'centroid': sc_region.centroid, 'eccentricity': sc_region.eccentricity, 'equivalent_diameter': diameter, 'euler_number': sc_region.euler_number, 'inertia_tensor': sc_region.inertia_tensor, 'inertia_tensor_eigvals': sc_region.inertia_tensor_eigvals, 'minor_axis_length': minor_l, 'major_axis_length': major_l, 'moments': sc_region.moments, 'moments_central': sc_region.moments_central, 'orientation': sc_region.orientation * 180.0 / math.pi, 'perimeter': sc_region.perimeter, 'ratio_minor_major': ratio_minor_major, 'solidity': sc_region.solidity, # convexity measure 'symmetry': dice_symmetry } else: sc_properties = None return sc_properties
def process_frames(self, data): mat_corrected = np.reshape( map_coordinates(data[0], self.indices, order=1, mode='reflect'), (self.height, self.width)) return mat_corrected[self.crop:self.height - self.crop, self.crop:self.width - self.crop]
def regular_prior_interpolator(old_prior, new_prior, filter_size=None): old_nodes_z, old_nodes_y, old_nodes_x = calculate_node_spacing( old_prior[:, 1:4]) # Figure out spacing from first two nodes positions if len(old_nodes_z) == 1: old_z_spacing = 1 else: old_z_spacing = old_nodes_z[1] - old_nodes_z[0] old_y_spacing = old_nodes_y[1] - old_nodes_y[0] old_x_spacing = old_nodes_x[1] - old_nodes_x[0] try: logging.log.info( "regular_prior_interpolator: Prior node spacing (z,y,x) is:\t{:.0f} {:.0f} {:.0f}" .format(old_z_spacing, old_y_spacing, old_x_spacing)) except: print "regular_prior_interpolator: Prior node spacing (z,y,x) is:\t{:.0f} {:.0f} {:.0f}".format( old_z_spacing, old_y_spacing, old_x_spacing) # Reshape prior field to a three dimensional arrays z_field = old_prior[:, 4].reshape( (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x))) y_field = old_prior[:, 5].reshape( (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x))) x_field = old_prior[:, 6].reshape( (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x))) z_rot = old_prior[:, 7].reshape( (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x))) y_rot = old_prior[:, 8].reshape( (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x))) x_rot = old_prior[:, 9].reshape( (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x))) #Replacing the Inf in the prior with the median of finte values around (in None replace with zero) inf_positions = numpy.where(numpy.isinf(x_field)) for inf_number in range(len(inf_positions[0])): z = inf_positions[0][inf_number] y = inf_positions[1][inf_number] x = inf_positions[2][inf_number] try: z_field[z, y, x] = numpy.media(z_field[where( numpy.isfinite(z_filed[z - 1:z + 2, y - 1:y + 2, z - 1:x + 2]))]) y_field[z, y, x] = numpy.media(y_field[where( numpy.isfinite(y_filed[z - 1:z + 2, y - 1:y + 2, z - 1:x + 2]))]) x_field[z, y, x] = numpy.media(x_field[where( numpy.isfinite(x_filed[z - 1:z + 2, y - 1:y + 2, z - 1:x + 2]))]) except: pass z_field[numpy.where(numpy.isinf(z_field))] = 0 y_field[numpy.where(numpy.isinf(y_field))] = 0 x_field[numpy.where(numpy.isinf(x_field))] = 0 if filter_size is not None and filter_size > 0: try: logging.log.info( "regular_prior_interpolator: Smoothing kinematics field") except: print "regular_prior_interpolator: Smoothing kinematics field" # 2014-07-18 -- Edward Ando # Changing the median filter for the field from scipy.ndimage.filters.median_filter # (which seems to propagate NaNs) to our own, home-developed median filter: z_field = median_filter_nans(numpy.squeeze(z_field), filter_size).reshape( (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x))) y_field = median_filter_nans(numpy.squeeze(y_field), filter_size).reshape( (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x))) x_field = median_filter_nans(numpy.squeeze(x_field), filter_size).reshape( (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x))) z_rot = median_filter_nans(numpy.squeeze(z_rot), filter_size).reshape( (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x))) y_rot = median_filter_nans(numpy.squeeze(y_rot), filter_size).reshape( (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x))) x_rot = median_filter_nans(numpy.squeeze(x_rot), filter_size).reshape( (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x))) # Normalise coordinates of new prior nodes positions # (subtract position of old top corner and divide by old node spacing), to get into the SHAPE => SIZE # of the old prior for interpolation. new_prior_normalised = numpy.zeros((new_prior.shape[0], 3)) new_prior_normalised[:, 0] = (new_prior[:, 1] - old_nodes_z[0]) / old_z_spacing new_prior_normalised[:, 1] = (new_prior[:, 2] - old_nodes_y[0]) / old_y_spacing new_prior_normalised[:, 2] = (new_prior[:, 3] - old_nodes_x[0]) / old_x_spacing # Interpolate each prior field for each new node # 2014-07-23 Edward Andò: # map_coordinates does not handle NaNs, and cannot handle masked arrays for the moment, # ...so we will seek and destroy the NaNs in the displacement fields before doing a map_coordinates # This means for each NaN position, we will grow a window until we get a real value, # and then we'll use that window do make a median to fill in our NaN measurement. # Figure out NaN positions... (they will be in the same place for every field) nan_positions = numpy.where(numpy.isnan(x_field)) # A mask of ones and zeros in order to quickly work out the smallest window size for the filter mask = numpy.ones((len(old_nodes_z), len(old_nodes_y), len(old_nodes_x)), dtype='bool') mask[nan_positions] = False number_of_nans = len(nan_positions[0]) if number_of_nans > 0: try: logging.log.warn( "regular_prior_interpolator(): {:.0f} NaNs detected, replacing them with a median value of the smallest window that touches real data" .format(number_of_nans)) except: print "regular_prior_interpolator(): {:.0f} NaNs detected, replacing them with a median value of the smallest window that touches real data".format( number_of_nans) for nan_number in range(number_of_nans): z = nan_positions[0][nan_number] y = nan_positions[1][nan_number] x = nan_positions[2][nan_number] z_top = z y_top = y x_top = x z_bot = z y_bot = y x_bot = x window_sum = 0 step = 0 while window_sum == 0: step += 1 #print "step = ", step if z_top >= 0: z_top -= step if y_top >= 0: y_top -= step if x_top >= 0: x_top -= step if z_bot <= len(old_nodes_z): z_bot += step if y_bot <= len(old_nodes_y): y_bot += step if x_bot <= len(old_nodes_x): x_bot += step window_sum = numpy.sum( mask[ z_top:z_bot+1,\ y_top:y_bot+1,\ x_top:x_bot+1 ] ) local_mask = numpy.where( mask[ z_top:z_bot+1,\ y_top:y_bot+1,\ x_top:x_bot+1 ] ) z_field[ z, y, x ] = numpy.median( z_field[ z_top:z_bot+1,\ y_top:y_bot+1,\ x_top:x_bot+1 ][local_mask] ) y_field[ z, y, x ] = numpy.median( y_field[ z_top:z_bot+1,\ y_top:y_bot+1,\ x_top:x_bot+1 ][local_mask] ) x_field[ z, y, x ] = numpy.median( x_field[ z_top:z_bot+1,\ y_top:y_bot+1,\ x_top:x_bot+1 ][local_mask] ) z_rot[ z, y, x ] = numpy.median( z_rot[ z_top:z_bot+1,\ y_top:y_bot+1,\ x_top:x_bot+1 ][local_mask] ) y_rot[ z, y, x ] = numpy.median( y_rot[ z_top:z_bot+1,\ y_top:y_bot+1,\ x_top:x_bot+1 ][local_mask] ) x_rot[ z, y, x ] = numpy.median( x_rot[ z_top:z_bot+1,\ y_top:y_bot+1,\ x_top:x_bot+1 ][local_mask] ) new_z_field = ndimage.map_coordinates(z_field, new_prior_normalised.T, order=1, mode='nearest', prefilter=False).T new_y_field = ndimage.map_coordinates(y_field, new_prior_normalised.T, order=1, mode='nearest').T new_x_field = ndimage.map_coordinates(x_field, new_prior_normalised.T, order=1, mode='nearest').T new_z_rot = ndimage.map_coordinates(z_rot, new_prior_normalised.T, order=1, mode='nearest', prefilter=False).T new_y_rot = ndimage.map_coordinates(y_rot, new_prior_normalised.T, order=1, mode='nearest').T new_x_rot = ndimage.map_coordinates(x_rot, new_prior_normalised.T, order=1, mode='nearest').T # Update and return new prior guesses array new_prior[:, 4] = new_z_field new_prior[:, 5] = new_y_field new_prior[:, 6] = new_x_field new_prior[:, 7] = new_z_rot new_prior[:, 8] = new_y_rot new_prior[:, 9] = new_x_rot return new_prior
def simulate_slice( map_r, psize, n_particles, N_crop=None, snr=0.1, do_snr=True, do_ctf=True, df_min=15000, df_max=20000, df_diff_min=100, df_diff_max=500, df_ang_min=0, df_ang_max=360, kv=300, cs=2.0, ac=0.1, phase=0, bf=0, do_log=True, random_seed=0, ): """ Simulates a particle stack from a 3D voxelized array using the Fourier slice theorem (projection assumption). Parameters ---------- map_r : numpy.ndarray, shape (N,N,N) 3D real space map of shape psize : float pixel size in Angstroms n_particles: int number of particles to simulate N_crop : in number of pixels to crop to snr : float signal to noise ratio. defined as the std(signal) / std(noise). the signal is the projections (with ctf if that's included) do_snr : bool add nosie when True do_ctf : bool add ctf when True df_min : float defocus range min df_max : float defocus range max df_diff_min : float defocus difference range min df_diff_max : float defocus difference range max df_ang_min : float angle of astigmatism range min df_ang_max : float angle of astigmatism range max kv : float voltate of microscope in kilo electron volts (typicaly 120, 200, 300 on electron microscopes) cs : float spherical aberation constant in mm ac : float amplitude contrast phase : float ctf phase bf : float B-factor for CTF envelope. no envelope when 0 do_log : bool log progress if True. TODO: add to logger instead of print random_seed : int random_seed for np.random.seed(random_seed) Returns ------- projs_r: numpy.ndarray, shape (n_particles,N_crop,N_crop) particle stack of simulated projections projs_r_noise : numpy.ndarray, shape (n_particles,N_crop,N_crop) particle stack of simulated projections with noise meta_data_df : pandas.DataFrame metadata of simulated particles, including sampled ctf """ assert len(map_r.shape) == 3 assert np.unique(map_r.shape).size == 1 N = map_r.shape[0] assert N % 2 == 0, "even pixel length" map_f = fourier.do_fft(map_r, d=3) N = map_f.shape[0] xyz = coords.coords_n_by_d(np.arange(-N // 2, N // 2), d=3) idx_z0 = xyz[:, -1] == 0 xy0 = xyz[idx_z0] if random_seed is not None: np.random.seed(random_seed) rots, qs = coords.uniform_rotations(n_particles) projs_f = np.zeros((n_particles, N, N), dtype=np.complex64) for idx in range(n_particles): if do_log and idx % max(1, (n_particles // 10)) == 0: print(idx) rot = rots[idx, :, :] xy0_rot = rot.dot(xy0.T).T projs_f[idx] = ( map_coordinates(map_f.real, xy0_rot.T + N // 2, order=1).astype( np.complex64 ) + 1j * map_coordinates(map_f.imag, xy0_rot.T + N // 2, order=1).astype( np.complex64 ) ).reshape( N, N ) # important to keep order=1 for speed. linear is good enough if do_ctf: ctfs, df1s, df2s, df_ang_deg = transfer.random_ctfs( N=N, psize=psize, n_particles=n_particles, df_min=df_min, df_max=df_max, df_diff_min=df_diff_min, df_diff_max=df_diff_max, df_ang_min=df_ang_min, df_ang_max=df_ang_max, kv=kv, cs=cs, ac=ac, phase=phase, bf=bf, do_log=do_log, ) projs_f *= ctfs if N_crop is not None: i, f = N // 2 - N_crop // 2, N // 2 + N_crop // 2 projs_r = fourier.do_ifft(projs_f[:, i:f, i:f], d=2, batch=True) psize *= N / N_crop else: projs_r = fourier.do_ifft(projs_f, d=2, batch=True) if do_snr: signal = np.std(projs_r) noise = signal / snr projs_r_noise = np.random.normal(loc=projs_r, scale=noise) else: projs_r_noise = projs_r meta_data_d = { "N": N_crop, "psize": psize, "snr": snr, "rotation_quaternion": [np.array2string(q) for q in qs], } if do_ctf: meta_data_d.update( { "df1_A": df1s, "df2_A": df2s, "df_ang_deg": df_ang_deg, "kev": kv, "ac": ac, "cs_mm": cs, } ) meta_data_df = pd.DataFrame(meta_data_d) return (projs_r, projs_r_noise, meta_data_df)
def mobius_fast_interpolation(image, M, mode, output_height=None, output_width=None, user_defined=False, start_points=None, end_points=None): image = np.array(image) original_image = image height = image.shape[0] width = image.shape[1] # User can pick output size if output_height == None: output_height = height if output_width == None: output_width = width if user_defined == True: # Method one # You pick starting and ending point a, b, c, d, original_points, new_points = getabcd_1fix( height, width, start_points, end_points) else: # Method two # Randomly generated starting the ending point a, b, c, d, original_points, new_points = madmissable_abcd( M, height, width) e = [complex(0, 0)] * height * width z = np.array(e).reshape(height, width) for i in range(0, height): for j in range(0, width): z[i, j] = complex(i, j) i = np.array(list(range(0, height)) * width).reshape(width, height).T j = np.array(list(range(0, width)) * height).reshape(height, width) r = ones((output_height, output_width, 3), dtype=uint8) * 255 * 0 w = (a * z + b) / (c * z + d) first = real(w) * 1 second = imag(w) * 1 first = first.astype(int) second = second.astype(int) f1 = first >= 0 f2 = first < output_height f = f1 & f2 s1 = second >= 0 s2 = second < output_width s = s1 & s2 combined = s & f r[first[combined], second[combined], :] = image[i[combined], j[combined], :] r_interpolated = r.copy() u = [True] * output_height * output_width canvas = np.array(u).reshape(output_height, output_width) canvas[first[combined], second[combined]] = False converted_empty_index = np.where(canvas == True) converted_first = converted_empty_index[0] converted_second = converted_empty_index[1] new = converted_first.astype(complex) new.imag = converted_second ori = (d * new - b) / (-c * new + a) p = np.hstack([ori.real, ori.real, ori.real]) k = np.hstack([ori.imag, ori.imag, ori.imag]) zero = np.zeros_like(ori.real) one = np.ones_like(ori.real) two = np.ones_like(ori.real) * 2 third = np.hstack([zero, one, two]) number_of_interpolated_point = len(one) e = number_of_interpolated_point interpolated_value_unfinished = map_coordinates(image, [p, k, third], order=1, mode=mode, cval=0) t = interpolated_value_unfinished interpolated_value = np.stack([t[0:e], t[e:2 * e], t[2 * e:]]).T r_interpolated[converted_first, converted_second, :] = interpolated_value new_image = Image.fromarray(r_interpolated) uninterpolated_image = Image.fromarray(r) figure(figsize=(15, 10)) subplot(1, 3, 1) title('Original') imshow(original_image) subplot(1, 3, 2) title('No interpolation') imshow(r) subplot(1, 3, 3) # figure() title('With interpolation') imshow(r_interpolated) return new_image, uninterpolated_image
#samples used sampleNumber = (p - 1) * mu print("Samples used:", sampleNumber, ", proportion:", sampleNumber / float(N * N)) #------------- # Measure finite slice from scipy import ndimage print("Measuring slices") drtSpace = np.zeros((p + 1, p), floatType) for lines, mValues in zip(subsetsLines, subsetsMValues): for i, line in enumerate(lines): u, v = line sliceReal = ndimage.map_coordinates(np.real(fftLenaShifted), [u, v]) sliceImag = ndimage.map_coordinates(np.imag(fftLenaShifted), [u, v]) slice = sliceReal + 1j * sliceImag # print("slice", i, ":", slice) finiteProjection = fftpack.ifft( slice) # recover projection using slice theorem drtSpace[mValues[i], :] = finiteProjection #print("drtSpace:", drtSpace) #------------------------------- #define MLEM def ossirt_expand_complex(iterations, t, p, g_j,
def __call__(self, m): if self.random_state.uniform() < self.execution_probability: if (m.ndim == 3): dz = gaussian_filter(self.random_state.randn(*m.shape), self.sigma, mode="constant", cval=0) * self.alpha dy = gaussian_filter(self.random_state.randn(*m.shape), self.sigma, mode="constant", cval=0) * self.alpha dx = gaussian_filter(self.random_state.randn(*m.shape), self.sigma, mode="constant", cval=0) * self.alpha z_dim, y_dim, x_dim = m.shape z, y, x = np.meshgrid(np.arange(z_dim), np.arange(y_dim), np.arange(x_dim), indexing='ij') indices = z + dz, y + dy, x + dx return map_coordinates(m, indices, order=self.spline_order, mode='reflect') else: z_dim, y_dim, x_dim = m[0, :, :, :].shape dz = gaussian_filter( self.random_state.randn(*m[0, :, :, :].shape), self.sigma, mode="constant", cval=0) * self.alpha dy = gaussian_filter( self.random_state.randn(*m[0, :, :, :].shape), self.sigma, mode="constant", cval=0) * self.alpha dx = gaussian_filter( self.random_state.randn(*m[0, :, :, :].shape), self.sigma, mode="constant", cval=0) * self.alpha z, y, x = np.meshgrid(np.arange(z_dim), np.arange(y_dim), np.arange(x_dim), indexing='ij') indices = z + dz, y + dy, x + dx channels = [ map_coordinates(m[c, :, :, :], indices, order=self.spline_order, mode='reflect') for c in range(m.shape[0]) ] m = np.stack(channels, axis=0) # save_as_h5('ElasticDeformation', m) return m
def _single_session_fit(self, vols, quality=None, affine_correction=None): """ Realigns volumes (vols) from a single session. Parameters ---------- vols: list of `nibabel.Nifti1Image` objects the volumes to realign quality: float, optional (default None) to override instance value affine_correction: 2D array of shape (4, 4), optional (default None) affine transformation to be applied to vols before realignment (this is useful in multi-session realignment) Returns ------- 2D array of shape (n_scans, len(self.lkp) the estimated realignment parameters """ # sanitize input if quality is None: quality = self.quality if affine_correction is None: affine_correction = np.eye(4) # load first vol vols = load_vols(vols) n_scans = len(vols) vol_0 = vols[0] # single vol ? if n_scans < 2: return np.array([get_initial_motion_params()]) # affine correction vol_0 = nibabel.Nifti1Image( vol_0.get_data(), np.dot(affine_correction, vol_0.get_affine())) # voxel dimensions on the working grid skip = np.sqrt(np.sum(vol_0.get_affine()[:3, :3]**2, axis=0))**(-1) * self.sep # build working grid dim = vol_0.shape x1, x2, x3 = np.mgrid[0:dim[0] - .5 - 1:skip[0], 0:dim[1] - .5 - 1:skip[1], 0:dim[2] - .5 - 1:skip[2]].reshape((3, -1)) # smooth 0th volume to absorb noise before differentiating sref_vol = smooth_image(vol_0, self.fwhm).get_data() # resample the smoothed reference volume unto doped working grid G = ndimage.map_coordinates( sref_vol, [x1, x2, x3], order=self.interp, mode='wrap', ).reshape(x1.shape) # compute gradient of reference volume Gx, Gy, Gz = np.gradient(sref_vol) # resample gradient unto working grid Gx = ndimage.map_coordinates( Gx, [x1, x2, x3], order=self.interp, mode='wrap', ).reshape(x1.shape) Gy = ndimage.map_coordinates( Gy, [x1, x2, x3], order=self.interp, mode='wrap', ).reshape(x1.shape) Gz = ndimage.map_coordinates( Gz, [x1, x2, x3], order=self.interp, mode='wrap', ).reshape(x1.shape) # compute rate of change of chi2 w.r.t. parameters A0 = _compute_rate_of_change_of_chisq(vol_0.get_affine(), [x1, x2, x3], [Gx, Gy, Gz], lkp=self.lkp) # compute intercept vector for LSPs b = G.ravel() # garbage-collect unused local variables del sref_vol, Gx, Gy, Gz # Remove voxels that contribute very little to the final estimate. # It's essentially sufficient to remove voxels that contribute the # least to the determinant of the inverse convariance matrix # (i.e of the precision matrix) if n_scans > 2: self._log(("Eliminating unimportant voxels (target quality: %s)" "...") % quality) alpha = np.vstack((A0.T, b)).T alpha = np.dot(alpha.T, alpha) det0 = scipy.linalg.det(alpha) det1 = det0 # det1 / det0 is a precision measure n_eliminated_voxels = 0 while det1 / det0 > quality: # determine unimportant voxels to eliminate dets = np.ndarray(A0.shape[0]) for t in range(A0.shape[0]): tmp = np.hstack((A0[t, ...], b[t])).reshape( (1, A0.shape[1] + 1)) dets[t] = scipy.linalg.det(alpha - np.dot(tmp.T, tmp)) msk = np.argsort(det1 - dets) msk = msk[:np.round(len(dets) / 10.)] # eliminate unimportant voxels n_eliminated_voxels += len(msk) self._log("\tEliminating %i voxels (current quality = %s)..." % (len(msk), det1 / det0)) A0 = np.delete(A0, msk, axis=0) b = np.delete(b, msk, axis=0) x1 = np.delete(x1, msk, axis=0) x2 = np.delete(x2, msk, axis=0) x3 = np.delete(x3, msk, axis=0) # updates for next iteration alpha = np.vstack((A0.T, b)).T alpha = np.dot(alpha.T, alpha) det1 = scipy.linalg.det(alpha) self._log("...done; eliminated %i voxels.\r\n" % n_eliminated_voxels) # register the volumes to the reference volume self._log("Registering volumes to reference ( = volume 1)...") rp = np.ndarray((n_scans, 12)) rp[0, ...] = get_initial_motion_params() # don't mov the reference image for t in range(1, n_scans): self._log("\tRegistering volume %i/%i..." % (t + 1, n_scans)) # load volume t vol = vols[t] vol = nibabel.Nifti1Image( vol.get_data(), np.dot(affine_correction, vol.get_affine())) # initialize final rp for this vol rp[t, ...] = get_initial_motion_params() # smooth volume t V = smooth_image(vol, self.fwhm).get_data() # intialize motion params for this vol rp[t, ...] = get_initial_motion_params() # global optical flow problem with affine motion model: run # Gauss-Newton iterated LS (this loop should normally converge # after about as few as 5 iterations) dim = np.hstack((V.shape, [1, 1])) dim = dim[:3] ss = INFINITY countdown = -1 iteration = None for iteration in range(self.n_iterations): # starting point q = get_initial_motion_params() # pass from volume t's grid to that of the reference # volume (0) y1, y2, y3 = transform_coords(np.zeros(6), vol_0.get_affine(), vol.get_affine(), [x1, x2, x3]) # sanity mask: some voxels might have fallen out of business; # and zap'em msk = np.nonzero((y1 >= 0) & (y1 < dim[0]) & (y2 >= 0) & (y2 < dim[1]) & (y3 >= 0) & (y3 < dim[2]))[0] # if mask is too small, then we're screwed anyway if len(msk) < 32: raise RuntimeError( ("Almost all voxels have fallen out of the FOV. Only " "%i voxels survived. Registration can't work." % len(msk))) # warp: resample volume t on this new grid F = ndimage.map_coordinates(V, [y1[msk], y2[msk], y3[msk]], order=self.interp, mode='wrap') # formulate and solve LS problem for updating p A = A0[msk, ...].copy() b1 = b[msk].copy() sc = np.sum(b1) / np.sum(F) b1 -= F * sc q_update = scipy.linalg.lstsq(np.dot(A.T, A), np.dot(A.T, b1))[0] # update q q[self.lkp] += q_update rp[t, self.lkp] -= q_update # update affine matrix for volume t by applying M_q vol = apply_realignment_to_vol(vol, q) # compute convergence criterion variables pss = ss ss = np.sum(b1**2) / len(b1) # compute relative gain over last iteration relative_gain = np.abs( (pss - ss) / pss) if np.isfinite(pss) else INFINITY # verbose token = "\t" + "".join(['%-12.4g ' % z for z in q[self.lkp]]) token += '| %.5g' % relative_gain self._log(token) # check whether we've stopped converging altogether if relative_gain < self.tol and countdown == -1: countdown = 2 # countdown if countdown != -1: # converge if countdown == 0: break countdown -= 1 # what happened ? comments = " after %i iterations" % (iteration + 1) if iteration + 1 == self.n_iterations: comments = "did not coverge" + comments else: if relative_gain < self.tol: comments = "converged" + comments else: comments = "stopped converging" + comments self._log("") return rp
def to_worm_frame(images, center_tck, width_tck=None, width_margin=20, sample_distance=None, standard_length=None, standard_width=None, zoom=1, reflect_centerline=False, order=3, dtype=None, **kwargs): """Transform images from the lab reference frame to the worm reference frame. The width of the output image is defined by the center_tck, which defines the length of the worm and thus the width of the image. The height of the image can be specified either directly by the sample_distance parameter, or can be computed from a width_tck that defines the location of the sides of the worm (a fixed width_margin is added so that the image extends a bit past the worm). The size and shape of the output worm can be standardized to a "unit worm" by use of the "standard_length" and "standard_width" parameters; see below. Parameters: images: single numpy array, or list/tuple/3d array of multiple images to be transformed. center_tck: centerline spline defining the pose of the worm in the lab frame. width_tck: width spline defining the distance from centerline to worm edges. Optional; uses are as follows: (1) if sample_distance is not specified, a width_tck must be specified in order to calculate the output image height; (2) if standard_width is specified, a width_tck must also be specified to define the transform from this worm's width profile to the standardized width profile. width_margin: if sample_distance is not specified, width_margin is used to define the distance (in image pixels) that the output image will extend past the edge of the worm (at its widest). If a zoom is specified, note that the margin pixels will be zoomed too. sample_distance: number of pixels to sample in each direction perpendicular to the centerline. The height of the output image is int(round(2 * sample_distance * zoom)). standard_length: if not specified, the width of the output image is int(round(arc_length)*zoom), where arc_length is the path integral along center_tck (i.e. the length from beginning to end). If standard_length is specified, then the length of the output image is int(round(standard_length*zoom)). The full length of the worm will be compressed or expanded as necessary to bring it to the specified standard_length. standard_width: a width spline specifying the "standardized" width profile for the output image. If specified, the actual width profile must also be provided as width_tck. In this case, the output image will be compressed/expanded perpendicular to the centerline as needed to make the actual widths conform to the standard width profile. zoom: zoom factor, can be any real number > 0. reflect_centerline: reflect worm over its centerline. order: image interpolation order (0 = nearest neighbor, 1 = linear, 3 = cubic). Cubic is best, but slowest. dtype: if None, use dtype of input images for output. Otherwise, use the specified dtype. kwargs: additional keyword arguments to pass to ndimage.map_coordinates. Returns: single image or list of images (depending on whether the input is a single image or list/tuple/3d array). """ assert width_tck is not None or sample_distance is not None if standard_width is not None: assert width_tck is not None if standard_length is None: length = spline_geometry.arc_length(center_tck) else: length = standard_length x_samples = int(round(length * zoom)) if sample_distance is None: wtck = standard_width if standard_width is not None else width_tck sample_distance = interpolate.spline_interpolate( wtck, num_points=x_samples).max() + width_margin y_samples = int(round(2 * sample_distance * zoom)) # basic plan: # 1) get the centerline and the perpendiculars to it. # 2) define positions along each perpendicular at which to sample the input images. # (This is the "offset_distances" variable). x = numpy.arange( x_samples, dtype=float) + 0.5 # want to sample at pixel centers, not edges y = numpy.ones_like(x) * (y_samples / 2) worm_frame_centerline = numpy.transpose([x, y]) centerline, perpendiculars, spline_y = _lab_centerline_and_perps( worm_frame_centerline, (x_samples, y_samples), center_tck, width_tck, standard_width, zoom) # if the far edges of the top and bottom pixels are sample_distance from the centerline, # figure out the position of the *centers* of the top and bottom of the pixels. # i.e. correct for fencepost error sample_max = sample_distance * (y_samples - 1) / y_samples offsets = numpy.linspace( -sample_max, sample_max, y_samples ) # distances along each perpendicular across the width of the sample swath offset_distances = numpy.multiply.outer( perpendiculars.T, offsets) # shape = (2, x_samples, y_samples) centerline = centerline.T[:, :, numpy. newaxis] # from shape = (x_samples, 2) to shape = (2, x_samples, 1) if reflect_centerline: offset_distances *= -1 sample_coordinates = centerline + offset_distances # shape = (2, x_samples, y_samples) unpack_list = False if isinstance(images, numpy.ndarray): if images.ndim == 3: images = list(images) else: unpack_list = True images = [images] # subtract half-pixel offset because map_coordinates treats (0,0) as the middle # of the top-left pixel, not the far corner of that pixel. worm_frame = [ ndimage.map_coordinates(image, sample_coordinates - _HALF_PX_OFFSET.reshape(2, 1, 1), order=order, output=dtype, **kwargs) for image in images ] if unpack_list: worm_frame = worm_frame[0] return worm_frame
def undrift(imgstack, optflow): t_dim, c_dim, y_dim, x_dim = imgstack.shape TILE_SIZE = 16 checker_board = numpy.zeros((t_dim, y_dim, x_dim), numpy.uint8) block_1 = numpy.ones((TILE_SIZE, TILE_SIZE), numpy.uint8) block_2 = numpy.ones((TILE_SIZE, TILE_SIZE), numpy.uint8) block_1 *= 32 block_2 *= 128 block = numpy.c_[numpy.r_[block_1, block_2], numpy.r_[block_2, block_1]] checker_board[0, :(y_dim // (2 * TILE_SIZE)) * 2 * TILE_SIZE, :(x_dim // (2 * TILE_SIZE)) * 2 * TILE_SIZE] = numpy.tile(block, (y_dim // (2 * TILE_SIZE), x_dim // (2 * TILE_SIZE))) grid_visu = numpy.zeros((t_dim, c_dim + 1, y_dim, x_dim), numpy.uint8) grid_visu[:, :c_dim, :, :] = imgstack grid_visu[:, -1, :, :] = checker_board result = numpy.zeros((t_dim, c_dim, y_dim, x_dim), imgstack.dtype) def shift_func_forward(xy, of): return ( xy[0] - of[1, xy[0].astype(numpy.int32).clip(0, y_dim - 1), xy[1].astype(numpy.int32).clip(0, x_dim - 1)], xy[1] - of[0, xy[0].astype(numpy.int32).clip(0, y_dim - 1), xy[1].astype(numpy.int32).clip(0, x_dim - 1)], ) def shift_func_backward(xy, of): return ( xy[0] + of[1, xy[0].astype(numpy.int32).clip(0, y_dim - 1), xy[1].astype(numpy.int32).clip(0, x_dim - 1)], xy[1] + of[0, xy[0].astype(numpy.int32).clip(0, y_dim - 1), xy[1].astype(numpy.int32).clip(0, x_dim - 1)], ) result[0, :c_dim] = imgstack[0, :c_dim] xxyy = numpy.meshgrid(numpy.arange(x_dim), numpy.arange(y_dim))[::-1] xxyy2 = numpy.meshgrid(numpy.arange(x_dim), numpy.arange(y_dim))[::-1] for k in tqdm(range(1, t_dim), desc="{:40s}".format(' -- Un-drift movie')): xxyy = shift_func_backward(xxyy, of=optflow[k - 1, ...]) xxyy2 = shift_func_forward(xxyy2, of=optflow[k - 1, ...]) for c in range(c_dim): img = imgstack[k, c, :, :] result[k, c, :, :] = ndi.map_coordinates(img, xxyy) # coords_in_input = shift_func_forward((xx, yy), of=optflow[:k+1, ...].sum(0)) grid_visu[k, -1, :, :] = ndi.map_coordinates(grid_visu[0, -1, :, :], xxyy2) return result, grid_visu