Source code for xmipptomo.protocols.protocol_cltomo

# **************************************************************************
# *
# * Authors:     Carlos Oscar S. Sorzano (coss@cnb.csic.es)
# *
# * Unidad de  Bioinformatica of Centro Nacional de Biotecnologia , CSIC
# *
# * 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'
# *
# **************************************************************************
import os

from pwem.protocols import ProtClassify3D
from pyworkflow import BETA
from pyworkflow.protocol import (IntParam, PointerParam, LEVEL_ADVANCED, BooleanParam, StringParam, FloatParam)
from pyworkflow.utils import Environ
from xmipp3 import Plugin
from xmipp3.convert import readSetOfVolumes, readSetOfClassesVol, writeSetOfVolumes


[docs]class XmippProtCLTomo(ProtClassify3D): """ Averages a set of subtomograms taking into account the missing edge. """ _label = 'cltomo' _devStatus = BETA # --------------------------- DEFINE param functions -------------------------------------------- def _defineParams(self, form): form.addSection(label='General parameters') form.addParam('inputVolumes', PointerParam, pointerClass="SetOfVolumes", label='Set of volumes', help="Set of volumes to align") form.addParam('numberOfReferences', IntParam, label='Number of references', default=3, help="How many references are computed at the end of the process") form.addParam('numberOfIterations', IntParam, label='Number of iterations', default=15, expertLevel=LEVEL_ADVANCED, help="How many iterations at each of the Clustering levels") form.addParam('generateAligned', BooleanParam, default=True, label='Generate aligned subvolumes', help="If set to true, it will be created a new set of volumes with all of them aligned") form.addParam('align', BooleanParam, default=True, label="Align", help="Do not align if volumes are already aligned, only classify") form.addSection(label='Initial references') form.addParam('doGenerateInitial', BooleanParam, default=True, label='Generate initial volume', help="Let CLTomo to automatically generate the initial references") form.addParam('numberOfReferences0', IntParam, label='Number of initial references', default=1, condition="doGenerateInitial", help="How many initial volumes. If set to 1, all subvolumes are aligned to a single reference, " \ "and then they are classified") form.addParam('randomizeOrientation', BooleanParam, default=False, label='Randomize orientation', condition="doGenerateInitial", help="Use this option if all the input volumes have the same missing wedge or if they have not been previously aligned.") form.addParam('referenceList', PointerParam, pointerClass="SetOfVolumes", label='Set of initial volumes', condition="not doGenerateInitial", help="Set of initial volumes") form.addSection(label='Constraints') form.addParam('symmetry', StringParam, default='c1', label='Symmetry group', help="See http://xmipp.cnb.csic.es/twiki/bin/view/Xmipp/Symmetry for a description of the symmetry groups format." "If no symmetry is present, give c1") form.addParam('inputMask', PointerParam, pointerClass="VolumeMask", label="Spatial mask", allowsNull=True) form.addParam('maximumResolution', FloatParam, default=0.25, label='Maximum resolution (pixels^-1)', help="The maximum (Nyquist) resolution is 0.5. Use smaller values, e.g. 0.45, to prevent high-resolution artifacts.") form.addParam('sparsity', FloatParam, default=90, label='Sparsity in Fourier space', help="A value of 90 drops 90% of the smallest Fourier coefficients") form.addParam('dwtSparsity', FloatParam, default=90, label='Sparsity in wavelet space', help="A value of 95 drops 95% of the smallest wavelet coefficients") form.addSection(label='Search limits') form.addParam('maxRot', FloatParam, default=360, label='Maximum rotational angle', help="In degrees") form.addParam('maxTilt', FloatParam, default=360, label='Maximum tilt angle', help="In degrees") form.addParam('maxPsi', FloatParam, default=360, label='Maximum in-plane angle', help="In degrees") form.addParam('maxShiftX', FloatParam, default=10, label='Maximum shift X', help="In voxels") form.addParam('maxShiftY', FloatParam, default=10, label='Maximum shift Y', help="In voxels") form.addParam('maxShiftZ', FloatParam, default=10, label='Maximum shift Z', help="In voxels") form.addParallelSection(threads=0, mpi=4) # --------------------------- INSERT steps functions -------------------------------------------- def _insertAllSteps(self): self._insertFunctionStep('runCLTomo') self._insertFunctionStep('createOutput') # --------------------------- STEPS functions --------------------------------------------
[docs] def runCLTomo(self): fnVols = self._getPath('input_volumes.xmd') writeSetOfVolumes(self.inputVolumes.get(), fnVols) params = (' -i ' + fnVols + ' --oroot ' + self._getExtraPath("results") + ' --iter ' + str(self.numberOfIterations.get()) + ' --nref ' + str(self.numberOfReferences.get()) + ' --sym ' + self.symmetry.get() + ' --maxFreq ' + str(self.maximumResolution.get()) + ' --sparsity ' + str(self.sparsity.get() / 100.0) + ' --DWTsparsity ' + str(self.dwtSparsity.get() / 100.0) + ' --maxShiftX ' + str(self.maxShiftX.get()) + ' --maxShiftY ' + str(self.maxShiftY.get()) + ' --maxShiftZ ' + str(self.maxShiftZ.get()) + ' --maxRot ' + str(self.maxRot.get()) + ' --maxTilt ' + str(self.maxTilt.get()) + ' --maxPsi ' + str(self.maxPsi.get())) if self.doGenerateInitial.get(): params += ' --nref0 ' + str(self.numberOfReferences0.get()) if self.randomizeOrientation.get(): params += ' --randomizeStartingOrientation' else: fnInitialVols = self._getExtraPath('intial_volumes.xmd') writeSetOfVolumes(self.referenceList.get(), fnInitialVols) params += ' --ref0 ' + fnInitialVols if self.inputMask.hasValue(): params += ' --mask binary_file ' + self.inputMask.get().getLocation() if self.generateAligned.get(): params += " --generateAlignedVolumes" if not self.align: params += " --dontAlign" self.runJob('xmipp_mpi_classify_CLTomo', '%d %s' % (self.numberOfMpi.get(), params), env=self.getCLTomoEnviron(), numberOfMpi=1)
[docs] def createOutput(self): import glob levelFiles = glob.glob(self._getExtraPath("results_classes_level*.xmd")) if levelFiles: levelFiles.sort() lastLevelFile = levelFiles[-1] setOfClasses = self._createSetOfClassesVol() setOfClasses.setImages(self.inputVolumes.get()) readSetOfClassesVol(setOfClasses, lastLevelFile) self._defineOutputs(outputClasses=setOfClasses) self._defineSourceRelation(self.inputVolumes, self.outputClasses) if self.generateAligned: setOfVolumes = self._createSetOfVolumes() fnAligned = self._getExtraPath('results_aligned.xmd') readSetOfVolumes(fnAligned, setOfVolumes) volumeList = self.inputVolumes.get() setOfVolumes.setSamplingRate(volumeList.getSamplingRate()) self._defineOutputs(alignedVolumes=setOfVolumes) self._defineTransformRelation(self.inputVolumes, self.alignedVolumes)
# --------------------------- INFO functions -------------------------------------------- def _summary(self): messages = [] if self.doGenerateInitial.get(): messages.append('Number of initial references: %d' % self.numberOfReferences0.get()) if self.randomizeOrientation.get(): messages.append('Input subvolume orientations were randomized') if not self.align: messages.append('Input subvolumes were assumed to be already aligned') messages.append('Number of output references: %d' % self.numberOfReferences.get()) return messages def _validate(self): errors = [] (Xdim1, Ydim1, Zdim1) = self.inputVolumes.get().getDimensions() if Xdim1 != Ydim1 or Ydim1 != Zdim1: errors.append("Input subvolumes are not cubic") N0 = -1 if not self.doGenerateInitial.get(): if not self.referenceList.hasValue(): errors.append("If references are not self generated, you have to provide a reference set of volumes") else: (Xdim2, Ydim2, Zdim2) = self.referenceList.get().getDimensions() if Xdim2 != Ydim2 or Ydim2 != Zdim2: errors.append("Reference subvolumes are not cubic") if Xdim1 != Xdim2: errors.append("Input and reference subvolumes are of different size") else: N0 = self.numberOfReferences0.get() if N0 > 0 and N0 > self.numberOfReferences.get(): errors.append( "The number of initial references have to be smaller or equal than the number of final references") return errors def _citations(self): return ['Chen2013'] # --------------------------- UTILS functions --------------------------------------------
[docs] def getCLTomoEnviron(self): env = Plugin.getEnviron() env.set('PYTHONPATH', os.path.join(os.environ['SCIPION_HOME'], 'software', 'lib', 'python2.7', 'site-packages', 'sh_alignment'), Environ.BEGIN) return env