class Angles(EMObject): """Represents a triplet of angles""" def __init__(self, **args): EMObject.__init__(self, **args) self._angleY = Float() self._angleY2 = Float() self._angleTilt = Float() def setAngles(self, angleY, angleY2, angleTilt): self._angleY.set(angleY) self._angleY2.set(angleY2) self._angleTilt.set(angleTilt) def getAngles(self): return (self._angleY.get(), self._angleY2.get(), self._angleTilt.get())
class XmippProtMonoTomo(ProtAnalysis3D): """ Given a tomogram the protocol assigns local resolutions to each voxel of the tomogram. """ _label = 'local Resolution MonoTomo' _lastUpdateVersion = VERSION_2_0 def __init__(self, **args): ProtAnalysis3D.__init__(self, **args) self.min_res_init = Float() self.max_res_init = Float() # --------------------------- DEFINE param functions ---------------------- def _defineParams(self, form): form.addSection(label='Input') form.addParam('half1', PointerParam, pointerClass='Tomogram', label="Odd tomogram", important=True, help='Select a volume for determining its ' 'local resolution.') form.addParam('half2', PointerParam, pointerClass='Tomogram', label="Even Tomogram", important=True, help='Select a second volume for determining a ' 'local resolution.') form.addParam('useMask', BooleanParam, default=False, label="Use mask?", help='The mask determines which points are specimen' ' and which are not.') form.addParam('Mask', PointerParam, pointerClass='VolumeMask', condition='useMask', allowsNull=True, label="Binary Mask", help='The mask determines which points are specimen' ' and which are not') group = form.addGroup('Extra parameters') line = group.addLine('Resolution Range (Å)', help="Resolution range (and step in expert mode) " "to evaluate the local resolution.") group.addParam('significance', FloatParam, default=0.95, expertLevel=LEVEL_ADVANCED, label="Significance", help='Relution is computed using hipothesis tests, ' 'this value determines the significance of that test') line.addParam('minRes', FloatParam, default=0, label='High') line.addParam('maxRes', FloatParam, allowsNull=True, label='Low') line.addParam('stepSize', FloatParam, allowsNull=True, default=0.25, expertLevel=LEVEL_ADVANCED, label='Step') form.addParallelSection(threads=4, mpi=0) # --------------------------- INSERT steps functions -------------------------------------------- def _createFilenameTemplates(self): """ Centralize how files are called """ myDict = { FN_MEAN_VOL: self._getExtraPath('mean_Tomogram.mrc'), OUTPUT_RESOLUTION_FILE: self._getExtraPath('TomogramLocalResolution.mrc'), METADATA_MASK_FILE: self._getExtraPath('mask_data.xmd'), FN_METADATA_HISTOGRAM: self._getExtraPath('hist.xmd'), BINARY_MASK: self._getExtraPath('binarized_mask.mrc'), FN_GAUSSIAN_MAP: self._getExtraPath('gaussianfilted.mrc'), } self._updateFilenamesDict(myDict) def _insertAllSteps(self): # Convert input into xmipp Metadata format self._createFilenameTemplates() self._insertFunctionStep('convertInputStep') self._insertFunctionStep('resolutionMonoTomoStep') self._insertFunctionStep('createOutputStep') self._insertFunctionStep("createHistrogram") def convertInputStep(self): """ Read the input volume. """ self.vol1Fn = self.half1.get().getFileName() self.vol2Fn = self.half2.get().getFileName() extVol1 = getExt(self.vol1Fn) extVol2 = getExt(self.vol2Fn) if (extVol1 == '.mrc') or (extVol1 == '.map'): self.vol1Fn = self.vol1Fn + ':mrc' if (extVol2 == '.mrc') or (extVol2 == '.map'): self.vol2Fn = self.vol2Fn + ':mrc' if self.useMask.get(): if (not self.Mask.hasValue()): self.ifNomask(self.vol1Fn) else: self.maskFn = self.Mask.get().getFileName() extMask = getExt(self.maskFn) if (extMask == '.mrc') or (extMask == '.map'): self.maskFn = self.maskFn + ':mrc' if self.Mask.hasValue(): params = ' -i %s' % self.maskFn params += ' -o %s' % self._getFileName(BINARY_MASK) params += ' --select below %f' % 0.5 # Mask threshold = 0.5 self.maskthreshold.get() params += ' --substitute binarize' self.runJob('xmipp_transform_threshold', params) def ifNomask(self, fnVol): xdim, _ydim, _zdim = self.half1.get().getDim() params = ' -i %s' % fnVol params += ' -o %s' % self._getFileName(FN_GAUSSIAN_MAP) setsize = 0.02 * xdim params += ' --fourier real_gaussian %f' % (setsize) self.runJob('xmipp_transform_filter', params) img = ImageHandler().read(self._getFileName(FN_GAUSSIAN_MAP)) imgData = img.getData() max_val = np.amax(imgData) * 0.05 params = ' -i %s' % self._getFileName(FN_GAUSSIAN_MAP) params += ' --select below %f' % max_val params += ' --substitute binarize' params += ' -o %s' % self._getFileName(BINARY_MASK) self.runJob('xmipp_transform_threshold', params) self.maskFn = self._getFileName(BINARY_MASK) def maskRadius(self): xdim, _ydim, _zdim = self.half1.get().getDim() xdim = xdim * 0.5 return xdim def resolutionMonoTomoStep(self): # Number of frequencies max_ = self.maxRes.get() if self.stepSize.hasValue(): freq_step = self.stepSize.get() else: freq_step = 0.25 xdim = self.maskRadius() params = ' --vol %s' % self.vol1Fn params += ' --vol2 %s' % self.vol2Fn params += ' --meanVol %s' % self._getFileName(FN_MEAN_VOL) if self.useMask.get(): params += ' --mask %s' % self._getFileName(BINARY_MASK) params += ' --sampling_rate %f' % self.half1.get().getSamplingRate() params += ' --minRes %f' % self.minRes.get() params += ' --maxRes %f' % max_ params += ' --step %f' % freq_step params += ' -o %s' % self._getFileName(OUTPUT_RESOLUTION_FILE) params += ' --significance %f' % self.significance.get() self.runJob('xmipp_resolution_monotomo', params) def createHistrogram(self): freq_step = self.stepSize.get() if self.stepSize.hasValue() else 10 M = float(self.max_res_init) m = float(self.min_res_init) range_res = round((M - m) / freq_step) params = ' -i %s' % self._getFileName(OUTPUT_RESOLUTION_FILE) if self.useMask.get(): params += ' --mask binary_file %s' % self._getFileName(BINARY_MASK) params += ' --steps %f' % range_res params += ' --range %f %f' % (self.min_res_init.get(), (float(self.max_res_init.get()) - float(freq_step))) params += ' -o %s' % self._getFileName(FN_METADATA_HISTOGRAM) self.runJob('xmipp_image_histogram', params) def readMetaDataOutput(self): mData = md.MetaData(self._getFileName(METADATA_MASK_FILE)) NvoxelsOriginalMask = float(mData.getValue(md.MDL_COUNT, mData.firstObject())) NvoxelsOutputMask = float(mData.getValue(md.MDL_COUNT2, mData.firstObject())) nvox = int(round( ((NvoxelsOriginalMask - NvoxelsOutputMask) / NvoxelsOriginalMask) * 100)) return nvox def getMinMax(self, imageFile): img = ImageHandler().read(imageFile) imgData = img.getData() min_res = round(np.amin(imgData) * 100) / 100 max_res = round(np.amax(imgData) * 100) / 100 return min_res, max_res def createOutputStep(self): volume = Tomogram() volume.setFileName(self._getFileName(OUTPUT_RESOLUTION_FILE)) volume.setSamplingRate(self.half1.get().getSamplingRate()) self._defineOutputs(resolution_Volume=volume) self._defineSourceRelation(self.half1, volume) # Setting the min max for the summary imageFile = self._getFileName(OUTPUT_RESOLUTION_FILE) min_, max_ = self.getMinMax(imageFile) self.min_res_init.set(round(min_ * 100) / 100) self.max_res_init.set(round(max_ * 100) / 100) self._store(self.min_res_init) self._store(self.max_res_init) # --------------------------- INFO functions ------------------------------ def _methods(self): messages = [] if hasattr(self, 'LocalResolution_Tomogram'): messages.append( 'Information about the method/article in ' + MONOTOMO_METHOD_URL) return messages def _summary(self): summary = [] summary.append("Highest resolution %.2f Å, " "Lowest resolution %.2f Å. \n" % (self.min_res_init, self.max_res_init)) return summary def _citations(self): return ['Vilas2020']
class BsoftProtBlocres(ProtAnalysis3D): """ Bsoft program: blocres It calculates the local resolution map from to half maps. The method is based on a local measurement inside a mobile window. """ _label = 'blocres' def __init__(self, **args): ProtAnalysis3D.__init__(self, **args) self.min_res_init = Float() self.max_res_init = Float() self.halfVolumes = True # --------------------------- DEFINE param functions ----------------------- def _defineParams(self, form): form.addSection(label='Input') form.addParam('inputVolume', params.PointerParam, pointerClass='Volume', label="Half 1", help="Select first half volume to compute the " "local resolution.") form.addParam('inputVolume2', params.PointerParam, pointerClass='Volume', label="Half 2", help="Select first half volume to compute the " "local resolution.") form.addParam('mask', params.PointerParam, allowsNull=True, pointerClass='Volume', label='Mask', help="Mask file to use for limiting the analysis to a " "defined region and level value to use " "(optional, default: all but zero).") form.addParam('method', params.BooleanParam, default=True, label='Use Box', help="The local (box) and shell (shell) resolution " "calculations are mutually exclusive.") form.addParam('box', params.IntParam, default=20, condition='method', label='Box', help="Kernel size for determining " "local resolution (pixels/voxels).") form.addParam('shell', params.IntParam, default=20, condition='not method', label='Shell', help="Shell width for determining " "radial resolution (pixels/voxels).") form.addParam('cutoff', params.FloatParam, default=0.5, label='Cutoff', help="Resolution cutoff for FSC." "(default: 0.5).") form.addSection(label='Parameters') form.addParam('step', params.IntParam, default=1, label='Step', help="Interval between voxel samples or shells for " "resolution analysis (pixels, default: 1)") form.addParam( 'maxresolution', params.FloatParam, default=2, label='Maximum Resolution', help="Maximum frequency available in the data (angstrom).") form.addParam('fill', params.IntParam, allowsNull=True, label='Fill', help="Value to fill the background " "(non-masked regions; default 0).") form.addParam('pad', params.EnumParam, choices=['None', 'Box', 'Shell'], default=1, label='Padding Factor', help="Resolution box padding factor " "(0 = none, default: 1 (box) and 0 (shell)).") form.addParam('symmetry', params.StringParam, allowsNull=True, default='', label='Symmetry', help="Point group symmetry.") form.addParam('smooth', params.BooleanParam, default=True, label='Smooth', help="Smooth the shell edge.") def _createFilenameTemplates(self): """ Centralize how files are called """ myDict = { FN_HALF1: self._getTmpPath("half1.map"), FN_HALF2: self._getTmpPath("half2.map"), FN_MASKVOL: self._getTmpPath("mask.map"), FN_RESOLMAP: self._getExtraPath("resolutionMap.map") } self._updateFilenamesDict(myDict) # --------------------------- INSERT steps functions ----------------------- def _insertAllSteps(self): # Insert processing steps self._createFilenameTemplates() self._insertFunctionStep('convertInputStep') self._insertFunctionStep('resolutionStep') self._insertFunctionStep('createOutputStep') # --------------------------- STEPS functions ------------------------------ def convertInputStep(self): # blocres works with .map vol1Fn = self.inputVolume.get().getFileName() vol2Fn = self.inputVolume2.get().getFileName() if self.mask.get().getFileName() != '': maskFn = self.mask.get().getFileName() self.fnvol1 = self._getFileName("half1") self.fnvol2 = self._getFileName("half2") ImageHandler().convert(vol1Fn, self.fnvol1) ImageHandler().convert(vol2Fn, self.fnvol2) if self.mask.get().getFileName() != '': self.fnmask = self._getFileName("maskvol") ImageHandler().convert(maskFn, self.fnmask) else: self.fnmask = self.maks.get().getFileName() def resolutionStep(self): """ blocres parameters. """ sampling = self.inputVolume.get().getSamplingRate() # Actions params = ' -v 1' # No Verbose if self.method: params += ' -box %i' % self.box.get() else: params += ' -shell %i' % self.shell.get() # Parameters params += ' -sampling %f,%f,%f' % (sampling, sampling, sampling) params += ' -step %f' % self.step.get() params += ' -maxresolution %f' % self.maxresolution.get() params += ' -cutoff %f' % self.cutoff.get() if self.fill.get() != '': params += ' -fill %i' % self.fill.get() # Parameters for local resolution params += ' -pad %f' % self.pad.get() if self.symmetry.get() != '': params += ' -symmetry %s' % self.symmetry.get() if self.smooth.get(): params += ' -smooth' if self.mask.get().getFileName() != '': params += ' -Mask %s' % self.fnmask # input halves and output map params += ' %s %s %s' % (self.fnvol1, self.fnvol2, self._getFileName(FN_RESOLMAP)) self.runJob(bsoft.Plugin.getProgram('blocres'), params, env=bsoft.Plugin.getEnviron()) def createOutputStep(self): volume = Volume() volume.setFileName(self._getFileName(FN_RESOLMAP)) volume.setSamplingRate(self.inputVolume.get().getSamplingRate()) self._defineOutputs(resolution_Volume=volume) self._defineSourceRelation(self.inputVolume, volume) imageFile = self._getFileName(FN_RESOLMAP) min_, max_ = self.getMinMax(imageFile) self.min_res_init.set(round(min_ * 100) / 100) self.max_res_init.set(round(max_ * 100) / 100) self._store(self.min_res_init) self._store(self.max_res_init) def getMinMax(self, imageFile): img = ImageHandler().read(imageFile) imgData = img.getData() # Remove 0's imgData = imgData[np.nonzero(imgData)] min_res = round(np.amin(imgData) * 100) / 100 max_res = round(np.amax(imgData) * 100) / 100 return min_res, max_res # --------------------------- INFO functions ----------------------------------- def _validate(self): errors = [] return errors def _citations(self): cites = ['Cardone2013'] return cites def _summary(self): summary = [] summary.append("Highest resolution %.2f A, " "Lowest resolution %.2f A." % (self.min_res_init.get(), self.max_res_init.get())) def _methods(self): methods = [] return methods
class XmippProtScreenParticles(ProtProcessParticles): """ Attach different merit values to every particle in order to prune the set. zScore evaluates the similarity of a particles with an average (lower zScore -> high similarity). SSNR evaluates the signal/noise ration in the Fourier space. Variance evaluates the varaince on the micrographs context where the particle was picked. """ _label = 'screen particles' # Automatic Particle rejection enum ZSCORE_CHOICES = ['None', 'MaxZscore', 'Percentage'] SSNR_CHOICES = ['None', 'Percentage'] VAR_CHOICES = ['None', 'Variance', 'Var. and Gini'] REJ_NONE = 0 REJ_MAXZSCORE = 1 REJ_PERCENTAGE = 2 REJ_PERCENTAGE_SSNR = 1 REJ_VARIANCE = 1 REJ_VARGINI = 2 # --------------------------- DEFINE param functions --------------------- def _defineProcessParams(self, form): # --- zScore rejection --- form.addParam('autoParRejection', EnumParam, choices=self.ZSCORE_CHOICES, label="Automatic rejection by Zscore", default=self.REJ_NONE, display=EnumParam.DISPLAY_COMBO, help='zScore evaluates the similarity of a particles ' 'with an average. The rejection can be:\n' ' None (no rejection)\n' ' MaxZscore (reject a particle if its zScore ' 'is larger than this value).\n ' ' Percentage (reject a given percentage for ' 'this criteria).') form.addParam('maxZscore', FloatParam, default=3, validators=[Positive], condition='autoParRejection==1', label='zScore threshold', help='Maximum Zscore.') form.addParam('percentage', IntParam, default=5, label='Percentage (%)', condition='autoParRejection==2', help='The worse percentage of particles according to ' 'metadata labels: ZScoreShape1, ZScoreShape2, ' 'ZScoreSNR1, ZScoreSNR2, ZScoreHistogram are ' 'automatically disabled.', validators=[Range(0, 100, error="Percentage must be " "between 0 and 100.")]) # --- SSNR rejection --- form.addParam('autoParRejectionSSNR', EnumParam, choices=self.SSNR_CHOICES, label="Automatic rejection by SSNR", default=self.REJ_NONE, display=EnumParam.DISPLAY_COMBO, help='SSNR evaluates the signal/noise ration in the ' 'Fourier space. The rejection can be:\n' ' None (no rejection)\n' ' Percentage (reject a given percentage of the ' 'lowest SSNRs).') form.addParam('percentageSSNR', IntParam, default=5, condition='autoParRejectionSSNR==1', label='Percentage (%)', help='The worse percentage of particles according to ' 'SSNR are automatically disabled.', validators=[Range(0, 100, error="Percentage must be " "between 0 and 100.")]) # --- Variance rejection --- form.addParam('autoParRejectionVar', EnumParam, default=self.REJ_NONE, choices=self.VAR_CHOICES, label='Automatic rejection by Variance', help='Variance evaluates the varaince on the micrographs ' 'context where the particle was picked. ' 'The rejection can be:\n' ' None (no rejection)\n' ' Variance (taking into account only the variance)\n' ' Var. and Gini (taking into account also the Gini ' 'coeff.)') # --- Add features --- form.addParam('addFeatures', BooleanParam, default=False, label='Add features', expertLevel=LEVEL_ADVANCED, help='Add features used for the ranking to each one ' 'of the input particles') form.addParallelSection(threads=0, mpi=0) def _getDefaultParallel(self): """This protocol doesn't have mpi version""" return (0, 0) #--------------------------- INSERT steps functions ---------------------- def _insertAllSteps(self): self._initializeZscores() self.outputSize = 0 self.inputSize = 0 self.check = None self.fnInputMd = self._getExtraPath("input.xmd") self.fnInputOldMd = self._getExtraPath("inputOld.xmd") self.fnOutputMd = self._getExtraPath("output.xmd") self.inputSize, self.streamClosed = self._loadInput() partsSteps = self._insertNewPartsSteps() self._insertFunctionStep('createOutputStep', prerequisites=partsSteps, wait=True) def _getFirstJoinStep(self): for s in self._steps: if s.funcName == self._getFirstJoinStepName(): return s return None def _getFirstJoinStepName(self): # This function will be used for streaming, to check which is # the first function that need to wait for all micrographs # to have completed, this can be overriden in subclasses # (e.g., in Xmipp 'sortPSDStep') return 'createOutputStep' def createOutputStep(self): pass def _insertNewPartsSteps(self): deps = [] stepId = self._insertFunctionStep('sortImagesStep', prerequisites=[]) deps.append(stepId) return deps def _stepsCheck(self): # Input particles set can be loaded or None when checked for new inputs # If None, we load it self._checkNewInput() self._checkNewOutput() def _checkNewInput(self): # Check if there are new particles to process from the input set partsFile = self.inputParticles.get().getFileName() mTime = datetime.fromtimestamp(os.path.getmtime(partsFile)) # If the input movies.sqlite have not changed since our last check, # it does not make sense to check for new input data if self.lastCheck > mTime: return None self.inputSize, self.streamClosed = self._loadInput() if not isEmpty(self.fnInputMd): fDeps = self._insertNewPartsSteps() outputStep = self._getFirstJoinStep() if outputStep is not None: outputStep.addPrerequisites(*fDeps) self.updateSteps() def _loadInput(self): self.lastCheck = datetime.now() partsFile = self.inputParticles.get().getFileName() inPartsSet = SetOfParticles(filename=partsFile) inPartsSet.loadAllProperties() check = None for p in inPartsSet.iterItems(orderBy='creation', direction='DESC'): check = p.getObjCreation() break if self.check is None: writeSetOfParticles(inPartsSet, self.fnInputMd, alignType=ALIGN_NONE, orderBy='creation') else: writeSetOfParticles(inPartsSet, self.fnInputMd, alignType=ALIGN_NONE, orderBy='creation', where='creation>"' + str(self.check) + '"') writeSetOfParticles(inPartsSet, self.fnInputOldMd, alignType=ALIGN_NONE, orderBy='creation', where='creation<"' + str(self.check) + '"') self.check = check streamClosed = inPartsSet.isStreamClosed() inputSize = inPartsSet.getSize() inPartsSet.close() return inputSize, streamClosed def _checkNewOutput(self): if getattr(self, 'finished', False): return self.finished = self.streamClosed and \ self.outputSize == self.inputSize streamMode = Set.STREAM_CLOSED if self.finished else Set.STREAM_OPEN newData = os.path.exists(self.fnOutputMd) lastToClose = self.finished and hasattr(self, 'outputParticles') if newData or lastToClose: outSet = self._loadOutputSet(SetOfParticles, 'outputParticles.sqlite') if newData: partsSet = self._createSetOfParticles() readSetOfParticles(self.fnOutputMd, partsSet) outSet.copyItems(partsSet) for item in partsSet: self._calculateSummaryValues(item) self._store() writeSetOfParticles(outSet.iterItems(orderBy='_xmipp_zScore'), self._getPath("images.xmd"), alignType=ALIGN_NONE) cleanPath(self.fnOutputMd) self._updateOutputSet('outputParticles', outSet, streamMode) if self.finished: # Unlock createOutputStep if finished all jobs outputStep = self._getFirstJoinStep() if outputStep and outputStep.isWaiting(): outputStep.setStatus(cons.STATUS_NEW) def _loadOutputSet(self, SetClass, baseName): setFile = self._getPath(baseName) if os.path.exists(setFile): outputSet = SetClass(filename=setFile) outputSet.loadAllProperties() outputSet.enableAppend() else: outputSet = SetClass(filename=setFile) outputSet.setStreamState(outputSet.STREAM_OPEN) self._store(outputSet) self._defineTransformRelation(self.inputParticles, outputSet) outputSet.copyInfo(self.inputParticles.get()) return outputSet #--------------------------- STEP functions ----------------------------- def sortImagesStep(self): args = "-i Particles@%s -o %s --addToInput " % (self.fnInputMd, self.fnOutputMd) if os.path.exists(self.fnInputOldMd): args += "-t Particles@%s " % self.fnInputOldMd if self.autoParRejection == self.REJ_MAXZSCORE: args += "--zcut " + str(self.maxZscore.get()) elif self.autoParRejection == self.REJ_PERCENTAGE: args += "--percent " + str(self.percentage.get()) if self.addFeatures: args += "--addFeatures " self.runJob("xmipp_image_sort_by_statistics", args) args = "-i Particles@%s -o %s" % (self.fnInputMd, self.fnOutputMd) if self.autoParRejectionSSNR == self.REJ_PERCENTAGE_SSNR: args += " --ssnrpercent " + str(self.percentageSSNR.get()) self.runJob("xmipp_image_ssnr", args) if self.autoParRejectionVar != self.REJ_NONE: print('Rejecting by variance:') if self.outputSize == 0: varList = [] giniList = [] print(' - Reading metadata') mdata = emlib.MetaData(self.fnInputMd) for objId in mdata: varList.append(mdata.getValue(emlib.MDL_SCORE_BY_VAR, objId)) giniList.append(mdata.getValue(emlib.MDL_SCORE_BY_GINI, objId)) if self.autoParRejectionVar == self.REJ_VARIANCE: valuesList = varList self.mdLabels = [emlib.MDL_SCORE_BY_VAR] else: # not working pretty well valuesList = [var*(1-gini) for var, gini in zip(varList, giniList)] self.mdLabels = [emlib.MDL_SCORE_BY_VAR, emlib.MDL_SCORE_BY_GINI] self.varThreshold.set(histThresholding(valuesList)) print(' - Variance threshold: %f' % self.varThreshold) rejectByVariance(self.fnInputMd, self.fnOutputMd, self.varThreshold, self.autoParRejectionVar) # update the processed particles self.outputSize += getSize(self.fnInputMd) def _initializeZscores(self): # Store the set for later access , ;-( self.minZScore = Float() self.maxZScore = Float() self.sumZScore = Float() self.varThreshold = Float() self._store() def _calculateSummaryValues(self, particle): zScore = particle._xmipp_zScore.get() self.minZScore.set(min(zScore, self.minZScore.get(1000))) self.maxZScore.set(max(zScore, self.maxZScore.get(0))) self.sumZScore.set(self.sumZScore.get(0) + zScore) # -------------------------- INFO functions ------------------------------ def _summary(self): summary = [] sumRejMet = {} # A dict with the form choices if self.autoParRejection is not None: metStr = self.ZSCORE_CHOICES[self.autoParRejection.get()] if self.autoParRejection.get() == self.REJ_MAXZSCORE: metStr += " = %.2f" % self.maxZscore.get() elif self.autoParRejection.get() == self.REJ_PERCENTAGE: metStr += " = %.2f" % self.percentage.get() sumRejMet['Zscore'] = ("Zscore rejection method: " + metStr) if self.autoParRejectionSSNR is not None: metStr = self.SSNR_CHOICES[self.autoParRejectionSSNR.get()] if self.autoParRejectionSSNR.get() == self.REJ_PERCENTAGE_SSNR: metStr += " = %.2f" % self.percentageSSNR.get() sumRejMet['SSNR'] = ("SSNR rejection method: " + metStr) if self.autoParRejectionVar is not None: sumRejMet['Var'] = ("Variance rejection method: " + self.VAR_CHOICES[self.autoParRejectionVar.get()]) # If no output yet, just the form choices are shown plus a no-ready text if not hasattr(self, 'outputParticles'): summary += sumRejMet.values() summary.append("Output particles not ready yet.") else: summary.append(sumRejMet['Zscore']) if hasattr(self, 'sumZScore'): summary.append(" - The minimum ZScore is %.2f" % self.minZScore) summary.append(" - The maximum ZScore is %.2f" % self.maxZScore) meanZScore = self.sumZScore.get() * 1.0 / len(self.outputParticles) summary.append(" - The mean ZScore is %.2f" % meanZScore) else: summary.append( "Summary values not calculated during processing.") summary.append(sumRejMet['SSNR']) summary.append(sumRejMet['Var']) if self.autoParRejectionVar != self.REJ_NONE: if hasattr(self, 'varThreshold'): summary.append(" - Variance threshold: %.2f" % self.varThreshold) else: summary.append(" - Variance threshold not calculed yet.") return summary def _validate(self): validateMsgs = [] if self.autoParRejectionVar != self.REJ_NONE: part = self.inputParticles.get().getFirstItem() if not part.hasAttribute('_xmipp_scoreByVariance'): validateMsgs.append('The auto-rejection by Variance can not be ' 'done because the particles have not the ' 'scoreByVariance attribute. Use Xmipp to ' 'extract the particles.') return validateMsgs def _citations(self): return ['Vargas2013b'] def _methods(self): methods = [] if hasattr(self, 'outputParticles'): outParticles = (len(self.outputParticles) if self.outputParticles is not None else None) particlesRejected = (len(self.inputParticles.get())-outParticles if outParticles is not None else None) particlesRejectedText = (' ('+str(particlesRejected)+')' if particlesRejected is not None else '') rejectionText = ['', # REJ_NONE ' and removing those not reaching %s%s' % (str(self.maxZscore.get()), particlesRejectedText), # REJ_MAXZSCORE ' and removing worst %s percent %s' % (str(self.percentage.get()), particlesRejectedText) # REJ_PERCENTAGE ] methods.append('Input dataset %s of %s particles was sorted by' ' its ZScore using xmipp_image_sort_by_statistics' ' program%s. ' % (self.getObjectTag('inputParticles'), len(self.inputParticles.get()), rejectionText[self.autoParRejection.get()])) methods.append('Output set is %s.' % self.getObjectTag('outputParticles')) return methods