Source code for phenix.viewers.viewer_emringer

# **************************************************************************
# *
# * Authors:     Roberto Marabini
# *              Marta Martinez
# *
# * 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'
# *
# **************************************************************************

import json
import os
import collections
import glob

import PIL
from PIL import Image
from tkinter import *
from tkinter import messagebox
from phenix.protocols.protocol_emringer import PhenixProtRunEMRinger
from pyworkflow.protocol.params import LabelParam, EnumParam
from pyworkflow.viewer import DESKTOP_TKINTER, WEB_DJANGO, ProtocolViewer
from pwem.viewers import TableView, Chimera
from phenix import Plugin
from pwem import Domain

[docs]def errorWindow(tkParent, msg): try: # if tkRoot is null the error message may be behind # other windows messagebox.showerror("Error", # bar title msg, # message parent=tkParent) except: print(("Error:", msg))
[docs]class PhenixProtRunEMRingerViewer(ProtocolViewer): """ Viewer for Phenix program EMRinger """ _label = 'EMRinger Viewer' _environments = [DESKTOP_TKINTER, WEB_DJANGO] _targets = [PhenixProtRunEMRinger] EMRINGERTOTALTHRESH = 'Total.threshold_scan.png' EMRINGERSUBPLOTSFILENAME = 'residue_subplots.py' def __init__(self, **kwargs): ProtocolViewer.__init__(self, **kwargs) self.dataDict = json.loads(str(self.protocol.stringDataDict), object_pairs_hook=collections.OrderedDict) self.plots = glob.glob(self.protocol._getExtraPath("*_plots"))[0] self.EMRINGERSUBPLOTSFILENAME = self.protocol._getExtraPath( self.EMRINGERSUBPLOTSFILENAME) def _defineParams(self, form): form.addSection(label="Volume and models") form.addParam('displayMapModel', LabelParam, label="Volume and model in ChimeraX", help="Display of input volume, input pdb that has to be" "refined and final refined model of the structure.") form.addSection(label='EM Ringer results') # group = form.addGroup('Overall results') form.addParam('showFinalResults', LabelParam, label="Summary Table of Results", help="Table of Final Results\n\nOptimal Threshold: " "Electron potential map cutoff value at which the " "maximum EMRinger score was obtained.\nRotamer " "Ratio: Percentage of rotameric residues at the " "Optimal threshold value.\nMax Zscore: Z-score " "computed to determine the significance of the " "distribution at the Optimal threshold value.\n" "Model Length: Total of non-gamma-branched, " "non-proline aminoacids with a non-H gamma atom " "used in global EMRinger score computation.\n" "EMRinger Score: Maximum EMRinger score calculated " "at the Optimal Threshold.\n") form.addParam('showThresholdScan', LabelParam, label="Threshold Scan", help="Statistics across all thresholds\n\n" "Blue line: EMRinger Score regarding " "the map electron potential. " "The maximum value of EMRinger Score " "determines the Optimal Threshold.\nRed " "line: Percentage of rotameric residues " "regarding the map electron potential.") self.thresList = [str("%0.3f" % thres) for thres in self.dataDict[ '_thresholds']] _maxScoreIndex = self.dataDict['_maxScoreIndex'] form.addParam('threshold', EnumParam, choices=self.thresList, default=_maxScoreIndex, label="Density threshold", help="Choose one of the 20 map density cutoff values " "used to compute the percentage of rotameric " "residues. The Optimal threshold, at which the " "maximum EMRinger score was obtained, " "is shown by default.\n" ) form.addParam('showPeakCount', LabelParam, label="Peak count for the selected density threshold", help="Histograms for rotameric (blue) and non-rotameric " "(red) residues at the selected map density.") self.chainList = self.dataDict['_chains'] form.addParam('chain', EnumParam, choices=self.chainList, default=0, label="Chain", help="Choose one of the model chains. The first chain " "is shown by default.") form.addParam('showRollingWindows', LabelParam, label="Rolling window for the selected chain.", help="Visualize the rolling window EMRinger analysis of " "your selected chain to distinguish regions of " "improved model quality.This analysis was " "performed on rolling sliding 21-residue windows " "along the primary sequence of proteins.") self.residueList = self.dataDict['_residues_format'] form.addParam('residue', EnumParam, choices=self.residueList, default=0, label="Residue", help="Choose one of the non-H gamma atom-containing " "residues (at least with one Chi angle) " "located in one of the chains in the " "position indicated. ") form.addParam('showRingerResults', LabelParam, label="Ringer results for the selected residue.", help="Individual plots for each Chi angle of the " "selected residue. Numeric values are showed in " "the extra/*.csv file.") def _getVisualizeDict(self): return { 'displayMapModel': self._displayMapModel, 'showFinalResults': self._visualizeFinalResults, 'showThresholdScan': self._showThresholdScan, 'showPeakCount': self._showPeakCount, 'showRollingWindows': self._showRollingWindows, 'showRingerResults': self._showRingerResults } def _displayMapModel(self, e=None): bildFileName = self.protocol._getExtraPath("axis_output.bild") _inputVol = self.protocol.inputVolume.get() if _inputVol is None: _inputVol = self.protocol.inputStructure.get().getVolume() dim = _inputVol.getDim()[0] sampling = _inputVol.getSamplingRate() Chimera.createCoordinateAxisFile(dim, bildFileName=bildFileName, sampling=sampling) counter = 1 fnCmd = self.protocol._getExtraPath("chimera_output.cxc") f = open(fnCmd, 'w') # change to workingDir # If we do not use cd and the project name has an space # the protocol fails even if we pass absolute paths f.write('cd %s\n' % os.getcwd()) # reference axis model = 0 f.write("open %s\n" % bildFileName) f.write("cofr 0,0,0\n") # set center of coordinates # input 3D map counter += 1 # 1 fnVol = self._getInputVolume() if fnVol is not None: EMRINGERFILENAME = self.protocol._getExtraPath( self.protocol.EMRINGERFILE) f.write("open %s\n" % EMRINGERFILENAME) x, y, z = fnVol.getOrigin(force=True).getShifts() sampling = fnVol.getSamplingRate() f.write("volume #%d style surface voxelSize %f\nvolume #%d origin " "%0.2f,%0.2f,%0.2f\n" % (counter, sampling, counter, x, y, z)) # input PDB (usually from coot) counter += 1 # 2 pdbFileName = self.protocol.inputStructure.get().getFileName() f.write("open %s\n" % pdbFileName) f.close() # run in the background chimeraPlugin = Domain.importFromPlugin('chimera', 'Plugin', doRaise=True) chimeraPlugin.runChimeraProgram(chimeraPlugin.getProgram(), fnCmd + "&", cwd=os.getcwd()) return [] def _getInputVolume(self): if self.protocol.inputVolume.get() is None: fnVol = self.protocol.inputStructure.get().getVolume() else: fnVol = self.protocol.inputVolume.get() return fnVol def _visualizeFinalResults(self, e=None): headerList = ['statistic', 'value'] dataList = [] for k, v in list(self.dataDict.items()): if k[0] == "_": continue elif isinstance(v, int): dataList.append((k, v)) elif isinstance(v, float): dataList.append((k, "%0.3f" % v)) if not dataList: errorWindow(self.getTkRoot(), "No data available") return TableView(headerList=headerList, dataList=dataList, mesg="Final Statistics for Model/Map Pair\n", title="EMRinger: Final Results Summary", height=len(dataList), width=250, padding=40)
[docs] def showImage(self, fileName): fileName = os.path.join(self.plots, fileName) img = PIL.Image.open(fileName) img.show()
def _showThresholdScan(self, e=None): self.showImage(self.EMRINGERTOTALTHRESH) def _showPeakCount(self, e=None): threshold_index = int(self.threshold) fileName = "%s.histogram.png" % self.thresList[threshold_index] self.showImage(fileName) def _showRollingWindows(self, e=None): chain_index = int(self.chain) fileName = "%s_rolling.png" % self.chainList[chain_index] self.showImage(fileName) def _showRingerResults(self, e=None): i = int(self.residue) index = int(self.dataDict['_residues_dict'][self.residueList[i]]) # emringer main file mainDataFile = glob.glob(self.protocol._getExtraPath( "*_emringer.pkl"))[0] command = """from mmtbx.ringer.em_rolling import easy_pickle import matplotlib.pyplot as plt # process file '%s' file_name='%s' ringer_results = easy_pickle.load(file_name) figure = plt.figure() # (figsize=(20,1000)) def show_residue (residue, show_background_boxes=True) : subplots = [] for i in range(1, residue.n_chi + 1) : chi = residue.get_angle(i) if (chi is None) : continue if (len(subplots) > 0) : p = figure.add_subplot(4, 1, i, sharex=subplots[0]) else: p = figure.add_subplot(4, 1, i) p.set_title(residue.format()) p.set_position([0.15, 0.725 - 0.225*(i-1), 0.8, 0.225]) x = [ k*chi.sampling for k in range(len(chi.densities)) ] p.plot(x, chi.densities, 'r-', linewidth=1) if (chi.fofc_densities is not None) : p.plot(x, chi.fofc_densities, linestyle='--', color=[0.5,0.0,1.0]) p.axvline(chi.angle_current, color='b', linewidth=2, linestyle='--') p.axhline(0, color=(0.4,0.4,0.4), linestyle='--', linewidth=1) if show_background_boxes: p.axhspan(0.3,1,facecolor="green",alpha=0.5) p.axhspan(-1,0.3,facecolor="grey",alpha=0.5) p.set_xlim(0,360) p.set_ylabel("Rho") p.set_xlabel("Chi" + str(i)) subplots.append(p) plt.subplots_adjust(left = 0.18, bottom = 0.00, right = 0.94, top = 0.93, wspace = 0.80, hspace = 0.43) plt.tight_layout() plt.show() index = %d show_residue(ringer_results[index]) """ % (mainDataFile, mainDataFile, index) with open(self.EMRINGERSUBPLOTSFILENAME, "w") as f: f.write(command) # execute file with phenix.python Plugin.runPhenixProgram("", self.EMRINGERSUBPLOTSFILENAME)