def test_resize2D(self): """ test re-sizing in Fourier space """ from pytom.basic.transformations import resize from pytom_volume import vol from pytom.basic.fourier import fft dim = 32 px = 11 py = 19 scf = dim * dim myVol = vol(dim, dim, 1) myVol.setAll(0.) myVol.setV(1., px, py, 0) #fmyVol = fft(myVol) (resizeVol, resizefVol) = resize(volume=myVol, factor=2., interpolation='Fourier') resizeVol.write('test1.em') ftresizeVol = fft(data=resizeVol) for ix in range(resizefVol.sizeX()): for iy in range(resizefVol.sizeY()): diff = ftresizeVol.getV( ix, iy, 0) - scf * 4 * resizefVol.getV(ix, iy, 0) self.assertTrue(expr=abs(diff) < .05, msg="inconsistency FFT/IFFT for magnification") (resizeVol, resizefVol) = resize(volume=resizeVol, factor=.5, interpolation='Fourier') from pytom_volume import variance diff = myVol - resizeVol self.assertTrue(expr=variance(diff, False) < .0000001, msg="2D image before and after rescales differs")
def test_resize3D(self): """ test 3D re-sizing in Fourier space """ from pytom.basic.transformations import resize from pytom_volume import vol dim = 32 px = 11 py = 19 pz = 21 myVol = vol(dim, dim, dim) myVol.setAll(0.) myVol.setV(1., px, py, pz) (resizeVol, resizefVol) = resize(volume=myVol, factor=2., interpolation='Fourier') (resizeVol, resizefVol) = resize(volume=resizeVol, factor=.5, interpolation='Fourier') from pytom_volume import variance diff = myVol - resizeVol self.assertTrue(expr=variance(diff, False) < .0000001, msg="2D image before and after rescales differs")
def paverage(particleList, norm, binning, verbose, outdir='./'): from pytom_volume import read, vol from pytom_volume import transformSpline as transform from pytom.basic.structures import Particle from pytom.basic.normalise import mean0std1 from pytom.tools.ProgressBar import FixedProgBar from pytom.basic.transformations import resize if len(particleList) == 0: raise RuntimeError('The particlelist provided is empty. Aborting!') if verbose: progressBar = FixedProgBar(0, len(particleList), 'Particles averaged ') progressBar.update(0) numberAlignedParticles = 0 result = None wedgeSum = None newParticle = None for particleObject in particleList: particle = read(particleObject.getFilename(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1) if binning != 1: particle, particlef = resize(volume=particle, factor=1. / binning, interpolation='Fourier') if norm: mean0std1(particle) wedgeInfo = particleObject.getWedge() if result is None: # initialization sizeX = particle.sizeX() sizeY = particle.sizeY() sizeZ = particle.sizeZ() newParticle = vol(sizeX, sizeY, sizeZ) centerX = sizeX // 2 centerY = sizeY // 2 centerZ = sizeZ // 2 result = vol(sizeX, sizeY, sizeZ) result.setAll(0.0) wedgeSum = wedgeInfo.returnWedgeVolume(sizeX, sizeY, sizeZ) wedgeSum.setAll(0) # create spectral wedge weighting rotation = particleObject.getRotation() wedge = wedgeInfo.returnWedgeVolume(sizeX, sizeY, sizeZ, False, rotation.invert()) wedgeSum += wedge # shift and rotate particle shiftV = particleObject.getShift() newParticle.setAll(0) transform(particle, newParticle, -rotation[1], -rotation[0], -rotation[2], centerX, centerY, centerZ, -shiftV[0] // binning, -shiftV[1] // binning, -shiftV[2] // binning, 0, 0, 0) result += newParticle if verbose: numberAlignedParticles = numberAlignedParticles + 1 progressBar.update(numberAlignedParticles) # write to the disk fname_result = os.path.join(outdir, 'avg_{}.em'.format(mpi.rank)) fname_wedge = os.path.join(outdir, 'wedge_{}.em'.format(mpi.rank)) result.write(fname_result) result = Particle(fname_result) wedgeSum.write(fname_wedge) wedgeSum = Particle(fname_wedge) return (result, wedgeSum)
def bestAlignment(particle, reference, referenceWeighting, wedgeInfo, rotations, scoreObject=0, mask=None, preprocessing=None, progressBar=False, binning=1, bestPeak=None, verbose=False): """ bestAlignment: Determines best alignment of particle relative to the reference @param particle: A particle @type particle: L{pytom_volume.vol} @param reference: A reference @type reference: L{pytom_volume.vol} @param referenceWeighting: Fourier weighting of the reference (sum of wedges for instance) @type referenceWeighting: L{pytom.basic.structures.vol} @param wedgeInfo: What does the wedge look alike? @type wedgeInfo: L{pytom.basic.structures.Wedge} @param rotations: All rotations to be scanned @type rotations: L{pytom.angles.AngleObject} @param scoreObject: @type scoreObject: L{pytom.score.score.Score} @param mask: real-space mask for correlation function @type mask: L{pytom.basic.structures.Particle} @param preprocessing: Class storing preprocessing of particle and reference such as bandpass @type preprocessing: L{pytom.alignment.preprocessing.Preprocessing} @param progressBar: Display progress bar of alignment. False by default. @param binning: binning factor - e.g. binning=2 reduces size by FACTOR of 2 @type binning: int or float @param bestPeak: Initialise best peak with old values. @param verbose: Print out infos. Writes CC volume to disk!!! Default is False @return: Returns the best rotation for particle and the corresponding scoring result. @author: Thomas Hrabe """ from pytom.basic.correlation import subPixelPeak, subPixelPeakParabolic from pytom.alignment.structures import Peak from pytom_volume import peak, vol, vol_comp from pytom.basic.filter import filter,rotateWeighting from pytom.basic.structures import Rotation, Shift, Particle, Mask from pytom.angles.angle import AngleObject from pytom.alignment.preprocessing import Preprocessing from pytom.basic.transformations import resize, resizeFourier binningType = 'Fourier' # or 'Fourier' assert isinstance(rotations, AngleObject), "bestAlignment: rotations must be " \ "AngleObject!" currentRotation = rotations.nextRotation() if currentRotation == [None,None,None]: raise Exception('bestAlignment: No rotations are sampled! Something is wrong with input rotations') assert particle.__class__ == vol, "particle not of type vol" assert reference.__class__ == vol, "reference not of type vol" assert (referenceWeighting.__class__ == vol or referenceWeighting.__class__ == str), \ "referenceWeighting not volume or str" if mask: assert mask.__class__ == Mask, "Mask not of type Mask" m = mask.getVolume() if scoreObject == 0 or not scoreObject: from pytom.score.score import xcfScore scoreObject = xcfScore() # fix binning if binning == 0: binning = 1 if binning != 1: particleUnbinned = vol(particle.sizeX(), particle.sizeY(), particle.sizeZ()) particleUnbinned.copyVolume(particle) particle = resize(volume=particle, factor=1./binning, interpolation=binningType) if type(particle) == tuple: particle = particle[0] referenceUnbinned = vol(reference.sizeX(), reference.sizeY(), reference.sizeZ()) referenceUnbinned.copyVolume(reference) reference = resize(volume=reference, factor=1./binning, interpolation=binningType) if type(reference) == tuple: reference = reference[0] if mask: m = resize(volume=m, factor=1./binning, interpolation='Spline') if not referenceWeighting.__class__ == str: referenceWeightingUnbinned = vol_comp(referenceWeighting.sizeX(), referenceWeighting.sizeY(), referenceWeighting.sizeZ()) referenceWeightingUnbinned.copyVolume(referenceWeighting) if binning != 1: referenceWeighting = resizeFourier(fvol=referenceWeighting, factor=1./binning) centerX, centerY, centerZ = int(particle.sizeX()/2), int(particle.sizeY()/2), int(particle.sizeZ()/2) # create buffer volume for transformed particle particleCopy = vol(particle.sizeX(),particle.sizeY(),particle.sizeZ()) particle = wedgeInfo.apply(particle) #apply wedge to itself if preprocessing is None: preprocessing = Preprocessing() preprocessing.setTaper( taper=particle.sizeX()/10.) particle = preprocessing.apply(volume=particle, bypassFlag=True) # filter particle to some resolution particleCopy.copyVolume(particle) # compute standard veviation volume really only if needed if mask and (scoreObject._type=='FLCFScore'): from pytom_volume import sum from pytom.basic.correlation import meanUnderMask, stdUnderMask p = sum(m) meanV = meanUnderMask(particle, m, p) stdV = stdUnderMask(particle, m, p, meanV) else: meanV = None stdV = None while currentRotation != [None,None,None]: if mask: m = mask.getVolume(currentRotation) if binning != 1: m = resize(volume=m, factor=1./binning, interpolation='Spline') #update stdV if mask is not a sphere # compute standard deviation volume really only if needed if not mask.isSphere() and (scoreObject._type=='FLCFScore'): meanV = meanUnderMask(particle, m, p) stdV = stdUnderMask(particle, m, p, meanV) else: m = None simulatedVol = _rotateWedgeReference(reference, currentRotation, wedgeInfo, m, [centerX, centerY, centerZ]) simulatedVol = preprocessing.apply(volume=simulatedVol, bypassFlag=True) #weight particle if not referenceWeighting.__class__ == str: from pytom_freqweight import weight weightingRotated = rotateWeighting(weighting=referenceWeighting, z1=currentRotation[0], z2=currentRotation[1], x=currentRotation[2], isReducedComplex=True, returnReducedComplex=True, binarize=False) particleCopy.copyVolume(particle) r = list(filter(particleCopy, weight(weightingRotated))) particleCopy = r[0] scoringResult = scoreObject.score(particleCopy, simulatedVol, m, stdV) pk = peak(scoringResult) #with subPixelPeak [peakValue,peakPosition] = subPixelPeak(scoreVolume=scoringResult, coordinates=pk, interpolation='Quadratic', verbose=False) #[peakValue,peakPosition] = subPixelPeakParabolic(scoreVolume=scoringResult, coordinates=pk, verbose=False) # determine shift relative to center shiftX = (peakPosition[0] - centerX) * binning shiftY = (peakPosition[1] - centerY) * binning shiftZ = (peakPosition[2] - centerZ) * binning #NANs would fail this test. assert peakValue == peakValue, "peakValue seems to be NaN" newPeak = Peak(peakValue, Rotation(currentRotation), Shift(shiftX, shiftY, shiftZ)) if verbose: print('Rotation: z1=%3.1f, z2=%3.1f, x=%3.1f; Dx=%2.2f, Dy=%2.2f, Dz=%2.2f, CC=%2.3f' % \ (currentRotation[0], currentRotation[1], currentRotation[2], shiftX, shiftY, shiftZ, peakValue)) if bestPeak is None: bestPeak = newPeak if verbose: scoringResult.write('BestScore.em') if bestPeak < newPeak: bestPeak = newPeak if verbose: scoringResult.write('BestScore.em') currentRotation = rotations.nextRotation() # repeat ccf for binned sampling to get translation accurately if binning != 1: m = mask.getVolume(bestPeak.getRotation()) centerX, centerY, centerZ = int(particleUnbinned.sizeX()/2), int(particleUnbinned.sizeY()/2), \ int(particleUnbinned.sizeZ()/2) simulatedVol = _rotateWedgeReference(referenceUnbinned, bestPeak.getRotation(), wedgeInfo, m, [centerX, centerY, centerZ]) simulatedVol = preprocessing.apply(volume=simulatedVol, bypassFlag=True) if mask and scoreObject._type=='FLCFScore': p = sum(m) meanV = meanUnderMask(volume=particleUnbinned, mask=m, p=p) stdV = stdUnderMask(volume=particleUnbinned, mask=m, p=p, meanV=meanV) scoreObject._peakPrior.reset_weight() scoringResult = scoreObject.score(particle=particleUnbinned, reference=simulatedVol, mask=m, stdV=stdV) pk = peak(scoringResult) [peakValue,peakPosition] = subPixelPeak(scoreVolume=scoringResult, coordinates=pk, interpolation='Quadratic', verbose=False) shiftX = (peakPosition[0] - centerX) shiftY = (peakPosition[1] - centerY) shiftZ = (peakPosition[2] - centerZ) bestPeak = Peak(peakValue, bestPeak.getRotation(), Shift(shiftX, shiftY, shiftZ)) if verbose: print('BestAlignment: z1=%3.1f, z2=%3.1f, x=%3.1f; Dx=%2.2f, Dy=%2.2f, Dz=%2.2f, CC=%2.3f' % \ (bestPeak.getRotation()[0], bestPeak.getRotation()[1], bestPeak.getRotation()[2], bestPeak.getShift()[0], bestPeak.getShift()[1], bestPeak.getShift()[2], bestPeak.getScoreValue())) rotations.reset() scoreObject._peakPrior.reset_weight() return bestPeak
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 run(self, verbose=False): from sh_alignment.frm import frm_align from sh_alignment.constrained_frm import frm_constrained_align, AngularConstraint from pytom.basic.structures import Shift, Rotation from pytom.tools.ProgressBar import FixedProgBar from pytom.basic.transformations import resize, resizeFourier binningType = 'Fourier' while True: # get the job try: job = self.get_job() except: if verbose: print(self.node_name + ': end') break # get some non-job message, break it if verbose: prog = FixedProgBar(0, len(job.particleList) - 1, self.node_name + ':') i = 0 ref = job.reference.getVolume() if job.binning > 1: ref = resize(volume=ref, factor=1. / job.binning, interpolation=binningType) if type(ref) == tuple: ref = ref[0] # re-set max frequency in case it exceeds Nyquist - a bit brute force job.freq = min(job.freq, ref.sizeX() // 2 - 1) # run the job for p in job.particleList: if verbose: prog.update(i) i += 1 v = p.getVolume() if job.binning > 1: v = resize(volume=v, factor=1. / job.binning, interpolation=binningType) if type(v) == tuple: v = v[0] mask = job.mask.getVolume() if job.binning > 1: mask = resize(volume=mask, factor=1. / job.binning, interpolation='Spline') if type(mask) == tuple: mask = mask[0] if job.constraint: constraint = job.constraint if job.constraint.type == AngularConstraint.ADP_ANGLE: # set the constraint around certain angle rot = p.getRotation() constraint.setAngle(rot.getPhi(), rot.getPsi(), rot.getTheta()) #pos, angle, score = frm_constrained_align(v, p.getWedge(), ref, None, job.bw_range, job.freq, job.peak_offset, job.mask.getVolume(), constraint) if job.binning > 1: pos, angle, score = frm_constrained_align( v, p.getWedge(), ref, None, job.bw_range, job.freq, job.peak_offset / job.binning, mask, constraint) else: pos, angle, score = frm_constrained_align( v, p.getWedge(), ref, None, job.bw_range, job.freq, job.peak_offset, mask, constraint) else: #pos, angle, score = frm_align(v, p.getWedge(), ref, None, job.bw_range, job.freq, job.peak_offset, job.mask.getVolume()) #if job.binning >1: # print(job.peak_offset) # print(type(job.peak_offset)) # print(job.peak_offset/job.binning) # print(type(job.binning)) # pos, angle, score = frm_align(v, p.getWedge(), ref, None, job.bw_range, job.freq, # job.peak_offset/job.binning, mask) #else: pos, angle, score = frm_align(v, p.getWedge(), ref, None, job.bw_range, job.freq, job.peak_offset, mask) if job.binning > 1: pos[0] = job.binning * (pos[0] - v.sizeX() / 2) pos[1] = job.binning * (pos[1] - v.sizeY() / 2) pos[2] = job.binning * (pos[2] - v.sizeZ() / 2) p.setShift(Shift([pos[0], pos[1], pos[2]])) else: p.setShift( Shift([ pos[0] - v.sizeX() / 2, pos[1] - v.sizeY() / 2, pos[2] - v.sizeZ() / 2 ])) p.setRotation(Rotation(angle)) p.setScore(FRMScore(score)) # average the particle list name_prefix = os.path.join( job.destination, self.node_name + '_' + str(job.max_iter)) self.average_sub_pl(job.particleList, name_prefix, job.weighting) # send back the result self.send_result( FRMResult(name_prefix, job.particleList, self.mpi_id)) pytom_mpi.finalise()
def subPixelPeak(scoreVolume, coordinates, cubeLength=8, interpolation='Spline', verbose=False): """ subPixelPeak: Will determine the sub pixel area of peak. Utilizes spline, fourier or parabolic interpolation. @param verbose: be talkative @type verbose: L{str} @param scoreVolume: The score volume @param coordinates: [x,y,z] coordinates where the sub pixel peak will be determined @param cubeLength: length of cube - only used for Spline and Fourier interpolation @type cubeLength: int (even) @param interpolation: interpolation type: 'Spline', 'Quadratic', or 'Fourier' @type interpolation: str @return: Returns [peakValue,peakCoordinates] with sub pixel accuracy last change: 02/07/2013 FF: 2D functionality added """ assert type( interpolation) == str, 'subPixelPeak: interpolation must be str' if (interpolation.lower() == 'quadratic') or (interpolation.lower() == 'parabolic'): (peakValue, peakCoordinates) = subPixelPeakParabolic(scoreVolume=scoreVolume, coordinates=coordinates, verbose=verbose) return [peakValue, peakCoordinates] if gpu: import cupy as xp else: import numpy as xp from pytom_volume import vol, subvolume, rescaleSpline, peak from pytom.basic.transformations import resize #extend function for 2D twoD = (scoreVolume.shape) == 2 cubeStart = cubeLength // 2 sizeX = scoreVolume.sizeX() sizeY = scoreVolume.sizeY() sizeZ = scoreVolume.sizeZ() if twoD: if (coordinates[0]-cubeStart < 1 or coordinates[1]-cubeStart < 1) or\ (coordinates[0]-cubeStart + cubeLength >= sizeX or coordinates[1]-cubeStart + cubeLength >= sizeY): if verbose: print( "SubPixelPeak: position too close to border for sub-pixel") return [ scoreVolume(coordinates[0], coordinates[1], coordinates[2]), coordinates ] subVolume = subvolume(scoreVolume, coordinates[0] - cubeStart, coordinates[1] - cubeStart, 0, cubeLength, cubeLength, 1) else: if (coordinates[0]-cubeStart < 1 or coordinates[1]-cubeStart < 1 or coordinates[2]-cubeStart < 1) or \ (coordinates[0]-cubeStart + cubeLength >= sizeX or coordinates[1]-cubeStart + cubeLength >= sizeY or \ coordinates[2]-cubeStart + cubeLength >= sizeZ): if verbose: print( "SubPixelPeak: position too close to border for sub-pixel") return [ scoreVolume(coordinates[0], coordinates[1], coordinates[2]), coordinates ] subVolume = subvolume(scoreVolume, coordinates[0] - cubeStart, coordinates[1] - cubeStart, coordinates[2] - cubeStart, cubeLength, cubeLength, cubeLength) #size of interpolated volume scaleSize = 10 * cubeLength #ratio between interpolation area and large volume scaleRatio = 1.0 * cubeLength / scaleSize #resize into bigger volume if interpolation == 'Spline': if twoD: subVolumeScaled = vol(scaleSize, scaleSize, 1) else: subVolumeScaled = vol(scaleSize, scaleSize, scaleSize) rescaleSpline(subVolume, subVolumeScaled) else: subVolumeScaled = resize(volume=subVolume, factor=10)[0] peakCoordinates = peak(subVolumeScaled) peakValue = subVolumeScaled(peakCoordinates[0], peakCoordinates[1], peakCoordinates[2]) #calculate sub pixel coordinates of interpolated peak peakCoordinates[ 0] = peakCoordinates[0] * scaleRatio - cubeStart + coordinates[0] peakCoordinates[ 1] = peakCoordinates[1] * scaleRatio - cubeStart + coordinates[1] if twoD: peakCoordinates[2] = 0 else: peakCoordinates[ 2] = peakCoordinates[2] * scaleRatio - cubeStart + coordinates[2] if (peakCoordinates[0] > scoreVolume.sizeX() or peakCoordinates[1] > scoreVolume.sizeY() or peakCoordinates[2] > scoreVolume.sizeZ()): if verbose: print( "SubPixelPeak: peak position too large :( return input value") #something went awfully wrong here. return regular value return [ scoreVolume(coordinates[0], coordinates[1], coordinates[2]), coordinates ] return [peakValue, peakCoordinates]