Source code for pyseg.protocols.protocol_post_rec_particles

# -*- coding: utf-8 -*-
# **************************************************************************
# *
# * Authors:     Scipion Team
# *
# * National Center of Biotechnology, CSIC, Spain
# *
# * This program is free software; you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation; either version 2 of the License, or
# * (at your option) any later version.
# *
# * This program is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License
# * along with this program; if not, write to the Free Software
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# * 02111-1307  USA
# *
# *  All comments concerning this program package may be sent to the
# *  e-mail address 'scipion@cnb.csic.es'
# *
# **************************************************************************
from os.path import exists, abspath

from pwem.protocols import EMProtocol, PointerParam
from pyseg.utils import getFinalMaskFileName, checkMaskFormat
from pyworkflow import BETA
from pyworkflow.protocol import String, FloatParam, LEVEL_ADVANCED, BooleanParam, GT, LE, GE
from pyworkflow.utils import Message, makePath
from reliontomo.convert import writeSetOfSubtomograms
from scipion.constants import PYTHON
from tomo.objects import SetOfSubTomograms
from tomo.protocols import ProtTomoBase

from pyseg import Plugin
from pyseg.constants import POST_REC_OUT, POST_REC_SCRIPT_MEMB_ATT, SEE_METHODS_TAB
from pyseg.convert import readStarFile, RELION_SUBTOMO_STAR


