|
#$Id: autodockPage.py 270 2016-03-13 01:59:01Z sarkiss $
"""AutoDockPage.py contains the following classes.
"""
import wx, os, glob, time
from wx.lib.buttons import ThemedGenBitmapTextButton
from enthought import tvtk
import runProcess
import wx.lib.foldpanelbar as fpb
from miscCtrl import CheckMixListCtrl
import utils
from AutoDockTools.DockingParameters import DockingParameters, genetic_algorithm_list4_2, \
genetic_algorithm_local_search_list4_2, local_search_list4_2,\
simulated_annealing_list4_2, docking_parameter_list4_2
from traitedDockingParameters import TraitedDockingParameters, TraitedGeneticAlgorithmParameters, \
GeneticAlgorithmParametersGUI, SimulatedAnnealingParametersGUI, TraitedSimulatedAnnealingParameters, \
TraitedLocalSearchParameters, LocalSearchParametersGUI, LamarckianGAParametersGUI, TraitedLamarckianGAParameters
try:
from webServices import QueryRemoteJobs
except:
pass
import urllib
from vsModel import autodockPreferencesPage, autodockRemotePreferencesPage
class RunAutoDock(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1)
sizer = wx.BoxSizer(wx.VERTICAL)
topSizer = wx.BoxSizer(wx.HORIZONTAL)
listBoxSizer = wx.BoxSizer(wx.VERTICAL)
#self.ligText = wx.StaticText(self, -1, "No ligand selected for virtural screening.")
self.listCtrl = CheckMixListCtrl(self, style=wx.LC_REPORT | wx.LC_VRULES | wx.LC_HRULES )
self.listCtrl.InsertColumn(0, "Ligand")
self.listCtrl.InsertColumn(1, "Progress")
listBoxSizer.Add(self.listCtrl, 1, wx.EXPAND)
#listBoxSizer.Add(self.ligText, 0, wx.ALL, 5)
topSizer.Add(listBoxSizer, 1, wx.EXPAND)
listBoxSizer = wx.BoxSizer(wx.VERTICAL)
#topSizer.Add(listBoxSizer, 1, wx.EXPAND)
box1_title = wx.StaticBox( self, -1, "Docking Algorithm" )
box1 = wx.StaticBoxSizer( box1_title, wx.VERTICAL )
grid1 = wx.FlexGridSizer( 0, 2, 0, 0 )
# 1st group of controls:
self.algo_ctrls = []
radio1 = wx.RadioButton( self, -1, " Lamarckian GA ", style = wx.RB_GROUP )
radio2 = wx.RadioButton( self, -1, " Genetic Algorithm (GA) " )
radio3 = wx.RadioButton( self, -1, " Simulated Annealing " )
radio4 = wx.RadioButton( self, -1, " Local Search " )
button1 = wx.Button(self, -1, "Docking Parameters...")
button2 = wx.Button(self, -1, "Docking Parameters...")
button3 = wx.Button(self, -1, "Docking Parameters...")
button4 = wx.Button(self, -1, "Docking Parameters...")
self.Bind(wx.EVT_BUTTON, self.OnLGAButton, button1)
self.Bind(wx.EVT_BUTTON, self.OnGAButton, button2)
self.Bind(wx.EVT_BUTTON, self.OnSAButton, button3)
self.Bind(wx.EVT_BUTTON, self.OnLSButton, button4)
self.algo_ctrls.append((radio1, button1))
self.algo_ctrls.append((radio2, button2))
self.algo_ctrls.append((radio3, button3))
self.algo_ctrls.append((radio4, button4))
for radio, button in self.algo_ctrls:
grid1.Add( radio, 1, wx.ALIGN_LEFT|wx.LEFT|wx.RIGHT, 10 )
grid1.Add( button, 1, wx.EXPAND )
box1.Add( grid1, 1, wx.EXPAND|wx.ALIGN_BOTTOM|wx.ALL, 5 )
topSizer.Add(box1, 1, wx.EXPAND|wx.LEFT, 5)
for radio, button in self.algo_ctrls:
self.Bind(wx.EVT_RADIOBUTTON, self.OnGroup1Select, radio )
radio.SetValue(0)
button.Enable(False)
button1.Enable(True)
sizer.Add(topSizer, 1, wx.EXPAND)
self.forwardButton = wx.Button(self, wx.ID_FORWARD, "")
self.backButton = wx.Button(self, wx.ID_BACKWARD, "")
bitmap = wx.ArtProvider_GetBitmap(wx.ART_EXECUTABLE_FILE, wx.ART_BUTTON)
self.runAutoDockButton = ThemedGenBitmapTextButton(self, -1, bitmap, "Run AutoDock")
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
lin = wx.StaticLine(self)
self.selectButton = wx.Button(self, -1, "Select")
buttonSizer.Add(self.selectButton, 0)
buttonSizer.Add(self.runAutoDockButton, 0, wx.LEFT|wx.RIGHT, 10)
buttonSizer.Add((10, -1), 1, flag=wx.EXPAND | wx.ALIGN_RIGHT)
buttonSizer.Add(self.backButton, 0, wx.ALIGN_RIGHT)
buttonSizer.Add(self.forwardButton, 0, wx.ALIGN_RIGHT)
self.runnig = False
sizer.Add(lin,0,wx.EXPAND)
sizer.Add(buttonSizer, 0, wx.EXPAND|wx.ALIGN_BOTTOM)
self.SetSizer(sizer)
self.Bind(wx.EVT_BUTTON, self.Next, self.forwardButton)
self.Bind(wx.EVT_BUTTON, self.Back, self.backButton)
self.Bind(wx.EVT_BUTTON, self.Run, self.runAutoDockButton)
self.Bind(wx.EVT_BUTTON, self.Select, self.selectButton)
#self.Bind(wx.EVT_SHOW, self.SetActive)
self.frame = self.TopLevelParent
self.vsModel = self.frame.vsModel
self.dlgFiles = []
self.docking_algorithm_parameter_list = genetic_algorithm_local_search_list4_2
self.dpo = DockingParameters()
self.vsModel.dpo = self.dpo
self.genetic_algorithm_parameters = TraitedGeneticAlgorithmParameters()
self.genetic_algorithm_local_search_parameters = TraitedLamarckianGAParameters()
self.simulated_annealing_parameters = TraitedSimulatedAnnealingParameters()
self.local_search_parameters = TraitedLocalSearchParameters()
wx.CallAfter(radio1.SetValue, 1)
self.buttons = [self.forwardButton, self.backButton, self.runAutoDockButton, self.selectButton]
def EnableButtons(self, enable=True):
for item in self.buttons:
item.Enable(enable)
def Select(self, event):
menu = wx.Menu()
allMenu = menu.Append(wx.ID_ANY, "All")
self.Bind(wx.EVT_MENU, self.OnSelectAll, allMenu)
invertMenu = menu.Append(wx.ID_ANY, "Invert Selection")
self.Bind(wx.EVT_MENU, self.OnInvertSelection, invertMenu)
self.PopupMenu(menu)
event.Skip()
def OnSelectAll(self, event):
lenLigands = len(self.ligands)
for index in range(lenLigands):
self.listCtrl.CheckItem(index)
def OnInvertSelection(self, event):
lenLigands = len(self.ligands)
for index in range(lenLigands):
if self.listCtrl.IsChecked(index):
self.listCtrl.CheckItem(index, False)
else:
self.listCtrl.CheckItem(index)
def OnGroup1Select( self, event ):
radio_selected = event.GetEventObject()
for radio, button in self.algo_ctrls:
if radio is radio_selected:
button.Enable(True)
else:
button.Enable(False)
def SetActive(self, event):
"This method is bound to wx.EVT_SHOW, i.e., invoked when this page is shown"
#check if ligand_types are set
if self.runnig:
self.EnableButtons(False)
return
else:
self.EnableButtons(True)
if not self.frame.autodockWiz.selectMoleculesPage.ligandPass or not hasattr(self.vsModel,'ligands'):
self.frame.autodockWiz.selectMoleculesPage.Next(None)
dlg = wx.MessageDialog(self, "Please select a ligand!",'A Message Box',
wx.OK| wx.ICON_EXCLAMATION)
dlg.ShowModal()
dlg.Destroy()
wx.CallAfter(self.Parent.SetSelection, 1)
return
if not self.frame.autodockWiz.selectMoleculesPage.macromoleculePass or not hasattr(self.frame.autodockWiz.runAutoGrid, 'macromolecules'):
dlg = wx.MessageDialog(self, "Please select macromolecule!",'A Message Box',
wx.OK| wx.ICON_EXCLAMATION)
dlg.ShowModal()
dlg.Destroy()
wx.CallAfter(self.Parent.SetSelection, 2)
return
ligands = self.vsModel.ligands
self.ligandCount = len(ligands)
self.listCtrl.ClearAll()
self.listCtrl.InsertColumn(0, "Ligand", width=250)
self.listCtrl.InsertColumn(1, "Progress")
self.ligands = []
for index, ligand in enumerate(ligands):
txt = os.path.splitext(os.path.basename(ligand))[0]
self.ligands.append(txt)
self.listCtrl.InsertStringItem(self.ligandCount, txt)
self.OnSelectAll(None)
msg = str(self.ligandCount)+" ligand(s) slected for virtual screening. Click Forward to continue."
self.frame.statusBar.SetStatusText(msg, 0)
self.dlgFiles = []
self.flagRunAutoGrid = False
for macromolecule in self.frame.autodockWiz.runAutoGrid.macromolecules:
#check if we have grid maps
basePath = macromolecule.receptorFolder
molName = macromolecule.receptor_stem
mapFiles = glob.glob(basePath+os.sep+'*.map')
if mapFiles:
for ligandType in self.vsModel.ligand_types:
map_str = os.path.join(basePath, molName+'.'+ligandType+'.map')
if not os.path.exists(map_str):
self.flagRunAutoGrid = True
break
else:
self.flagRunAutoGrid = True
break
if self.flagRunAutoGrid:
dlg = wx.MessageDialog(self, "Please run AutoGrid!",'A Message Box',
wx.OK| wx.ICON_EXCLAMATION)
dlg.ShowModal()
dlg.Destroy()
wx.CallAfter(self.Parent.SetSelection, 2)
return
def Next(self, event):
"Goto next page"
self.dlgFiles = []
selectedLigands = []
for index, ligand in enumerate(self.ligands):
if self.listCtrl.IsChecked(index):
selectedLigands.append(ligand)
self.flagRunAutoDock = False
for macromolecule in self.frame.autodockWiz.runAutoGrid.macromolecules:
basePath = macromolecule.receptorFolder
molName = macromolecule.receptor_stem
dlgFiles = glob.glob(basePath+os.sep+'*'+os.sep+'*.dlg')
if dlgFiles:
for ligand in selectedLigands:
dlg_str = os.path.join(basePath, ligand, molName+'_'+ligand+'.dlg')
if not dlg_str in dlgFiles:
self.flagRunAutoDock = True
break
self.dlgFiles.append(dlg_str)
else:
self.flagRunAutoDock = True
break
if self.flagRunAutoDock:
self.Run(None)
else:
self.Forward()
def Forward(self):
self.frame.autodockWiz.book.Enable()
self.frame.view.SetSelection(0) #3D Graphics
analyzePage = self.frame.autodockWiz.analyzePage
analyzePage.Clear()
maximum = len(self.dlgFiles)
if maximum > 2:
dlg = wx.ProgressDialog("Parsing Docking Log Files. Please Wait...",
"Parsing Docking Log Files. Please Wait...",
maximum = maximum,
parent=self,
style = wx.PD_CAN_ABORT
| wx.PD_APP_MODAL
| wx.PD_ELAPSED_TIME
#| wx.PD_ESTIMATED_TIME
| wx.PD_REMAINING_TIME
)
self.frame.Refresh()
keepGoing = True
analyzePage.list = []
for index, dlgFile in enumerate(self.dlgFiles):
if maximum > 2:
(keepGoing, skip) = dlg.Update(index, "Parsing "+os.path.split(dlgFile)[-1]+" ("+str(index+1) +" of " +str(maximum)+")")
if not keepGoing:
break
if os.path.exists(dlgFile):
try:
analyzePage.AddDocking(dlgFile, updateTable=False)
except Exception, inst:
self.frame.log.error("Error parsing "+dlgFile+
"\nPlease open that dlg file with a text editor and look for error messages or "+
"any other message that would give a clue as to what's wrong with the dlg.\n The following is the Exception:\n"+ str(inst))
else:
self.frame.log.error("Error in analyzePage.AddDocking for "+dlgFile)
if maximum > 2:
dlg.Destroy()
if keepGoing:
self.Parent.SetSelection(4)
analyzePage.conformations.items.extend(analyzePage.list)
def Back(self, event):
"Goto previous page"
self.Parent.SetSelection(2)
def Run(self, event):
self.frame.TryCommand(self.TryRun, None)
def TryRun(self, event):
"Run AutoDock for selected ligands"
executionMode = self.frame.autodockWiz.startPage.runAutoDockOptions[autodockPreferencesPage.executionMode]
if not executionMode == "Remote (Opal Web Services)" and not utils.which(autodockPreferencesPage.autodock):
dlg = wx.MessageDialog(self, "Cannot find "+autodockPreferencesPage.autodock+
"\n\n. Use Edit -> Preferences to set Autodock path.",
'Command not found.',
wx.OK| wx.ICON_EXCLAMATION)
dlg.ShowModal()
dlg.Destroy()
return
lenLigands = len(self.ligands)
removeLigand = []
for index, ligand in enumerate(self.ligands):
if not self.listCtrl.IsChecked(index):
removeLigand.append(ligand)
for ligand in removeLigand:
self.ligands.remove(ligand)
if not self.ligands: return
self.dlgFiles = []
if self.algo_ctrls[0][1].Enabled:
self.docking_algorithm_parameter_list = genetic_algorithm_local_search_list4_2
self.vsModel.dpo = self.genetic_algorithm_local_search_parameters.dpo
elif self.algo_ctrls[1][1].Enabled:
self.docking_algorithm_parameter_list = genetic_algorithm_list4_2
self.vsModel.dpo = self.genetic_algorithm_parameters.dpo
elif self.algo_ctrls[2][1].Enabled:
self.docking_algorithm_parameter_list = simulated_annealing_list4_2
self.vsModel.dpo = self.simulated_annealing_parameters.dpo
elif self.algo_ctrls[3][1].Enabled:
self.docking_algorithm_parameter_list = local_search_list4_2
self.vsModel.dpo = self.local_search_parameters.dpo
self.frame.statusBar.SetStatusText("Running AutoDock. Please Wait...", 0)
if executionMode == "Remote (Opal Web Services)":
self.RunWS()
return
else:
if self.Parent.GetPage(0).rb.GetSelection() == 0:
self.availableCPUs = autodockPreferencesPage.cpu_num
self.currentLigand = self.ligands[0]
self.currentMacromolecule = self.frame.autodockWiz.runAutoGrid.macromolecules[0]
self.ligandCount = len(self.ligands)
self.macromoleculeCount = len(self.frame.autodockWiz.runAutoGrid.macromolecules)
self.remainingJobs = self.ligandCount*self.macromoleculeCount
self.Bind(wx.EVT_TIMER, self.CheckAvailability)
self.timer = wx.Timer(self)
self.timer.Start(500)
else:
import pbsJobs
pbsJob = pbsJobs.startAutodock(self)
return
self.EnableButtons(False)
def CheckAvailability(self, event):
"Called to see if there available CPU? If yes, runs AutoDock"
index = self.ligands.index(self.currentLigand)
if self.availableCPUs:
self.listCtrl.SetStringItem(index, 1, "Running...")
macromolecule_index = self.frame.autodockWiz.runAutoGrid.macromolecules.index(self.currentMacromolecule)
try:
self.vsModel.macromolecule = self.currentMacromolecule
self.vsModel.PrepareDPF(self.vsModel.molDict[self.currentLigand], self.docking_algorithm_parameter_list)
self.processPanel = runProcess.ProcessPanel(self.GrandParent, self.vsModel.dockCommand,
self.vsModel.dockingFolder, self.vsModel.dlgOutput,
self.CheckResults)
self.frame.view.AddPage(self.processPanel, "AutoDock - "+self.currentMacromolecule.name+"/"+self.currentLigand, select=True)
self.processPanel.Start()
except Exception, inst:
self.frame.log.error("Exception in RunAutoDock.CheckAvailability\n"+ str(inst))
self.availableCPUs -= 1
macromolecule_index += 1
if macromolecule_index < self.macromoleculeCount:
self.currentMacromolecule = self.frame.autodockWiz.runAutoGrid.macromolecules[macromolecule_index]
else:
self.currentMacromolecule = self.frame.autodockWiz.runAutoGrid.macromolecules[0]
index += 1
if index == self.ligandCount: #last ligand
self.timer.Stop()
del self.timer
else:
self.currentLigand = self.ligands[index]
def CheckResults(self, page, outputFile, success=False):
"Called after AutoDock finished running"
self.frame.view.DeletePage(self.frame.view.GetPageIndex(page))
ligand = os.path.split(outputFile)[1]
under_str = ligand.split("_")
ligand = ligand[len(under_str[0])+1:-4]
try:
index = self.ligands.index(ligand)
except:
print self.ligands
print ligand
index = 0
if success:
self.listCtrl.SetStringItem(index, 1, "Finished")
if os.path.exists(outputFile):
try:
self.Parent.GetPage(4).AddDocking(outputFile)
except Exception, inst:
self.frame.documentsView.OpenDocument(outputFile)
self.frame.documentsView._docManager.GetCurrentView().GetTextCtrl().ScrollToEnd()
self.frame.log.error("Read "+outputFile+" for error messages.\n"+ str(inst))
else:
self.frame.statusBar.SetStatusText("AutoDock Terminated.", 0)
self.listCtrl.SetStringItem(index, 1, "Terminated")
self.runnig = False
self.EnableButtons(True)
return
self.availableCPUs += 1
self.remainingJobs -= 1
if self.remainingJobs == 0:
self.frame.statusBar.SetStatusText("Finished Running AutoDock.", 0)
self.flagRunAutoDock = False
wx.CallAfter(self.Parent.SetSelection, 4)
self.runnig = False
self.EnableButtons(True)
self.frame.autodockNav.RefreshMacroolecules()
def RunWS(self):
"""Run all jobs at once using Web Services.
We keep the info about remote job running in /etc folder which contains
tab delimited list of job ID's and output files.
Here is an example how this file might look like:
http://kryptonite.nbcr.net/appAutodockOpalService12928799230561557750071 /home/sargis/.mgltools/PyRx/Macromolecules/1crn/6040503/1crn_6040503.dlg
http://kryptonite.nbcr.net/appAutodockOpalService1292879923588-1953303830 /home/sargis/.mgltools/PyRx/Macromolecules/1crn/HIS/1crn_HIS.dlg
"""
self.autogridURL = None
self.jobIDs = []
self.runnig = True
lenLigands = len(self.ligands)
lenMacromolecules = len(self.frame.autodockWiz.runAutoGrid.macromolecules)
maximum = lenLigands*lenMacromolecules
dlg = wx.ProgressDialog("Sending AutoDock Web Services Request. Please Wait...",
"Sending AutoDock Web Services Request. Please Wait...",
maximum = maximum,
parent=self,
style = wx.PD_CAN_ABORT
| wx.PD_APP_MODAL
| wx.PD_ELAPSED_TIME
#| wx.PD_ESTIMATED_TIME
| wx.PD_REMAINING_TIME
)
self.frame.Refresh()
keepGoing = True
try:
for macro_index, macromolecule in enumerate(self.frame.autodockWiz.runAutoGrid.macromolecules):
urlPath = os.path.join(macromolecule.receptorFolder,'url')
if os.path.exists(urlPath):
dTime = time.time() - os.stat(urlPath).st_mtime
if dTime/(60*60*24) < 7: #days
self.autogridURL = open(urlPath).read()
#make sure all the map types exiits
tmpTxt = urllib.urlopen(self.autogridURL).read()
for ligandType in self.vsModel.ligand_types:
if not '.'+ligandType+'.map' in tmpTxt:
self.autogridURL = None
break
else:
#this is actually done in StartAutoDockWS below
self.listCtrl.SetStringItem(0, 1, "Uploading grid files for "+macromolecule.receptor_stem)
self.frame.Refresh()
self.frame.statusBar.SetStatusText("Uploading grid files for "+macromolecule.receptor_stem, 0)
self.listCtrl.resizeColumn(1) #otherwise list is not shown fully
self.vsModel.macromolecule = macromolecule
for index, ligand in enumerate(self.ligands):
self.vsModel.PrepareDPF(self.vsModel.molDict[ligand], self.docking_algorithm_parameter_list)
jobID = self.frame.autodockWS.StartAutoDockWS(parent=self)
if jobID:
self.listCtrl.SetStringItem(index, 1, "Running")
self.jobIDs.append(jobID)
else: #
self.EnableButtons()
keepGoing = False
break
self.dlgFiles.append(self.vsModel.dlgOutput)
(keepGoing, skip) = dlg.Update(index+lenLigands*macro_index, "Sending Data for "+ligand+" ("+str(index+1) +" of " +str(lenLigands)+")"\
"\nnMacromolecule is "+macromolecule.name+" ("+str(macro_index+1) +" of " +str(lenMacromolecules)+")")
if not keepGoing:
break
except Exception,e:
self.frame.log.error("Error in running AutoDock via web services: \n"+str(e))
dlg.Destroy()
if keepGoing:
urlFilePath = os.path.join(self.vsModel.etcFolder,'AutoDock_RemoteJobs')
urlFile = open(urlFilePath,'w')
splitURL = self.autogridURL.split('/')
baseURL = splitURL[0]+"//"+splitURL[2]+"/"
for index, jobID in enumerate(self.jobIDs):
urlFile.write(baseURL+jobID+"\t" + self.dlgFiles[index]+"\n")
urlFile.close()
self.frame.autodockWS.parent = self
remJobs = QueryRemoteJobs(urlFilePath, self.frame)
remJobs.parent = self
self.frame.statusBar.SetStatusText("Running AutoDock at "+autodockRemotePreferencesPage.URI, 0)
self.runnig = True
else:
self.frame.statusBar.SetStatusText("Canceled Sending AutoDock Jobs.", 0)
self.runnig = False
self.SetActive(None)
for job in self.jobIDs:
self.frame.autodockWS.destroy(job)
def OnLGAButton(self, event):
dlg = LamarckianGAParametersGUI(self, self.genetic_algorithm_local_search_parameters)
dlg.ShowModal()
dlg.Destroy()
def OnGAButton(self, event):
dlg = GeneticAlgorithmParametersGUI(self, self.genetic_algorithm_parameters)
dlg.ShowModal()
dlg.Destroy()
def OnSAButton(self, event):
dlg = SimulatedAnnealingParametersGUI(self, self.simulated_annealing_parameters)
dlg.ShowModal()
dlg.Destroy()
def OnLSButton(self, event):
dlg = LocalSearchParametersGUI(self, self.local_search_parameters)
dlg.ShowModal()
dlg.Destroy()
|