|
#$Id: webServices.py 289 2017-01-14 16:53:50Z sarkiss $
"""
This module is obsolete. It used to interfaces with Opal Web Service Client - http://www2.nbcr.net/data/docs/opal/docs/2.X/opal-py-index.html
"""
from AppService.AppService_client import AppServiceLocator,\
launchJobRequest, getOutputsRequest, queryStatusRequest, destroyRequest
from AppService.AppService_types import ns0
import pickle, os, urllib, re, glob, shutil, pipes
import wx
import wx.html
from miscCtrl import CheckMixListCtrl
UPDATE_TIME = 4000
import webbrowser
from xml.dom import minidom
from threading import Thread
from enthought.preferences.ui.api import PreferencesPage
from enthought.traits.api import Int, Str, Trait
from enthought.preferences.api import get_default_preferences
from enthought.traits.ui.api import View, Item
from vsModel import autodockRemotePreferencesPage as ap
class AutoDockWebService:
def __init__(self, frame):
self.appServicePort = None
self.frame = frame
def initService(self):
import urllib2
try:
ap.URI = urllib2.urlopen(ap.URI).geturl()# avoids redirect
except Exception, inst:
self.frame.log.error("Failed to connect to "+ ap.URI +"\n" +str(inst) )
self.appLocator = AppServiceLocator()
self.req = launchJobRequest()
self.urlOpener = urllib.FancyURLopener()
self.appServicePort = self.appLocator.getAppServicePort(ap.URI+'/'+ap.AutoDockService)
def GetAutogridWSPanel(self, parent, checkResults):
"""Return WebServicePanel as a GUI for AutoGrid Web Services.
parent is used to get all the arguments for the WebServicePanel.
checkResults is called when all results from WS are downloaded.
"""
if not self.appServicePort:
self.initService()
vsModel = parent.TopLevelParent.vsModel
kw = {}
kw['paramFilePath'] = vsModel.gpf_filename
kw['moleculePath'] = vsModel.macromolecule.parser.filename
kw['URL'] = ap.URI
kw['service'] = "/"+ap.AutoGridService
kw['outputFolder'] = vsModel.macromolecule.receptorFolder
kw['command'] = vsModel.gridCommand
kw['checkResults'] = checkResults
kw['outputFile'] = vsModel.glgOutput
panel = WebServicePanel(parent, **kw)
return panel
def StartAutoDockWS(self, parent):
if not self.appServicePort:
self.initService()
dpf_file = parent.vsModel.full_dpf_filename
input_file = os.path.basename(dpf_file)
self.req._argList = ' '.join(parent.vsModel.dockCommand[1:])
input_dpf = ns0.InputFileType_Def('inputFile')
input_dpf._name = input_file
dpfFile = open(dpf_file, 'r')
dpfFileString = dpfFile.read()
dpfFileString = dpfFileString.replace(os.pardir+os.sep,'')
dpfFileString = dpfFileString.replace('Ligands'+os.sep,'')
dpfFile.close()
input_dpf._contents = dpfFileString
inputFiles = []
inputFiles.append(input_dpf)
inputs = re.findall("\w*.\w*\.map ", dpfFileString)
inputs.extend(re.findall("\w*\.maps.fld", dpfFileString))
inputs.extend(re.findall("\w*\.maps.xyz", dpfFileString))
receptor = inputs[0].split('.')[0]
if dpfFileString.find('flexres ') != -1:
receptor = inputs[0].split('.')[0]
input_flex = ns0.InputFileType_Def('inputFile')
input_flex._name = receptor.replace('_rigid', '_flex')+'.pdbqt'
input_flex._contents = open(os.path.join(parent.vsModel.macromolecule.receptorFolder, input_flex._name)).read()
inputFiles.append(input_flex)
inputs.extend(input_flex._name)
if parent.autogridURL:
for input in inputs:
self.req._argList += " " +parent.autogridURL+"/"+input
else:
mapFiles = glob.glob(parent.vsModel.macromolecule.receptorFolder+os.sep+'*.map*')
for input in mapFiles: #need to include all map files for future references
input = input.strip()
ws_input = ns0.InputFileType_Def('inputFile')
ws_input._name = os.path.basename(input)
inputFile = open(input, 'r')
inputFileString = inputFile.read()
inputFile.close()
ws_input._contents = inputFileString
inputFiles.append(ws_input)
parent.Update()
molecule = parent.vsModel.ligand
input_pdbqs = ns0.InputFileType_Def('inputFile')
input_pdbqs._name = molecule
pdbqsFile = open(os.path.join(parent.vsModel.ligandsFolder, parent.vsModel.ligand), 'r')
pdbqsFileString = pdbqsFile.read()
pdbqsFile.close()
input_pdbqs._contents = pdbqsFileString
inputFiles.append(input_pdbqs)
self.req._inputFile = inputFiles
self.appServicePort = self.appLocator.getAppServicePort(ap.URI+'/'+ap.AutoDockService)
try:
parent.Update()
resp = self.appServicePort.launchJob(self.req)
except Exception, inst:
parent.frame.log.error("Failed to lunch at "+ ap.URI +"\nError message: " +str(inst) )
return None
#jobIDFile = os.path.join(os.path.split(dpf_file)[0],"remote_Jobs")
#open(jobIDFile,'w').write(ap.URI +"\t" + resp._jobID)
#print self.req._argList
if parent.autogridURL is None:#saves autogrid URL for future use
splitURL = ap.URI.split('/')
parent.autogridURL = splitURL[0]+"//"+splitURL[2]+"/"+resp._jobID
open(os.path.join(parent.vsModel.macromolecule.receptorFolder,'url'),'w').write(parent.autogridURL)
# else:
# splitURL = parent.autogridURL.split('/')
return resp._jobID
def destroy(self, jobID):
self.appServicePort.destroy(destroyRequest(jobID))
class VinaWebService:
def __init__(self, frame):
self.appServicePort = None
self.frame = frame
self.firstTime = True
def initService(self):
import urllib2
try:
ap.URI = urllib2.urlopen(ap.URI).geturl()# avoids redirect
except Exception, inst:
self.frame.log.error("Failed to connect to "+ ap.URI +"\n" +str(inst) )
self.appLocator = AppServiceLocator()
self.req = launchJobRequest()
self.urlOpener = urllib.FancyURLopener()
self.appServicePort = self.appLocator.getAppServicePort(ap.URI+'/'+ap.VinaService)
def Start(self, parent, ligand):
if not self.appServicePort:
self.initService()
ligandName = ligand+'.pdbqt'
self.req._argList = '--config conf.txt --ligand ' +pipes.quote(ligandName)
#start with input conf.txt file
input_conf = ns0.InputFileType_Def('inputFile')
input_conf._name = "conf.txt"
input_conf._contents = open(os.path.join(parent.basePath,"conf.txt"), 'r').read()
inputFiles = []
inputFiles.append(input_conf)
#adds the ligand
input_ligand = ns0.InputFileType_Def('inputFile')
input_ligand._name = ligandName
input_ligand._contents = open(os.path.join(parent.vsModel.ligandsFolder, ligandName), 'r').read()
inputFiles.append(input_ligand)
#now we need to provide input files for the receptor
if self.firstTime:
input_receptor = ns0.InputFileType_Def('inputFile')
input_receptor._name = parent.receptorName+".pdbqt"
input_receptor._contents = open(os.path.join(parent.basePath, input_receptor._name), 'r').read()
inputFiles.append(input_receptor)
if parent.receptorName.endswith('_rigid'): #include flexible part of the receptor
flex = parent.receptorName.replace('_rigid','_flex')+".pdbqt"
input_flex = ns0.InputFileType_Def('inputFile')
input_flex._name = flex
input_flex._contents = open(os.path.join(parent.basePath, flex), 'r').read()
inputFiles.append(input_flex)
else: #we pass url for the input files instead
self.req._argList += " " +parent.autogridURL+"/"+parent.receptorName+".pdbqt"
if parent.receptorName.endswith('_rigid'): #include flexible part of the receptor
self.req._argList += " " +parent.autogridURL+"/"+parent.receptorName.replace('_rigid','_flex')+".pdbqt"
self.req._inputFile = inputFiles
try:
parent.Update()
resp = self.appServicePort.launchJob(self.req)
except Exception, inst: # this can happend when number of jobs per IP per hour exceeds opal.ip.limit - https://github.com/nbcrrolls/opaltoolkit/tree/master/opal
parent.frame.log.error("Failed to lunch at "+ ap.URI +"\nError message: " +str(inst) )
return None
if self.firstTime:#saves autogrid URL for future use
splitURL = ap.URI.split('/')
self.prevURL = splitURL[0]+"//"+splitURL[2]+"/"+resp._jobID
return resp._jobID
def destroy(self, jobID):
self.appServicePort.destroy(destroyRequest(jobID))
# Define notification event for thread completion
EVT_RESULT_ID = wx.NewId()
def EVT_RESULT(win, func):
"""Define Result Event."""
win.Connect(-1, -1, EVT_RESULT_ID, func)
class ResultEvent(wx.PyEvent, wx.Event):
"""Simple event to carry arbitrary result data."""
def __init__(self, newlyFinishedJobs, finishedJobs, status, _baseURLs):
"""Init Result Event."""
wx.PyEvent.__init__(self)
self.SetEventType(EVT_RESULT_ID)
self.newlyFinishedJobs = newlyFinishedJobs
self.finishedJobs = finishedJobs
self.status = status
self.email = None
self._baseURLs = _baseURLs
# Thread class that executes processing
class WorkerThread(Thread):
"""Worker Thread Class."""
def __init__(self, notify_window):
"""Init Worker Thread Class."""
Thread.__init__(self)
self._notify_window = notify_window
self._want_abort = 0
self.savedURLs = []
self.finishedJobs = []
def run(self):
"""Run Worker Thread."""
# This is the code executing in the new thread. Simulation of
# a long process (well, 10s here) as a simple loop - you will
# need to structure your processing so that you periodically
# peek at the abort variable
urlOpener = urllib.FancyURLopener()
while(1):
newlyFinishedJobs = []
status = {}
_baseURLs = {}
try:
urlFile = open(self.file+"_copy",'w') #copy of the original in case application gets closed and data is lost
except: #TODO: store _copy in a db or some other way so that multiple remote jobs can be saved in PyRx quits
pass
for index, jobID in enumerate(self.jobIDs):
if jobID in self.finishedJobs: continue
resp = None
try:
resp = self.appServicePort.queryStatus(queryStatusRequest(jobID) )
except Exception, inst:
newlyFinishedJobs.append(jobID)
status[index] = "Error!"
if resp:
if resp._code == 8: # 8 = GramJob.STATUS_DONE
try:
resp = self.appServicePort.getOutputs(getOutputsRequest(jobID))
if self.vina:
remoteDLG = [x for x in resp._outputFile if x._name[-10:] =='_out.pdbqt']
else:#autodock
remoteDLG = [x for x in resp._outputFile if x._name[-3:] =='dlg']
txt = urlOpener.open(remoteDLG[0]._url).read()
open(self.outFiles[index],'w').write(txt)
self.savedURLs.append(remoteDLG[0]._url)
status[index] = "Finished"
newlyFinishedJobs.append(jobID)
except Exception, inst:
# print jobID, inst
newlyFinishedJobs.append(jobID)
status[index] = "Error!"
elif resp._code == 4: # GramJob.STATUS_FAILED
newlyFinishedJobs.append(jobID)
status[index] = "Failed"
else:
status[index] = resp._message
try:
urlFile.write(resp._baseURL+"\t"+self.outFiles[index]+"\n")
except: pass# ValueError: I/O operation on closed file
_baseURLs[index] = resp._baseURL
self.finishedJobs.extend(newlyFinishedJobs)
try:
wx.PostEvent(self._notify_window, ResultEvent(newlyFinishedJobs, self.finishedJobs, status, _baseURLs))
except Exception, inst:
#print newlyFinishedJobs, self.finishedJobs, status, inst
pass
newlyFinishedJobs = []
urlFile.close()
try:
shutil.copyfile(self.file+"_copy", self.file)
os.remove(self.file+"_copy")
except:
pass
if self._want_abort:
# Use a result of None to acknowledge the abort (of
# course you can use whatever you'd like or even
# a separate event type)
wx.PostEvent(self._notify_window, ResultEvent(None, None, None, None))
return
if len(self.finishedJobs) == len(self.jobIDs) or len(self.jobIDs) == 0:
return
def abort(self):
"""abort worker thread."""
# Method for use by main thread to signal an abort
self._want_abort = 1
def sendMail(self):
import smtplib
sender = "PyRx"
headers = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % (sender, to, "PyRx: Remote AutoDock jobs are completed.")
txt = """This message is send by PyRx to notify completion of remote AutoDock jobs.
Start PyRx to analyze results.
The following Docking Log Files (DLGs) are downloaded:\n"""
for item in savedURLs:
txt += item+"\n"
message = headers + text
mailServer = smtplib.SMTP('localhost')
mailServer.sendmail(sender, self.email, message)
mailServer.quit()
class QueryRemoteJobs:
def __init__(self, file, frame, vina=False):
"""This shows a list of remote jobs running.
file: is the input file that contains delimited list of job ID's and output files. See an example in autodockPage.RunWS.
frame: is the place holder
vina: is a boolean which was added later on to account for differences in AutoDock and Vina web services
"""
try:
lines = open(file).readlines()
if not lines: #empty file
os.remove(file)
return
except Exception,e:
frame.log.info("Exception in QueryRemoteJobs: \n"+str(e))
return
self.parent = None
self.jobIDs = []
self.outFiles = []
self.firstTime = True
self.canceled = []
self.pulse = True
self.vina = vina
if vina:
ws = frame.vinaWS
else:
ws = frame.autodockWS
if not ws.appServicePort:
ws.initService()
self.appLocator = ws.appLocator
self.queryPanel = wx.Panel(frame.view, -1)
sizer = wx.BoxSizer(wx.VERTICAL)
self.listCtrl = CheckMixListCtrl(self.queryPanel, style=wx.LC_REPORT | wx.LC_VRULES | wx.LC_HRULES| wx.LC_EDIT_LABELS)
self.gauge = wx.Gauge(self.queryPanel, -1)
sizer.Add(self.listCtrl,1,wx.EXPAND)
lin = wx.StaticLine(self.queryPanel)
sizer.Add(lin, 0, wx.EXPAND)
bottomSizer = wx.BoxSizer(wx.HORIZONTAL)
self.bottomSizer = bottomSizer
self.selectButton = wx.Button(self.queryPanel, -1, "Select")
bottomSizer.Add(self.selectButton, 0, wx.ALL, 2)
bottomSizer.Add(self.gauge, 1, wx.EXPAND | wx.ALL, 2)
self.cancelButton = wx.Button(self.queryPanel, -1, "Cancel Selected")
bottomSizer.Add(self.cancelButton, 0, wx.ALL, 2)
sizer.Add(bottomSizer, 0, wx.EXPAND|wx.ALIGN_BOTTOM)
self.queryPanel.SetSizer(sizer)
#ont = wx.SystemSettings_GetFont(0)
#ont.SetUnderlined(True)
self.listCtrl.ClearAll()
self.listCtrl.InsertColumn(0, "Job ID")
self.listCtrl.InsertColumn(1, "Progress")
self.listCtrl.SetColumnWidth(0, 500)
for index, line in enumerate(lines):
tmp = line.split('\t')
self.jobIDs.append(tmp[0][tmp[0].rfind('/')+1:])
self.outFiles.append(tmp[1].strip())
self.listCtrl.InsertStringItem(index, tmp[0])
self.listCtrl.SetStringItem(index, 1, "Please wait, this might take some time...")
#tem = self.listCtrl.GetItem(index)
#elf.listCtrl.SetItemTextColour(index, wx.BLUE)
#elf.listCtrl.SetItemFont(index, font)
self.listCtrl.resizeColumn(1)
if vina:
self.QappServicePort = self.appLocator.getAppServicePort(ap.URI+'/'+ap.VinaService)
else:
self.QappServicePort = self.appLocator.getAppServicePort(ap.URI+'/'+ap.AutoDockService)
self.file = file
self.frame = frame
frame.view.InsertPage(1, self.queryPanel, "Remote Jobs Query", select=True)
self.selectButton.Bind(wx.EVT_BUTTON, self.Select)
self.cancelButton.Bind(wx.EVT_BUTTON, self.Cancel)
#index = frame.view.GetPageIndex(self.queryPanel)
#wx.CallAfter(frame.view.SetSelection, index)
self.listCtrl.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
self.listCtrl.SetToolTipString("Double-click on a list item to open webbrowser.")
#"Navigator -> AutoDock -> Macromolecules/RemoteJobs contains the list of remote jobs."
EVT_RESULT(self.queryPanel, self.UpdateRemoteJobs)
self.worker = WorkerThread(self.queryPanel)
self.worker.jobIDs = self.jobIDs
self.worker.file = self.file
self.worker.appServicePort = self.QappServicePort
self.worker.outFiles = self.outFiles
self.worker.vina = vina
self.worker.start()
def OnLeftDClick(self, event):
index = self.listCtrl.GetFirstSelected()
if index != -1:
url = self.listCtrl.GetItem(index, 0).GetText()
webbrowser.open(url)
def UpdateRemoteJobs(self, event):
if event.status == None:
return
if self.pulse:
self.gauge.Pulse()
self.pulse = False
else:
self.pulse = True
for item in event.status:
if event._baseURLs.has_key(item):
try:
jobID = event._baseURLs[item].split("/")[-1]
if not jobID in self.canceled:
self.listCtrl.SetStringItem(item, 0, event._baseURLs[item])
self.listCtrl.SetStringItem(item, 1, event.status[item])
except: pass #this will get fixed during the next call
for job in event.newlyFinishedJobs:
if job in self.canceled: continue
index = self.jobIDs.index(job)
if os.path.exists(self.outFiles[index]):
try:
if self.vina:
self.frame.vinaWiz.analyzePage.AddDocking(self.outFiles[index])
else:
self.frame.autodockWiz.analyzePage.AddDocking(self.outFiles[index])
except Exception, inst:
url = self.listCtrl.GetItem(index, 0).GetText()
self.frame.log.error("Error in parsing "+url+".\n"+ str(inst))
if self.firstTime:
if self.vina:
adPage = self.frame.vinaWiz.runVinaPage
adPage.EnableButtons(True)
self.frame.vinaWiz.book.SetSelection(3)
else:
adPage = self.frame.autodockWiz.runAutoDock
adPage.EnableButtons(True)
self.frame.autodockWiz.book.SetSelection(4)
self.firstTime = False
#self.outFiles.pop(index)
#self.jobIDs.remove(job)
if len(event.finishedJobs) == len(self.jobIDs) or len(self.jobIDs) == 0: #all jobs are done
self.worker.abort()
try:
os.remove(self.file)
except: pass
if self.vina:
adPage = self.frame.vinaWiz.runVinaPage
adPage.runnig = False
adPage.EnableButtons(True)
try:
os.remove(os.path.join(self.frame.vsModel.etcFolder,'Vina_RemoteJobs'))
except:
pass
else:
adPage = self.frame.autodockWiz.runAutoDock
adPage.runnig = False
adPage.EnableButtons(True)
try:
os.remove(os.path.join(self.frame.vsModel.etcFolder,'AutoDock_RemoteJobs'))
except:
pass
if self.jobIDs:
try:
self.gauge.Destroy()
self.cancelButton.Destroy()
self.selectButton.Destroy()
except: pass #isn't worth debugging this
if job in self.jobIDs:
index = self.jobIDs.index(job)
if os.path.exists(self.outFiles[index]):
try:
if self.vina:
self.frame.vinaWiz.analyzePage.AddDocking(self.outFiles[index])
else:
self.frame.autodockWiz.analyzePage.AddDocking(self.outFiles[index])
except: pass
for index in range(self.listCtrl.GetItemCount()):
self.listCtrl.SetStringItem(index, 1, "")
closeButton = wx.Button(self.queryPanel, -1, "Close")
self.bottomSizer.Add((150, -1), 1, flag=wx.EXPAND | wx.ALIGN_RIGHT)
self.bottomSizer.Add(wx.StaticText(self.queryPanel, -1, "Finished running all remote jobs. Click on Close button to close this panel."),
0, wx.ALIGN_CENTER|wx.ALL, 2 )
self.bottomSizer.Add(closeButton, 0, wx.ALL, 2)
self.bottomSizer.Add((150, -1), 1, flag=wx.EXPAND | wx.ALIGN_RIGHT)
closeButton.Bind(wx.EVT_BUTTON, self.Close)
self.bottomSizer.Layout()
else:
if self.parent:
self.parent.SetActive(None)
self.Close(None)
return
def Close(self, event):
if self.vina:
try:
os.remove(os.path.join(self.frame.vsModel.etcFolder,'Vina_RemoteJobs'))
except:
pass
try:
os.remove(os.path.join(self.frame.vsModel.etcFolder,'Vina_RemoteJobs_old'))
except:
pass
else:
try:
os.remove(os.path.join(self.frame.vsModel.etcFolder,'AutoDock_RemoteJobs'))
except:
pass
try:
os.remove(os.path.join(self.frame.vsModel.etcFolder,'AutoDock_RemoteJobs_old'))
except:
pass
self.frame.view.SetSelection(self.frame.view.GetPageIndex(self.frame.canvas3D))
wx.CallAfter(self.frame.view.DeletePage, self.frame.view.GetPageIndex(self.queryPanel))
def queryStatus(self, jobID):
return self.appServicePort.queryStatus(queryStatusRequest(jobID))
def getOutputs(self, jobID):
return self.appServicePort.getOutputs(getOutputsRequest(jobID))
def Select(self, event):
menu = wx.Menu()
allMenu = menu.Append(wx.ID_ANY, "All")
self.queryPanel.Bind(wx.EVT_MENU, self.OnSelectAll, allMenu)
selectNoneMenu = menu.Append(wx.ID_ANY, "None")
self.queryPanel.Bind(wx.EVT_MENU, self.OnSelectNone, selectNoneMenu)
invertMenu = menu.Append(wx.ID_ANY, "Invert Selection")
self.queryPanel.Bind(wx.EVT_MENU, self.OnInvertSelection, invertMenu)
self.queryPanel.PopupMenu(menu)
event.Skip()
def OnSelectAll(self, event):
lenJobs = self.listCtrl.GetItemCount()
for index in range(lenJobs):
self.listCtrl.CheckItem(index)
def OnSelectNone(self, event):
lenJobs = self.listCtrl.GetItemCount()
for index in range(lenJobs):
self.listCtrl.CheckItem(index, False)
def OnInvertSelection(self, event):
lenJobs = self.listCtrl.GetItemCount()
for index in range(lenJobs):
if self.listCtrl.IsChecked(index):
self.listCtrl.CheckItem(index, False)
else:
self.listCtrl.CheckItem(index)
def Cancel(self, event):
lenJobs = self.listCtrl.GetItemCount()
removedJobs = []
removedListIndex = []
if lenJobs:
for index in range(lenJobs):
if self.listCtrl.IsChecked(index):
try:
if self.vina:
self.frame.vinaWS.destroy(self.jobIDs[index])
else:
self.frame.autodockWS.destroy(self.jobIDs[index])
self.frame.statusBar.SetStatusText("", 0)
except Exception, inst:
if hasattr(inst, 'fault'):
dom = minidom.parseString(inst.fault.AsSOAP())
msg = dom.getElementsByTagName('message')[0].firstChild.data
else:
msg = "no info is available on this job."
if len(self.jobIDs) > index:
self.frame.log.error(self.jobIDs[index]+" - "+msg)
else:
self.frame.log.error(str(index)+" - "+msg)
removedJobs.append(self.jobIDs[index])
removedListIndex.append(index)
if removedJobs:
self.canceled.extend(removedJobs)
for item in removedJobs:
self.jobIDs.remove(item)
if removedListIndex:
for index in removedListIndex:
self.listCtrl.DeleteItem(index)
else:
dlg = wx.MessageDialog(self.queryPanel, 'No Docking Log File is selected form the list.',
'No Item Selected',
wx.OK | wx.ICON_INFORMATION
)
dlg.ShowModal()
dlg.Destroy()
else:
self.Close(None)
class MyHtmlWindow(wx.html.HtmlWindow):
def __init__(self, parent):
wx.html.HtmlWindow.__init__(self, parent, -1, )
if "gtk2" in wx.PlatformInfo:
self.SetStandardFonts()
#DOTO text when needed
def OnLinkClicked(self, linkinfo):
dlg = wx.MessageDialog(self, linkinfo.GetHref(), 'Info', wx.OK)
dlg.ShowModal()
dlg.Destroy()
class WebServicePanel(wx.Panel):
"A generic Web Service panel"
def __init__(self, parent, **kw):
wx.Panel.__init__(self, parent, -1)
self.kw = kw
self.frame = parent
sizer = wx.BoxSizer(wx.VERTICAL)
box = wx.StaticBox(self, -1, "")
bsizer = wx.StaticBoxSizer(box, wx.VERTICAL)
URLsizer = wx.BoxSizer(wx.HORIZONTAL)
URLsizer.Add(wx.StaticText(self, -1, 'URL:'), 0, wx.ALL, 5)
self.URLTextCtrl = wx.TextCtrl(self, -1, "")
URLsizer.Add(self.URLTextCtrl, 1, wx.EXPAND)
bsizer.Add(URLsizer, 1, wx.EXPAND)
sizer.Add(bsizer, 0, wx.EXPAND)
self.html = MyHtmlWindow(self)
sizer.Add(self.html, 1, wx.EXPAND)
Lsizer = wx.BoxSizer(wx.HORIZONTAL)
self.label = wx.StaticText(self, -1, 'Status:')
Lsizer.Add(self.label, 1, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 2)
self.gauge = wx.Gauge(self, -1)
Lsizer.Add(self.gauge, 1, wx.EXPAND|wx.ALL, 5)
cancelButton = wx.Button(self, -1, "Cancel")
Lsizer.Add(cancelButton, 0, wx.ALL, 2)
sizer.Add(Lsizer, 0, wx.EXPAND|wx.ALIGN_BOTTOM)
self.SetSizer(sizer)
self.SetAutoLayout(True)
self.Bind(wx.EVT_TIMER, self.OnTestTimer)
cancelButton.Bind(wx.EVT_BUTTON, self.Cancel)
def Start(self):
self.appLocator = AppServiceLocator()
self.req = launchJobRequest()
self.req._argList = ' '.join(self.kw['command'][1:])
self.req._argList = self.req._argList.encode()
paramFilePath = os.path.basename(self.kw['paramFilePath'])
paramFileType = ns0.InputFileType_Def('inputFile')
paramFileType._name = paramFilePath
paramFile = open(self.kw['paramFilePath'], 'r')
self.paramtFileString = paramFile.read()
paramFile.close()
paramFileType._contents = self.paramtFileString
moleculePath = os.path.basename(self.kw['moleculePath'])
moleculeFileType = ns0.InputFileType_Def('inputFile')
moleculeFileType._name = moleculePath
moleculeFile = open(self.kw['moleculePath'], 'r')
moleculeFileString = moleculeFile.read()
moleculeFile.close()
moleculeFileType._contents = moleculeFileString
self.inputFiles = []
self.inputFiles.append(moleculeFileType)
self.inputFiles.append(paramFileType)
self.req._inputFile = self.inputFiles
self.ProcessInputs()
self.appServicePort = self.appLocator.getAppServicePort(self.kw['URL'] + self.kw['service'])
resp = self.appServicePort.launchJob(self.req)
self.JobID = resp._jobID
resp = self.appServicePort.queryStatus(queryStatusRequest(self.JobID))
self.URLTextCtrl.SetValue(resp._baseURL)
self.html.LoadPage(resp._baseURL+"/")
self.timer = wx.Timer(self)
self.timer.Start(UPDATE_TIME)
self.count = 0
def OnTestTimer(self, event):
resp = self.appServicePort.queryStatus(queryStatusRequest(self.JobID))
if resp._code == 8: # 8 = GramJob.STATUS_DONE
self.timer.Stop()
self.opener = urllib.FancyURLopener()
self.download_finished = False
self.new_download = True
self.file_counter = -1
self.label.SetLabel('Downloading')
self.resp = self.appServicePort.getOutputs(getOutputsRequest(self.JobID))
self.Bind(wx.EVT_TIMER, self.Download)
self.timer.Start(1, oneShot=True)
#self.html.LoadPage(resp._baseURL+"/")
open(os.path.join(self.kw['outputFolder'],'url'),'w').write(resp._baseURL)
else:
self.gauge.Pulse()
self.label.SetLabel('Status: ' + resp._message)
if self.count == 10:
self.html.LoadPage(resp._baseURL+"/")
self.count = 0
else:
self.count += 1
def Download(self, event):
if self.new_download:
self.file_counter += 1
if self.file_counter > self.resp._outputFile.__len__() - 1:
self.timer.Stop()
del self.timer
wx.CallAfter(self.kw['checkResults'], page=self, success=True, outputFile=self.kw['outputFile'])
return
self.gauge.SetValue(0)
remote_file = self.resp._outputFile[self.file_counter]
self.label.SetLabel("Downloading " + remote_file._name + " " +
str(self.file_counter+1) +" of " +
str(self.resp._outputFile.__len__()))
self._url = self.opener.open(remote_file._url)
self._out = open(os.path.join(self.kw['outputFolder'], remote_file._name) ,"w")
bytes = int(self._url.headers.dict['content-length'])
self._progress_counter = 0
self._download_bytes = bytes/100
if self._download_bytes == 0: self._download_bytes = 1
self.new_download = False
self.timer.Start(1, oneShot=True)
else:
self._progress_counter += 1
if self._progress_counter > 100:
self._progress_counter = 100
self.gauge.SetValue(self._progress_counter)
tmp = self._url.read(self._download_bytes)
if tmp:
self._out.write(tmp)
else:
self._url.close()
self._out.close()
self.new_download = True
self.timer.Start(5, oneShot=True)
def Cancel(self, event):
self.timer.Stop()
del self.timer
if self.vina:
self.Parent.TopLevelParent.vinaWS.destroy(self.JobID)
else:
self.Parent.TopLevelParent.autodockWS.destroy(self.JobID)
wx.CallAfter(self.kw['checkResults'], page=self, success=False )
def ProcessInputs(self):
"This is needed for AutoDock"
pass
if __name__ == '__main__':
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Testing...")
d = AutoGridPanel(self, None, None, None)
d.URLTextCtrl.SetValue("http://ws.nbcr.net:8080/app1200520598009/")
d.html.LoadPage("http://ws.nbcr.net:8080/app1200520598009/")
class TestApp(wx.App):
def OnInit(self):
frame = MainFrame()
frame.Show(True)
self.SetTopWindow(frame)
return True
app = TestApp(False)
app.MainLoop()
|