Source code for xmipp3.protocols.protocol_shift_particles

# -*- coding: utf-8 -*-
# **************************************************************************
# *
# * Authors:     Estrella Fernandez Gimenez (me.fernandez@cnb.csic.es)
# *
# *  BCU, 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'
# *
# **************************************************************************

from pwem.emlib.image import ImageHandler as ih
from pwem.objects import Volume
from pyworkflow.protocol.params import PointerParam, BooleanParam, IntParam, EnumParam, FloatParam
from pyworkflow.protocol.constants import LEVEL_ADVANCED
import pyworkflow.object as pwobj
from pwem import ALIGN_3D, ALIGN_2D
import pwem.emlib.metadata as md
from pwem.protocols import EMProtocol
from xmipp3.convert import xmippToLocation, writeSetOfParticles, readSetOfParticles


[docs]class XmippProtShiftParticles(EMProtocol): """ This protocol shifts particles to center them into a point selected in a volume. To do so, it generates new shifted images and modify the transformation matrix according to the shift performed.""" _label = 'shift particles' # --------------------------- DEFINE param functions -------------------------------------------- def _defineParams(self, form): form.addSection(label='Input') form.addParam('inputParticles', PointerParam, pointerClass='SetOfParticles', label="Particles", help='Select the SetOfParticles with transformation matrix to be shifted.') form.addParam('option', BooleanParam, label='Select position in volume?', default='True', help='Select the position where the particles will be shifted in a volume displayed in a wizard.') form.addParam('inputVol', PointerParam, pointerClass='Volume', label="Volume", allowsNull=True, condition='option', help='Volume to select the point (by clicking in the wizard for selecting the' ' new center) that will be the new center of the particles.') form.addParam('xin', FloatParam, label="x", condition='option', help='Use the wizard to select the new center for the shifted particles by shift+click on the ' 'blue point a drag it to the desired location while pressing shift.') form.addParam('yin', FloatParam, label="y", condition='option') form.addParam('zin', FloatParam, label="z", condition='option') form.addParam('inputMask', PointerParam, pointerClass='VolumeMask', label="Volume mask", allowsNull=True, condition='not option', help='3D mask to compute the center of mass, the particles will be ' 'shifted to the computed center of mass') form.addParam('applyShift', BooleanParam, label='Apply shift to particles?', default='True', help='Yes: The shift is applied to particle images and zero shift is stored in the metadata. No: ' 'The shift is stored in the transformation matrix in the metadata, but not applied to the ' 'particle image (i.e. the output images are the same of input images). This option takes ' 'less time and the shift could be applied later using protocol "xmipp3 - apply alignment 2d"' ' or by re-extracting the particles.') form.addParam('boxSizeBool', BooleanParam, label='Use original box size for the shifted particles?', default='True', help='Use input particles box size for the shifted particles.') form.addParam('boxSize', IntParam, label='Final box size', condition='not boxSizeBool', help='Box size for the shifted particles.') form.addParam('inv', BooleanParam, label='Inverse', expertLevel=LEVEL_ADVANCED, default='True', help='Use inverse transformation matrix') form.addParam('interp', EnumParam, default=0, choices=['Linear', 'Spline'], expertLevel=LEVEL_ADVANCED, display=EnumParam.DISPLAY_HLIST, label='Interpolation', help='Linear: Use bilinear/trilinear interpolation\nSpline: Use spline interpolation') # --------------------------- INSERT steps functions -------------------------------------------- def _insertAllSteps(self): self._insertFunctionStep('convertStep') self._insertFunctionStep('shiftStep') self._insertFunctionStep('createOutputStep') # --------------------------- STEPS functions --------------------------------------------
[docs] def convertStep(self): """convert input particles into .xmd file """ writeSetOfParticles(self.inputParticles.get(), self._getExtraPath("input_particles.xmd"), alignType=ALIGN_3D)
[docs] def shiftStep(self): """call xmipp program to shift the particles""" centermd = self._getExtraPath("center_particles.xmd") args = '-i "%s" -o "%s" ' % (self._getExtraPath("input_particles.xmd"), centermd) if self.option: self.x = self.xin.get() self.y = self.yin.get() self.z = self.zin.get() else: fnvol = self.inputMask.get().getFileName() if fnvol.endswith('.mrc'): fnvol += ':mrc' vol = Volume() vol.setFileName(fnvol) vol = ih().read(vol.getFileName()) masscenter = vol.centerOfMass() self.x = masscenter[0] self.y = masscenter[1] self.z = masscenter[2] args += '--shift_to %f %f %f ' % (self.x, self.y, self.z) program = "xmipp_transform_geometry" if not self.interp.get(): interp = 'linear' else: interp = 'spline' if self.applyShift.get(): args += ' --apply_transform' args += ' --dont_wrap --interp %s' % interp if self.inv.get(): args += ' --inverse' self.runJob(program, args) if not self.boxSizeBool.get(): box = self.boxSize.get() self.runJob('xmipp_transform_window', '-i "%s" -o "%s" --size %d %d %d --save_metadata_stack' % (centermd, self._getExtraPath("crop_particles.stk"), box, box, 1))
[docs] def createOutputStep(self): """create output with the new particles""" self.ix = 0 inputParticles = self.inputParticles.get() outputSet = self._createSetOfParticles() outputSet.copyInfo(inputParticles) if self.boxSizeBool.get(): outputmd = self._getExtraPath("center_particles.xmd") else: outputmd = self._getExtraPath("crop_particles.xmd") readSetOfParticles(outputmd, outputSet) self._defineOutputs(outputParticles=outputSet) self._defineOutputs(shiftX=pwobj.Float(self.x), shiftY=pwobj.Float(self.y), shiftZ=pwobj.Float(self.z)) self._defineSourceRelation(inputParticles, outputSet)
# --------------------------- INFO functions -------------------------------------------- def _summary(self): summary = [] if not hasattr(self, 'outputParticles'): summary.append("Output particles not ready yet.") else: if self.option: option = "User defined shift" else: option = "Shift to center of mass" if not self.interp.get(): interp = 'linear' else: interp = 'spline' summary.append("%s\ninterpolation: %s" % (option, interp)) if self.inv.get(): summary.append("inverse matrix applied") return summary def _validate(self): for part in self.inputParticles.get().iterItems(): if not part.hasTransform(): validatemsg = ['Please provide particles which have transformation matrix.'] return validatemsg