def test_FRM(self): import swig_frm from sh_alignment.frm import frm_align from pytom_volume import vol, rotate, shift from pytom.basic.structures import Rotation, Shift from pytom.tools.maths import rotation_distance v = vol(32,32,32) v.setAll(0) vMod = vol(32,32,32) vRot = vol(32,32,32) v.setV(1,10,10,10) v.setV(1,20,20,20) v.setV(1,15,15,15) v.setV(1,7,21,7) rotation = Rotation(10,20,30) shiftO = Shift(1,-3,5) rotate(v,vRot,rotation.getPhi(),rotation.getPsi(),rotation.getTheta()) shift(vRot,vMod,shiftO.getX(),shiftO.getY(),shiftO.getZ()) pos, ang, score = frm_align(vMod, None, v, None, [4, 64], 10) rotdist = rotation_distance(ang1=rotation, ang2=ang) diffx = shiftO[0] - (pos[0] - 16) diffy = shiftO[1] - (pos[1] - 16) diffz = shiftO[2] - (pos[2] - 16) self.assertTrue( rotdist < 5., msg='Rotations are different') self.assertTrue( diffx < .5, msg='x-difference > .5') self.assertTrue( diffy < .5, msg='y-difference > .5') self.assertTrue( diffz < .5, msg='z-difference > .5')
def fromXML(self, xmlObj): """ fromXML : Assigns values to result attributes from XML object @param xmlObj: A xml object @author: Thomas Hrabe """ from lxml.etree import _Element if xmlObj.__class__ != _Element: from pytom.basic.exceptions import ParameterError raise ParameterError( 'Is not a lxml.etree._Element! You must provide a valid XML object.' ) from pytom.score.score import fromXML as fromXMLScore from pytom.angles.angle import AngleObject if xmlObj.tag == "Result": result = xmlObj else: result = xmlObj.xpath('Result') if len(result) == 0: raise PyTomClassError( "This XML is not an MaximisationResult. No Result provided." ) result = result[0] from pytom.basic.structures import Particle, Reference, Rotation, Shift particle_element = result.xpath('Particle')[0] p = Particle('') p.fromXML(particle_element) self._particle = p r = result.xpath('Reference') ref = Reference('') ref.fromXML(r[0]) self._reference = ref scoreXML = result.xpath('Score')[0] self._score = fromXMLScore(scoreXML) shiftXML = result.xpath('Shift')[0] self._shift = Shift() self._shift.fromXML(shiftXML) rotationXML = result.xpath('Rotation')[0] self._rotation = Rotation() self._rotation.fromXML(rotationXML) angleElement = result.xpath('Angles') ang = AngleObject() self._angleObject = ang.fromXML(angleElement[0])
def __init__(self, particle='', reference=-1.0, score=-1.0, shift=-1.0, rotation=-1.0, angleObject=-1): from pytom.basic.structures import Particle, Reference, Shift, Rotation from numpy import long if particle.__class__ == str: self._particle = Particle(particle) elif particle.__class__ == Particle: self._particle = particle else: self._particle = Particle() if reference.__class__ == str: self._reference = Reference(reference) elif reference.__class__ == Reference: self._reference = reference else: self._reference = Reference() if shift.__class__ == list: self._shift = Shift(shift) elif shift.__class__ == float: self._shift = Shift() else: self._shift = shift if rotation.__class__ == list: self._rotation = Rotation(rotation) elif rotation.__class__ == Rotation: self._rotation = rotation else: self._rotation = Rotation() if score.__class__ == float: from pytom.score.score import xcfScore self._score = xcfScore() else: self._score = score if angleObject.__class__ == float or isinstance( angleObject, (int, long)): from pytom.angles.angleList import AngleList self._angleObject = AngleList() else: self._angleObject = angleObject
def getShift(self): from pytom.basic.structures import Shift if self._shift.__class__ == list: return Shift(self._shift) else: return self._shift
def frm_proxy(p, ref, freq, offset, binning, mask): from pytom_volume import read, pasteCenter, vol from pytom.basic.transformations import resize from pytom.basic.structures import Shift, Rotation from sh_alignment.frm import frm_align import time v = p.getVolume(binning) if mask.__class__ == str: maskBin = read(mask, 0, 0, 0, 0, 0, 0, 0, 0, 0, binning, binning, binning) if v.sizeX() != maskBin.sizeX() or v.sizeY() != maskBin.sizeY( ) or v.sizeZ() != maskBin.sizeZ(): mask = vol(v.sizeX(), v.sizeY(), v.sizeZ()) mask.setAll(0) pasteCenter(maskBin, mask) else: mask = maskBin pos, angle, score = frm_align(v, p.getWedge(), ref.getVolume(), None, [4, 64], freq, offset, mask) return (Shift([ pos[0] - v.sizeX() // 2, pos[1] - v.sizeY() // 2, pos[2] - v.sizeZ() // 2 ]), Rotation(angle), score, p.getFilename())
def general_transform2d(v, rot=None, shift=None, scale=None, order=[0, 1, 2], crop=True): """Perform general transformation of 2D data using 3rd order spline interpolation. @param v: volume in 2d (it's got to be an image) @type v: L{pytom_volume.vol} @param rot: rotate @type rot: float @param shift: shift @type shift: L{pytom.basic.structures.Shift} or list [x,y] @param scale: uniform scale @type scale: float @param order: the order in which the three operations are performed (smaller means first) \ e.g.: [2,1,0]: rotation: 2, scale: 1, translation:0 => translation 1st @type order: list @param crop: crop the resulting volume to have the same size as original volume (default: True) @type crop: boolean @return: pytom_volume """ from pytom.basic.structures import Shift from pytom_volume import vol if not isinstance(v,vol): if isinstance(v,tuple) and isinstance(v[0],vol): v = v[0] else: raise TypeError('general_transform2d: v must be of type pytom_volume.vol! Got ' + str(v.__class__) + ' instead!') if v.sizeZ() != 1: raise RuntimeError('general_transform2d: v must be 2D!') if rot is None: rot = [0., 0., 0.] elif rot.__class__ != int and rot.__class__ != float: raise RuntimeError("Please provide only 1 angle because you are dealing with 2D data!") else: rot = [rot, 0., 0.] if shift.__class__ == list and len(shift) == 2: shift = Shift(shift[0], shift[1], 0.) if shift.__class__ == list and len(shift) == 3: shift = Shift(shift[0], shift[1], 0.) # you cannot shift 2D image along z axis, can you? if crop: vv= general_transform_crop(v, rot=rot, shift=shift, scale=[scale, scale, 1], order=order) else: vv = general_transform(v, rot, shift, [scale, scale, 1], order) return vv
def writeCroppedParticles(particleListName, output, center, cubesize): """ @param particleListName: name of particle list @type particleListName: str @param output: Name of output particles @type output: str @param center: center of output particles in template orientation @type center: list @param cubesize: Size of output particles in pixel @type cubesize: int """ from pytom.basic.structures import ParticleList, Particle, Shift from pytom_volume import transformSpline as transform from pytom_volume import subvolume, vol pl = ParticleList() pl.fromXMLFile(filename=particleListName) #copy particle list for list of cropped particles pl_new = pl.copy() pvol = pl[0].getVolume() sizeX = pvol.sizeX() sizeY = pvol.sizeY() sizeZ = pvol.sizeZ() pvol_ali = vol(sizeX, sizeY, sizeZ) subV = vol(cubesize, cubesize, cubesize) sub_startX = center[0]-cubesize/2 sub_startY = center[1]-cubesize/2 sub_startZ = center[2]-cubesize/2 if (sub_startX < 0) or (sub_startY < 0) or (sub_startZ < 0): raise ValueError('cubesize too large :(') for (ipart, part) in enumerate(pl): pvol_ali.setAll(0) subV.setAll(0) pvol = part.getVolume() rot = part.getRotation() rotinvert = rot.invert() shiftV = part.getShift() transform(pvol, pvol_ali, rotinvert[0], rotinvert[1], rotinvert[2], sizeX/2, sizeY/2, sizeZ/2, -shiftV[0], -shiftV[1], -shiftV[2], 0, 0, 0) # box out subvolume subV = subvolume(pvol_ali, sub_startX, sub_startY, sub_startZ, cubesize, cubesize, cubesize) transform(subV, subV, rot[0], rot[1], rot[2], cubesize/2, cubesize/2, cubesize/2, 0, 0, 0, 0, 0, 0) fname = part.getFilename() idx = fname.split('_')[-1].split('.')[0] nfname = output+'_'+idx+'.em' print("write file " + nfname) subV.write(nfname) pl_new[ipart].setFilename(newFilename=nfname) pl_new[ipart].setShift(shift=Shift(0,0,0)) return pl_new
def run(self, verbose=False): from sh_alignment.frm import frm_align from pytom.basic.structures import Shift, Rotation from pytom.tools.ProgressBar import FixedProgBar 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[0].getVolume() # run the job for p in job.particleList: if verbose: prog.update(i) i += 1 v = p.getVolume() pos, angle, score = frm_align(v, p.getWedge(), ref, None, job.bw_range, job.freq, job.peak_offset, job.mask.getVolume()) 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( self.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 FRMAlignmentWrapper(particle,wedgeParticle, reference, wedgeReference,bandwidth, highestFrequency, mask = None , peakPrior = None): """ FRMAlignmentWrapper: Wrapper for frm_align to handle PyTom objects. @param particle: The particle @type particle: L{pytom.basic.structures.Particle} @param wedgeParticle: Wedge object of particle @type wedgeParticle: L{pytom.basic.structures.Wedge} @param reference: Reference used for alignment @type reference: L{pytom.basic.structures.Reference} @param wedgeReference: Information about reference wedge @type wedgeReference: L{pytom.basic.structures.Wedge} @param bandwidth: The bandwidth of the spherical harmonics - lowestBand used, highestBand used @type bandwidth: [lowestBand,highestBand] @param highestFrequency: Highest frequency for lowpass filter in fourierspace @type highestFrequency: int @param mask: Mask that is applied to the particle @type mask: L{pytom.basic.structures.Mask} @param peakPrior: Maximum distance of peak from origin @type peakPrior: L{pytom.score.score.PeakPrior} or an integer @return: Returns a list of [L{pytom.basic.structures.Shift}, L{pytom.basic.structures.Rotation}, scoreValue] """ from pytom.basic.structures import Particle,Reference,Mask,Wedge,Shift,Rotation from pytom.score.score import PeakPrior from sh_alignment.frm import frm_align if particle.__class__ == Particle: particle = particle.getVolume() if reference.__class__ == Reference: reference = reference.getVolume() if mask.__class__ == Mask: mask = mask.getVolume() else: mask = None if bandwidth.__class__ == list and len(bandwidth) != 2: raise RuntimeError('Bandwidth parameter must be a list of two integers!') if peakPrior and peakPrior.__class__ == PeakPrior: peakPrior = int(peakPrior.getRadius()) if not peakPrior or peakPrior < 0.0001: peakPrior = None pos, angle, score = frm_align(particle, wedgeParticle.getWedgeObject(), reference*mask, wedgeReference.getWedgeObject(), bandwidth, int(highestFrequency), peakPrior) return [Shift([pos[0]-particle.sizeX()/2, pos[1]-particle.sizeY()/2, pos[2]-particle.sizeZ()/2]), Rotation(angle), score]
def vector2transRot(self, rot_trans): """ convert 6-dimensional vector to rotation and translation @param rot_trans: rotation and translation vector (6-dim: z1,z2,x \ angles, x,y,z, translations) @type rot_trans: L{list} @return: rotation of vol2, translation of vol2 @rtype: L{pytom.basic.Rotation}, L{pytom.basic.Shift} @author: FF """ from pytom.basic.structures import Rotation, Shift rot = Rotation() trans = Shift() for ii in range(0, 3): rot[ii] = self.rot_trans[ii] for ii in range(3, 6): trans[ii - 3] = self.rot_trans[ii] return rot, trans
def run(self, verbose=False): from pytom.gui.additional.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 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() # run the job for p in job.particleList: if verbose: prog.update(i) i += 1 v = p.getVolume() 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) else: pos, angle, score = frm_align(v, p.getWedge(), ref, None, job.bw_range, job.freq, job.peak_offset, job.mask.getVolume()) 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 = 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 alignTwoVolumes(particle,reference,angleObject,mask,score,preprocessing,progressBar=False): """ alignTwoVolumes: align two volumes with respect to each other @param particle: volume to be aligned @param reference: reference volume (not translated and rotated) @param angleObject: angular sampling @param mask: mask volume @param score: score type @param preprocessing: preprocessing parameters @param progressBar: show progress bar @type progressBar: bool """ from pytom.alignment.structures import GrowingAverageInterimResult from pytom.basic.structures import Rotation,Shift partVolume = particle.getVolume() refVolume = reference.getVolume() refWeight = reference.getWeighting() peak = bestAlignment(partVolume,refVolume,refWeight,particle.getWedge(), angleObject,score,mask,preprocessing) score.setValue(peak.getScoreValue()) return GrowingAverageInterimResult(particle,reference,Rotation(peak.getRotation()),Shift(peak.getShift()),score)
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 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 run(self, verbose=False): from sh_alignment.frm import frm_align from pytom.basic.structures import Shift, Rotation from pytom.tools.ProgressBar import FixedProgBar from pytom.basic.fourier import convolute from pytom_volume import read, power 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 = [] ref.append(job.reference[0].getVolume()) ref.append(job.reference[1].getVolume()) # convolute with the approximation of the CTF if job.sum_ctf_sqr: ctf = read(job.sum_ctf_sqr) power(ctf, 0.5) # the number of CTFs should not matter, should it? ref0 = ref[0] ref1 = ref[1] ref0 = convolute(ref0, ctf, True) ref1 = convolute(ref1, ctf, True) ref = [ref0, ref1] if job.bfactor and job.bfactor != 'None': # restore_kernel = create_bfactor_restore_vol(ref.sizeX(), job.sampleInformation.getPixelSize(), job.bfactor) from pytom_volume import vol, read bfactor_kernel = read(job.bfactor) unit = vol(bfactor_kernel) unit.setAll(1) restore_kernel = unit / bfactor_kernel # run the job for p in job.particleList: if verbose: prog.update(i) i += 1 v = p.getVolume() # if weights is None: # create the weights according to the bfactor # if job.bfactor == 0: # weights = [1 for k in xrange(job.freq)] # else: # restore_fnc = create_bfactor_restore_fnc(ref.sizeX(), job.sampleInformation.getPixelSize(), job.bfactor) # # cut out the corresponding part and square it to get the weights! # weights = restore_fnc[1:job.freq+1]**2 if job.bfactor and job.bfactor != 'None': v = convolute(v, restore_kernel, True) # if bfactor is set, restore it pos, angle, score = frm_align(v, p.getWedge(), ref[int(p.getClass())], None, job.bw_range, job.freq, job.peak_offset, job.mask.getVolume()) 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 = self.node_name + '_' + str(job.max_iter) pair = ParticleListPair('', job.ctf_conv_pl, None, None) pair.set_phase_flip_pl(job.particleList) self.average_sub_pl( pair.get_ctf_conv_pl(), name_prefix) # operate on the CTF convoluted projection! # send back the result self.send_result( FRMResult(name_prefix, job.particleList, self.mpi_id)) pytom_mpi.finalise()
def create_RandomParticleList(reffile, pl_filename='pl.xml', pdir='./testparticles', nparticles=10): """ @param reffile: reference file @type reffile: C{str} @param nparticles: number of particles (default: 10) @type nparticles: C{int} @param pl_filename: particle list filename @type pl_filename: C{str} @param pdir: particle directory @type pdir: C{str} @return: particleList @rtype: L{pytom.basic.ParticleList} """ from pytom.basic.structures import Particle, ParticleList, Rotation, Shift, Wedge from pytom_volume import vol, rotate, shift, read from pytom.basic.transformations import general_transform_crop from pytom.basic.functions import initSphere from pytom.simulation.whiteNoise import add as addNoise import random from os import mkdir from pytom.score.score import FLCFScore as score try: mkdir(pdir) except FileExistsError: print('directory ' + pdir + ' existed already - using this one') random.seed(0) a = 0 wedge = Wedge(wedgeAngles=[30.0, 30.0], cutoffRadius=50.0) pl = ParticleList(directory='./') ref1 = read(reffile) ref2 = initSphere(sizeX=ref1.sizeX(), sizeY=ref1.sizeY(), sizeZ=ref1.sizeZ(), radius=45) #ref2.write('testData/mask_45.em') parts = {0: ref1, 1: ref2} for ii in range(0, nparticles): if not ii % 2: ref = read(reffile) else: ref = initSphere(sizeX=ref1.sizeX(), sizeY=ref1.sizeY(), sizeZ=ref1.sizeZ(), radius=30, smooth=30 / 10) rot = Rotation(random.uniform(0, 360), random.uniform(0, 360), random.uniform(0, 180)) shift = Shift(x=a * random.uniform(-5, 5), y=a * random.uniform(-5, 5), z=a * random.uniform(-5, 5)) rotvol = general_transform_crop(v=ref, rot=rot, shift=shift, scale=None, order=[0, 1, 2]) # add some noise noisy = addNoise(volume=rotvol, SNR=1) fname = pdir + '/particle_' + str(ii) + '.em' #noisy.write( fname) p = Particle(filename=fname, rotation=rot, shift=shift, wedge=wedge, className=0, pickPosition=None, score=score, sourceInfo=None) p.setScoreValue(0.0) wg = p.getWedge().getWedgeObject() wg.apply(noisy, Rotation(0, 0, 0)).write(fname) pl.append(particle=p) pl.setFileName(filename=pl_filename) pl.toXMLFile(filename=pl_filename) return pl
def create_RandomParticleList(reffile, pl_filename='pl.xml', pdir='./testparticles', nparticles=10): """ @param reffile: reference file @type reffile: C{str} @param nparticles: number of particles (default: 10) @type nparticles: C{int} @param pl_filename: particle list filename @type pl_filename: C{str} @param pdir: particle directory @type pdir: C{str} @return: particleList @rtype: L{pytom.basic.ParticleList} """ from pytom.basic.structures import Particle, ParticleList, Rotation, Shift from pytom_volume import vol, rotate, shift, read from pytom.basic.transformations import general_transform_crop from pytom.simulation.whiteNoise import add as addNoise import random from os import mkdir from pytom.score.score import FLCFScore as score try: mkdir(pdir) except FileExistsError: print('directory ' + pdir + ' existed already - using this one') random.seed(0) pl = ParticleList(directory='./') ref = read(reffile) for ii in range(0, nparticles): rot = Rotation(random.uniform(0, 360), random.uniform(0, 360), random.uniform(0, 180)) shift = Shift(x=random.uniform(-5, 5), y=random.uniform(-5, 5), z=random.uniform(-5, 5)) rotvol = general_transform_crop(v=ref, rot=rot, shift=shift, scale=None, order=[0, 1, 2]) # add some noise noisy = addNoise(volume=rotvol, SNR=1) fname = pdir + '/particle_' + str(ii) + '.em' noisy.write(fname) p = Particle(filename=fname, rotation=rot, shift=shift, wedge=None, className=0, pickPosition=None, score=score, sourceInfo=None) p.setScoreValue(0.0) pl.append(particle=p) pl.setFileName(filename=pl_filename) pl.toXMLFile(filename=pl_filename) return pl
def general_transform(v, rot=None, shift=None, scale=None, order=[0, 1, 2]): """Perform general transformation using 3rd order spline interpolation. @param v: volume @type v: L{pytom_volume.vol} @param rot: rotate @type rot: pytom.basic.structures.Rotate or list @param shift: shift @type shift: pytom.basic.structures.Shift or list @param scale: scale / magnification along each dimension @type scale: list @param order: the order in which the three operations are performed (smaller means first) @type order: list @return: pytom_volume """ from pytom.basic.structures import Rotation, Shift from pytom_volume import vol if not isinstance(v,vol): raise TypeError('general_transform: v must be of type pytom_volume.vol! Got ' + str(v.__class__) + ' instead!') if rot is None: rot = Rotation(0.,0.,0.) if rot.__class__ == list and len(rot) == 3: rot = Rotation(rot[0], rot[1], rot[2]) if shift is None: shift = Shift(0.,0.,0.) if shift.__class__ == list and len(shift) == 3: shift = Shift(shift[0], shift[1], shift[2]) if scale is None: scale = [1.0, 1.0, 1.0] if scale.__class__ == list and len(scale) == 3: #check if int(v.sizeX()*scale[0]) < 1 or int(v.sizeY()*scale[1]) < 1 or int(v.sizeZ()*scale[2]) < 1: raise Exception("Scale not possible! Please check all the dimension after scaling is bigger than 1!") else: raise Exception("Scale parameter invalid! Should be a list of 3 values!") from pytom_volume import vol, general_transform from pytom.tools.maths import Matrix # invert matrix rotM = rot.toMatrix(True) shiftM = shift.toMatrix() scaleM = Matrix(4,4) scaleM[0,0] = scale[0] scaleM[1,1] = scale[1] scaleM[2,2] = scale[2] scaleM[3,3] = 1 # multiply them according to the order all_mtx = [None, None, None] try: if order[2] > order[0]: # rotation first rotCenter1 = Shift(-int(v.sizeX()/2), -int(v.sizeY()/2), -int(v.sizeZ()/2)).toMatrix() rotCenter2 = Shift(int(v.sizeX()/2), int(v.sizeY()/2), int(v.sizeZ()/2)).toMatrix() else: # scale first, so the center is different rotCenter1 = Shift(-int(v.sizeX()*scale)/2, -int(v.sizeY()*scale)/2, -int(v.sizeZ()*scale)/2).toMatrix() rotCenter2 = Shift(int(v.sizeX()*scale)/2, int(v.sizeY()*scale)/2, int(v.sizeZ()*scale)/2).toMatrix() all_mtx[order[0]] = rotCenter2 * (rotM * rotCenter1) # for the rotation center! all_mtx[order[1]] = shiftM all_mtx[order[2]] = scaleM except: raise Exception("The given order is wrong! Should be a list of 0,1,2!") mtx = all_mtx[2] * (all_mtx[1] * all_mtx[0]) res = vol(int(v.sizeX()*scale[0]), int(v.sizeY()*scale[1]), int(v.sizeZ()*scale[2])) general_transform(v, res, mtx._matrix) return res
def __init__(self, vol1, vol2, score, mask=None, iniRot=None, iniTrans=None, opti='fmin_powell', interpolation='linear', verbose=False): """ alignment of a particle against a reference @param vol1: (constant) volume @type vol1: L{pytom_volume.vol} @param vol2: volume that is matched to reference @type vol2: L{pytom_volume.vol} @param score: score for alignment - e.g., pytom.basic.correlation.nxcc @type score: L{pytom.basic.correlation} @param mask: mask correlation is constrained on @type mask: L{pytom_volume.vol} @param iniRot: initial rotation of vol2 @type iniRot: L{pytom.basic.Rotation} @param iniTrans: initial translation of vol2 @type iniTrans: L{pytom.basic.Shift} @param opti: optimizer ('fmin_powell', 'fmin', 'fmin_cg', 'fmin_slsqp', 'fmin_bfgs') @param interpolation: interpolation type - 'linear' (default) or 'spline' @type interpolation: str @type opti: L{str} @author: FF """ from pytom.basic.normalise import normaliseUnderMask, mean0std1 from pytom.tools.macros import volumesSameSize from pytom_volume import vol from pytom.basic.structures import Rotation, Shift assert isinstance(interpolation, str), "interpolation must be of type str" self.verbose = verbose if not volumesSameSize(vol1, vol2): raise RuntimeError('Vol1 and vol2 must have same size!') # normalize constant volume if mask: (v, p) = normaliseUnderMask(vol1, mask) else: v = mean0std1(vol1, True) self.vol1 = v self.vol2 = vol2 self.rotvol2 = vol(self.vol1.sizeX(), self.vol2.sizeY(), self.vol2.sizeZ()) self.mask = mask if not iniRot: iniRot = Rotation() if not iniTrans: iniTrans = Shift() self.rot_trans = self.transRot2vector(rot=iniRot, trans=iniTrans) self.score = score self.val = -100000. self.centX = int(self.vol1.sizeX() // 2) self.centY = int(self.vol1.sizeY() // 2) self.centZ = int(self.vol1.sizeZ() // 2) self.binning = 1 self.interpolation = interpolation # set optimizer self.opti = opti if opti == 'fmin': self.optimizer = scipy.optimize.fmin elif opti == 'fmin_slsqp': self.optimizer = scipy.optimize.fmin_slsqp elif opti == 'fmin_cg': self.optimizer = scipy.optimize.fmin_cg elif opti == 'fmin_bfgs': self.optimizer = scipy.optimize.fmin_bfgs elif opti == 'fmin_powell': self.optimizer = scipy.optimize.fmin_powell else: raise TypeError('opti must be of type str')
def _startGrowingAverageLoop(self): """ _startGrowingAverageLoop: Loops over all particles in self.particleList and computes growing average """ from pytom.alignment.structures import GrowingAverageInterimResult from pytom.basic.structures import Rotation,Shift from pytom.alignment.alignmentFunctions import alignTwoVolumes numberParticles = len(self._particleList) self._resultList = [] result = GrowingAverageInterimResult(self._particleList[self._startParticleNumber],self._reference,Rotation(0,0,0),Shift(0,0,0),self._score) #init result list with first element self._resultList.append(result) self._createNewAverage(self._startParticleNumber) for particleIterator in range(numberParticles): if particleIterator == self._startParticleNumber: continue print('Running particle no ' + str(particleIterator)) particle = self._particleList[particleIterator] #determine alignment of current reference with particle result = alignTwoVolumes(particle,self._reference,self._angleObject,self._maskFile,self._score,self._preprocessing) self._angleObject.reset() self._resultList.append(result) self._createNewAverage(particleIterator)
from pytom_volume import read from sh.frm import frm_align_vol from pytom.tools.maths import rotation_distance, euclidianDistance from pytom.tools.timing import Timing from pytom.basic.structures import ParticleList from pytom.basic.structures import Shift, Rotation pl = ParticleList('.') pl.fromXMLFile('/fs/home/ychen/4Chen/first100.xml') r = read('/fs/home/ychen/4Chen/avg_first100.em') for pp in pl: v = read(pp.getFilename()) pos, ang = frm_align_vol(v, [-60.0, 60.0], r, [8, 32], 10, mask=30) pp.setShift( Shift([ pos[0] - v.sizeX() / 2, pos[1] - v.sizeY() / 2, pos[2] - v.sizeZ() / 2 ])) pp.setRotation(Rotation(ang)) pl.average('average.em', True)
class MaximisationResult(PyTomClass): """ MaximisationResult : Stores results of one maximisation process """ def __init__(self, particle='', reference=-1.0, score=-1.0, shift=-1.0, rotation=-1.0, angleObject=-1): from pytom.basic.structures import Particle, Reference, Shift, Rotation from numpy import long if particle.__class__ == str: self._particle = Particle(particle) elif particle.__class__ == Particle: self._particle = particle else: self._particle = Particle() if reference.__class__ == str: self._reference = Reference(reference) elif reference.__class__ == Reference: self._reference = reference else: self._reference = Reference() if shift.__class__ == list: self._shift = Shift(shift) elif shift.__class__ == float: self._shift = Shift() else: self._shift = shift if rotation.__class__ == list: self._rotation = Rotation(rotation) elif rotation.__class__ == Rotation: self._rotation = rotation else: self._rotation = Rotation() if score.__class__ == float: from pytom.score.score import xcfScore self._score = xcfScore() else: self._score = score if angleObject.__class__ == float or isinstance( angleObject, (int, long)): from pytom.angles.angleList import AngleList self._angleObject = AngleList() else: self._angleObject = angleObject def toParticle(self): """ toParticle: Converts this object to a Particle object. @return: @rtype: L{pytom.basic.structures.Particle} """ from pytom.basic.structures import Particle particle = self._particle particle.setRotation(self._rotation) particle.setShift(self._shift) particle.setScore(self._score) return particle def getParticle(self): return self._particle def getShift(self): from pytom.basic.structures import Shift if self._shift.__class__ == list: return Shift(self._shift) else: return self._shift def setShift(self, shift): from pytom.basic.structures import Shift assert shift.__class__ == Shift self._shift = shift def getAngleObject(self): return self._angleObject def getRotation(self): from pytom.basic.structures import Rotation if self._rotation.__class__ == list: return Rotation(self._rotation[0], self._rotation[1], self._rotation[2]) else: return self._rotation.copy() def getScore(self): """ getScore: Returns score object """ return self._score def setRotation(self, rotation): """ setRotation: @param rotation: """ from pytom.basic.structures import Rotation if rotation.__class__ == list: rotation = Rotation(rotation) self._rotation = rotation def fromXML(self, xmlObj): """ fromXML : Assigns values to result attributes from XML object @param xmlObj: A xml object @author: Thomas Hrabe """ from lxml.etree import _Element if xmlObj.__class__ != _Element: from pytom.basic.exceptions import ParameterError raise ParameterError( 'Is not a lxml.etree._Element! You must provide a valid XML object.' ) from pytom.score.score import fromXML as fromXMLScore from pytom.angles.angle import AngleObject if xmlObj.tag == "Result": result = xmlObj else: result = xmlObj.xpath('Result') if len(result) == 0: raise PyTomClassError( "This XML is not an MaximisationResult. No Result provided." ) result = result[0] from pytom.basic.structures import Particle, Reference, Rotation, Shift particle_element = result.xpath('Particle')[0] p = Particle('') p.fromXML(particle_element) self._particle = p r = result.xpath('Reference') ref = Reference('') ref.fromXML(r[0]) self._reference = ref scoreXML = result.xpath('Score')[0] self._score = fromXMLScore(scoreXML) shiftXML = result.xpath('Shift')[0] self._shift = Shift() self._shift.fromXML(shiftXML) rotationXML = result.xpath('Rotation')[0] self._rotation = Rotation() self._rotation.fromXML(rotationXML) angleElement = result.xpath('Angles') ang = AngleObject() self._angleObject = ang.fromXML(angleElement[0]) def toXML(self): """ toXML : Compiles a XML from result object @author: Thomas Hrabe """ from lxml import etree resultElement = etree.Element("Result") resultElement.append(self._particle.toXML()) if self._reference.hasGeneratedByInfo(): from pytom.basic.structures import Reference newRef = Reference(self._reference.getReferenceFilename()) resultElement.append(newRef.toXML()) else: resultElement.append(self._reference.toXML()) resultElement.append(self._shift.toXML()) resultElement.append(self._rotation.toXML()) resultElement.append(self._score.toXML()) resultElement.append(self._angleObject.toXML()) return resultElement def copy(self): return MaximisationResult(self._particle, self._reference, self._score, self._shift, self._rotation, self._angleObject)