def extractCandidates(jobFilename='', resultFilename='', orientFilename='', sizeParticle=None, maxNumParticle=0, minScore=-1, write2disk=0, margin=None,mask=None, structuredMask=None): # construct the original job from the xml file if jobFilename=='': jobFilename='JobInfo.xml' from pytom.localization.peak_job import PeakJob job = PeakJob() job.fromXMLFile(jobFilename) from pytom.localization.extraction_peak_result import ExPeakResult res = ExPeakResult() res.volFilename = job.volume.getFilename() from pytom.basic.files import read from pytom_numpy import vol2npy from copy import deepcopy if resultFilename=='': res.resultFilename='scores.em' else: res.resultFilename = resultFilename if orientFilename=='': res.orientFilename='angles.em' else: res.orientFilename = orientFilename if mask: resultfile, maskfile = read(res.resultFilename), read(mask) resultdata, maskdata = deepcopy(vol2npy(resultfile)), deepcopy(vol2npy(maskfile)) import mrcfile x,y,z,sx,sy,sz = job.volume.subregion masked_data = (resultdata*maskdata[x:x+sx,y:y+sy,z:z+sz]) #masked_data[masked_data < 0.00001] = resultdata.median() mrcfile.new(res.resultFilename.replace('.em', '_masked.em'),masked_data.T, overwrite=True) res.resultFilename = res.resultFilename.replace('.em', '_masked.em') res.angleList = job.rotations[:] res.score = job.score.__class__ if maxNumParticle <= 0: return None res.readAll() if sizeParticle==None: ref = job.reference.getVolume() sizeParticle = [ref.sizeX(),ref.sizeY(),ref.sizeZ()] print(job.volume.subregion[:3]) particleList = res.findParticles(sizeParticle,maxNumParticle,minScore,write2disk,margin, offset=job.volume.subregion[:3], structured_mask=structuredMask) return particleList
def fourierReconstructGPU(vol_img, vol_bp, vol_phi, vol_the, recPosVol=[0, 0, 0], vol_offsetProjections=[0, 0, 0]): from pytom_numpy import vol2npy import cupy as cp from pytom.voltools import transform from cupy.fft import fftshift, ifftn, fftn import numpy from cupyx.scipy.ndimage import rotate interpolation = 'filt_bspline' projections = vol2npy(vol_img) projections = cp.array(projections) proj_angles = vol2npy(vol_the)[0, 0, :] dims = (projections.shape[0], projections.shape[0], projections.shape[0]) tot = cp.zeros(dims, cp.complex64) for n in range(projections.shape[2]): org = cp.zeros(dims, dtype=cp.complex64) rot = cp.zeros(dims, dtype=cp.complex64) ff = fftshift(fftn(fftshift(projections[:, :, n]))) org[:, :, dims[0] // 2] = ff #print(n,ff.shape, org.shape) if 0: rot.real = rotate(org.real, proj_angles[n], axes=(2, 0), reshape=False) rot.imag = rotate(org.imag, proj_angles[n], axes=(2, 0), reshape=False) else: rot.real = transform(org.real, rotation=(0, proj_angles[n], 0), rotation_order='sxyz', interpolation=interpolation) rot.imag = transform(org.imag, rotation=(0, proj_angles[n], 0), rotation_order='sxyz', interpolation=interpolation) tot += rot del org, rot if dims[0] % 2: t = cp.zeros_like(tot) t[1:, 1:, 1:] = tot[:-1, :-1, :-1] else: t = tot return fftshift((ifftn(fftshift(t)).real)).get()
def project(v, rot, verbose=False): """ rotate and subsequently project volume along z @param v: volume @type v: L{pytom_volume.vol} @param rot: rotation - either Rotation object or single angle interpreted as rotation along y-axis @type rot: L{pytom.basic.structures.Rotation} or float @return: projection (2D image) @rtype: L{pytom_volume.vol} @author: FF """ from pytom_volume import vol from pytom_numpy import vol2npy, npy2vol from numpy import ndarray, float32 from pytom.basic.transformations import general_transform_crop from pytom.basic.structures import Rotation from numpy import sum as proj if not isinstance(v, vol): raise TypeError('project: v must be of type pytom_volume.vol! Got ' + str(v.__class__) + ' instead!') if isinstance(rot, float): rot = Rotation(z1=90., z2=270., x=rot, paradigm='ZXZ') if not isinstance(rot, Rotation): raise TypeError('project: rot must be of type Rotation or float! Got ' + str(v.__class__) + ' instead!') if verbose: print("project: Rotation for projection: "+str(rot)) rotvol = general_transform_crop(v=v, rot=rot, shift=None, scale=None, order=[0, 1, 2]) # slightly awkward: projection in numpy ... npvol = vol2npy(rotvol) npprojection = ndarray([v.sizeX(), v.sizeY(), 1], dtype=float32, buffer=None, offset=0, strides=npvol.strides, order='F') proj(npvol, axis=2, dtype=float32, out=npprojection) projection = npy2vol(npprojection,3) return projection
def pcacov(matrix): """ pcacov: Will determine eigenVector, eigenValue, eigenValueNormed for a matrix consistent to the matlab pcacov function. @param matrix: The matrix @return: [eigenVector, eigenValue, eigenVectorNormed] - eigenvectors are [nth vector, value] @author: Thomas Hrabe """ from numpy import sum,max,diag from scipy.linalg import svd from pytom_volume import vol if matrix.__class__ == vol: from pytom_numpy import vol2npy matrix = vol2npy(matrix) [x,latent,coeff] = svd(matrix) totalvar = sum(diag(latent)) explained = 100*latent / totalvar [sizeX,sizeY] = coeff.shape abscoeff = abs(coeff) maxIndex = abscoeff.argmax(1) for x in range(sizeX): if coeff[x,maxIndex[x]] < 0: coeff[x,:] = coeff[x,:] * -1 return [coeff,latent,explained]
def write(filename, data, tilt_angle=0, pixel_size=1): """Write EM or MRC file. Now only support written in type float32 on little-endian machines. @param filename: file name. @param data: data which should be written to file. Can be ndarray or pytom volume @param tilt_angle: if data is a projection, this is the tilt angle of the projection. @param ndarray: is the data a ndarray or not (if not it is assumed to be a pytom volume). @param data: data to write. """ assert filename assert filename.split('.')[-1].lower() in ('em', 'mrc') if not type(data) == type(np.array((1))): from pytom_numpy import vol2npy try: data = vol2npy(data).copy() except: raise Exception( 'Invalid data type of data. Please provide an ndarray or a pytom volume object.' ) if data.dtype != np.dtype("float32"): data = data.astype(np.float32) if filename.endswith('.em'): write_em(filename, data, tilt_angle) elif filename.endswith('.mrc'): write_mrc(filename, data, tilt_angle, pixel_size=pixel_size) else: raise Exception( 'Unsupported file format, cannot write an {}-file'.format( filename.split('.')[-1]))
def gaussian_filter(vol, sigma): """ @param vol: input volume @type vol: L{pytom_volume.vol} @param sigma: xxx @type sigma: xxx @return: resulting volume @rtype: L{pytom_volume.vol} """ # # construct the Gaussian kernel # import numpy as np # from scipy import mgrid, exp # sizex = vol.sizeX() # sizey = vol.sizeY() # sizez = vol.sizeZ() # # [x, y, z] = mgrid[-(sizex/2):(sizex+1)/2, -(sizey/2):(sizey+1)/2, -(sizez/2):(sizez+1)/2] # g = exp(-(x**2+y**2+z**2)/(2*float(sigma)**2)) # g /= g.sum() # # # transfer to vol obj and do the filtering # from pytom_numpy import npy2vol # kernel = npy2vol(np.array(g, dtype='float32', order='F'), 3) # # from pytom.basic.fourier import convolute # res = convolute(vol, kernel, False) import numpy as np from pytom_numpy import vol2npy, npy2vol from scipy.ndimage.filters import gaussian_filter v = vol2npy(vol) r = gaussian_filter(v, sigma) res = npy2vol(np.array(r, dtype='float32', order='F'), 3) return res
def em2markerfile(filename, tiltangles): vol = read(filename) mf = copy.deepcopy(vol2npy(vol)) (d, angles, num) = mf.shape # print mf.shape locX, locY = 1, 2 mark_frames = -1 * numpy.ones((len(tiltangles), num, 2)) # print mf[0,:,1:3].shape,self.coordinates[:,0,:].shape markers = [] for i in range(num): for j in range(angles): m = -1 for n, angle in enumerate(tiltangles): if abs(mf[0, j, i] - angle) < 1: m = n break if m == -1: continue mark_frames[m, i, 0] = mf[locX, j, i] mark_frames[m, i, 1] = mf[locY, j, i] return mark_frames
def fourier_interpolate_3d_vol(v, nodes): """Given a real 3D volume data in PyTom format, interpolate at specified locations in Fourier space. @param v: 3D volume data in PyTom format. @dtype v: Pytom_volume.vol @param nodes: a list of locations in Fourier space. Each node must be in the range [-0.5, 0.5). @dtype nodes: List. [[-0.5, -0.5, 0.3], ...] @return: interpolated complex values in a list. @rtype: List. """ from pytom_numpy import vol2npy # convert to numpy format v = vol2npy(v) dim_x, dim_y, dim_z = v.shape # shift it v = np.fft.fftshift(v) # linearize it v = v.reshape((v.size)) # linearize it nodes = np.array(nodes, dtype="double") nodes = nodes.reshape((nodes.size)) # call the function res = fourier_interpolate_3d(v, dim_x, dim_y, dim_z, nodes, nodes.size / 3) # convert to complex format res = res[::2] + 1j * res[1::2] return res
def extractPeaksGPU(volume, reference, rotations, scoreFnc=None, mask=None, maskIsSphere=False, wedgeInfo=None, padding=True, **kwargs): from pytom_numpy import vol2npy from pytom.gpu.gpuStructures import TemplateMatchingGPU from pytom.tools.calcFactors import calc_fast_gpu_dimensions import time import numpy as np from pytom_freqweight import weight angles = rotations[:] volume, ref, mask = [vol2npy(vol) for vol in (volume, reference, mask)] wedgeAngle = 30 wedgeFilter = weight(wedgeAngle, wedgeAngle, ref.shape[0] // 2, ref.shape[0], ref.shape[1], ref.shape[2], 0) wedgeVolume = wedgeFilter.getWeightVolume(True) wedge = vol2npy(wedgeVolume).copy() if padding: dimx, dimy, dimz = volume.shape cx = calc_fast_gpu_dimensions(dimx - 2, 4000)[0] cy = calc_fast_gpu_dimensions(dimy - 2, 4000)[0] cz = calc_fast_gpu_dimensions(dimz - 2, 4000)[0] voluNDAs = np.zeros([cx, cy, cz], dtype=np.float32) voluNDAs[:min(cx, dimx), :min(cy, dimy), :min(cz, dimz)] = volume[:min(cx, dimx), :min(cy, dimy), :min(cz, dimz)] volume = voluNDAs print(f'dimensions of volume: {ref.shape}') input = (volume, ref, mask, wedge, angles, volume.shape) tm_process = TemplateMatchingGPU(0, kwargs['gpuID'][0], input=input) tm_process.start() while tm_process.is_alive(): time.sleep(1) if tm_process.completed: print('Templated matching completed successfully') return [tm_process.plan.scores.get(), tm_process.plan.angles.get(), None, None] else: raise Exception('failed template matching')
def numpy_T(self, v=None): import pytom_numpy if not v: from pytom_volume import vol, gaussianNoise v = vol(10, 10, 10) gaussianNoise(v, 0, 1) nv = pytom_numpy.vol2npy(v) #print 'hier' #print nv.shape,nv.strides,nv.dtype #print v.strideX(),v.strideY(),v.strideZ() vv = pytom_numpy.npy2vol(nv, 3) self.assertTrue(v.equalsTo(vv), msg='numpy issue :(')
def readMarkerfile(filename, num_tilt_images=0): if filename.endswith('.em'): from pytom.basic.files import read from pytom_numpy import vol2npy markerfile = read(filename) markerdata = vol2npy(markerfile).copy() return markerdata elif filename.endswith('.txt'): data = loadstar(filename) datalen = data.shape[0] num_tilt_images = (data[:, 0] == data[0, 0]).sum() x, y = datalen // num_tilt_images, num_tilt_images markerdata = data.reshape(x, y, 4)[:, :, 1:].transpose(2, 1, 0) return markerdata
def getSlice(self, n, projectionAxis='z'): assert n>= 0 from pytom_numpy import vol2npy nvol = vol2npy(self.vol) from pytom_volume import subvolume if projectionAxis == 'x': slice = nvol[n,:,:] elif projectionAxis == 'y': slice = nvol[:,n,:] elif projectionAxis == 'z': slice = nvol[:,:,n] else: raise Exception("Projection axis must be either 'x', 'y' or 'z'!") return slice
def recenterVolume(volume, densityNegative=False): from scipy.ndimage import center_of_mass from pytom.tompy.io import read, write from pytom.tompy.tools import paste_in_center from pytom.gpu.initialize import xp from pytom_numpy import vol2npy import os try: a = vol2npy(volume).copy() vol = True except: a = volume vol = False if densityNegative: a *= -1 x, y, z = list(map(int, center_of_mass(a))) cx, cy, cz = a.shape[0] // 2, a.shape[1] // 2, a.shape[2] // 2 sx = min(x, a.shape[0] - x) sy = min(y, a.shape[0] - y) sz = min(z, a.shape[0] - z) ac = a[x - sx:x + sx, y - sy:y + sy, z - sz:z + sz] b = xp.zeros_like(a) b = paste_in_center(ac, b) if densityNegative: b *= -1 if vol: write('recenteredDBV21.em', b) from pytom.basic.files import read vol = read('recenteredDBV21.em') os.system('rm recenteredDBV21.em') return vol else: return b
def fourier_rotate_vol(v, angle): """Be careful with rotating a odd-sized volume, since nfft will not give correct result! """ # get the rotation matrix from pytom.basic.structures import Rotation rot = Rotation(angle) m = rot.toMatrix() m = m.transpose() # get the invert rotation matrix m = np.array([m.getRow(0), m.getRow(1), m.getRow(2)], dtype="float32") m = m.flatten() # prepare the volume from pytom_numpy import vol2npy v = vol2npy(v) dim_x, dim_y, dim_z = v.shape # twice shift means no shift! # v = np.fft.fftshift(v) # linearize it v = v.reshape((v.size)) # allocate the memory for the result res = np.zeros(v.size * 2, dtype="float32") # call the low level c function swig_nufft.fourier_rotate_vol(v, dim_x, dim_y, dim_z, m, res) res = res[::2] + 1j * res[1::2] res = res.reshape((dim_x, dim_y, dim_z), order='F') # inverse fft ans = np.fft.ifftshift(np.real(np.fft.ifftn(np.fft.ifftshift(res)))) # transfer to pytom volume format from sh.frm import np2vol res = np2vol(ans) return res
def decomposeMatrix(matrixFile): """ decomposeMatrix: Will perform analysis on calculated matrix using scipy.linalg tools @param matrixFile: Correlation matrix in em format @type matrixFile: Either the matrix as volume or a string @return: [eigenValues,eigenVectors] of the matrix """ from scipy import linalg from numpy import matrix if matrixFile.__class__ == str: from pytom_volume import read corrMatrix = read(matrixFile) else: corrMatrix = matrixFile matStr = '' #copy all matrix values into string try: #try to use shortest path by converting from tom volume to numpy matrix from pytom_numpy import vol2npy mat = matrix(vol2npy(corrMatrix)) except ImportError: #numpy did not work. copy each entry into string and proceed, takes long time for x in range(corrMatrix.sizeX()): for y in range(corrMatrix.sizeY()): matStr = matStr + ' ' + str(corrMatrix.getV(x, y, 0)) if x < (corrMatrix.sizeX() - 1): matStr = matStr + ';' mat = matrix(matStr) #generate numpy.matrix from string return linalg.eigh(mat) #determine values
def extractPeaksGPU(volume, reference, rotations, scoreFnc=None, mask=None, maskIsSphere=False, wedgeInfo=None, padding=True, **kwargs): from pytom_numpy import vol2npy from pytom.tompy.filter import create_wedge, applyFourierFilter from pytom.tompy.io import write from pytom.gpu.gpuStructures import TemplateMatchingGPU from pytom.tools.calcFactors import calc_fast_gpu_dimensions import time import numpy as np from pytom_freqweight import weight angles = rotations[:] #volume = wedgeInfo.apply(volume) volume, ref, mask = [vol2npy(vol) for vol in (volume, reference, mask)] SX, SY, SZ = volume.shape sx, sy, sz = ref.shape angle = wedgeInfo.getWedgeAngle() if angle.__class__ != list: w1 = w2 = angle else: w1, w1 = angle if w1 > 1E-3 or w2 > 1E-3: print('Wedge applied to volume') cutoff = wedgeInfo._wedgeObject._cutoffRadius if wedgeInfo._wedgeObject._cutoffRadius > 1E-3 else sx // 2 smooth = wedgeInfo._wedgeObject._smooth wedge = create_wedge(w1, w2, cutoff, sx, sy, sz, smooth).astype(np.complex64) wedgeVolume = create_wedge(w1, w2, SX // 2 - 2, SX, SY, SZ, smooth).astype(np.float32) volume = np.real( np.fft.irfftn(np.fft.rfftn(volume) * wedgeVolume.get())) else: wedge = np.ones((sx, sy, sz // 2 + 1), dtype='float32') #wedgeVolume = np.ones_like(volume,dtype='float32') if padding: dimx, dimy, dimz = volume.shape cx = max(ref.shape[0], calc_fast_gpu_dimensions(dimx - 2, 4000)[0]) cy = max(ref.shape[1], calc_fast_gpu_dimensions(dimy - 2, 4000)[0]) cz = max(ref.shape[2], calc_fast_gpu_dimensions(dimz - 2, 4000)[0]) voluNDAs = np.zeros([cx, cy, cz], dtype=np.float32) voluNDAs[:min(cx, dimx), :min(cy, dimy), :min(cz, dimz)] = volume[:min( cx, dimx), :min(cy, dimy), :min(cz, dimz)] volume = voluNDAs print(f'dimensions of volume: {ref.shape} {mask.shape} ') input = (volume, ref, mask, wedge, angles, volume.shape) tm_process = TemplateMatchingGPU(0, kwargs['gpuID'][0], input=input) tm_process.start() while tm_process.is_alive(): time.sleep(1) if tm_process.completed: print('Templated matching completed successfully') return [ tm_process.plan.scores.get(), tm_process.plan.angles.get(), None, None ] else: raise Exception('failed template matching')
def createMetaDataFiles(nanographfolder, mdocfiles=[], target='', mdoc_only=False): if not mdocfiles: mdocfiles = [ mdocfile for mdocfile in os.listdir(nanographfolder) if mdocfile.endswith('.mdoc') ] datafiles = [ fname for fname in os.listdir(nanographfolder) if fname.split('.')[-1] in ('tif', 'mrc', 'em', 'st') and not (fname[0] in '0123456789') ] annotated = {} tomo_from_filename = {} tomo_from_stack = {} for df in datafiles: annotated[os.path.basename(df)] = 0 if os.path.basename(df).endswith('.st'): annotated[os.path.basename(df)] = 'st' tiltAxis = 180 pixelSpacing = 1.5 voltage = 300 for nr, mdocfile in enumerate(sorted(mdocfiles)): metadata = [] mdocfilepath = os.path.join(nanographfolder, mdocfile) header = False datadict = { 'TiltAngle': tiltAxis, 'Magnification': 79000, 'Intensity': 0.0, 'PixelSpacing': pixelSpacing, 'Defocus': 3, 'RotationAngle': 270, 'SubFramePath': '', 'Voltage': voltage, 'MarkerDiameter': 100, 'SphericalAberration': 2.7, 'AmplitudeContrast': 0.08, 'PhaseContrast': 0., } for description, dtype in datatype: if not description in datadict.keys(): datadict[description] = 0. mdocdata = [ line.split() for line in open(mdocfilepath).readlines() if len(line.split()) >= 3 ] nrTiltImages = 0 for nn, line in enumerate(mdocdata): if '[ZValue' == line[0] and not header: header = True continue if not header: if line[0] == 'PixelSpacing': datadict[line[0]] = float(line[2]) elif line[0] == 'Voltage': datadict[line[0]] = int(line[2]) elif line[0] == 'ImageSize': try: datadict[line[0]] = min(int(line[2]), int(line[3])) except: pass elif 'axis' in line: datadict['InPlaneRotation'] = float( line[6].strip(',')) - 250 continue if line[0] in datadict.keys(): if line[0] == 'RotationAngle': line[0] = 'RotationTheta' try: datadict[line[0]] = float(line[2]) except: fname = os.path.basename(line[2].replace('\\', '/')) datadict['FileName'] = fname if fname in annotated.keys(): annotated[fname] += 1 if '[ZValue' == line[0] or nn + 1 == len(mdocdata): data = [ 0., ] * len(datatype) for n, (description, dtype) in enumerate(datatype): if description in datadict.keys(): data[n] = datadict[description] if 'Defocus' in datadict.keys(): data[0] = datadict['Defocus'] data[1] = datadict['Defocus'] if 'AcquisitionOrder' == datatype[-2][0]: data[-2] = nrTiltImages nrTiltImages += 1 metadata.append(tuple(data)) if len(metadata) == 0: continue a = numpy.rec.array(metadata, dtype=datatype) a = numpy.sort(a, order='TiltAngle') outname = mdocfilepath.replace('mdoc', 'meta') if target: outname = os.path.join(target, mdocfile.replace('mdoc', 'meta')) savestar(outname, a, fmt=fmt, header=headerText) if mdoc_only: return acquisition_order = {} size = {} for k, v in annotated.items(): if v == 0: tomoname = k.split('_')[0] if not tomoname in tomo_from_filename.keys(): tomo_from_filename[tomoname] = [] if k.split('.')[-1] in ('mrc', 'em'): vol = read(os.path.join(nanographfolder, k)) data = copy.deepcopy(vol2npy(vol)) size[tomoname] = numpy.min(data.shape) else: #try: # data = imread( os.path.join(nanographfolder,k) ) # size[tomoname] = numpy.min(data.shape) #except: aa = os.popen( 'header {} | grep "Number of columns, rows, sections" ' .format(os.path.join(nanographfolder, k))).read()[:-1] dd = list(map(int, aa.split()[-3:-1])) size[tomoname] = numpy.min(dd) #Find tiltangle if k.endswith('em'): fileHeader = read_em_header(os.path.join(nanographfolder, k)) tiltangle = fileHeader.get_tiltangle() elif k.endswith('mrc'): tiltangle = read_angle(os.path.join(nanographfolder, k)) else: tiltangle = 0. tomo_from_filename[tomoname].append([ k.replace('[', '_').replace(']', '_').split('_'), tiltangle, k ]) if v == 'st': from pytom.tompy.io import read as readNPY, read_size, read_pixelsize from numpy import loadtxt stackfile = os.path.join(nanographfolder, k) tltfile = stackfile.replace('.st', '.tlt') x, y, z = read_size(os.path.join(nanographfolder, k)) pixelsize = read_pixelsize(stackfile, 'x') print(f'\n\n\n{tltfile}') if not os.path.exists(tltfile): print(f'failed for {tltfile}') continue tiltangles = loadtxt(tltfile) tomoname = k[:-3] metadata = numpy.zeros((len(tiltangles)), dtype=datatype) for i, tiltangle in enumerate(tiltangles): metadata['TiltAngle'][i] = tiltangle metadata['FileName'][ i] = f'{nanographfolder}/IMODSTACK_{tomoname}_{i:02d}.mrc' metadata['ImageSize'][i] = min(x, y) metadata['PixelSpacing'][i] = pixelsize metadata['DefocusU'][i] = 3 metadata['DefocusV'][i] = 3 metadata['Voltage'][i] = 200 metadata['SphericalAberration'][i] = 2.7 metadata['AmplitudeContrast'][i] = 0.8 metadata['MarkerDiameter'][i] = 100 a = numpy.sort(metadata, order='TiltAngle') outname = '{}/{}.meta'.format(nanographfolder, tomoname) print(outname) savestar(outname, a, fmt=fmt, header=headerText) for NR, (k, v) in enumerate(tomo_from_filename.items()): neg = numpy.array([ 0, ] * len(v[0][0]), dtype=int) tiltangles_header = [] for list2, angle, fname in v: tiltangles_header.append(angle) for n, part in enumerate(list2): if '-' in part: neg[n] += 1 loc = numpy.argmax(neg[neg < len(v)]) if not neg[loc] > 0: loc = -1 tiltangles_header = numpy.array(tiltangles_header) metadata = [ [ 0., ] * len(datatype), ] * len(v) for NR, (d, t) in enumerate(datatype): if d == 'TiltAngle': break if len(v) < 10: return if loc > -0.5: for i in range(len(v)): metadata[i][NR] = float(v[i][0][loc]) metadata[i][-1] = v[i][2] if datatype[-3][0] == 'ImageSize': metadata[i][-3] = size[k] metadata[i] = tuple(metadata[i]) elif len(numpy.unique(numpy.round(tiltangles_header).astype( int))) == len(tiltangles_header): for i in range(len(v)): metadata[i][NR] = float(tiltangles_header[i]) metadata[i][-1] = v[i][2] if datatype[-3][0] == 'ImageSize': metadata[i][-3] = size[k] metadata[i] = tuple(metadata[i]) else: continue a = numpy.rec.array(metadata, dtype=datatype) a = numpy.sort(a, order='TiltAngle') outname = '{}/{}.meta'.format(nanographfolder, v[0][0][0]) savestar(outname, a, fmt=fmt, header=headerText)
def bart_align_vol(vf, wf, vg, wg, b, radius=None, peak_offset=None): """Implementation of Bartesaghi's approach for alignment. For detail, please check the paper. Parameters ---------- vf: The volume you want to match. pytom_volume.vol wf: The single tilt wedge information of volume vf. [missing_wedge_angle1, missing_wedge_angle2]. Note this is defined different with frm_align im frm.py! vg: The reference volume. pytom_volume.vol wg: The single tilt wedge information of volume vg. [missing_wedge_angle1, missing_wedge_angle2]. Note this is defined different with frm_align im frm.py! b: The bandwidth of spherical harmonics. Integer in the range [4, 64] radius: The maximal radius in the Fourier space, which is equal to say the maximal frequency involved in calculation. Integer. By default is half of the volume size. peak_offset: The maximal offset which allows the peak of the score to be. Or simply speaking, the maximal distance allowed to shift vg to match vf. This parameter is needed to prevent shifting the reference volume out of the frame. Integer. By default is half of the volume size. Returns ------- The best translation and rotation (Euler angle, ZXZ convention [Phi, Psi, Theta]) to transform vg to match vf. (best_translation, best_rotation, correlation_score) """ from pytom_volume import vol, rotateSpline, max, peak from pytom.basic.correlation import nXcf from pytom.basic.filter import lowpassFilter from pytom.basic.structures import WedgeInfo from pytom_volume import initSphere if not radius: # set the radius radius = vf.sizeX()/2 if peak_offset is None: peak_offset = vol(vf.sizeX(), vf.sizeY(), vf.sizeZ()) initSphere(peak_offset, vf.sizeX()/2, 0,0, vf.sizeX()/2,vf.sizeY()/2,vf.sizeZ()/2) elif isinstance(peak_offset, int): peak_radius = peak_offset peak_offset = vol(vf.sizeX(), vf.sizeY(), vf.sizeZ()) initSphere(peak_offset, peak_radius, 0,0, vf.sizeX()/2,vf.sizeY()/2,vf.sizeZ()/2) elif peak_offset.__class__ == vol: pass else: raise RuntimeError('Peak offset is given wrong!') from pytom.basic.fourier import fft, ifft, ftshift, iftshift from pytom_volume import vol, reducedToFull, rescale, abs, real from .vol2sf import vol2sf from pytom_numpy import vol2npy from math import log, ceil, pow # IMPORTANT!!! Should firstly do the IFFTSHIFT on the volume data (NOT FFTSHIFT since for odd-sized data it matters!), # and then followed by the FFT. ff = abs(ftshift(reducedToFull(fft(iftshift(vf, inplace=False))), inplace=False)) ff = real(ff) gg = abs(ftshift(reducedToFull(fft(iftshift(vg, inplace=False))), inplace=False)) gg = real(gg) sf = None sg = None mf = create_wedge_sf(wf[0], wf[1], b) mg = create_wedge_sf(wg[0], wg[1], b) for r in range(3, radius+1): # Should start from 3 since the interpolation in the first 2 bands is not accurate. if sf is None: sf = vol2sf(ff, r, b) sg = vol2sf(gg, r, b) else: sf += vol2sf(ff, r, b) sg += vol2sf(gg, r, b) corr = frm_constrained_corr(sf, mf, sg, mg) ang, val = frm_find_best_angle_interp(corr) tmp = vol(vg.sizeX(),vg.sizeY(),vg.sizeZ()) rotateSpline(vg, tmp, ang[0], ang[1], ang[2]) wedge_f = WedgeInfo(90+wf[0], 90-wf[1]) wedge_g = WedgeInfo(90+wg[0], 90-wg[1]) cc = nXcf(lowpassFilter(wedge_g.apply(vf), radius, 0)[0], lowpassFilter(wedge_f.apply(tmp), radius, 0)[0]) pos = peak(cc, peak_offset) pos, score = find_subpixel_peak_position(vol2npy(cc), pos) return (pos, ang, score)
def xu_align_vol(vf, wf, vg, wg, b, radius=None, mask=None, peak_offset=None): """Implementation of Xu's approach for alignment. For detail, please check the paper. Parameters ---------- vf: The volume you want to match. pytom_volume.vol wf: The single tilt wedge information of volume vf. [missing_wedge_angle1, missing_wedge_angle2]. Note this is defined different with frm_align im frm.py! vg: The reference volume. pytom_volume.vol wg: The single tilt wedge information of volume vg. [missing_wedge_angle1, missing_wedge_angle2]. Note this is defined different with frm_align im frm.py! b: The adaptive bandwidth of spherical harmonics. List [min_bandwidth, max_bandwidth], min_bandwidth, max_bandwidth in the range [4, 64]. Or integer, which would then mean to use fixed bandwidth: min_bandwidth = max_bandwidth = integer. radius: The maximal radius in the Fourier space, which is equal to say the maximal frequency involved in calculation. Integer. By default is half of the volume size. peak_offset: The maximal offset which allows the peak of the score to be. Or simply speaking, the maximal distance allowed to shift vg to match vf. This parameter is needed to prevent shifting the reference volume out of the frame. Integer. By default is half of the volume size. Returns ------- The best translation and rotation (Euler angle, ZXZ convention [Phi, Psi, Theta]) to transform vg to match vf. (best_translation, best_rotation, correlation_score) """ from pytom_volume import vol, rotateSpline, peak from pytom.basic.transformations import shift from pytom.basic.correlation import nXcf from pytom.basic.filter import lowpassFilter from pytom.basic.structures import Mask from pytom_volume import initSphere from pytom_numpy import vol2npy if vf.sizeX()!=vg.sizeX() or vf.sizeY()!=vg.sizeY() or vf.sizeZ()!=vg.sizeZ(): raise RuntimeError('Two volumes must have the same size!') if mask is None: mask = vol(vf.sizeX(), vf.sizeY(), vf.sizeZ()) initSphere(mask, vf.sizeX()/2, 0,0, vf.sizeX()/2,vf.sizeY()/2,vf.sizeZ()/2) elif mask.__class__ == vol: pass elif mask.__class__ == Mask: mask = mask.getVolume() elif isinstance(mask, int): mask_radius = mask mask = vol(vf.sizeX(), vf.sizeY(), vf.sizeZ()) initSphere(mask, mask_radius, 0,0, vf.sizeX()/2,vf.sizeY()/2,vf.sizeZ()/2) else: raise RuntimeError('Given mask has wrong type!') if peak_offset is None: peak_offset = vol(vf.sizeX(), vf.sizeY(), vf.sizeZ()) initSphere(peak_offset, vf.sizeX()/2, 0,0, vf.sizeX()/2,vf.sizeY()/2,vf.sizeZ()/2) elif isinstance(peak_offset, int): peak_radius = peak_offset peak_offset = vol(vf.sizeX(), vf.sizeY(), vf.sizeZ()) initSphere(peak_offset, peak_radius, 0,0, vf.sizeX()/2,vf.sizeY()/2,vf.sizeZ()/2) elif peak_offset.__class__ == vol: pass else: raise RuntimeError('Peak offset is given wrong!') # cut out the outer part which normally contains nonsense vf = vf*mask position = None if position is None: # if position is not given, we have to find it ourself # first roughtly determine the orientation (only according to the energy info) # get multiple candidate orientations orientations = frm_determine_orientation(vf, wf, vg, wg, b, radius, None, None, False) else: # the position is given by the user vf2 = shift(vf, -position[0]+vf.sizeX()/2, -position[1]+vf.sizeY()/2, -position[2]+vf.sizeZ()/2, 'spline') res = frm_fourier_adaptive_wedge_vol(vf2, wf, vg, wg, b, radius, None, None, False) orientation, max_value = frm_find_best_angle_interp(res) return position, orientation, max_value from pytom.basic.structures import WedgeInfo from pytom.tools.maths import euclidianDistance max_iter = 1 # maximal number of iterations wedge = WedgeInfo([90+wf[0], 90-wf[1]]) old_pos = [-1, -1, -1] vg2 = vol(vg.sizeX(), vg.sizeY(), vg.sizeZ()) lowpass_vf = lowpassFilter(vf, radius, 0)[0] peak_value = 0.0 position = None ang = None for orientation in orientations: orientation = orientation[0] rotateSpline(vg, vg2, orientation[0], orientation[1], orientation[2]) # first rotate vg2 = wedge.apply(vg2) # then apply the wedge vg2 = lowpassFilter(vg2, radius, 0)[0] res = nXcf(lowpass_vf, vg2) # find the position pos = peak(res, peak_offset) # val = res(pos[0], pos[1], pos[2]) pos, val = find_subpixel_peak_position(vol2npy(res), pos) if val > peak_value: position = pos ang = orientation peak_value = val return position, ang, peak_value
InterFunc = 1. + (IijFunc_sum) wf = 1. / InterFunc for ix in range(0, sX): for iy in range(0, sizeY): weightFunc.setV(wf[ix], ix, iy, 0) return weightFunc #import matplotlib #matplotlib.use('Qt5Agg') sX, sY = 1000, 1000 tilt_angles = range(-60, 60, 2) tiltAngle = 0 sliceWidth = 1000 from pytom_numpy import vol2npy from copy import deepcopy d = exactFilter(tilt_angles, tiltAngle, sX, sY, sliceWidth) data = deepcopy(vol2npy(d)) print(data.shape, data.sum()) from pylab import * plot(data) show()
num_angles, size = map(int, sys.argv[1:3]) size2 = int(sys.argv[3]) csize = int(sys.argv[4]) try: start, end = map(int, sys.argv[5:7]) except: start, end = 0, csize wedgeAngle = 30 wedgeFilter = weight(wedgeAngle, 0, end - start, size, size) wedgeVolume = wedgeFilter.getWeightVolume(True) filterVolume = pytom_volume.reducedToFull(wedgeVolume) wedgeV = vol2npy(filterVolume).copy() from pytom.tompy.io import read import mrcfile # NDARRAYS voluNDA = mrcfile.open('tomo.mrc', permissive=True).data.copy() tempNDA = read('template.em') maskNDA = read("mask.em") sox, soy, soz = tempNDA.shape spx, spy, spz = voluNDA.shape #GPUARRAYS voluGPU = gu.to_gpu(voluNDA.astype(np.float32)) tempGPU = gu.to_gpu(tempNDA.astype(np.float32))
def frm_constrained_align(vf, wf, vg, wg, b, max_freq, peak_offset=None, mask=None, constraint=None, weights=None, position=None, num_seeds=5, pytom_volume=None): """Find the best alignment (translation & rotation) of volume vg (reference) to match vf. For details, please check the paper. Parameters ---------- vf: Volume Nr. 1 pytom_volume.vol wf: Mask of vf in Fourier space. pytom.basic.structures.Wedge. If none, no missing wedge. vg: Volume Nr. 2 / Reference pytom_volume.vol wg: Mask of vg in Fourier space. pytom.basic.structures.Wedge. If none, no missing wedge. b: Bandwidth range of spherical harmonics. None -> [4, 64] List -> [b_min, b_max] Integer -> [b, b] max_freq: Maximal frequency involved in calculation. Integer. peak_offset: The maximal offset which allows the peak of the score to be. Or simply speaking, the maximal distance allowed to shift vg to match vf. This parameter is needed to prevent shifting the reference volume out of the frame. pytom_volume.vol / Integer. By default is half of the volume radius. mask: Mask volume for vg in real space. pytom_volume.vol constraint: Angular constraint sh_alignment.constrained_frm.AngularConstraint weights: Obsolete. position: If the translation is already known or not. If provided, no translational search will be conducted. List: [x,y,z], default None. num_seeds: Number of threads for the expectation maximization procedure. The more the better, yet slower. Integer, default is 5. Returns ------- (The best translation and rotation (Euler angle, ZXZ convention [Phi, Psi, Theta]) to transform vg to match vf. (best_translation, best_rotation, correlation_score) """ from pytom_volume import vol, rotateSpline, peak from pytom.basic.transformations import shift from pytom.basic.correlation import FLCF from pytom.basic.filter import lowpassFilter from pytom.basic.structures import Mask, SingleTiltWedge from pytom_volume import initSphere from pytom_numpy import vol2npy if vf.sizeX() != vg.sizeX() or vf.sizeY() != vg.sizeY() or vf.sizeZ( ) != vg.sizeZ(): raise RuntimeError('Two volumes must have the same size!') if wf is None: wf = SingleTiltWedge(0) if wg is None: wg = SingleTiltWedge(0) if peak_offset is None: peak_offset = vol(vf.sizeX(), vf.sizeY(), vf.sizeZ()) initSphere(peak_offset, vf.sizeX() / 4, 0, 0, vf.sizeX() / 2, vf.sizeY() / 2, vf.sizeZ() / 2) elif peak_offset.__class__ == int: peak_radius = peak_offset peak_offset = vol(vf.sizeX(), vf.sizeY(), vf.sizeZ()) initSphere(peak_offset, peak_radius, 0, 0, vf.sizeX() / 2, vf.sizeY() / 2, vf.sizeZ() / 2) elif peak_offset.__class__ == vol: pass else: raise RuntimeError('Peak offset is given wrong!') # cut out the outer part which normally contains nonsense m = vol(vf.sizeX(), vf.sizeY(), vf.sizeZ()) initSphere(m, vf.sizeX() / 2, 0, 0, vf.sizeX() / 2, vf.sizeY() / 2, vf.sizeZ() / 2) vf = vf * m vg = vg * m if mask is None: mask = m else: vg = vg * mask if position is None: # if position is not given, we have to find it ourself # first roughtly determine the orientation (only according to the energy info) # get multiple candidate orientations numerator, denominator1, denominator2 = frm_correlate( vf, wf, vg, wg, b, max_freq, weights, True, None, None, False) score = numerator / (denominator1 * denominator2)**0.5 res = frm_find_topn_constrained_angles_interp( score, num_seeds, get_adaptive_bw(max_freq, b) / 16., constraint) else: # the position is given by the user vf2 = shift(vf, -position[0] + vf.sizeX() / 2, -position[1] + vf.sizeY() / 2, -position[2] + vf.sizeZ() / 2, 'fourier') score = frm_correlate(vf2, wf, vg, wg, b, max_freq, weights, ps=False) orientation, max_value = frm_find_best_constrained_angle_interp( score, constraint=constraint) return position, orientation, max_value # iteratively refine the position & orientation from pytom.tools.maths import euclidianDistance max_iter = 10 # maximal number of iterations mask2 = vol(mask.sizeX(), mask.sizeY(), mask.sizeZ()) # store the rotated mask vg2 = vol(vg.sizeX(), vg.sizeY(), vg.sizeZ()) lowpass_vf = lowpassFilter(vf, max_freq, max_freq / 10.)[0] max_position = None max_orientation = None max_value = -1.0 for i in xrange(num_seeds): old_pos = [-1, -1, -1] lm_pos = [-1, -1, -1] lm_ang = None lm_value = -1.0 orientation = res[i][0] # initial orientation for j in xrange(max_iter): rotateSpline(vg, vg2, orientation[0], orientation[1], orientation[2]) # first rotate rotateSpline(mask, mask2, orientation[0], orientation[1], orientation[2]) # rotate the mask as well vg2 = wf.apply(vg2) # then apply the wedge vg2 = lowpassFilter(vg2, max_freq, max_freq / 10.)[0] score = FLCF(lowpass_vf, vg2, mask2) # find the position pos = peak(score, peak_offset) pos, val = find_subpixel_peak_position(vol2npy(score), pos) if val > lm_value: lm_pos = pos lm_ang = orientation lm_value = val if euclidianDistance(lm_pos, old_pos) <= 1.0: # terminate this thread if lm_value > max_value: max_position = lm_pos max_orientation = lm_ang max_value = lm_value break else: old_pos = lm_pos # here we shift the target, not the reference # if you dont want the shift to change the energy landscape, use fourier shift vf2 = shift(vf, -lm_pos[0] + vf.sizeX() / 2, -lm_pos[1] + vf.sizeY() / 2, -lm_pos[2] + vf.sizeZ() / 2, 'fourier') score = frm_correlate(vf2, wf, vg, wg, b, max_freq, weights, False, denominator1, denominator2, True) orientation, val = frm_find_best_constrained_angle_interp( score, constraint=constraint) else: # no converge after the specified iteration, still get the best result as we can if lm_value > max_value: max_position = lm_pos max_orientation = lm_ang max_value = lm_value # print max_value # for show the convergence of the algorithm return max_position, max_orientation, max_value
def backProjectGPU2(vol_img, vol_bp, vol_phi, vol_the, recPosVol=[0,0,0], vol_offsetProjections=[0,0,0]): from pytom_numpy import vol2npy import cupy as cp from cupy import cos, sin import voltools projections = vol2npy(vol_img) proj_angles = vol2npy(vol_the)[0,0,:] dims = (vol_bp.sizeX(), vol_bp.sizeY(), vol_bp.sizeZ()) # TODO add offsets # preparation reconstruction = cp.zeros(dims, dtype=cp.float32) theta_angles = cp.deg2rad(cp.array(proj_angles)) # theta_angles_rad = (theta_angles) assert len(theta_angles) == projections.shape[2] #'Number of angles and projections should match' # create coordinates and stack them x, y, z = cp.meshgrid(cp.arange(0, dims[0]), cp.arange(0, dims[1]), cp.arange(0, dims[2]), indexing='ij') # backproject each projection into reconstruction for n in range(projections.shape[2]): # get projection src = cp.array(projections[:,:,n]) # previous Z1 = Z2 = 0.0 Y = theta_angles[n] x_offset = y_offset = z_offset = 0 x_proj_offset = y_proj_offset = 0 tr11 = cos(Y)*cos(Z1)*cos(Z2)-sin(Z1)*sin(Z2) # tr21 = cos(Y)*sin(Z1)*cos(Z2)+cos(Z1)*sin(Z2) tr31 = -sin(Y)*cos(Z2) # tr12 = -cos(Y)*cos(Z1)*sin(Z2)-sin(Z1)*cos(Z2) tr22 = -cos(Y)*sin(Z1)*sin(Z2)+cos(Z1)*cos(Z2) # tr32 = sin(Y)*sin(Z2) reconstruction_center_x = dims[0] // 2 - x_offset reconstruction_center_y = dims[1] // 2 - y_offset reconstruction_center_z = dims[2] // 2 - z_offset projection_center_x = dims[0] // 2 + x_proj_offset projection_center_y = dims[1] // 2 + y_proj_offset # interpolation_position_x = tr11 * (x - reconstruction_center_x) + tr21 * (y - reconstruction_center_y) + tr31 * (z - reconstruction_center_z) + projection_center_x # interpolation_position_y = tr12 * (x - reconstruction_center_x) + tr22 * (y - reconstruction_center_y) + tr32 * (z - reconstruction_center_z) + projection_center_y interpolation_position_x = tr11 * (x - reconstruction_center_x) + tr31 * (z - reconstruction_center_z) + projection_center_x interpolation_position_y = tr22 * (y - reconstruction_center_y) + projection_center_y proj_position_x = interpolation_position_x.astype(int) proj_position_y = interpolation_position_y.astype(int) interpolation_offset_x = (interpolation_position_x - proj_position_x) interpolation_offset_y = (interpolation_position_y - proj_position_y) m0, m1, m2 = cp.where((proj_position_x >= 1) & (proj_position_x < dims[0]) & (proj_position_y >= 1) & (proj_position_y < dims[1])) value_x1 = src[proj_position_x[m0, m1, m2]-1, proj_position_y[m0, m1, m2]-1] + \ (src[proj_position_x[m0, m1, m2], proj_position_y[m0, m1, m2]-1] - src[proj_position_x[m0, m1, m2]-1, proj_position_y[m0, m1, m2]-1]) * interpolation_offset_x[m0, m1, m2] value_x2 = src[proj_position_x[m0, m1, m2]-1, proj_position_y[m0, m1, m2]] + \ (src[proj_position_x[m0, m1, m2], proj_position_y[m0, m1, m2]] - src[proj_position_x[m0, m1, m2]-1, proj_position_y[m0, m1, m2]]) * interpolation_offset_x[m0, m1, m2] value_y = value_x1 + (value_x2 - value_x1) * interpolation_offset_y[m0, m1, m2] reconstruction[m0, m1, m2] += value_y del value_y del value_x1 del value_x2 del m0, m1, m2 # import napari # with napari.gui_qt(): # viewer = napari.Viewer() # viewer.add_image(reconstruction.get(), name='recon', interpolation='bilinear') # viewer.add_image(np.log10(np.abs(np.fft.fftshift(np.fft.fftn(reconstruction.get())))), name='fft', interpolation='bilinear') rec = reconstruction.get() return rec for i in range(dims[0]): for j in range(dims[1]): for k in range(dims[2]): vol_bp.setV(float(rec[i][j][k]), int(i), int(j), int(k)) return vol_bp
def vol2sf(vol, r, b, center=None): """Transfer a volume into a serial of spherical functions. The volume will be decomposed into a serials of concentric shells. It will sample the volume on equiangular 2B*2B grid. (Trilinear interpolation) For more detail, see "http://www.cs.dartmouth.edu/~geelong/sphere/". Parameters ---------- vol: Target volume pytom_volume.vol r: The radius of shell you want to get from the volume (in voxel) Integer b: Bandwidth, which determines the sampling on the sphere Integer center: The center of the circle (By default is the center of the volume) list [x, y, z] Returns ------- f(the_0, phi_0) ... f(the_0, phi_2B-1), f(the_2B-1, phi_0) ... f(the_2B-1, phi_2B-1) List """ if r >= vol.sizeX() / 2 or r >= vol.sizeY() / 2 or r >= vol.sizeZ() / 2: raise RuntimeError("Given radius is larger than the volume!") elif r <= 0: raise RuntimeError("Radius should be larger than the 0!") from pytom_volume import volTOsf from pytom_numpy import vol2npy if center: m_x, m_y, m_z = center else: # the middle point of the volume m_x = int(vol.sizeX() / 2) m_y = int(vol.sizeY() / 2) m_z = int(vol.sizeZ() / 2) res = volTOsf(vol, r, b, m_x, m_y, m_z) # transfer the data format from volume to numpy array tmp = vol2npy( res) # somehow have to split the steps like this, otherwise wont work import numpy as np res = np.array( tmp) # copy the memory, otherwise the memory is shared with volume # from math import pi, sin, cos # res = [] # result list # # from pytom_volume import interpolateSpline # # if center: # m_x, m_y, m_z = center # else: # # the middle point of the volume # m_x = int(vol.sizeX()/2); m_y = int(vol.sizeY()/2); m_z = int(vol.sizeZ()/2) # # for j in xrange(2*b): # for k in xrange(2*b): # the = pi*(2*j+1)/(4*b) # (0,pi) # phi = pi*k/b # [0,2*pi) # # # trilinear interpolation # x = r*cos(phi)*sin(the); # _x = int(ceil(x)); x_ = int(floor(x)); dx = x-x_ # y = r*sin(phi)*sin(the); # _y = int(ceil(y)); y_ = int(floor(y)); dy = y-y_ # z = r*cos(the); # _z = int(ceil(z)); z_ = int(floor(z)); dz = z-z_ ## c_000 = vol.getV(m_x+x_,m_y+y_,m_z+z_) ## c_100 = vol.getV(m_x+_x,m_y+y_,m_z+z_) ## c_001 = vol.getV(m_x+x_,m_y+y_,m_z+_z) ## c_101 = vol.getV(m_x+_x,m_y+y_,m_z+_z) ## c_010 = vol.getV(m_x+x_,m_y+_y,m_z+z_) ## c_110 = vol.getV(m_x+_x,m_y+_y,m_z+z_) ## c_011 = vol.getV(m_x+x_,m_y+_y,m_z+_z) ## c_111 = vol.getV(m_x+_x,m_y+_y,m_z+_z) ## ## c_00 = c_000*(1-dx)+c_100*dx ## c_01 = c_001*(1-dx)+c_101*dx ## c_10 = c_010*(1-dx)+c_110*dx ## c_11 = c_011*(1-dx)+c_111*dx ## c_0 = c_00*(1-dy)+c_10*dy ## c_1 = c_01*(1-dy)+c_11*dy ## c = c_0*(1-dz)+c_1*dz # # c = interpolateSpline(vol, m_x+x, m_y+y, m_z+z) # res.append(c) return res
def generate_model(outputFolder, modelID, listpdbs, waterdensity=1, numberOfParticles=1000): if not os.path.exists(os.path.join(outputFolder, f'model_{modelID}')): os.mkdir(os.path.join(outputFolder, f'model_{modelID}')) # ['3cf3', '1s3x','1u6g','4b4t','1qvr','3h84','2cg9','3qm1','3gl1','3d2f','4d8q','1bxn'] factor = 10 skipped = 0 models = [] dims = [] for n, pdbid in enumerate(listpdbs): if not os.path.exists('{}/{}_model.mrc'.format(outputFolder, pdbid)): fname = generate_map(pdbid, n + skipped) else: fname = '{}/{}_model.mrc'.format(outputFolder, pdbid) skipped += 1 if 1 or not os.path.exists('{}/{}_model_binned.mrc'.format( outputFolder, pdbid)): m = read_mrc(fname) size = max(m.shape) m2 = numpy.zeros((size, size, size)) dx, dy, dz = m.shape sx, ex = (size - dx) // 2, size - int(ceil((size - dx) / 2.)) sy, ey = (size - dy) // 2, size - int(ceil((size - dy) / 2.)) sz, ez = (size - dz) // 2, size - int(ceil((size - dz) / 2.)) m2[sx:ex, sy:ey, sz:ez] = m m_r = crop(m2, factor) # print m_r.sum(), m2.sum(), m_r.max(), m2.max() # m_str = addStructuralNoise(m_r,m_r.shape[0]) # print median(m_str[m_str > 1.]),median(m_r[m_r > 1.]) convert_numpy_array3d_mrc( m_r, '{}/{}_model_binned.mrc'.format(outputFolder, pdbid)) else: m_r = read_mrc('{}/{}_model_binned.mrc'.format( outputFolder, pdbid)) models.append(m_r) dims.append(m_r.shape[0]) X, Y, Z = 200, SIZE, SIZE cell = numpy.zeros((X, Y, Z)) cell[:, :, :] = waterdensity mask = numpy.zeros_like(cell) #if addStructNoise: # cell = addStructuralNoise(cell) volumes = [] for i in range(len(models)): vol = read('{}_model_binned.mrc'.format(listpdbs[i])) volumes.append(vol) total = [ 0, ] * len(models) particleNr = 0 outline = '' for i in range(numberOfParticles): if i % 200 == 0: print(i) a = numpy.random.randint(0, len(models)) q = rand_quat() euler = euler_from_quat(q) euler *= 180. / pi mdl_vol = rotate(volumes[a], float(euler[0]), x=float(euler[1]), z2=float(euler[2])) mdl = vol2npy(mdl_vol) # mdl = rotate(models[a],randint(0,360),reshape=False) xx, yy, zz = mdl.shape for i in range(900): loc_x = numpy.random.randint(xx // 2 + 1, X - xx // 2 - 1) loc_y = numpy.random.randint(yy // 2 + 1, Y - yy // 2 - 1) loc_z = numpy.random.randint(zz // 2 + 1, Z - zz // 2 - 1) if mask[loc_x - dims[a] // 2:loc_x + dims[a] // 2 + dims[a] % 2, loc_y - dims[a] // 2:loc_y + dims[a] // 2 + dims[a] % 2, loc_z - dims[a] // 2:loc_z + dims[a] // 2 + dims[a] % 2].sum() == 0: break if i > 898: continue # print ('place particle {} at: {},{},{}'.format(particleNr,loc_x,loc_y,loc_z)) mask[loc_x - dims[a] // 2:loc_x + dims[a] // 2 + dims[a] % 2, loc_y - dims[a] // 2:loc_y + dims[a] // 2 + dims[a] % 2, loc_z - dims[a] // 2:loc_z + dims[a] // 2 + dims[a] % 2] = 1 cell[loc_x - dims[a] // 2:loc_x + dims[a] // 2 + dims[a] % 2, loc_y - dims[a] // 2:loc_y + dims[a] // 2 + dims[a] % 2, loc_z - dims[a] // 2:loc_z + dims[a] // 2 + dims[a] % 2] = mdl if abs(512 - loc_y) < 256 and abs(512 - loc_z) < 256: outline += "{} {:4d} {:4d} {:4d} {:4.0f} {:4.0f} {:4.0f}\n".format( listpdbs[a], loc_x, loc_y - 256, loc_z - 256, euler[0], euler[1], euler[2]) particleNr += 1 total[a] += 1 cell = addStructuralNoise(cell) grandcell = zeros((750, SIZE, SIZE)) grandcell[275:475, :, :] = cell convert_numpy_array3d_mrc( grandcell, f'{outputFolder}/model_{modelID}/grandmodel_{modelID}.mrc') convert_numpy_array3d_mrc( cell[:, SIZE // 4:-SIZE // 4, SIZE // 4:-SIZE // 4], f'{outputFolder}/model_{modelID}/grandmodel_{modelID}.mrc') outfile = open( f'{outputFolder}/model_{modelID}/particle_locations_model_{modelID}.txt', 'w') outfile.write(outline) return grandcell
def toProjectionStackFromAlignmentResultsFile(alignmentResultsFile, weighting=None, lowpassFilter=0.9, binning=1, circleFilter=False, num_procs=1, outdir='', prefix='sorted_aligned'): """read image and create aligned projection stack, based on the results described in the alignmentResultFile. @param alignmentResultsFile: result file generate by the alignment script. @type datatypeAR: gui.guiFunction.datatypeAR @param weighting: weighting (<0: analytical weighting, >1: exact weighting, 0/None: no weighting ) @type weighting: float @param lowpassFilter: lowpass filter (in Nyquist) @type lowpassFilter: float @param binning: binning (default: 1 = no binning). binning=2: 2x2 pixels -> 1 pixel, binning=3: 3x3 pixels -> 1 pixel, etc. @author: GvdS """ print('weighting: ', weighting) import numpy from pytom_numpy import vol2npy from pytom.basic.files import read_em, write_em from pytom.basic.functions import taper_edges from pytom.basic.transformations import general_transform2d from pytom.basic.fourier import ifft, fft from pytom.basic.filter import filter as filterFunction, bandpassFilter from pytom.basic.filter import circleFilter, rampFilter, exactFilter, fourierFilterShift, \ fourierFilterShift_ReducedComplex from pytom_volume import complexRealMult, vol, paste import pytom_freqweight from pytom.basic.transformations import resize, rotate from pytom.gui.guiFunctions import fmtAR, headerAlignmentResults, datatype, datatypeAR, loadstar from pytom.reconstruction.reconstructionStructures import Projection, ProjectionList from pytom_numpy import vol2npy import mrcfile from pytom.tompy.io import write, read_size import os print("Create aligned images from alignResults.txt") alignmentResults = loadstar(alignmentResultsFile, dtype=datatypeAR) imageList = alignmentResults['FileName'] tilt_angles = alignmentResults['TiltAngle'] imdim = int(read_size(imageList[0], 'x')) if binning > 1: imdim = int(float(imdim) / float(binning) + .5) else: imdim = imdim sliceWidth = imdim # pre-determine analytical weighting function and lowpass for speedup if (weighting != None) and (float(weighting) < -0.001): weightSlice = fourierFilterShift(rampFilter(imdim, imdim)) if circleFilter: circleFilterRadius = imdim // 2 circleSlice = fourierFilterShift_ReducedComplex( circleFilter(imdim, imdim, circleFilterRadius)) else: circleSlice = vol(imdim, imdim // 2 + 1, 1) circleSlice.setAll(1.0) # design lowpass filter if lowpassFilter: if lowpassFilter > 1.: lowpassFilter = 1. print("Warning: lowpassFilter > 1 - set to 1 (=Nyquist)") # weighting filter: arguments: (angle, cutoff radius, dimx, dimy, lpf = pytom_freqweight.weight(0.0, lowpassFilter * imdim // 2, imdim, imdim // 2 + 1, 1, lowpassFilter / 5. * imdim) # lpf = bandpassFilter(volume=vol(imdim, imdim,1),lowestFrequency=0,highestFrequency=int(lowpassFilter*imdim/2), # bpf=None,smooth=lowpassFilter/5.*imdim,fourierOnly=False)[1] projectionList = ProjectionList() imageList = [] tilt_angles = [] for n, image in enumerate(alignmentResults['FileName']): atx = alignmentResults['AlignmentTransX'][n] aty = alignmentResults['AlignmentTransY'][n] rot = alignmentResults['InPlaneRotation'][n] mag = alignmentResults['Magnification'][n] # print(image, alignmentResults['TiltAngle'][n]) # if abs(alignmentResults['TiltAngle'][n]) > 20: # continue tilt_angles.append(alignmentResults['TiltAngle'][n]) imageList.append(image) projection = Projection(imageList[-1], tiltAngle=tilt_angles[-1], alignmentTransX=atx, alignmentTransY=aty, alignmentRotation=rot, alignmentMagnification=mag) projectionList.append(projection) stack = vol(imdim, imdim, len(imageList)) stack.setAll(0.0) phiStack = vol(1, 1, len(imageList)) phiStack.setAll(0.0) thetaStack = vol(1, 1, len(imageList)) thetaStack.setAll(0.0) offsetStack = vol(1, 2, len(imageList)) offsetStack.setAll(0.0) for (ii, projection) in enumerate(projectionList): if projection._filename.split('.')[-1] == 'st': from pytom.basic.files import EMHeader, read idx = projection._index image = read(file=projection._filename, subregion=[0, 0, idx - 1, imdim, imdim, 1], sampling=[0, 0, 0], binning=[0, 0, 0]) if not (binning == 1) or (binning == None): image = resize(volume=image, factor=1 / float(binning))[0] else: # read projection files from pytom.basic.files import EMHeader, read, read_em_header image = read(str(projection._filename)) # image = rotate(image,180.,0.,0.) image = resize(volume=image, factor=1 / float(binning))[0] if lowpassFilter: filtered = filterFunction(volume=image, filterObject=lpf, fourierOnly=False) image = filtered[0] tiltAngle = projection._tiltAngle # normalize to contrast - subtract mean and norm to mean immean = vol2npy(image).mean() image = (image - immean) / immean print(ii, immean, projection._filename) # smoothen borders to prevent high contrast oscillations image = taper_edges(image, imdim // 30)[0] # transform projection according to tilt alignment transX = projection._alignmentTransX / binning transY = projection._alignmentTransY / binning rot = float(projection._alignmentRotation) mag = float(projection._alignmentMagnification) image = general_transform2d(v=image, rot=rot, shift=[transX, transY], scale=mag, order=[2, 1, 0], crop=True) # smoothen once more to avoid edges image = taper_edges(image, imdim // 30)[0] # analytical weighting if (weighting != None) and (weighting < 0): # image = (ifft(complexRealMult(fft(image), w_func)) / (image.sizeX() * image.sizeY() * image.sizeZ())) image = ifft(complexRealMult( complexRealMult(fft(image), weightSlice), circleSlice), scaling=True) elif (weighting != None) and (weighting > 0): weightSlice = fourierFilterShift( exactFilter(tilt_angles, tiltAngle, imdim, imdim, sliceWidth)) # image = (ifft(complexRealMult(fft(image), w_func)) / (image.sizeX() * image.sizeY() * image.sizeZ())) image = ifft(complexRealMult( complexRealMult(fft(image), weightSlice), circleSlice), scaling=True) thetaStack(int(round(projection.getTiltAngle())), 0, 0, ii) offsetStack(int(round(projection.getOffsetX())), 0, 0, ii) offsetStack(int(round(projection.getOffsetY())), 0, 1, ii) paste(image, stack, 0, 0, ii) fname = '{}_{:02d}.mrc'.format( prefix, int(imageList[ii].split('_')[-1].split('.')[0])) if outdir: import mrcfile # write_em(os.path.join(outdir, fname.replace('mrc', 'em')), image) write(os.path.join(outdir, fname), vol2npy(image).copy().astype('float32')) print('written file: ', fname) return [stack, phiStack, thetaStack, offsetStack]
sys.exit() try: fname, ps, sliceId, f_ds, sliceDir, phases, b_help = parse_script_options( sys.argv[1:], helper) except: print(helper) sys.exit() if b_help: print(helper) sys.exit() if fname.endswith('.em'): vol = read(fname) data = copy.deepcopy(vol2npy(vol)).T else: import mrcfile data = copy.deepcopy(mrcfile.open(fname, permissive=True).data) print('max: {} min: {} mean: {} std: {}'.format(data.max(), data.min(), data.mean(), data.std())) print(data.shape) from scipy.ndimage import gaussian_filter print(data.shape) if sliceDir is None: sliceDir = 'z' else: sliceDir = sliceDir.lower() if not sliceDir in ['x', 'y', 'z']:
def writeAlignedProjections(TiltSeries_, weighting=None, lowpassFilter=None, binning=None, verbose=False, write_images=True): """write weighted and aligned projections to disk1 @param TiltSeries_: Tilt Series @type TiltSeries_: reconstruction.TiltSeries @param weighting: weighting (<0: analytical weighting, >1 exact weighting (value corresponds to object diameter in pixel AFTER binning) @type weighting: float @param lowpassFilter: lowpass filter (in Nyquist) @type lowpassFilter: float @param binning: binning (default: 1 = no binning). binning=2: 2x2 pixels -> 1 pixel, binning=3: 3x3 pixels -> 1 pixel, etc. @author: FF """ import numpy from pytom_numpy import vol2npy from pytom.basic.files import read_em, write_em from pytom.basic.functions import taper_edges from pytom.basic.transformations import general_transform2d from pytom.basic.fourier import ifft, fft from pytom.basic.filter import filter as filterFunction, bandpassFilter from pytom.basic.filter import circleFilter, rampFilter, exactFilter, fourierFilterShift, rotateFilter from pytom_volume import complexRealMult, vol import pytom_freqweight from pytom.basic.transformations import resize from pytom.gui.guiFunctions import fmtAR, headerAlignmentResults, datatypeAR import os if binning: imdim = int(float(TiltSeries_._imdim) / float(binning) + .5) else: imdim = TiltSeries_._imdim print('imdim', imdim) sliceWidth = imdim # pre-determine analytical weighting function and lowpass for speedup if (weighting != None) and (weighting < -0.001): w_func = fourierFilterShift(rampFilter(imdim, imdim)) print('start weighting') # design lowpass filter if lowpassFilter: if lowpassFilter > 1.: lowpassFilter = 1. print("Warning: lowpassFilter > 1 - set to 1 (=Nyquist)") # weighting filter: arguments: (angle, cutoff radius, dimx, dimy, lpf = pytom_freqweight.weight(0.0, lowpassFilter * imdim / 2, imdim, imdim // 2 + 1, 1, lowpassFilter / 5. * imdim) #lpf = bandpassFilter(volume=vol(imdim, imdim,1),lowestFrequency=0,highestFrequency=int(lowpassFilter*imdim/2), # bpf=None,smooth=lowpassFilter/5.*imdim,fourierOnly=False)[1] tilt_angles = [] for projection in TiltSeries_._ProjectionList: tilt_angles.append(projection._tiltAngle) tilt_angles = sorted(tilt_angles) print(tilt_angles) #q = numpy.matrix(abs(numpy.arange(-imdim//2, imdim//2))) alignmentResults = numpy.zeros((len(TiltSeries_._ProjectionList)), dtype=datatypeAR) alignmentResults['TiltAngle'] = tilt_angles for (ii, projection) in enumerate(TiltSeries_._ProjectionList): alignmentResults['FileName'][ii] = os.path.join( os.getcwd(), projection._filename) transX = -projection._alignmentTransX / binning transY = -projection._alignmentTransY / binning rot = -(projection._alignmentRotation + 90.) mag = projection._alignmentMagnification alignmentResults['AlignmentTransX'][ii] = transX alignmentResults['AlignmentTransY'][ii] = transY alignmentResults['InPlaneRotation'][ii] = rot alignmentResults['Magnification'][ii] = mag if write_images: if projection._filename.split('.')[-1] == 'st': from pytom.basic.files import EMHeader, read header = EMHeader() header.set_dim(x=imdim, y=imdim, z=1) idx = projection._index if verbose: print("reading in projection %d" % idx) image = read(file=projection._filename, subregion=[ 0, 0, idx - 1, TiltSeries_._imdim, TiltSeries_._imdim, 1 ], sampling=[0, 0, 0], binning=[0, 0, 0]) if not (binning == 1) or (binning == None): image = resize(volume=image, factor=1 / float(binning))[0] else: # read projection files from pytom.basic.files import EMHeader, read, read_em_header print(projection._filename) image = read(projection._filename) image = resize(volume=image, factor=1 / float(binning))[0] if projection._filename[-3:] == '.em': header = read_em_header(projection._filename) else: header = EMHeader() header.set_dim(x=imdim, y=imdim, z=1) if lowpassFilter: filtered = filterFunction(volume=image, filterObject=lpf, fourierOnly=False) image = filtered[0] tiltAngle = projection._tiltAngle header.set_tiltangle(tiltAngle) # normalize to contrast - subtract mean and norm to mean immean = vol2npy(image).mean() image = (image - immean) / immean # smoothen borders to prevent high contrast oscillations image = taper_edges(image, imdim // 30)[0] # transform projection according to tilt alignment if projection._filename.split('.')[-1] == 'st': newFilename = (TiltSeries_._alignedTiltSeriesName + "_" + str(projection.getIndex()) + '.em') else: TiltSeries_._tiltSeriesFormat = 'mrc' newFilename = (TiltSeries_._alignedTiltSeriesName + "_" + str(projection.getIndex()) + '.' + TiltSeries_._tiltSeriesFormat) if verbose: tline = ("%30s" % newFilename) tline = tline + (" (tiltAngle=%6.2f)" % tiltAngle) tline = tline + (": transX=%6.1f" % transX) tline = tline + (", transY=%6.1f" % transY) tline = tline + (", rot=%6.2f" % rot) tline = tline + (", mag=%5.4f" % mag) print(tline) image = general_transform2d(v=image, rot=rot, shift=[transX, transY], scale=mag, order=[2, 1, 0], crop=True) # smoothen once more to avoid edges image = taper_edges(image, imdim // 30)[0] # analytical weighting if (weighting != None) and (weighting < 0): image = (ifft(complexRealMult(fft(image), w_func)) / (image.sizeX() * image.sizeY() * image.sizeZ())) elif (weighting != None) and (weighting > 0): if abs(weighting - 2) < 0.001: w_func = fourierFilterShift( rotateFilter(tilt_angles, tiltAngle, imdim, imdim, sliceWidth)) else: w_func = fourierFilterShift( exactFilter(tilt_angles, tiltAngle, imdim, imdim, sliceWidth)) image = (ifft(complexRealMult(fft(image), w_func)) / (image.sizeX() * image.sizeY() * image.sizeZ())) header.set_tiltangle(tilt_angles[ii]) if newFilename.endswith('.mrc'): data = copy.deepcopy(vol2npy(image)) mrcfile.new(newFilename, data.T.astype(float32), overwrite=True) else: write_em(filename=newFilename, data=image, header=header) if verbose: tline = ("%30s written ..." % newFilename) outname = os.path.join(os.path.dirname(TiltSeries_._alignedTiltSeriesName), 'alignmentResults.txt') numpy.savetxt(outname, alignmentResults, fmt=fmtAR, header=headerAlignmentResults) print('Alignment successful. See {} for results.'.format(outname))
def sag_fine_grained_alignment(vf, wf, vg, wg, max_freq, ang=[0, 0, 0], loc=[0, 0, 0], mask=None, B, alpha, maxIter, lambda1): """SAG-based fine-grained alignment between experimental data and reference data. Parameters vf: Experimental data pytom_volume.vol wf: Mask of vf in Fourier space. pytom.basic.structures.Wedge. If none, no missing wedge. vg: Reference data pytom_volume.vol wg: Mask of vg in Fourier space. pytom.basic.structures.Wedge. If none, no missing wedge. max_freq: Maximal frequency involved in calculation. Integer. ang: Initial rotation angle loc: Initial translation value mask: Mask volume in real space. pytom_volume.vol B: Batch number alpha: Step size maxIter: The max iteration number lambda1: Regularization parameter Returns ------- (Optimal rotation angle and translation value. (best_translation, best_rotation, correlation_score) """ from pytom_volume import vol, rotateSpline, peak, sum, power from pytom.basic.transformations import shift from pytom.basic.filter import lowpassFilter from pytom.basic.structures import Mask, SingleTiltWedge, Rotation from pytom_volume import initSphere from pytom_numpy import vol2npy import math import random if vf.sizeX() != vg.sizeX() or vf.sizeY() != vg.sizeY() or vf.sizeZ( ) != vg.sizeZ(): raise RuntimeError('Two volumes must have the same size!') if wf is None: wf = SingleTiltWedge(0) else: vf = wf.apply(vf) if wg is None: wg = SingleTiltWedge(0) else: vg = wg.apply(vg) if mask is None: m = vol(vf.sizeX(), vf.sizeY(), vf.sizeZ()) initSphere(m, vf.sizeX() / 2, 0, 0, vf.sizeX() / 2, vf.sizeY() / 2, vf.sizeZ() / 2) mask = m old_value = -1 max_pos = [-1, -1, -1] max_ang = None max_value = -1.0 ang_epsilon = np.ones(3) * (math.pi * (1.0 / 180)) loc_epsilon = np.ones(3) * 1.0 n = vf.sizeX() vf0_n = vol2npy(vf) if maxIter is None: maxIter = n / 2 iVals = np.int32(np.ceil((n - B) * np.random.random(maxIter))) if lambda1 is None: lambda1 = 1 / n eps = np.finfo(np.float32).eps Lmax = 0.25 * np.max(np.sum(vf0_n**2)) + lambda1 if alpha is None: alpha = 1 / Lmax d = np.zeros(6) g = np.zeros([n, 6]) covered = np.int32(np.zeros(n)) nCovered = 0 grad = np.zeros(6) deri = np.zeros(6) vg2 = vol(vf.sizeX(), vf.sizeY(), vf.sizeZ()) mask2 = vol(mask.sizeX(), mask.sizeY(), mask.sizeZ()) for i in range(n): if (covered[i] != 0): nCovered += 1 for k in range(maxIter): i = iVals[k] - 1 if k == 0: rotateSpline(vg, vg2, ang[0], ang[1], ang[2]) rotateSpline(mask, mask2, ang[0], ang[1], ang[2]) vg2 = wf.apply(vg2) vg2 = lowpassFilter(vg2, max_freq, max_freq / 10.)[0] vg2_s = transform_single_vol(vg2, mask2) vf2 = shift(vf, -loc[0] + vf.sizeX() / 2, -loc[1] + vf.sizeY() / 2, -loc[2] + vf.sizeZ() / 2, imethod='spline') vf2 = lowpassFilter(vf2, max_freq, max_freq / 10.)[0] vf2 = wg.apply(vf2, Rotation(ang)) vf2_s = transform_single_vol(vf2, mask2) i = 0 ri = np.sum( vol2npy(vf2_s)[i:i + B, :, :] - vol2npy(vg2_s)[i:i + B, :, :]) vg2_p = vol(n, n, n) vg2_m = vol(n, n, n) mask2_p = vol(n, n, n) mask2_m = vol(n, n, n) for dim_i in range(3): if abs(ang_epsilon[dim_i]) > eps: ang_epsilon_t = np.zeros(3) ang_epsilon_t[dim_i] = ang_epsilon[dim_i] angle = ang + ang_epsilon_t rotateSpline(vg, vg2_p, angle[0], angle[1], angle[2]) rotateSpline(mask, mask2_p, angle[0], angle[1], angle[2]) vg2_p = wf.apply(vg2_p) vg2_p = lowpassFilter(vg2_p, max_freq, max_freq / 10.)[0] vg2_pf = transform_single_vol(vg2_p, mask2_p) angle = ang - ang_epsilon_t rotateSpline(vg, vg2_m, angle[0], angle[1], angle[2]) rotateSpline(mask, mask2_m, angle[0], angle[1], angle[2]) vg2_m = wf.apply(vg2_m) vg2_m = lowpassFilter(vg2_m, max_freq, max_freq / 10.)[0] vg2_mf = transform_single_vol(vg2_m, mask2_m) vg2_ang_deri = (vg2_pf - vg2_mf) / (2 * ang_epsilon[dim_i]) vg2_ang_deri_n = vol2npy(vg2_ang_deri) deri[dim_i] = np.sum(vg2_ang_deri_n[i:i + B, :, :]) del vg2_pf, vg2_mf, vg2_ang_deri, vg2_ang_deri_n, angle del vg2_p, vg2_m, mask2_p, mask2_m vf1_ps = vol(n, n, n) vf1_ms = vol(n, n, n) ang_f = [ang[0], ang[1], ang[2]] for dim_i in range(3): if abs(loc_epsilon[dim_i]) > eps: loc_epsilon_t = np.zeros(3) loc_epsilon_t[dim_i] = ang_epsilon[dim_i] vf1_ps.copyVolume(vf) vf1_ms.copyVolume(vf) loc_r = loc + loc_epsilon_t vf1_tp = shift(vf1_ps, -loc_r[0] + vf1_ps.sizeX() / 2, -loc_r[1] + vf1_ps.sizeY() / 2, -loc_r[2] + vf1_ps.sizeZ() / 2, 'spline') vf1_tp = lowpassFilter(vf1_tp, max_freq, max_freq / 10.)[0] vf1_tp = wg.apply(vf1_tp, Rotation(ang_f)) loc_r = loc - loc_epsilon_t vf1_tm = shift(vf1_ms, -loc_r[0] + vf1_ms.sizeX() / 2, -loc_r[1] + vf1_ms.sizeY() / 2, -loc_r[2] + vf1_ms.sizeZ() / 2, 'spline') vf1_tm = lowpassFilter(vf1_tm, max_freq, max_freq / 10.)[0] vf1_tm = wg.apply(vf1_tm, Rotation(ang_f)) vf1_tpf = transform_single_vol(vf1_tp, mask2) vf1_tmf = transform_single_vol(vf1_tm, mask2) vf1_loc_deri = (vf1_tpf - vf1_tmf) / (2 * ang_epsilon[dim_i]) vf1_loc_deri_n = vol2npy(vf1_loc_deri) deri[dim_i + 3] = np.sum(vf1_loc_deri_n[i:i + B, :, :]) del vf1_tp, vf1_tm, vf1_tpf, vf1_tmf, vf1_loc_deri, vf1_loc_deri_n del vf1_ps, vf1_ms, ang_f for dim_i in range(6): grad[dim_i] = ri * deri[dim_i] / B for dim_i in range(6): d[dim_i] += grad[dim_i] - np.sum(g[i:i + B, dim_i]) for dim_i in range(6): g[i:i + B, dim_i] = grad[dim_i] for j0 in range(i, i + B + 1): if (covered[j0] == 0): covered[j0] = 1 nCovered += 1 for dim_i in range(6): opt_beta[dim_i] -= alpha * d[dim_i] / nCovered ang = opt_beta[:3] loc = opt_beta[3:] rotateSpline(vg, vg2, ang[0], ang[1], ang[2]) rotateSpline(mask, mask2, ang[0], ang[1], ang[2]) vg2 = wf.apply(vg2) vg2 = lowpassFilter(vg2, max_freq, max_freq / 10.)[0] vg2_s = transform_single_vol(vg2, mask2) vf2 = shift(vf, -loc[0] + vf.sizeX() / 2, -loc[1] + vf.sizeY() / 2, -loc[2] + vf.sizeZ() / 2, imethod='spline') vf2 = lowpassFilter(vf2, max_freq, max_freq / 10.)[0] vf2 = wg.apply(vf2, Rotation(ang)) vf2_s = transform_single_vol(vf2, mask2) ri = np.sum( vol2npy(vf2_s)[i:i + B, :, :] - vol2npy(vg2_s)[i:i + B, :, :]) from pytom.basic.correlation import nxcc val = nxcc(vf2_s, vg2_s, mask) if val > max_value: max_pos = loc max_ang = ang max_value = val if abs(max_value - old_value) <= eps: break else: old_value = max_value del vg2_s, vf2, vf2_s del d, g, grad, deri return max_pos, max_ang, max_value
boxhalf_x = boxhalf_y = boxhalf_z = window_size/2 nvox = pid = 0 pid_matrix = [] for zz in xrange(0,nz): for yy in xrange(0,ny): for xx in xrange(0,nx): if (pmask(xx,yy,zz)): nvox+=1 pid += 1 key_value = (pid,(xx,yy,zz)) pid_matrix.append(key_value) del nvox vol1_n = vol2npy(hm1) #must transform into 3D matrix vol2_n = vol2npy(hm20) vol1_np = np.zeros((nx,ny,nz),dtype=np.float32,order='F') vol2_np = np.zeros((nx,ny,nz),dtype=np.float32,order='F') vol1_np = vol1_n vol2_np = vol2_n BC_vol1 = sc.broadcast(vol1_np) BC_vol2 = sc.broadcast(vol2_np) BC_max_resolution = sc.broadcast(max_resolution) BC_pixelSize = sc.broadcast(pixelSize) BC_numberBands = sc.broadcast(numberBands) BC_fsc_criterion = sc.broadcast(fsc_criterion) BC_sizeX = sc.broadcast(sizeX)