def subPixelPeak(inp, k=1, ignore_border=1): from pytom.voltools import transform is2d = len(inp.shape.squeeze()) == 2 if is2d: inp2 = inp.squeeze()[ignore_border:-ignore_border, ignore_border:-ignore_border] scale = (k, k, 1) out = xp.array(inp.squeeze(), dtype=xp.float32) x, y = xp.array(xp.unravel_index(inp2.argmax(), inp2.shape)) + ignore_border out = xp.expand_dims(out, 2) translation = [inp.shape[0] // 2 - x, inp.shape[1] // 2 - y, 0] else: inp2 = inp[ignore_border:-ignore_border, ignore_border:-ignore_border, ignore_border:-ignore_border] scale = (k, k, k) out = xp.array(inp, dtype=xp.float32) x, y, z = xp.array(xp.unravel_index(inp2.argmax(), inp2.shape)) + ignore_border translation = [ inp.shape[0] // 2 - x, inp.shape[1] // 2 - y, inp.shape[2] // 2 - z ] zoomed = xp.zeros_like(out, dtype=xp.float32) transform(out, output=zoomed, scale=scale, translation=translation, device='gpu:0', interpolation='filt_bspline') shifts = [x2, y2, z2] = xp.unravel_index(zoomed.argmax(), zoomed.shape) return [zoomed[x2, y2, z2], shifts[3 - is2d]]
def back_projection(image, angle, interpolation=None): ''' back_projection: Returns 3D volume with values projected under an angle @param image: 2d projection image @type image: 2d numpy/cupy array of floats @param angle: Tilt angle of projection @type angle: float32 @param interpolation: interpolation type using in rotation. filtered bspline is recommended. @return: @author Gijs van der Schot ''' dimx, dimy = image.shape dims = [dimx, dimy, dimx] ndim = (dimx * 3) // 2 out = xp.dstack([image] * (ndim)) bp = xp.zeros_like(out) transform(out, output=bp, rotation=(0, angle, 0), rotation_order='sxyz', interpolation=interpolation, center=numpy.array([dims[0] // 2, dims[1] // 2, ndim // 2]), device=device) return bp[:, :, ndim // 2 - dimx // 2:ndim // 2 + dimx // 2].copy()
def subPixelShifts(volume, scale=[1, 1, 1], cutout=20, shifts=True): from pytom.voltools import transform import numpy as np volC = xp.array( [volume.shape[0] // 2, volume.shape[1] // 2, volume.shape[2] // 2]) cx, cy, cz = center = find_coords_max_ccmap(volume) x, y, z = volume.shape if cx - cutout // 2 < 0 or cy - cutout // 2 < 0 or cz - cutout // 2 < 0 or cx + cutout // 2 >= x or cy + cutout // 2 >= y or cz + cutout // 2 >= z: return [ volume.max(), xp.array([cx - x // 2, cy - y // 2, cz - z // 2]) ] cutvol = volume[cx - cutout // 2:cx + cutout // 2, cy - cutout // 2:cy + cutout // 2, cz - cutout // 2:cz + cutout // 2] nx, ny, nz = [int(np.ceil(cutout / s)) for s in scale] nC = xp.array([nx // 2, ny // 2, nz // 2]) centered = xp.zeros((nx, ny, nz), dtype=xp.float32) centered[nx // 2 - cutout // 2:nx // 2 + cutout // 2, ny // 2 - cutout // 2:ny // 2 + cutout // 2, nz // 2 - cutout // 2:nz // 2 + cutout // 2] = cutvol interpolated_peak = xp.zeros_like(centered) transform(centered, scale=scale, device=device, interpolation='filt_bspline', output=interpolated_peak) interpol_center = find_coords_max_ccmap(interpolated_peak) shifts = xp.array(center) - volC + (xp.array(interpol_center) - xp.array(nC)) * xp.array(scale) return [interpolated_peak.max(), shifts]
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 applyRotatedFilter(particle, filter, rotation, rotation_order='rzxz'): return applyFourierFilter( particle, transform(filter, rotation=rotation, rotation_order=rotation_order, device=device))
def subPixelShiftsImage(volume, scale=[1, 1, 1], cutout=20, shifts=True): from pytom.voltools import transform import numpy as np if shifts: volC = xp.array( [vol.shape[0] // 2, volume.shape[1] // 2, vol.shape[2] // 2]) else: volC = xp.array([0, 0, 0], dtype=xp.int32) cx, cy, cz = center = find_coords_max_ccmap(volume) cutvol = volume[cx - cutout // 2:cx + cutout // 2, cy - cutout // 2:cy + cutout // 2, :] nx, ny, nz = [int(np.ceil(cutout / s)) for s in scale] nC = xp.array([nx // 2, ny // 2, 0]) centered = xp.zeros((nx, ny, 1), dtype=xp.float32) centered[nx // 2 - cutout // 2:nx // 2 + cutout // 2, ny // 2 - cutout // 2:ny // 2 + cutout // 2, :] = cutvol interpolated_peak = transform(centered, scale=scale, device=device, interpolation='filt_bspline') interpol_center = find_coords_max_ccmap(interpolated_peak) shifts = xp.array(center) - volC + (xp.array(interpol_center) - xp.array(nC)) * xp.array(scale) return [interpolated_peak.max(), shifts]
def rotateWeighting(weighting, rotation, mask=None, binarize=False): """ rotateWeighting: Rotates a frequency weighting volume around the center. If the volume provided is reduced complex, it will be rescaled to full size, ftshifted, rotated, iftshifted and scaled back to reduced size. @param weighting: A weighting volume in reduced complex convention @type weighting: cupy or numpy array @param rotation: rotation angles in zxz order @type rotation: list @param mask:=None is there a rotation mask? A mask with all = 1 will be generated otherwise. Such mask should be \ provided anyway. @type mask: cupy or numpy ndarray @return: weight as reduced complex volume @rtype: L{pytom_volume.vol_comp} """ from pytom_volume import vol, limit, vol_comp from pytom_volume import rotate from pytom.voltools import transform assert type(weighting) == vol or type( weighting ) == vol_comp, "rotateWeighting: input neither vol nor vol_comp" from pytom.tompy.transform import fourier_reduced2full, fourier_full2reduced weighting = fourier_reduced2full(weighting, isodd=weighting.shape[0] % 2 == 1) weighting = xp.fft.fftshift(weighting) weightingRotated = xp.zeros_like(weighting) transform(weighting, output=weightingRotated, rotation=rotation, rotation_order='rzxz', device=device, interpolation='filt_bspline') if not mask is None: weightingRotated *= mask weightingRotated = xp.fft.fftshift(weightingRotated) returnVolume = fourier_full2reduced(weightingRotated) if binarize: returnVolume[returnVolume < 0.5] = 0 returnVolume[returnVolume >= 0.5] = 1 return returnVolume
def cut_patch(projection, ang, pick_position, vol_size=200, binning=8, dimz=None, offset=[0, 0, 0], projection_name=None): from pytom.tompy.tools import taper_edges #from pytom.gpu.initialize import xp from pytom.voltools import transform from pytom.tompy.transform import rotate3d, rotate_axis from pytom.tompy.transform import cut_from_projection from pytom.tompy.io import read # Get the size of the original projection dim_x = projection.shape[0] dim_z = dim_x if dimz is None else dimz x, y, z = pick_position x = (x + offset[0]) * binning y = (y + offset[1]) * binning z = (z + offset[2]) * binning # Get coordinates of the paricle adjusted for the tilt angle yy = y # assume the rotation axis is around y xx = (xp.cos(ang * xp.pi / 180) * (x - dim_x / 2) - xp.sin(ang * xp.pi / 180) * (z - dim_z / 2)) + dim_x / 2 # Cut the small patch out patch = projection[max(0, int(xp.floor(xx)) - vol_size // 2):int(xp.floor(xx)) + vol_size // 2, int(yy) - vol_size // 2:int(yy) + vol_size // 2, :] shiftedPatch = xp.zeros_like(patch) transform(patch, output=shiftedPatch, translation=[xx % 1, yy % 1, 0], device=device, interpolation='filt_bspline') return shiftedPatch.squeeze()
def find_sub_pixel_max_value_voltools(inp, k=.1, ignore_border=50): """ To find the highest point in a 2D array, with subpixel accuracy based on 1D spline interpolation. The algorithm is based on a matlab script "tom_peak.m" @param inp: A 2D numpy array containing the data points. @type inp: numpy array 2D @param k: The smoothing factor used in the spline interpolation, must be 1 <= k <= 5. @type k: int @return: A list of all points of maximal value in the structure of tuples with the x position, the y position and the value. @returntype: list """ # assert len(ixp.shape) == 2 # assert isinstance(k, int) and 1 <= k <= 5 import cupy import numpy as xp from scipy.interpolate import InterpolatedUnivariateSpline from pytom.voltools import transform inp2 = inp[ignore_border:-ignore_border, ignore_border:-ignore_border] out = cupy.array(inp, dtype=cupy.float32) x, y = xp.array(xp.unravel_index(inp2.argmax(), inp2.shape)) + ignore_border out = cupy.expand_dims(out, 2) zoomed = cupy.zeros_like(out, dtype=cupy.float32) transform(out, output=zoomed, scale=(k, k, 1), translation=[inp.shape[0] // 2 - x, inp.shape[1] // 2 - y, 0], device='gpu:0', interpolation='filt_bspline') z = zoomed.get().squeeze() x2, y2 = xp.unravel_index(z.argmax(), z.shape) return [ x + (x2 - z.shape[0] // 2) * k - z.shape[0] // 2, y + (y2 - z.shape[1] // 2) * k - z.shape[0] // 2, z, x, y, x2, y2 ]
def find_sub_pixel_voltools(inp, k=0.1, border=75, max_shift=15): import pytom.voltools as vt inp = xp.ascontiguousarray(inp) # find the position of the initial maximum dimx, dimy = inp.squeeze().shape initial_max = xp.unravel_index( inp[border:-border, border:-border].argmax(), (dimx - border * 2, dimy - border * 2)) ix, iy = [v + border for v in initial_max] # Create an array with specific size so the zoom fits in (size = max_shift * 2 /k) # Center of array is initial max out = int(xp.around(max_shift * 2 / k)) model = xp.zeros((out, out), dtype=xp.float32) model[out // 2 - max_shift:out // 2 + max_shift, out // 2 - max_shift:out // 2 + max_shift] = inp[ix - max_shift:ix + max_shift, iy - max_shift:iy + max_shift] zoomedVol = xp.expand_dims(model, 2) # Scale image vt.transform(zoomedVol, scale=(k, k, 1), interpolation='filt_bspline', device=device, output=zoomedVol) # fig, ax = subplots(1, 2, figsize=(10, 5)) # ax[0].imshow(inp.get().squeeze()) # ax[1].imshow(zoomedVol.squeeze().get()) # show() # Find new max and update the initial max according to the shift transformed_max = xp.unravel_index(zoomedVol.argmax(), zoomedVol.shape) interpolX, interpolY = ix + (transformed_max[0] - out // 2) * k, iy + ( transformed_max[1] - out // 2) * k return interpolX, interpolY, zoomedVol.squeeze()
def add_transformed_particle_to_sum(particle, sum, rotation=None, rotation_order='rzxz', translation=None, scale=None): from pytom.voltools import transform rot = transform(particle, rotation=rotation, translation=translation, scale=scale, rotation_order=rotation_order, device=device, interpolation='filt_bspline') sum += xp.array(rot) return sum
def subPixelMax3D(volume, k=.01, ignore_border=50, interpolation='filt_bspline', plan=None, profile=True, num_threads=1024, zoomed=None, fast_sum=None, max_id=None): """ Function to find the highest point in a 3D array, with subpixel accuracy using cubic spline interpolation. @param inp: A 3D numpy/cupy array containing the data points. @type inp: numpy/cupy array 3D @param k: The interpolation factor used in the spline interpolation, k < 1 is zoomed in, k>1 zoom out. @type k: float @return: A list of maximal value in the interpolated volume and a list of x position, the y position and the value. @returntype: list """ from pytom.voltools import transform from pytom.tompy.io import write ox, oy, oz = volume.shape ib = ignore_border cropped_volume = volume[ib:ox - ib, ib:oy - ib, ib:oz - ib].astype(xp.float32) if profile: stream = xp.cuda.Stream.null t_start = stream.record() # x,y,z = xp.array(maxIndex(cropped_volume)) + ignore_border x, y, z = xp.array( xp.unravel_index(cropped_volume.argmax(), cropped_volume.shape)) + ignore_border dx, dy, dz = volume.shape translation = [dx // 2 - x, dy // 2 - y, dz // 2 - z] if profile: t_end = stream.record() t_end.synchronize() time_took = xp.cuda.get_elapsed_time(t_start, t_end) print(f'initial find max time: \t{time_took:.3f}ms') t_start = stream.record() b = border = max(0, int(volume.shape[0] // 2 - 4 / k)) zx, zy, zz = volume.shape out = volume[b:zx - b, b:zy - b, b:zz - b] transform(out, output=zoomed, scale=(k, k, k), device=device, translation=translation, interpolation=interpolation) if profile: t_end = stream.record() t_end.synchronize() time_took = xp.cuda.get_elapsed_time(t_start, t_end) print(f'transform finished in \t{time_took:.3f}ms') t_start = stream.record() nblocks = int(xp.ceil(zoomed.size / num_threads / 2)) argmax(( nblocks, 1, ), (num_threads, 1, 1), (zoomed, fast_sum, max_id, zoomed.size), shared_mem=8 * num_threads) x2, y2, z2 = xp.unravel_index(max_id[fast_sum.argmax()], zoomed.shape) peakValue = zoomed[x2][y2][z2] peakShift = [ x + (x2 - zoomed.shape[0] // 2) * k - volume.shape[0] // 2, y + (y2 - zoomed.shape[1] // 2) * k - volume.shape[1] // 2, z + (z2 - zoomed.shape[2] // 2) * k - volume.shape[2] // 2 ] if profile: t_end = stream.record() t_end.synchronize() time_took = xp.cuda.get_elapsed_time(t_start, t_end) print(f'argmax finished in \t{time_took:.3f}ms') t_start = stream.record() print() return [peakValue, peakShift]
def alignImagesUsingAlignmentResultFile(alignmentResultsFile, weighting=None, lowpassFilter=0.9, binning=1, circleFilter=False): import os from pytom.basic.files import read as readCVol from pytom_numpy import vol2npy, npy2vol from pytom.gui.guiFunctions import fmtAR, headerAlignmentResults, datatype, datatypeAR, loadstar from pytom.reconstruction.reconstructionStructures import Projection, ProjectionList from pytom.tompy.io import read, write, read_size from pytom.tompy.tools import taper_edges, create_circle from pytom.tompy.filter import circle_filter, ramp_filter, exact_filter import pytom.voltools as vt from pytom.gpu.initialize import xp, device print("Create aligned images from alignResults.txt") alignmentResults = loadstar(alignmentResultsFile, dtype=datatypeAR) imageList = alignmentResults['FileName'] tilt_angles = alignmentResults['TiltAngle'] imdim = read_size(imageList[0], 'x') if binning > 1: imdim = int(float(imdim) / float(binning) + .5) else: imdim = imdim sliceWidth = imdim if (weighting != None) and (float(weighting) < -0.001): weightSlice = xp.fft.fftshift(ramp_filter(imdim, imdim)) if circleFilter: circleFilterRadius = imdim // 2 circleSlice = xp.fft.fftshift( circle_filter(imdim, imdim, circleFilterRadius)) else: circleSlice = xp.ones((imdim, imdim)) # design lowpass filter if lowpassFilter: if lowpassFilter > 1.: lowpassFilter = 1. print("Warning: lowpassFilter > 1 - set to 1 (=Nyquist)") # weighting filter: arguments: (()dimx, dimy), cutoff radius, sigma lpf = xp.fft.fftshift( create_circle((imdim, imdim), lowpassFilter * (imdim // 2), sigma=0.4 * lowpassFilter * (imdim // 2))) projectionList = ProjectionList() for n, image in enumerate(imageList): atx = alignmentResults['AlignmentTransX'][n] / binning aty = alignmentResults['AlignmentTransY'][n] / binning rot = alignmentResults['InPlaneRotation'][n] mag = 1 / alignmentResults['Magnification'][n] projection = Projection(imageList[n], tiltAngle=tilt_angles[n], alignmentTransX=atx, alignmentTransY=aty, alignmentRotation=rot, alignmentMagnification=mag) projectionList.append(projection) stack = xp.zeros((imdim, imdim, len(imageList)), dtype=xp.float32) phiStack = xp.zeros((1, 1, len(imageList)), dtype=xp.float32) thetaStack = xp.zeros((1, 1, len(imageList)), dtype=xp.float32) offsetStack = xp.zeros((1, 2, len(imageList)), dtype=xp.float32) for (ii, projection) in enumerate(projectionList): print(f'Align {projection._filename}') image = read(str(projection._filename))[::binning, ::binning].squeeze() if lowpassFilter: image = xp.abs((xp.fft.ifftn(xp.fft.fftn(image) * lpf))) tiltAngle = projection._tiltAngle # normalize to contrast - subtract mean and norm to mean immean = 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 transX = projection._alignmentTransX / binning transY = projection._alignmentTransY / binning rot = float(projection._alignmentRotation) mag = float(projection._alignmentMagnification) inputImage = xp.expand_dims(image, 2).copy() outputImage = xp.zeros_like(inputImage, dtype=xp.float32) vt.transform(inputImage.astype(xp.float32), rotation=[0, 0, rot], rotation_order='rxyz', output=outputImage, device=device, translation=[transX, transY, 0], scale=[mag, mag, 1], interpolation='filt_bspline') image = outputImage.squeeze() # 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 = xp.fft.ifftn( xp.fft.fftn(image) * weightSlice * circleSlice) elif (weighting != None) and (weighting > 0): weightSlice = xp.fft.fftshift( exact_filter(tilt_angles, tiltAngle, imdim, imdim, sliceWidth)) image = xp.fft.ifftn( xp.fft.fftn(image) * weightSlice * circleSlice) thetaStack[0, 0, ii] = int(round(projection.getTiltAngle())) offsetStack[0, :, ii] = xp.array([ int(round(projection.getOffsetX())), int(round(projection.getOffsetY())) ]) stack[:, :, ii] = image arrays = [] for fname, arr in (('stack.mrc', stack), ('offsetStack.mrc', offsetStack), ('thetaStack.mrc', thetaStack), ('phiStack.mrc', phiStack)): if 'gpu' in device: arr = arr.get() import numpy as np res = npy2vol(np.array(arr, dtype='float32', order='F'), 3) arrays.append(res) # # write('stack.mrc', stack) # stack = readCVol('stack.mrc') # write('offsetstack.mrc', offsetStack) # offsetStack = readCVol('offsetstack.mrc') # write('thetastack.mrc', thetaStack) # thetaStack = readCVol('thetastack.mrc') # write('phistack.mrc', phiStack) # phiStack = readCVol('phistack.mrc') # # os.remove('stack.mrc') # os.remove('offsetstack.mrc') # os.remove('thetastack.mrc') # os.remove('psistack.mrc') return arrays
def alignImageUsingAlignmentResultFile(alignmentResultsFile, indexImage, weighting=None, lowpassFilter=0.9, binning=1, circleFilter=False): import pytom_freqweight from pytom_numpy import vol2npy from pytom.gui.guiFunctions import fmtAR, headerAlignmentResults, datatype, datatypeAR, loadstar from pytom.reconstruction.reconstructionStructures import Projection, ProjectionList from pytom.tompy.io import read, write, read_size from pytom.tompy.tools import taper_edges, create_circle from pytom.tompy.filter import circle_filter, ramp_filter, exact_filter, ellipse_filter import pytom.voltools as vt from pytom.gpu.initialize import xp, device # print("Create aligned images from alignResults.txt") alignmentResults = loadstar(alignmentResultsFile, dtype=datatypeAR) imageList = alignmentResults['FileName'] tilt_angles = alignmentResults['TiltAngle'] imdimX = read_size(imageList[0], 'x') imdimY = read_size(imageList[0], 'y') if binning > 1: imdimX = int(float(imdimX) / float(binning) + .5) imdimY = int(float(imdimY) / float(binning) + .5) sliceWidth = imdimX if (weighting != None) and (float(weighting) < -0.001): weightSlice = xp.fft.fftshift(ramp_filter(imdimY, imdimX)) if circleFilter: circleFilterRadiusX = imdimX // 2 circleFilterRadiusY = imdimY // 2 circleSlice = xp.fft.fftshift( ellipse_filter(imdimX, imdimY, circleFilterRadiusX, circleFilterRadiusY)) else: circleSlice = xp.ones((imdimX, imdimY)) # design lowpass filter if lowpassFilter: if lowpassFilter > 1.: lowpassFilter = 1. print("Warning: lowpassFilter > 1 - set to 1 (=Nyquist)") # weighting filter: arguments: (()dimx, dimy), cutoff radius, sigma # lpf = xp.fft.fftshift(create_circle((imdimX,imdimY),lowpassFilter*(imdim//2), sigma=0.4*lowpassFilter*(imdim//2))) projectionList = ProjectionList() for n, image in enumerate(imageList): atx = alignmentResults['AlignmentTransX'][n] aty = alignmentResults['AlignmentTransY'][n] rot = alignmentResults['InPlaneRotation'][n] mag = 1 / (alignmentResults['Magnification'][n]) projection = Projection(imageList[n], tiltAngle=tilt_angles[n], alignmentTransX=atx, alignmentTransY=aty, alignmentRotation=rot, alignmentMagnification=mag) projectionList.append(projection) imdim = min(imdimY, imdimX) for (ii, projection) in enumerate(projectionList): if not ii == indexImage: continue from pytom.tompy.transform import resize # print(f'read {projection._filename}') image = read(str(projection._filename)).squeeze() if binning > 1: image = resize(image, 1 / binning) #write(f'test/image_{ii}.mrc', image, tilt_angle=tilt_angles[ii]) tiltAngle = projection._tiltAngle # 1 -- normalize to contrast - subtract mean and norm to mean immean = image.mean() image = (image - immean) / immean # 2 -- smoothen borders to prevent high contrast oscillations image = taper_edges(image, imdim // 30)[0] # 3 -- square if needed if 0 and imdimY != imdimX: newImage = xp.zeros((imdim, imdim, 1), dtype=xp.float32) pasteCenter(image, newImage) image = newImage # 4 -- transform projection according to tilt alignment transX = projection._alignmentTransX / binning transY = projection._alignmentTransY / binning rot = float(projection._alignmentRotation) mag = float(projection._alignmentMagnification) inputImage = xp.expand_dims(image, 2).copy() outputImage = xp.zeros_like(inputImage, dtype=xp.float32) vt.transform( inputImage.astype(xp.float32), rotation=[0, 0, rot], rotation_order='rxyz', output=outputImage, center=[inputImage.shape[0] // 2, inputImage.shape[1] // 2, 0], device=device, translation=[transX, transY, 0], scale=[mag, mag, 1], interpolation='filt_bspline') del image image = outputImage.squeeze() # 5 -- Optional Low Pass Filter if lowpassFilter: from pytom.tompy.filter import bandpass_circle image = bandpass_circle( image, high=lowpassFilter * (min(imdimX, imdimY) // 2), sigma=0.4 * lowpassFilter * (min(imdimX, imdimY) // 2)) # image = xp.abs((xp.fft.ifftn(xp.fft.fftn(image) * lpf))) # 6 -- smoothen once more to avoid edges image = taper_edges(image, imdim // 30)[0] # 7 -- analytical weighting if (weighting != None) and (weighting < 0): # image = (ifft(complexRealMult(fft(image), w_func)) / (image.sizeX() * image.sizeY() * image.sizeZ())) image = xp.fft.ifftn( xp.fft.fftn(image) * weightSlice.T * circleSlice).real elif (weighting != None) and (weighting > 0): weightSlice = xp.fft.fftshift( exact_filter(tilt_angles, tiltAngle, imdim, imdim, sliceWidth)) image = xp.fft.ifftn( xp.fft.fftn(image) * weightSlice * circleSlice).real del inputImage, outputImage, circleSlice write(f'inputImage_{ii}.mrc', image) return image.astype(xp.float32)
def scale(volume, factor, interpolation='Spline'): """ scale: Scale a volume by a factor in REAL SPACE - see also resize function for more accurate operation in Fourier \ space @param volume: input volume @type volume: L{pytom_volume.vol} @param factor: a factor > 0. Factors < 1 will de-magnify the volume, factors > 1 will magnify. @type factor: L{float} @param interpolation: Can be Spline (default), Cubic or Linear @type interpolation: L{str} @return: The scaled volume @author: Thomas Hrabe """ from pytom.voltools import transform from pytom.tompy.tools import paste_in_center if factor <= 0: raise RuntimeError('Scaling factor must be > 0!') interpolation_dict = { 'Spline': 'filt_bspline', 'Linear': 'linear', 'Cubic': 'filt_bspline', 'filt_bspline': 'filt_bspline', 'linear': 'linear' } interpolation = interpolation_dict[interpolation] volume = volume.squeeze() sizeX = volume.shape[0] sizeY = volume.shape[1] sizeZ = 1 newSizeX = int(xp.floor(sizeX * float(factor) + 0.5)) newSizeY = int(xp.floor(sizeY * float(factor) + 0.5)) newSizeZ = 1 if len(volume.shape) == 3: sizeZ = volume.shape[2] newSizeZ = int(xp.floor(sizeZ * factor + 0.5)) scaleF = [1 / factor, 1 / factor, 1 / factor] else: scaleF = [1 / factor, 1 / factor, 1] volume = xp.expand_dims(volume, 2) if factor == 1: rescaledVolume = volume elif factor > 1: newVolume = xp.zeros((newSizeX, newSizeY, newSizeZ), dtype=volume.dtype) newVolume = paste_in_center(volume, newVolume) rescaledVolume = xp.zeros_like(newVolume) transform(newVolume, scale=scaleF, output=rescaledVolume, device=device, interpolation=interpolation) else: rescaledVolumeFull = xp.zeros_like(volume) transform(volume, scale=scaleF, output=rescaledVolumeFull, device=device, interpolation=interpolation) rescaledVolume = xp.zeros((newSizeX, newSizeY, newSizeZ), dtype=volume.dtype) rescaledVolume = paste_in_center(rescaledVolumeFull, rescaledVolume) return rescaledVolume
def alignVolumesAndFilterByFSC(vol1, vol2, mask=None, nband=None, iniRot=None, iniTrans=None, interpolation='linear', fsc_criterion=0.143, verbose=0): """ align two volumes, compute their FSC, and filter by FSC @param vol1: volume 1 @param vol2: volume 2 @mask: mask volume @type mask: L{pytom_volume.vol} @param nband: Number of bands @type nband: L{int} @param iniRot: initial guess for rotation @param iniTrans: initial guess for translation @param interpolation: interpolation type - 'linear' (default) or 'spline' @param fsc_criterion: filter -> 0 according to resolution criterion @type fsc_criterion: float @param verbose: verbose level (0=mute, 1 some output, 2=talkative) @type verbose: int @type interpolation: str @return: (filvol1, filvol2, fsc, fsc_fil, optiRot, optiTrans) i.e., filtered volumes, their FSC, the corresponding\ filter that was applied to the volumes, and the optimal rotation and translation of vol2 with respect to vol1\ note: filvol2 is NOT rotated and translated! @author: FF """ from pytom_volume import transformSpline, vol from pytom.tompy.correlation import FSC from pytom.tompy.filter import filter_volume_by_profile from pytom.tompy.structures import Alignment from pytom.tompy.correlation import nxcc from pytom.voltools import transform assert isinstance(object=vol1, class_or_type_or_tuple=vol ), "alignVolumesAndFilterByFSC: vol1 must be of type vol" assert isinstance(object=vol2, class_or_type_or_tuple=vol ), "alignVolumesAndFilterByFSC: vol2 must be of type vol" # filter volumes prior to alignment according to SNR fsc = FSC(volume1=vol1, volume2=vol2, numberBands=nband) fil = design_fsc_filter(fsc=fsc, fildim=int(vol2.shape[2] // 2)) #filter only one volume so that resulting CCC is weighted by SNR only once filvol2 = filter_volume_by_profile(volume=vol2, profile=fil) # align vol2 to vol1 if verbose == 2: alignment = Alignment(vol1=vol1, vol2=filvol2, score=nxcc, mask=mask, iniRot=iniRot, iniTrans=iniTrans, opti='fmin_powell', interpolation=interpolation, verbose=verbose) else: alignment = Alignment(vol1=vol1, vol2=filvol2, score=nxcc, mask=mask, iniRot=iniRot, iniTrans=iniTrans, opti='fmin_powell', interpolation=interpolation, verbose=False) optiScore, optiRot, optiTrans = alignment.localOpti(iniRot=iniRot, iniTrans=iniTrans) if verbose: from pytom.angles.angleFnc import differenceAngleOfTwoRotations from pytom.basic.structures import Rotation diffAng = differenceAngleOfTwoRotations(rotation1=Rotation(0, 0, 0), rotation2=optiRot) print( "Alignment densities: Rotations: %2.3f, %2.3f, %2.3f; Translations: %2.3f, %2.3f, %2.3f " % (optiRot[0], optiRot[1], optiRot[2], optiTrans[0], optiTrans[1], optiTrans[2])) print("Orientation difference: %2.3f deg" % diffAng) vol2_alig = xp.zeros(vol2.shape, dtype=xp.float32) transform(vol2, output=vol2_alig, rotation=[optiRot[0], optiRot[2], optiRot[1]], rotation_order='rzxz', center=[ int(vol2.shape[0] // 2), int(vol2.shape[1] // 2), int(vol2.shape[2] // 2) ], interpolation='filt_bspline', translation=[optiTrans[0], optiTrans[1], optiTrans[2]], device=device) # finally compute FSC and filter of both volumes if not nband: nband = int(vol2.sizeX() / 2) fsc = FSC(volume1=vol1, volume2=vol2_alig, numberBands=nband) fil = design_fsc_filter(fsc=fsc, fildim=int(vol2.shape[0] // 2), fsc_criterion=fsc_criterion) filvol1 = filter_volume_by_profile(volume=vol1, profile=fil) #filvol2 = filter_volume_by_profile( volume=vol2_alig, profile=fil) filvol2 = filter_volume_by_profile(volume=vol2, profile=fil) return (filvol1, filvol2, fsc, fil, optiRot, optiTrans)