# **************************************************************************
# *
# * Authors: Jose Gutierrez Tabuenca (jose.gutierrez@cnb.csic.es)
# * J.M. De la Rosa Trevin (jmdelarosa@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'
# *
# **************************************************************************
from pyworkflow.object import String
import pyworkflow.protocol.params as params
import pyworkflow.utils as pwutils
from pwem.protocols import ProtParticlePicking
from pwem.objects import CoordinatesTiltPair
from pwem.viewers import launchTiltPairPickerGUI
from xmipp3 import convert
from xmipp3.base import XmippProtocol
[docs]class XmippProtParticlePickingPairs(ProtParticlePicking, XmippProtocol):
""" Picks particles in a set of untilted-tilted pairs of micrographs. """
_label = 'tilt pairs particle picking'
def __init__(self, **args):
ProtParticlePicking.__init__(self, **args)
# The following attribute is only for testing
self.importFolder = String(args.get('importFolder', None))
#--------------- DEFINE param functions ---------------------------------
def _defineParams(self, form):
form.addSection(label='Input')
form.addParam('inputMicrographsTiltedPair', params.PointerParam,
pointerClass='MicrographsTiltPair',
label="Micrographs tilt pair",
help='Select the MicrographsTiltPair ')
#----------- INSERT steps functions ----------------------------------
def _insertAllSteps(self):
""" The Particle Picking process is realized for a pair
of set of micrographs
"""
self.micsFn = self._getPath('input_micrographs.xmd')
# Convert input into xmipp Metadata format
self._insertFunctionStep('convertInputStep')
# Launch Particle Picking GUI
if not self.importFolder.hasValue():
self._insertFunctionStep('launchParticlePickGUIStep', interactive=True)
else: # This is only used for test purposes
self._insertFunctionStep('_importFromFolderStep')
#------------------- STEPS functions -----------------------------------
[docs] def convertInputStep(self):
micTiltPairs = self.inputMicrographsTiltedPair.get()
# Get the converted input micrographs in Xmipp format
convert.writeSetOfMicrographsPairs(micTiltPairs.getUntilted(),
micTiltPairs.getTilted(),
self.micsFn)
[docs] def launchParticlePickGUIStep(self):
process = launchTiltPairPickerGUI(self.micsFn, self._getExtraPath(), self)
process.wait()
def _importFromFolderStep(self):
""" This function will copy Xmipp .pos files for
simulating a particle picking run...this is only
for testing purposes.
"""
extraDir = self._getExtraPath()
for f in pwutils.getFiles(self.importFolder.get()):
pwutils.copyFile(f, extraDir)
self.registerCoords(extraDir, readFromExtra=True)
#--------------------------- INFO functions --------------------------------------------
def _citations(self):
return []
#--------------------------- UTILS functions -------------------------------------------
def __str__(self):
""" String representation of a Particle Picking Tilt run """
outputs = self.getOutputsSize()
if outputs == 0:
msg = "No particles picked yet."
elif outputs == 1:
picked = self.getCoords().getSize()
mics = self.inputMicrographsTiltedPair.get().getTilted().getSize()
msg = "Number of particles picked: %d " % picked
msg += "(from %d micrographs)" % mics
else:
msg = 'Number of outputs: %d' % outputs
return msg
[docs] def getInputMicrographs(self):
return self.inputMicrographsTiltedPair.get().getTilted()
[docs] def getCoords(self):
return self.getCoordsTiltPair()
def _summary(self):
summary = []
if self.getInputMicrographs() is not None:
summary.append("Number of input micrographs: %d"
% self.getInputMicrographs().getSize())
if self.getOutputsSize() >= 1:
for key, output in self.iterOutputAttributes(CoordinatesTiltPair):
summary.append("*%s:*" % key)
summary.append(" Particles pairs picked: %d" % output.getSize())
summary.append(" Particle size: %d \n" % output.getBoxSize())
else:
summary.append("Output tilpairs not ready yet.")
return summary
def __getOutputSuffix(self):
maxCounter = -1
for attrName, _ in self.iterOutputAttributes(CoordinatesTiltPair):
suffix = attrName.replace('outputCoordinatesTiltPair', '')
try:
counter = int(suffix)
except:
counter = 1 # when there is not number assume 1
maxCounter = max(counter, maxCounter)
return str(maxCounter+1) if maxCounter > 0 else '' # empty if not outputs
def _getBoxSize(self):
""" Redefine this function to set a specific box size to the output
coordinates untilted and tilted.
"""
return None
def _readCoordinates(self, coordsDir, suffix=''):
micTiltPairs = self.inputMicrographsTiltedPair.get()
uSuffix = 'Untilted' + suffix
tSuffix = 'Tilted' + suffix
uSet = micTiltPairs.getUntilted()
tSet = micTiltPairs.getTilted()
# Create Untilted and Tilted SetOfCoordinates
uCoordSet = self._createSetOfCoordinates(uSet, suffix=uSuffix)
convert.readSetOfCoordinates(coordsDir, uSet, uCoordSet)
uCoordSet.write()
tCoordSet = self._createSetOfCoordinates(tSet, suffix=tSuffix)
convert.readSetOfCoordinates(coordsDir, tSet, tCoordSet)
tCoordSet.write()
boxSize = self._getBoxSize()
if boxSize:
uCoordSet.setBoxSize(boxSize)
tCoordSet.setBoxSize(boxSize)
return uCoordSet, tCoordSet
def _readAngles(self, micsFn, suffix=''):
# Read Angles from input micrographs
anglesSet = self._createSetOfAngles(suffix=suffix)
convert.readAnglesFromMicrographs(micsFn, anglesSet)
anglesSet.write()
return anglesSet
[docs] def registerCoords(self, coordsDir, store=True, readFromExtra=False):
micTiltPairs = self.inputMicrographsTiltedPair.get()
suffix = self.__getOutputSuffix()
uCoordSet, tCoordSet = self._readCoordinates(coordsDir, suffix)
if readFromExtra:
micsFn = self._getExtraPath('input_micrographs.xmd')
else:
micsFn = self._getPath('input_micrographs.xmd')
anglesSet = self._readAngles(micsFn, suffix)
# Create CoordinatesTiltPair object
outputset = self._createCoordinatesTiltPair(micTiltPairs,
uCoordSet, tCoordSet,
anglesSet, suffix)
summary = self.getSummary(outputset)
outputset.setObjComment(summary)
outputName = 'outputCoordinatesTiltPair' + suffix
outputs = {outputName: outputset}
self._defineOutputs(**outputs)
self._defineSourceRelation(self.inputMicrographsTiltedPair, outputset)
if store:
self._store()