[docs]class ProtPySegPostRecParticles(EMProtocol, ProtTomoBase): """post-process already reconstructed particles: rot angle randomization and membrane suppression""" _label = 'posrec' _devStatus = BETA inStarName = 'input_particles.star' warningMsg = None subtomoSet = None # -------------------------- DEFINE param functions ---------------------- def _defineParams(self, form): """ Define the input parameters that will be used. Params: form: this is the form to be populated with sections and params. """ # You need a params to belong to a section: form.addSection(label=Message.LABEL_INPUT) form.addParam('inputSubtomos', PointerParam, pointerClass='SetOfSubTomograms', important=True, label="Input subtomograms", help='Select the input subtomograms from the project.') form.addParam('inMask', PointerParam, pointerClass='VolumeMask', label='Mask', important=True, allowsNull=False, help='Mask used for the post processing') group = form.addGroup('Membrane suppression') group.addParam('mbMask', PointerParam, pointerClass='VolumeMask', allowsNull=True, label='Mask for membrane supression') group.addParam('mbSupFactor', FloatParam, label='Membrane suppression factor [0, 1]', default=0.5, allowsNull=False, validators=[GE(0), LE(1)], condition='mbMask', help='Value 0 suppress the area corresponding to the suppression mask, while higher values ' 'up to 1 attenuate it.') group = form.addGroup('Gaussian low pass filter', expertLevel=LEVEL_ADVANCED) group.addParam('doGaussLowPassFilter', BooleanParam, label='Apply filter to the particles?', default=False) group.addParam('cutOffRes', FloatParam, label='Cut-off resolution (nm)', condition='doGaussLowPassFilter') group.addParam('ampCutOff', FloatParam, label='Amplitude at cut-off (0, 1]', default=0.01, validators=[GT(0), LE(1)], condition='doGaussLowPassFilter') group.addParam('filterCTF', BooleanParam, label='Apply this filter to the CTF?', default=False, condition='doGaussLowPassFilter') form.addParallelSection(threads=4, mpi=0) def _insertAllSteps(self): outStar = self._getExtraPath(POST_REC_OUT + '.star') self._insertFunctionStep(self.convertInputStep) self._insertFunctionStep(self.pysegPostRec, outStar) self._insertFunctionStep(self.createOutputStep, outStar)
[docs] def convertInputStep(self): """ Create the input file in STAR format as expected by Relion. """ # Check masks format and convert if necessary checkMaskFormat(self.inMask.get()) # Subtomogram mask if self.mbMask.get(): checkMaskFormat(self.mbMask.get()) # Membrane mask for attenuation (optional) # Write star from set of subtomograms imgSet = self.inputSubtomos.get() imgStar = self._getExtraPath(self.inStarName) writeSetOfSubtomograms(imgSet, imgStar, isPyseg=True)
[docs] def pysegPostRec(self, outStar): # Generate output subtomo dir outDir = self._getExtraPath(POST_REC_OUT) makePath(outDir) # Script called Plugin.runPySeg(self, PYTHON, self._getCommand(outDir, outStar))
[docs] def createOutputStep(self, outStar): self.subtomoSet = SetOfSubTomograms.create(self._getPath(), template='setOfSubTomograms%s.sqlite') self.subtomoSet.copyInfo(self.inputSubtomos.get()) # Read generated star file and create the output objects warningMsg = readStarFile(self, self.subtomoSet, RELION_SUBTOMO_STAR, starFile=outStar) if warningMsg: self.warningMsg = String(warningMsg) self._store() self._defineOutputs(outputSetOfSubtomogram=self.subtomoSet)
# --------------------------- INFO functions ----------------------------------- def _summary(self): summary = [] if self.isFinished(): summary.append('*Generated files location*:\n' '\t- Subtomograms files directory: %s\n' '\t- Star file: %s\n' '%s' % (self._getExtraPath(POST_REC_OUT), self._getExtraPath(POST_REC_OUT + '.star'), SEE_METHODS_TAB)) return summary def _methods(self): methods = [] if self.isFinished(): mbMask = self.mbMask.get() if mbMask: methods.append('*Membrane suppression applied with*\n' '\t- MembraneMask = %s\n' '\t- SuppressionFactor = %1.2f\n' % (mbMask.getFileName(), self.mbSupFactor.get())) if self.doGaussLowPassFilter.get(): methods.append('*Gaussian low pass filter applied with*\n' '\t- CutOffResolution[nm] = %2.1f\n' '\t- AmplitudeCutOff = %1.2f\n' '\t- AppliedToCTF = %s\n' % (self.cutOffRes.get(), self.ampCutOff.get(), self.filterCTF.get())) return methods def _validate(self): validationMsg = [] tol = 0.01 subTomosRes = self.inputSubtomos.get().getSamplingRate() inMask = self.inMask.get() maskRes = inMask.getSamplingRate() mbMask = self.mbMask.get() if abs(maskRes - subTomosRes) > tol: validationMsg.append('Sampling rate of the input subtomograms and the input mask should be the same\n' '%2.3f != %2.3f' % (subTomosRes, maskRes)) if mbMask: mbMaskRes = mbMask.getSamplingRate() if abs(mbMaskRes - subTomosRes) > tol: validationMsg.append('Sampling rate of the input subtomograms and the input membrane suppression mask ' 'should be the same\n' '%2.3f != %2.3f' % (subTomosRes, mbMaskRes)) if self.doGaussLowPassFilter.get(): # CTF3D required COORD_CTF_3D = '_3dcftMrcFile' coord3D = self.inputSubtomos.get().getCoordinates3D().get().getFirstItem() ctf3d = getattr(coord3D, COORD_CTF_3D, None) if ctf3d: ctf3d = abspath(ctf3d.get()) if not exists(ctf3d): validationMsg.append('CTF3D not found.\nValue read for the first coordinate is\n%s = %s' % (COORD_CTF_3D, ctf3d)) else: validationMsg.append('CTF3D is required to apply the gaussian low pass filter. Please calculate it\n' 'or do not apply the filter.') failingInputs = [] if not self.cutOffRes.get(): failingInputs.append('Cut-off resolution') if not self.ampCutOff.get(): failingInputs.append('Amplitude at cut-off') if failingInputs: validationMsg.append('Inputs *%s* should not be empty to apply the gaussian low pas filter' % ', '.join(failingInputs)) return validationMsg # --------------------------- UTIL functions ----------------------------------- def _getCommand(self, outDir, outStar): doGaussianLPFilter = self.doGaussLowPassFilter.get() cutOffRes = 0 ampCutOff = 0 if doGaussianLPFilter: cutOffRes = self.cutOffRes.get() ampCutOff = self.ampCutOff.get() posRecCmd = ' ' posRecCmd += '%s ' % Plugin.getHome(POST_REC_SCRIPT_MEMB_ATT) posRecCmd += '--inStar %s ' % self._getExtraPath(self.inStarName) posRecCmd += '--inMask %s ' % getFinalMaskFileName(self.inMask.get()) posRecCmd += '--inMaskMbSup %s ' % (getFinalMaskFileName(self.mbMask.get()) if self.mbMask.get() else 'None') posRecCmd += '--mbSupFactor %s ' % (self.mbSupFactor.get() if self.mbSupFactor.get() else '0') posRecCmd += '--doGaussLowPass %s ' % doGaussianLPFilter posRecCmd += '--resolution %s ' % (float(self.inputSubtomos.get().getSamplingRate()) / 10) # in nm posRecCmd += '--cutOffRes %s ' % cutOffRes posRecCmd += '--ampCutOff %s ' % ampCutOff posRecCmd += '--filterCTF %s ' % self.filterCTF.get() posRecCmd += '--outDir %s ' % outDir posRecCmd += '--outStar %s ' % outStar posRecCmd += '-j %s ' % self.numberOfThreads.get() return posRecCmd