Source code for ccpn.AnalysisStructure.gui.ProcessXplorStructureCalculationPopup
"""
Alpha version of a popup for processing a structure calculation using Xplor-NIH calculations.
"""
#=========================================================================================
# Licence, Reference and Credits
#=========================================================================================
__copyright__ = "Copyright (C) CCPN project (https://www.ccpn.ac.uk) 2014 - 2022"
__credits__ = ("Ed Brooksbank, Joanna Fox, Victoria A Higman, Luca Mureddu, Eliza Płoskoń",
"Timothy J Ragan, Brian O Smith, Gary S Thompson & Geerten W Vuister")
__licence__ = ("CCPN licence. See https://ccpn.ac.uk/software/licensing/")
__reference__ = ("Skinner, S.P., Fogh, R.H., Boucher, W., Ragan, T.J., Mureddu, L.G., & Vuister, G.W.",
"CcpNmr AnalysisAssign: a flexible platform for integrated NMR analysis",
"J.Biomol.Nmr (2016), 66, 111-124, http://doi.org/10.1007/s10858-016-0060-y")
#=========================================================================================
# Last code modification
#=========================================================================================
__modifiedBy__ = "$modifiedBy: Geerten Vuister $"
__dateModified__ = "$dateModified: 2022-03-09 21:13:06 +0000 (Wed, March 09, 2022) $"
__version__ = "$Revision: 3.1.0 $"
#=========================================================================================
# Created
#=========================================================================================
__author__ = "$Author: CCPN $"
__date__ = "$Date: 2021-04-27 16:04:57 +0100 (Tue, April 27, 2021) $"
#=========================================================================================
# Start of code
#=========================================================================================
import os
from PyQt5 import QtCore, QtGui, QtWidgets
from ccpn.ui.gui.widgets.PulldownListsForObjects import PeakListPulldown, ChemicalShiftListPulldown, ChainPulldown
from ccpn.ui.gui.popups.Dialog import CcpnDialogMainWidget
from ccpn.ui.gui.widgets.ListWidget import ListWidgetPair
from ccpn.ui.gui.widgets.Button import Button
from ccpn.ui.gui.lib.GuiPath import PathEdit
from ccpn.ui.gui.widgets.Label import Label
from ccpn.ui.gui.widgets import MessageDialog
from ccpn.ui.gui.widgets import CheckBox
from ccpn.ui.gui.widgets import Entry
from ccpn.ui.gui.widgets.HLine import LabeledHLine
from ccpn.ui.gui.widgets.FileDialog import OtherFileDialog, ProjectFileDialog
from ccpn.ui.gui.widgets.MessageDialog import showWarning, progressManager
from ccpn.ui.gui.widgets.Frame import Frame
from ccpn.framework.Application import getApplication
from ccpn.framework.Version import applicationVersion
from ccpn.framework.Preferences import getPreferences, XPLOR_NIH_PATH, TALOS_PATH
from ccpn.core.lib.ContextManagers import undoBlockWithoutSideBar, notificationEchoBlocking
from ccpn.AnalysisStructure.lib.runManagers.XplorNihRunManager import XplorNihRunManager
from ccpn.util.Path import aPath
if '3.1' in applicationVersion:
ccpnVersion310 = True
else:
ccpnVersion310 = False
[docs]class ProcessXplorCalculationFolderPopup(CcpnDialogMainWidget):
"""
Process the Xplor-NIH Structure calculation run by
- performing a cleanup
- creating an structure ensemble
- (optionally) generating the violations nef file
"""
FIXEDWIDTH = True
FIXEDHEIGHT = False
_GREY = '#888888'
title = 'Process Xplor-NIH Structure Calculation (Alpha)'
def __init__(self, parent=None, mainWindow=None, title=title, **kwds):
super().__init__(parent, setLayout=True, windowTitle=title,
size=(500, 10), minimumSize=None, **kwds)
if mainWindow:
self.mainWindow = mainWindow
self.application = mainWindow.application
self.current = self.application.current
self.project = mainWindow.project
else:
self.mainWindow = None
self.application = None
self.current = None
self.project = None
self._createWidgets()
# enable the buttons
# self.tipText = ''
# self.setOkButton(callback=self._okCallback, tipText =self.tipText, text='Clean up', enabled=True)
self.setCloseButton(callback=self.reject, tipText='Close')
self.setDefaultButton(CcpnDialogMainWidget.CLOSEBUTTON)
self.__postInit__()
# self._okButton = self.dialogButtons.button(self.OKBUTTON)
def _createWidgets(self):
"""Make the widgets
"""
_height = 30
row = -1
row += 1
self.pathLabel = Label(self.mainWidget, text="Xplor-NIH Run Directory", grid=(row, 0), hAlign='right')
self.pathData = PathEdit(self.mainWidget, grid=(row, 1), vAlign='t', editable=False)
self.pathData.setMinimumWidth(400)
_b = Button(self.mainWidget, grid=(row, 2), callback=self._getPathFromDialog,
icon='icons/directory', hPolicy='fixed')
_b.setFixedHeight(_height)
row += 1
Label(self.mainWidget, text="Run name", grid=(row, 0), hAlign='right' )
self.runName = Entry.Entry(self.mainWidget, grid=(row, 1), editable=False)
row += 1
Label(self.mainWidget, text="Run number", grid=(row, 0), hAlign='right')
self.runId = Entry.IntEntry(self.mainWidget, grid=(row, 1), editable=False)
row += 1
Label(self.mainWidget, text="State", grid=(row, 0), hAlign='right')
doneFrame = Frame(self.mainWidget, grid=(row, 1), gridSpan=(1,2), setLayout=True)
self.setupDone = CheckBox.CheckBox(doneFrame, grid=(0, 0), text='setup done', checked=False)
self.setupDone.setEnabled(False)
self.calculationDone = CheckBox.CheckBox(doneFrame, grid=(0, 1), text='calculated', checked=False)
self.calculationDone.setEnabled(False)
self.processDone = CheckBox.CheckBox(doneFrame, grid=(0, 2), text='processed', checked=False)
self.processDone.setEnabled(False)
self.importDone = CheckBox.CheckBox(doneFrame, grid=(0, 3), text='imported', checked=False)
self.importDone.setEnabled(False)
# settings
row += 1
LabeledHLine(self.mainWidget, text='Settings', grid=(row,0), gridSpan=(1,2),
style='DashLine', colour=self._GREY)
_preferences = getPreferences()
row += 1
Label(self.mainWidget, text="xplor_nih path", grid=(row, 0), hAlign='right')
self.xplorPath = Entry.Entry(self.mainWidget, grid=(row, 1), editable=False)
# self.xplorPath.set(_preferences.get(XPLOR_NIH_PATH))
row += 1
Label(self.mainWidget, text="talosN path", grid=(row, 0), hAlign='right')
self.talosnPath = Entry.Entry(self.mainWidget, grid=(row, 1), editable=False)
# self.talosnPath.set(_preferences.get(TALOS_PATH))
row += 1
self.checkLabel = Label(self.mainWidget, text="Use multicore CPU", grid=(row, 0), hAlign='right')
self.useParallel = CheckBox.CheckBox(self.mainWidget, grid=(row, 1))
self.useParallel.setEnabled(False)
row += 1
self.entryLabel = Label(self.mainWidget, text="Number of CPU Cores", grid=(row, 0), hAlign='right')
self.numberOfCores = Entry.IntEntry(self.mainWidget, grid=(row, 1), editable=False)
# Actions
row += 1
LabeledHLine(self.mainWidget, text='Actions', grid=(row,0), gridSpan=(1,2),
style='DashLine', colour=self._GREY)
# row += 1
# _b = Button(self.mainWidget, grid=(row, 1), text='Load Run Data', callback=self._loadRunData,
# hPolicy='expanding')
# _b.setFixedHeight(_height)
# row += 1
# Label(self.mainWidget, text="setup done", grid=(row, 0), hAlign='right')
# self.setupDone = CheckBox.CheckBox(self.mainWidget, grid=(row, 1), checked=False)
# self.setupDone.setEnabled(False)
#
# row += 1
# Label(self.mainWidget, text="calculation done", grid=(row, 0), hAlign='right')
# self.calculationDone = CheckBox.CheckBox(self.mainWidget, grid=(row, 1), checked=False)
# self.calculationDone.setEnabled(False)
row += 1
Label(self.mainWidget, text="Processed", grid=(row, 0), hAlign='right')
processDoneFrame = Frame(self.mainWidget, grid=(row, 1), gridSpan=(1,2), setLayout=True)
self.cleanupDone = CheckBox.CheckBox(processDoneFrame, grid=(0, 0), text='cleanup', checked=False)
self.cleanupDone.setEnabled(False)
self.violationDone = CheckBox.CheckBox(processDoneFrame, grid=(0, 1), text='violations', checked=False)
self.violationDone.setEnabled(False)
self.ensembleDone = CheckBox.CheckBox(processDoneFrame, grid=(0, 2), text='ensemble', checked=False)
self.ensembleDone.setEnabled(False)
# row += 1
# Label(self.mainWidget, text="cleanup done", grid=(row, 0), hAlign='right')
# self.cleanupDone = CheckBox.CheckBox(self.mainWidget, grid=(row, 1), checked=False)
# self.cleanupDone.setEnabled(False)
#
# row += 1
# Label(self.mainWidget, text="violations done", grid=(row, 0), hAlign='right')
# self.violationDone = CheckBox.CheckBox(self.mainWidget, grid=(row, 1), checked=False)
# self.violationDone.setEnabled(False)
#
# row += 1
# Label(self.mainWidget, text="ensemble done", grid=(row, 0), hAlign='right')
# self.ensembleDone = CheckBox.CheckBox(self.mainWidget, grid=(row, 1), checked=False)
# self.ensembleDone.setEnabled(False)
row += 1
Label(self.mainWidget, text="Generate violations.nef", grid=(row, 0), hAlign='right')
self.generateViolations = CheckBox.CheckBox(self.mainWidget,grid=(row,1), checked=True)
row += 1
self.processButton = Button(self.mainWidget, grid=(row, 1), text='Process', callback=self._processXplorCalculation,
hPolicy='expanding')
self.processButton.setFixedHeight(_height)
# Try to set a sensible initial path by finding the most recent xplor run
_path = self.project.application.dataPath / XplorNihRunManager._RUN_TYPE
_runs = [str(p) for p in _path.glob('*') \
if p.is_dir() and (p / XplorNihRunManager._JSON_FILE).exists()]
_runs.sort()
if len(_runs) > 0:
self.pathData.setText(str(_runs[-1]))
self._loadRunData()
def _getPathFromDialog(self):
"""Select a new path from using a dialog
"""
_path = self.project.application.dataPath / XplorNihRunManager._RUN_TYPE
dialog = ProjectFileDialog(parent=self.mainWindow, directory=str(_path))
dialog._show()
if (path := dialog.selectedFile()) is not None:
self.pathData.setText(str(path))
self._loadRunData()
def _loadRunData(self):
"""Load the data from json file in pathData
"""
_path = self.pathData.get()
if _path is None or len(_path) == 0:
showWarning(self.title, f'Path is undefined')
return
_path = aPath(_path)
if not _path.exists():
showWarning(self.title, f'Path {_path} not found')
return
_jsonPath = _path / XplorNihRunManager._JSON_FILE
if not _jsonPath.exists():
showWarning(self.title, f'Json file {_jsonPath} not found')
return
myRun = XplorNihRunManager(project=self.project)
myRun.restoreState(runPath=_path)
self.runName.set(myRun.runName)
self.runId.set(myRun.runId)
self.xplorPath.set(str(myRun._xplorPath))
self.talosnPath.set(str(myRun._talosnPath))
self.useParallel.set(myRun.useParallel)
self.numberOfCores.set(myRun.numberOfCores)
self.setupDone.set(myRun.setupDone)
self.calculationDone.set(myRun.calculationDone)
self.cleanupDone.set(myRun.cleanupDone)
self.violationDone.set(myRun.violationDone)
self.ensembleDone.set(myRun.ensembleDone)
self.processDone.set(myRun.cleanupDone and myRun.ensembleDone)
if (not myRun.setupDone) or \
(not myRun.calculationDone) or \
(myRun.cleanupDone and myRun.ensembleDone):
self.processButton.setEnabled(False)
else:
self.processButton.setEnabled(True)
def _processXplorCalculation(self):
"""Clicked 'Process': process the calculation files
"""
if not self.project:
raise RuntimeError('Project is not defined')
pathRun = self.pathData.get()
if not pathRun:
MessageDialog.showWarning(self.title, 'First define the path to Xplor-nih run data directory')
return
# process the calculation
myRun = XplorNihRunManager(project=self.project)
myRun.restoreState(runPath=self.pathData.get())
# Process the directory
with progressManager(self, f'Processing {myRun.runPath}'):
myRun.processCalculation()
if self.generateViolations.isChecked():
myRun._runViolationAnalysis()
myRun.saveState()
self._loadRunData()
MessageDialog.showInfo(self.title,
f'Processed directory {myRun.runPath}'
)
if __name__ == '__main__':
from ccpn.ui.gui.widgets.Application import TestApplication
app = TestApplication()
popup = ProcessXplorCalculationFolderPopup()
popup.show()
popup.raise_()
# app.start()