Source code for bamfordlab.protocols.protocol_ethan_picking

# **************************************************************************
# *
# * Authors:     J.M. de la Rosa Trevin (delarosatrevin@scilifelab.se) [1]
# *
# * [1] Science for Life Laboratory, Stockholm University
# *
# * 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 3 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

import pyworkflow.utils as pwutils
import pyworkflow.protocol.params as params
from pyworkflow.protocol.constants import LEVEL_ADVANCED
from pwem.objects import Coordinate
from pwem.protocols import ProtParticlePickingAuto
from pwem.emlib.image import ImageHandler
import pwem.emlib.metadata as md

import bamfordlab


[docs]class ProtEthanPicker(ProtParticlePickingAuto): """ ETHAN is a program for automatic detection of spherical particles from electron micrographs. The ETHAN software was written at the Department of Computer Science of University of Helsinki, Finland by Teemu Kivioja. """ _label = 'ethan picker' #--------------------------- DEFINE param functions ----------------------- def _defineParams(self, form): ProtParticlePickingAuto._defineParams(self, form) form.addParam('radius', params.IntParam, label='Radius of particle (px)') form.addParam('height', params.FloatParam, default=0.5, label="Min. height", help='The minimum height of the virus peak compared to ' 'the average peak.') form.addParam('squareWidth', params.FloatParam, default=1.5, label="Square width", help='Minimum distance between two viruses is:\n' '2 * SQUARE_WIDTH_PARAM * RADIUS.') form.addParam('ringWidth', params.FloatParam, default=1.2, label="Ring width", help='Width of the ring in ring filter is: \n' 'RING_WIDTH_PARAM * RADIUS - RADIUS.') form.addParam('dist', params.FloatParam, default=0.1, label="Distance", help='Distance which the peak can move in x or y ' 'direction during center refinement is: \n' 'DIST_PARAM * RADIUS.') form.addParam('reduction', params.IntParam, default=0, label="Reduction", help='REDUCTION_PARAM * REDUCTION_PARAM pixels are ' 'averaged before filtering. The value has to be ' 'integer. Special value 0 means that the program ' 'determines the parameter.') form.addParam('doRefine', params.BooleanParam, default=True, expertLevel=LEVEL_ADVANCED, label="Refine particle centers?", help='') form.addParam('doSectorTest', params.BooleanParam, default=True, expertLevel=LEVEL_ADVANCED, label="Perform sector test?", help='') form.addParam('doHeightTest', params.BooleanParam, default=True, expertLevel=LEVEL_ADVANCED, label="Perform height test?", help='') form.addParam('doDistanceTest', params.BooleanParam, default=True, expertLevel=LEVEL_ADVANCED, label="Perform peak pair distance test?", help='') #--------------------------- STEPS functions ------------------------------ def _pickMicrograph(self, mic, radius): micFn = mic.getFileName() micDir = self._getMicDir(micFn) fnMicBase = pwutils.replaceBaseExt(micFn, 'mrc') fnMicCfg = pwutils.replaceBaseExt(micFn, 'cfg') fnMicFull = os.path.join(micDir, fnMicBase) fnPosBase = self._getMicPosFn(micFn) # Convert micrographs to mrc (uint8) as required by ETHAN program ih = ImageHandler() ih.convert(micFn, fnMicFull, md.DT_UCHAR) # Create a configuration file to be used by ETHAN with the parameters # selected by the user self.writeConfigFile(os.path.join(micDir, fnMicCfg)) # Run ethan program with the required arguments args = "%s %s %s %s" % (radius, fnMicBase, fnPosBase, fnMicCfg) self.runJob(bamfordlab.Plugin.getProgram(), args, cwd=micDir) # Clean temporary micrograph pwutils.cleanPath(fnMicFull)
[docs] def createOutputStep(self): pass
# --------------------------- INFO functions ------------------------------ def _validate(self): errors = [] return errors #--------------------------- UTILS functions ------------------------------ def _getMicDir(self, micFn): return self._getExtraPath() def _getMicPosFn(self, micFn): return pwutils.replaceBaseExt(micFn, 'txt') def _getPickArgs(self): """ In this case, only return the radius as argument. """ return [self.radius.get()]
[docs] def readCoordsFromMics(self, workingDir, micList, coordSet): coordSet.setBoxSize(self.radius.get() * 2) for mic in micList: micFn = mic.getFileName() micDir = self._getMicDir(micFn) coordFile = os.path.join(micDir, self._getMicPosFn(micFn)) if os.path.exists(coordFile): coordMd = md.MetaData() coordMd.readPlain(coordFile, 'xcoor ycoor') for objId in coordMd: x = coordMd.getValue(md.MDL_XCOOR, objId) y = coordMd.getValue(md.MDL_YCOOR, objId) coord = Coordinate() coord.setPosition(x, y) coord.setMicrograph(mic) coordSet.append(coord) else: print("Coordinate file '%s' not found. " % coordFile)
[docs] def writeConfigFile(self, configFn): f = open(configFn, 'w') argsDict = { 'height': self.height.get(), 'squareWidth': self.squareWidth.get(), 'ringWidth': self.ringWidth.get(), 'dist': self.dist.get(), 'reduction': self.reduction.get(), 'refinement': 1 if self.doRefine else 0, 'sectorTest': 1 if self.doSectorTest else 0, 'heightTest': 1 if self.doHeightTest else 0, 'distanceTest': 1 if self.doDistanceTest else 0 } f.write(""" # The minimum height of the virus peak compared to the average peak. HEIGHT_PARAM %(height)s # Minimum distance between two viruses is 2 * SQUARE_WIDTH_PARAM * RADIUS. SQUARE_WIDTH_PARAM %(squareWidth)s # Width of the ring in ring filter is RING_WIDTH_PARAM * RADIUS - RADIUS. RING_WIDTH_PARAM %(ringWidth)s # Distance which the peak can move in x or y direction during center # refinement is DIST_PARAM * RADIUS. DIST_PARAM %(dist)s # REDUCTION_PARAM * REDUCTION_PARAM pixels are averaged before filtering. # The value has to be integer # Special value 0 means that the program determines the parameter. REDUCTION_PARAM %(reduction)s # Is refinement of particle centers performed? Put 1 for yes, 0 for no. # Producing virus files is not possible when refinement is off REFINEMENT_PARAM %(refinement)s # Is sector test performed? Put 1 for yes, 0 for no. SECTOR_TEST %(sectorTest)s # Is height test performed? Put 1 for yes, 0 for no. HEIGHT_TEST %(heightTest)s # Is peak pair distance test performed? Put 1 for yes, 0 for no. DISTANCE_TEST %(distanceTest)s """ % argsDict) f.close()