# **************************************************************************
# *
# * Authors: 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 pwem.viewers import showj, DataViewer, EmPlotter, CtfView, ObjectView
from pyworkflow.utils import removeBaseExt
from pyworkflow.viewer import DESKTOP_TKINTER, WEB_DJANGO
from pwem.protocols import *
from pwem.viewers.showj import *
from pwem import emlib
from xmipp3.convert import *
from xmipp3.protocols import XmippProtCompareReprojections
from xmipp3.protocols import XmippProtCompareAngles
from xmipp3.protocols import XmippProtConsensusLocalCTF
from xmipp3.protocols import XmippProtExtractParticles
from xmipp3.protocols import XmippProtExtractParticlesPairs
from xmipp3.protocols import XmippProtKerdensom
from xmipp3.protocols import XmippParticlePickingAutomatic
from xmipp3.protocols import XmippProtParticlePickingPairs
#from xmipp3.protocols import XmippProtRotSpectra
from xmipp3.protocols import XmippProtScreenParticles
from xmipp3.protocols import XmippProtCTFMicrographs
from xmipp3.protocols import XmippProtValidateNonTilt
from xmipp3.protocols import XmippProtMultiRefAlignability
from xmipp3.protocols import XmippProtAngularGraphConsistency
from xmipp3.protocols import XmippProtAssignmentTiltPair
from xmipp3.protocols import XmippProtMovieGain
from .plotter import XmippPlotter
from xmipp3.protocols import XmippProtTiltAnalysis
from pwem.viewers.viewers_data import MicrographsView
[docs]class XmippViewer(DataViewer):
""" Wrapper to visualize different type of objects
with the Xmipp program xmipp_showj
"""
_environments = [DESKTOP_TKINTER, WEB_DJANGO]
_targets = [
XmippProtCompareReprojections,
XmippProtCompareAngles,
XmippProtConsensusLocalCTF,
XmippParticlePickingAutomatic,
XmippProtExtractParticles,
XmippProtExtractParticlesPairs,
XmippProtKerdensom,
XmippProtParticlePickingPairs,
XmippProtScreenParticles,
XmippProtCTFMicrographs,
XmippProtValidateNonTilt,
XmippProtAssignmentTiltPair,
XmippProtMultiRefAlignability,
XmippProtAngularGraphConsistency,
XmippProtMovieGain,
XmippProtTiltAnalysis
]
def __createTemporaryCtfs(self, obj, setOfMics):
pwutils.cleanPath(obj._getPath("ctfs_temporary.sqlite"))
self.protocol._createFilenameTemplates()
ctfSet = self.protocol._createSetOfCTF("_temporary")
for mic in setOfMics:
micDir = obj._getExtraPath(removeBaseExt(mic.getFileName()))
ctfparam = self.protocol._getFileName('ctfparam', micDir=micDir)
if exists(ctfparam) or exists('xmipp_default_ctf.ctfparam'):
if not os.path.exists(ctfparam):
ctfparam = 'xmipp_default_ctf.ctfparam'
ctfModel = readCTFModel(ctfparam, mic)
self.protocol._setPsdFiles(ctfModel, micDir)
ctfSet.append(ctfModel)
if not ctfSet.isEmpty():
ctfSet.write()
ctfSet.close()
return ctfSet
def _visualize(self, obj, **kwargs):
cls = type(obj)
if issubclass(cls, XmippProtCTFMicrographs):
if obj.hasAttribute('outputCTF'):
ctfSet = obj.outputCTF
else:
mics = obj.inputMicrographs.get()
ctfSet = self.__createTemporaryCtfs(obj, mics)
if ctfSet.isEmpty():
self._views.append(self.infoMessage("No CTF estimation has finished yet"))
else:
self.getCTFViews(ctfSet)
# elif issubclass(cls, SetOfNormalModes):
# from .viewer_nma import OBJCMD_NMA_PLOTDIST, OBJCMD_NMA_VMD
# fn = obj.getFileName()
# objCommands = "'%s' '%s'" % (OBJCMD_NMA_PLOTDIST, OBJCMD_NMA_VMD)
# self._views.append(ObjectView(self._project, self.protocol.strId(),
# fn, obj.strId(),
# viewParams={OBJCMDS: objCommands},
# **kwargs))
elif (issubclass(cls, XmippProtExtractParticles) or
issubclass(cls, XmippProtScreenParticles)):
particles = obj.outputParticles
self._visualize(particles)
fn = obj._getPath('images.xmd')
if os.path.exists(fn): # it doesnt unless cls is Xmipp
md = emlib.MetaData(fn)
# If Zscore on output images plot Zscore particle sorting
if md.containsLabel(emlib.MDL_ZSCORE):
xplotter = XmippPlotter(windowTitle="Zscore particles sorting")
xplotter.createSubPlot("Particle sorting", "Particle number", "Zscore")
xplotter.plotMd(md, False, mdLabelY=emlib.MDL_ZSCORE)
self._views.append(xplotter)
# If VARscore on output images plot VARscore particle sorting
if md.containsLabel(emlib.MDL_SCORE_BY_VAR):
xplotter = XmippPlotter(windowTitle="Variance particles sorting")
xplotter.createSubPlot("Variance Histogram", "Variance", "Number of particles")
xplotter.plotMd(md, False, mdLabelY=emlib.MDL_SCORE_BY_VAR, nbins=100)
self._views.append(xplotter)
elif issubclass(cls, XmippProtMovieGain):
if obj.hasAttribute('outputGains'):
self._visualize(obj.outputGains)
# movieGainMonitor = MonitorMovieGain(obj,
# workingDir=obj.workingDir.get(),
# samplingInterval=60,
# monitorTime=300,
# stddevValue=0.04,
# ratio1Value=1.15,
# ratio2Value=4.5)
# self._views.append(MovieGainMonitorPlotter(movieGainMonitor))
elif issubclass(cls, XmippProtKerdensom):
self._visualize(obj.outputClasses, viewParams={'columns': obj.SomXdim.get(),
'render': 'average._filename '
'_representative._filename',
'labels': '_size',
'sortby': 'id'})
elif issubclass(cls, XmippProtTiltAnalysis):
if obj.hasAttribute('discardedMicrographs'):
fn = obj.discardedMicrographs.getFileName()
labels = ('id enabled psdCorr._filename _filename _tilt_mean_corr _tilt_std_corr '
'_tilt_max_corr _tilt_min_corr _tilt_psds_image._filename ')
labelRender = (' psdCorr._filename _tilt_psds_image._filename')
self._views.append(ObjectView(self._project, obj.strId(), fn,
viewParams={ORDER: labels,
VISIBLE: labels,
RENDER: labelRender,
ZOOM: 5,
MODE: MODE_MD}))
if obj.hasAttribute('outputMicrographs'):
fn = obj.outputMicrographs.getFileName()
labels = ('id enabled psdCorr._filename _filename _tilt_mean_corr _tilt_std_corr '
'_tilt_max_corr _tilt_min_corr _tilt_psds_image._filename ')
labelRender = (' psdCorr._filename _tilt_psds_image._filename')
self._views.append(ObjectView(self._project, obj.strId(), fn,
viewParams={ORDER: labels,
VISIBLE: labels,
RENDER: labelRender,
ZOOM: 5,
MODE: MODE_MD}))
if not(obj.hasAttribute('discardedMicrographs')) and not(obj.hasAttribute('outputMicrographs')):
self._views.append(self.infoMessage("Output micrographs has "
"not been produced yet."))
elif issubclass(cls, XmippProtCompareReprojections):
labels = ('id enabled _index _xmipp_image._filename _xmipp_imageRef._filename '
'_xmipp_imageResidual._filename _xmipp_imageCovariance._filename '
'_xmipp_cost _xmipp_zScoreResCov _xmipp_zScoreResMean _xmipp_zScoreResVar '
'_xmipp_continuousA _xmipp_continuousB _xmipp_continuousX _xmipp_continuousY')
labelRender = ("_xmipp_image._filename _xmipp_imageRef._filename "
"_xmipp_imageResidual._filename _xmipp_imageCovariance._filename")
try:
for outputName in obj.readOutputDict().values():
reprojections = getattr(obj, outputName)
fn = reprojections.getFileName()
self._views.append(ObjectView(self._project, reprojections.strId(), fn,
viewParams={ORDER: labels,
VISIBLE: labels,
SORT_BY: '_xmipp_cost asc',
RENDER: labelRender,
MODE: MODE_MD}))
except FileNotFoundError:
self._views.append(self.infoMessage('This may be an old version of this protocol, trying older viewer.'))
try:
fn = obj.reprojections.getFileName()
self._views.append(ObjectView(self._project, obj.reprojections.strId(), fn,
viewParams={ORDER: labels,
VISIBLE: labels,
SORT_BY: '_xmipp_cost asc',
RENDER: labelRender,
MODE: MODE_MD}))
except Exception as e:
self._views.append(self.infoMessage("There is a problem with the output: %s" % e))
except Exception as e:
self._views.append(self.infoMessage("There is not an output yet: %s" % e))
elif issubclass(cls, XmippProtCompareAngles):
fn = obj.outputParticles.getFileName()
labels = 'id enabled _index _filename _xmipp_shiftDiff _xmipp_angleDiff'
labelRender = "_filename"
self._views.append(ObjectView(self._project, obj.outputParticles.strId(), fn,
viewParams={ORDER: labels,
VISIBLE: labels,
SORT_BY: '_xmipp_angleDiff asc',
RENDER: labelRender,
MODE: MODE_MD}))
elif issubclass(cls, XmippProtConsensusLocalCTF):
fn = obj.outputParticles.getFileName()
labels = ('id enabled _index _filename _ctfModel._xmipp_ctfDefocusA '
'_ctfModel._xmipp_ctfDefocusResidual')
labelRender = "_filename"
self._views.append(ObjectView(self._project, obj.outputParticles.strId(), fn,
viewParams={ORDER: labels,
VISIBLE: labels,
SORT_BY: '_ctfModel._xmipp_ctfDefocusResidual',
RENDER: labelRender,
MODE: MODE_MD}))
elif issubclass(cls, XmippParticlePickingAutomatic):
micSet = obj.getInputMicrographs()
mdFn = getattr(micSet, '_xmippMd', None)
inTmpFolder = False
if mdFn:
micsfn = mdFn.get()
else: # happens if protocol is not an xmipp one
micsfn = obj._getExtraPath(micSet.getName() + '_micrographs.xmd')
writeSetOfMicrographs(micSet, micsfn)
inTmpFolder = True
posDir = obj._getExtraPath()
memory = showj.getJvmMaxMemory()
launchSupervisedPickerGUI(micsfn, posDir, obj, mode='review',
memory=memory, inTmpFolder=inTmpFolder)
# We need this case to happens before the ProtParticlePicking one
elif issubclass(cls, XmippProtAssignmentTiltPair):
if obj.getOutputsSize() >= 1:
coordsSet = obj.getCoordsTiltPair()
self._visualize(coordsSet)
elif issubclass(cls, XmippProtValidateNonTilt):
outputVols = obj.outputVolumes
labels = 'id enabled comment _filename weight'
self._views.append(ObjectView(self._project, outputVols.strId(),
outputVols.getFileName(),
viewParams={MODE: MODE_MD,
VISIBLE: labels,
ORDER: labels,
SORT_BY: 'weight desc',
RENDER: '_filename'}))
elif issubclass(cls, XmippProtMultiRefAlignability):
outputVols = obj.outputVolumes
labels = ('id enabled comment _filename weightAlignabilityPrecision '
'weightAlignabilityAccuracy')
self._views.append(ObjectView(self._project, outputVols.strId(),
outputVols.getFileName(),
viewParams={MODE: MODE_MD,
VISIBLE: labels,
ORDER: labels,
SORT_BY: 'weightAlignabilityAccuracy desc',
RENDER: '_filename'}))
fn = obj.outputParticles.getFileName()
labels = ('id enabled _index _filename _xmipp_scoreAlignabilityAccuracy '
'_xmipp_scoreAlignabilityPrecision')
labelRender = "_filename"
self._views.append(ObjectView(self._project, obj.outputParticles.strId(), fn,
viewParams={ORDER: labels,
VISIBLE: labels,
SORT_BY: '_xmipp_scoreAlignabilityAccuracy desc',
RENDER: labelRender,
MODE: MODE_MD}))
fn = obj._getExtraPath('vol001_pruned_particles_alignability.xmd')
md = emlib.MetaData(fn)
plotter = XmippPlotter()
plotter.createSubPlot('Soft-alignment validation plot',
'Angular Precision', 'Angular Accuracy')
plotter.plotMdFile(md, emlib.MDL_SCORE_BY_ALIGNABILITY_PRECISION,
emlib.MDL_SCORE_BY_ALIGNABILITY_ACCURACY,
marker='.', markersize=.55, color='red', linestyle='')
self._views.append(plotter)
elif issubclass(cls, XmippProtAngularGraphConsistency):
fn = obj.outputParticles.getFileName()
labels = ('id enabled _index _filename _xmipp_assignedDirRefCC '
'_xmipp_maxCCprevious _xmipp_graphCCPrevious _xmipp_distance2MaxGraphPrevious '
'_xmipp_maxCC _xmipp_graphCC _xmipp_distance2MaxGraph')
labelRender = "_filename"
self._views.append(ObjectView(self._project, obj.outputParticles.strId(), fn,
viewParams={ORDER: labels,
VISIBLE: labels,
SORT_BY: '_xmipp_assignedDirRefCC desc',
RENDER: labelRender,
MODE: MODE_MD}))
elif issubclass(cls, XmippProtExtractParticlesPairs):
self._visualize(obj.outputParticlesTiltPair)
else:
# Use default visualization defined in base class
DataViewer._visualize(self, obj, **kwargs)
return self._views
[docs] def getCTFViews(self, ctfSet):
# This could be used by any CTF viewer to show CTF plus, phaseShift plot
# if applies.
# Return phaseShift plot if apply
firstCtf = ctfSet.getFirstItem()
if firstCtf.hasPhaseShift():
phase_shift = []
for ctf in ctfSet.iterItems():
phShift = ctf.getPhaseShift()
phase_shift.append(phShift)
plotter = EmPlotter()
plotter.createSubPlot("Phase Shift estimation",
"Number of CTFs", "Phase Shift")
plotter.plotData(np.arange(0, len(phase_shift)), phase_shift)
self._views.append(plotter)
# Return Standard CTF view (showJ)
self._views.append(CtfView(self._project, ctfSet))