Source code for relion.viewers.viewer_postprocess

# ******************************************************************************
# *
# * Authors:     Jose Gutierrez (jose.gutierrez@cnb.csic.es) [1]
# *
# * [1] 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 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'
# *
# ******************************************************************************

from pyworkflow.viewer import ProtocolViewer

from .viewer_base import *
from ..protocols import ProtRelionPostprocess


[docs]class PostprocessViewer(ProtocolViewer): """ Visualization of Relion postprocess results. """ _targets = [ProtRelionPostprocess] _environments = [DESKTOP_TKINTER] _label = 'viewer postprocess'
[docs] def setProtocol(self, protocol): ProtocolViewer.setProtocol(self, protocol) self.__defineParams(self._form) self._createVarsFromDefinition()
def _defineParams(self, form): self._form = form def __defineParams(self, form): form.addSection(label='Visualization') group = form.addGroup('3D analysis') group.addParam('displayVol', params.EnumParam, choices=['slices', 'chimera'], display=params.EnumParam.DISPLAY_HLIST, default=VOLUME_SLICES, label='Display volume with', help='*slices*: display volumes as 2D slices along z axis.\n' '*chimera*: display volumes as surface with Chimera.') group.addParam('displayMaskedVol', params.EnumParam, choices=['slices', 'chimera'], display=params.EnumParam.DISPLAY_HLIST, default=VOLUME_SLICES, label='Display masked volume with', help='*slices*: display masked volume as 2D slices along z axis.\n' '*chimera*: display masked volume as surface with Chimera.') group.addParam('figure', params.EnumParam, default=0, choices=['new', 'active'], label='Figure', display=params.EnumParam.DISPLAY_HLIST, help="Plot in a new window vs the last opened one") group.addParam('resolutionPlotsFSC', params.EnumParam, choices=['Corrected', 'Unmasked Maps', 'Masked Maps', 'Phase Randomized Masked Maps', 'all'], default=FSC_CORRECTED, display=params.EnumParam.DISPLAY_COMBO, label='Display resolution plots (FSC)') group.addParam('resolutionThresholdFSC', params.FloatParam, default=0.143, expertLevel=LEVEL_ADVANCED, label='Threshold in resolution plots') group.addParam('guinierPlots', params.LabelParam, default=True, label='Display Guinier plots', help='Guinier plots are the logarithm of the ' 'amplitudes of the individual-frame ' 'reconstructions divided by the amplitudes of ' 'the average reconstruction from all frames ' 'versus the square of the resolution. Linear ' 'fits through these Guinier plots (which may ' 'often be performed for resolution higher ' 'than 20 Angstroms) then yield a slope (the ' 'B-factor) and an intercept (a ' 'resolution-independent scale-factor) which ' 'are used to device the resolution-dependent ' 'weghting scheme.') def _getVisualizeDict(self): self._load() return {'displayVol': self._showVolume, 'displayMaskedVol': self._showMaskedVolume, 'guinierPlots': self._showGuinier, 'resolutionPlotsFSC': self._showFSC } # ========================================================================= # ShowVolumes # ========================================================================= def _showVolumeShowj(self, volPath): return [DataView(volPath)] def _showVolumesChimera(self, volPath): """ Create a chimera script to visualize selected volumes. """ view = ChimeraView(volPath) return [view] def _showVolume(self, paramName=None): volPath = self.protocol._getExtraPath('postprocess.mrc:mrc') if self.displayVol == VOLUME_CHIMERA: return self._showVolumesChimera(volPath) elif self.displayVol == VOLUME_SLICES: return self._showVolumeShowj(volPath) def _showMaskedVolume(self, paramName=None): volPath = self.protocol._getExtraPath('postprocess_masked.mrc:mrc') if self.displayMaskedVol == VOLUME_CHIMERA: return self._showVolumesChimera(volPath) elif self.displayMaskedVol == VOLUME_SLICES: return self._showVolumeShowj(volPath) # ========================================================================= # plotFSC # ========================================================================= def _getFigure(self): return None if self.figure == 0 else 'active' def _showFSC(self, paramName=None): threshold = self.resolutionThresholdFSC.get() fscViewer = FscViewer(project=self.protocol.getProject(), threshold=threshold, protocol=self.protocol, figure=self._getFigure(), addButton=True) fscSet = self.protocol._createSetOfFSCs() modelStar = self.protocol._getExtraPath('postprocess.star') for label in self._getFSCLabels(): if os.path.exists(modelStar): legend = self._getLegend(label) fsc = self._plotFSC(None, modelStar, label, legend) fscSet.append(fsc) fscViewer.visualize(fscSet) return [fscViewer] # ROB this function is duplicated def _plotFSC(self, a, model_star, label, legend=None): if legend is None: legend = label table = Table(fileName=model_star, tableName='fsc') resolution_inv = table.getColumnValues('rlnResolution') frc = table.getColumnValues(label) fsc = FSC(objLabel=legend) fsc.setData(resolution_inv, frc) return fsc # ========================================================================= # plotGuinier # ========================================================================= def _showGuinier(self, paramName=None): xplotter = RelionPlotter(windowTitle='Guinier Plot') a = xplotter.createSubPlot("", 'Angstroms^-2', 'log(Amplitude)') legends = [] modelStar = self.protocol._getExtraPath('postprocess.star') for label in self._getGuinerLabels(): if os.path.exists(modelStar): self._plotGuinier(a, modelStar, label) legends.append(self._getGuinerLegend(label)) xplotter.showLegend(legends) a.grid(True) return [xplotter] def _plotGuinier(self, a, model, label): table = Table(fileName=model, tableName='guinier') resolSqInv = table.getColumnValues('rlnResolutionSquared') logAmp = table.getColumnValues(label) self.maxfsc = max(logAmp) self.minInv = min(resolSqInv) self.maxInv = max(resolSqInv) a.plot(resolSqInv, logAmp) a.xaxis.set_major_formatter(self._plotFormatter) # ========================================================================= # Utils Functions # ========================================================================= def _load(self): """ Load selected iterations and classes 3D for visualization mode. """ from matplotlib.ticker import FuncFormatter self._plotFormatter = FuncFormatter(self._formatFreq) def _formatFreq(self, value, pos): """ Format function for Matplotlib formatter. """ inv = 999. if value: inv = 1 / value return "1/%0.2f" % inv def _getFSCLabels(self): if self.resolutionPlotsFSC.get() == 0: return ['rlnFourierShellCorrelationCorrected'] elif self.resolutionPlotsFSC.get() == 1: return ['rlnFourierShellCorrelationUnmaskedMaps'] elif self.resolutionPlotsFSC.get() == 2: return ['rlnFourierShellCorrelationMaskedMaps'] elif self.resolutionPlotsFSC.get() == 3: return ['rlnCorrectedFourierShellCorrelationPhaseRandomizedMaskedMaps'] else: return ['rlnFourierShellCorrelationCorrected', 'rlnFourierShellCorrelationUnmaskedMaps', 'rlnFourierShellCorrelationMaskedMaps', 'rlnCorrectedFourierShellCorrelationPhaseRandomizedMaskedMaps'] def _getLegend(self, label): if label == 'rlnFourierShellCorrelationCorrected': return 'Corrected' elif label == 'rlnFourierShellCorrelationUnmaskedMaps': return 'Unmasked Maps' elif label == 'rlnFourierShellCorrelationMaskedMaps': return 'Masked Maps' else: return 'Phase Randomized Masked Maps' def _getGuinerLabels(self): return ['rlnLogAmplitudesOriginal', 'rlnLogAmplitudesWeighted', 'rlnLogAmplitudesSharpened', 'rlnLogAmplitudesIntercept'] def _getGuinerLegend(self, label): if label == 'rlnLogAmplitudesOriginal': return 'log(Amplitudes) Original' elif label == 'rlnLogAmplitudesWeighted': return 'log(Amplitudes) Weighted' elif label == 'rlnLogAmplitudesSharpened': return 'log(Amplitudes) Sharpened' else: return 'log(Amplitudes) Intercept'