""" qtgui/downloadPdb.py: CCP4MG Molecular Graphics Program Copyright (C) 2001-2008 University of York, CCLRC Copyright (C) 2009-2010 University of York Copyright (C) 2012 STFC This library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3, modified in accordance with the provisions of the license to address the requirements of UK law. You should have received a copy of the modified GNU Lesser General Public License along with this library. If not, copies may be downloaded from http://www.ccp4.ac.uk/ccp4license.php 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 Lesser General Public License for more details. """ import sys import os from PyQt4 import QtGui,QtCore import MGSimpleDialog def setup_proxies(): import urllib2 from global_definitions import PM proxy_uri = PM('download_preferences').get('http_proxy') user = PM('download_preferences').get('http_user') passwd = PM('download_preferences').get('http_password') if proxy_uri == "": return None proxy = urllib2.ProxyHandler({'http': proxy_uri}) proxy_auth_handler = urllib2.HTTPBasicAuthHandler() # No idea if this is correct if user != "": proxy_auth_handler.add_password(None, uri=proxy_uri, user=user, passwd=passwd) opener = urllib2.build_opener(proxy, proxy_auth_handler) return opener class downloadPdbCore(QtCore.QObject): def __init__(self): QtCore.QObject.__init__(self) self.interrupt_dl = False def downloadMain(self,url=None,urlCIF=None,finishedSignal="DownloadFinished"): import urllib2 if url is None: url = self.url if urlCIF is None: urlCIF = self.urlCIF if not url: self.emit(QtCore.SIGNAL("Error"),'No pdb to download' ) #self.progressBar.reset() self.emit(QtCore.SIGNAL("ProgressBarRangeChanged"),0,100) self.emit(QtCore.SIGNAL("ProgressChanged"),0) return suffix = ".pdb" try: opener = setup_proxies() if opener: dl = opener.open(url) else: dl = urllib2.urlopen(url) except: try: opener = setup_proxies() if opener: dl = opener.open(urlCIF) else: dl = urllib2.urlopen(urlCIF) if urlCIF.endswith(".gz"): suffix = ".cif.gz" else: suffix = ".cif" except: exc_type, exc_value,exc_tb = sys.exc_info()[:3] sys.stderr.write(str(exc_type)+'\n') sys.stderr.write(str(exc_value)+'\n') self.emit(QtCore.SIGNAL("Error"),'Error opening urls '+ str(url) + ' and\n' + str(urlCIF)+'\nPlease check that you have internet connection.\nand that the pdb id is valid.\nAlso the data may not exist on the server.') return import tempfile self.localFile = tempfile.mkstemp(suffix=suffix) print 'downloadPdb.download localFile',self.localFile try: info = dl.info() contentLength = -1 for h in info.headers: if h.find('Content-Length:')>-1: cl = h.split(':')[1].strip() try: contentLength = int(cl) self.emit(QtCore.SIGNAL("ProgressBarRangeChanged"),0,100) except: self.emit(QtCore.SIGNAL("ProgressBarRangeChanged"),0,0) self.emit(QtCore.SIGNAL("ProgressChanged"),0) contentLength = -1 break readBytes = 0 buffer = "" read = dl.read(100) while len(read)>0 and not self.interrupt_dl: os.write(self.localFile[0],read) buffer = buffer + read readBytes = readBytes + len(read) pc = int(float(readBytes)/contentLength * 100) if contentLength>-1: self.emit(QtCore.SIGNAL("ProgressChanged"),pc) read = dl.read(100) dl.close() if not self.interrupt_dl: fname = self.localFile[1] os.close(self.localFile[0]) self.emit(QtCore.SIGNAL("ProgressBarRangeChanged"),0,100) self.emit(QtCore.SIGNAL("ProgressChanged"),0) print "Emitting",finishedSignal,"from",QtCore.QThread.currentThread(); sys.stdout.flush() self.emit(QtCore.SIGNAL(finishedSignal),fname) # Just in case self.interrupt_dl = False self.interrupt_dl = False except: self.interrupt_dl = False print "Error gettting",url exc_type, exc_value = sys.exc_info()[:2] print exc_type print exc_value os.close(self.localFile[0]) # Is this thread-safe? #self.emit(QtCore.SIGNAL("Error"),'Error getting file '+ str(self.dataID.text())+'\n'+ str(exc_value) ) self.emit(QtCore.SIGNAL("Error"),'Error getting file'+ str(exc_value) ) self.emit(QtCore.SIGNAL("ProgressBarRangeChanged"),0,100) self.emit(QtCore.SIGNAL("ProgressChanged"),0) #self.progressBar.reset() class downloadMultipleACs(MGSimpleDialog.MGSimpleDialog,downloadPdbCore): FileSaved = QtCore.pyqtSignal(str) DownloadedAllFiles = QtCore.pyqtSignal() def InterruptAndClose(self): self.interrupt_dl = True self.progressBar.setRange(0,100) self.progressBar.setValue(0) self.Close() def __init__(self,parent=None): MGSimpleDialog.MGSimpleDialog.__init__(self,parent) self.interrupt_dl = False self.setWindowTitle(self.tr("Download multiple Accession Codes")) layout = QtGui.QVBoxLayout() self.progressBar = QtGui.QProgressBar() self.progressBar.setRange(0,100) self.progressBar.setValue(0) self.connect(self,QtCore.SIGNAL("ProgressChanged"),self.progressBar.setValue) self.connect(self,QtCore.SIGNAL("ProgressChanged"),self.progressBar.update) self.connect(self,QtCore.SIGNAL("ProgressChanged"),self.update) self.connect(self,QtCore.SIGNAL("ProgressBarRangeChanged"),self.progressBar.setRange) self.textLabel = QtGui.QLabel() self.connect(self,QtCore.SIGNAL("LabelTextChanged"),self.textLabel.setText) dialog_buttons = QtGui.QDialogButtonBox() ok_button = dialog_buttons.addButton(self.tr("Download"),QtGui.QDialogButtonBox.AcceptRole) cancel_button = dialog_buttons.addButton(QtGui.QDialogButtonBox.Cancel) self.connect(dialog_buttons,QtCore.SIGNAL("accepted()"),self.download) self.connect(cancel_button,QtCore.SIGNAL('clicked()'),self.InterruptAndClose) layout.addWidget(self.progressBar) layout.addWidget(self.textLabel) layout.addWidget(dialog_buttons) self.setLayout(layout) self.title = "Download multiple accession codes" self.CreateMenuEntry() self.Close() self.files = [] self.directory = None import UtilityThread self.FileSaved.connect(self.loadSavedFile) self.DownloadedAllFiles.connect(self.Close) self.downloadThread = UtilityThread.UtilityThread(self.downloadFiles) def loadSavedFile(self,fname): from global_definitions import MAINWINDOW print "Saved",str(fname.toUtf8()) MAINWINDOW().openFile(str(fname.toUtf8()),use_current_style=1,show_wizard_choices=0) def setDirectory(self,directory): self.directory = directory def setFiles(self,files): self.files = files if len(files) < 1: self.textLabel.setText('') return text = 'Download accession codes: ' for f in files[:-1]: text = text + f + ', ' text = text + files[-1] text = text[:100] if len(text) == '100': text = text + '...' self.textLabel.setText(text) def downloadFiles(self): import re import shutil site = 'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=nuccore' id = '&id=34577062,24475906' site_suffix = '&rettype=fasta&retmode=text' for i,f in zip(range(len(self.files)),self.files): self.emit(QtCore.SIGNAL("ProgressBarRangeChanged"),0,0) self.emit(QtCore.SIGNAL("ProgressChanged"),0) url = site+'&id='+f+site_suffix #print url; sys.stdout.flush() print self.tr("Downloading "+f+". "+str(i+1)+" of "+str(len(self.files))) self.emit(QtCore.SIGNAL("LabelTextChanged"),self.tr("Downloading "+f+". "+str(i+1)+" of "+str(len(self.files)))) self.downloadMain(url) fname = self.localFile[1] #print fname if self.directory != None: shutil.copy2(fname,os.path.abspath(os.path.join(self.directory,f+'.fasta'))) else: shutil.copy2(fname,os.path.abspath(f+'.fasta')) os.unlink(fname) print self.tr("Download of "+f+" complete. "+str(i+1)+" of "+str(len(self.files))) self.emit(QtCore.SIGNAL("LabelTextChanged"),self.tr("Download of "+f+" complete. "+str(i+1)+" of "+str(len(self.files)))) if self.directory != None: self.FileSaved.emit(os.path.abspath(os.path.join(self.directory,f+'.fasta'))) else: self.FileSaved.emit(os.path.abspath(f+'.fasta')) self.DownloadedAllFiles.emit() def download(self): self.progressBar.reset() self.progressBar.setRange(0,0) self.progressBar.setValue(0) self.interrupt_dl = False self.downloadThread.start() class downloadMultiplePdbs(MGSimpleDialog.MGSimpleDialog,downloadPdbCore): FileSaved = QtCore.pyqtSignal(str) DownloadedAllFiles = QtCore.pyqtSignal() def InterruptAndClose(self): self.interrupt_dl = True self.progressBar.setRange(0,100) self.progressBar.setValue(0) self.Close() def __init__(self,parent=None): MGSimpleDialog.MGSimpleDialog.__init__(self,parent) self.interrupt_dl = False self.setWindowTitle(self.tr("Download multiple pdbs")) layout = QtGui.QVBoxLayout() self.progressBar = QtGui.QProgressBar() self.progressBar.setRange(0,100) self.progressBar.setValue(0) self.connect(self,QtCore.SIGNAL("ProgressChanged"),self.progressBar.setValue) self.connect(self,QtCore.SIGNAL("ProgressChanged"),self.progressBar.update) self.connect(self,QtCore.SIGNAL("ProgressChanged"),self.update) self.connect(self,QtCore.SIGNAL("ProgressBarRangeChanged"),self.progressBar.setRange) self.textLabel = QtGui.QLabel() self.connect(self,QtCore.SIGNAL("LabelTextChanged"),self.textLabel.setText) dialog_buttons = QtGui.QDialogButtonBox() ok_button = dialog_buttons.addButton(self.tr("Download"),QtGui.QDialogButtonBox.AcceptRole) cancel_button = dialog_buttons.addButton(QtGui.QDialogButtonBox.Cancel) self.connect(dialog_buttons,QtCore.SIGNAL("accepted()"),self.download) self.connect(cancel_button,QtCore.SIGNAL('clicked()'),self.InterruptAndClose) layout.addWidget(self.progressBar) layout.addWidget(self.textLabel) layout.addWidget(dialog_buttons) self.setLayout(layout) self.title = "Download multiple pdbs" self.CreateMenuEntry() self.Close() self.files = [] self.directory = None import UtilityThread self.FileSaved.connect(self.loadSavedFile) self.DownloadedAllFiles.connect(self.Close) self.downloadThread = UtilityThread.UtilityThread(self.downloadFiles) def loadSavedFile(self,fname): from global_definitions import MAINWINDOW print "Saved",str(fname.toUtf8()) MAINWINDOW().openFile(str(fname.toUtf8()),use_current_style=1,show_wizard_choices=0) def setDirectory(self,directory): self.directory = directory def setFiles(self,files): self.files = files if len(files) < 1: self.textLabel.setText('') return text = 'Download pdbs: ' for f in files[:-1]: text = text + f + ', ' text = text + files[-1] text = text[:100] if len(text) == '100': text = text + '...' self.textLabel.setText(text) def downloadFiles(self): import re import shutil from global_definitions import PM site = PM('download_preferences').get('preferred_site') com = PM('download_preferences').get(site+'_Download_PDB') comCIF = PM('download_preferences').get(site+'_Download_CIF') for i,f in zip(range(len(self.files)),self.files): self.emit(QtCore.SIGNAL("ProgressBarRangeChanged"),0,0) self.emit(QtCore.SIGNAL("ProgressChanged"),0) url = re.sub('PDBID',f.lower(),com) urlCIF = re.sub('PDBID',f.lower(),comCIF) #print url; sys.stdout.flush() self.emit(QtCore.SIGNAL("LabelTextChanged"),self.tr("Downloading "+f+". "+str(i+1)+" of "+str(len(self.files)))) self.downloadMain(url,urlCIF) fname = self.localFile[1] #print fname if fname.endswith(".cif"): suffix = ".cif" elif fname.endswith(".cif.gz"): suffix = ".cif.gz" else: suffix = ".pdb" if self.directory != None: shutil.copy2(fname,os.path.abspath(os.path.join(self.directory,f+suffix))) else: shutil.copy2(fname,os.path.abspath(f+'.pdb')) os.unlink(fname) self.emit(QtCore.SIGNAL("LabelTextChanged"),self.tr("Download of "+f+" complete. "+str(i+1)+" of "+str(len(self.files)))) if self.directory != None: self.FileSaved.emit(os.path.abspath(os.path.join(self.directory,f+suffix))) else: self.FileSaved.emit(os.path.abspath(f+suffix)) self.DownloadedAllFiles.emit() def download(self): self.progressBar.reset() self.progressBar.setRange(0,0) self.progressBar.setValue(0) self.interrupt_dl = False self.downloadThread.start() class downloadPdb(MGSimpleDialog.MGSimpleDialog,downloadPdbCore): def saveFile(self,sfname=''): import os,shutil,MGApplication from global_definitions import MAINWINDOW #print 'downloadPdb.saveFile sfname ',sfname if not os.path.splitext(sfname)[1]: sfname = sfname+'.pdb' fname = self.localFile[1] shutil.copy2(fname,sfname) ''' This is not working - use createMolData instead event = QtGui.QFileOpenEvent(sfname) app = MGApplication.QtApp() app.flush() app.postEvent(app,event) ''' if hasattr(self,"fileDialog") and hasattr(self.fileDialog,"close"): self.fileDialog.close() del self.fileDialog MAINWINDOW().openFile(sfname,use_current_style=1,show_wizard_choices=0) self.Close() def saveDownloadedFile(self,fname=''): print "saveDownloadedFile",fname; sys.stdout.flush() self.emit(QtCore.SIGNAL("LabelTextChanged"),self.tr("Download complete")) self.dataID.setDisabled(0) import os if not os.path.exists(fname) or not int(os.stat(fname).st_size)>10: self.emit(QtCore.SIGNAL("Error"),'No file downloaded for '+str(self.dataID.text())+'\nIs there a PDB entry with this name?') self.resetSelection() return if fname.endswith(".cif"): suffix = ".cif" elif fname.endswith(".cif.gz"): suffix = ".cif.gz" else: suffix = ".pdb" defaultFileName = str(self.dataID.text())+suffix #print 'saveDownloadedFile.defaultFileName',defaultFileName import mgWidgets self.fileDialog = mgWidgets.MGSaveFileDialog(self,filters=["Model coordinate files (*"+suffix+")"], defaultFileName=defaultFileName) self.connect(self.fileDialog,QtCore.SIGNAL('save'),self.saveFile) self.fileDialog.show() def download(self): import re from global_definitions import PM pdbid = str(self.dataID.text()).lower() if len(pdbid)<3: return self.dataID.setDisabled(1) self.textLabel.setText(self.tr("Preparing download of "+pdbid)) site = PM('download_preferences').get('preferred_site') com = PM('download_preferences').get(site+'_Download_PDB') comCIF = PM('download_preferences').get(site+'_Download_CIF') self.url = re.sub('PDBID',pdbid,com) self.urlCIF = re.sub('PDBID',pdbid,comCIF) print 'download url',self.url self.progressBar.reset() self.progressBar.setRange(0,0) self.progressBar.setValue(0) self.emit(QtCore.SIGNAL("LabelTextChanged"),self.tr("Downloading ")) self.interrupt_dl = False self.downloadThread.start() def InterruptAndClose(self): self.interrupt_dl = True self.dataID.setDisabled(0) self.progressBar.setRange(0,100) self.progressBar.setValue(0) self.Close() def resetSelection(self): self.textLabel.setText('') self.progressBar.setValue(0) def __init__(self,parent=None): MGSimpleDialog.MGSimpleDialog.__init__(self,parent) from global_definitions import PM self.interrupt_dl = False self.setWindowTitle(self.tr("Download coordinates")) codeLayout = QtGui.QHBoxLayout() pdbLabel = QtGui.QLabel(self.tr("PDB id:")) self.dataID = QtGui.QLineEdit() self.dataID.setToolTip(self.tr("Enter 4-letter pdb id and press return")) codeLayout.addWidget(pdbLabel) codeLayout.addWidget(self.dataID) self.progressBar = QtGui.QProgressBar() self.progressBar.setRange(0,100) self.progressBar.setValue(0) self.textLabel = QtGui.QLabel() self.connect(self,QtCore.SIGNAL("ProgressChanged"),self.progressBar.setValue) self.connect(self,QtCore.SIGNAL("ProgressBarRangeChanged"),self.progressBar.setRange) self.connect(self,QtCore.SIGNAL("LabelTextChanged"),self.textLabel.setText) dialog_buttons = QtGui.QDialogButtonBox() ok_button = dialog_buttons.addButton(self.tr("Download"),QtGui.QDialogButtonBox.AcceptRole) cancel_button = dialog_buttons.addButton(QtGui.QDialogButtonBox.Cancel) help_button = dialog_buttons.addButton(QtGui.QDialogButtonBox.Help) self.viewSite = dialog_buttons.addButton('Search '+PM('download_preferences').get('preferred_site')+' database',QtGui.QDialogButtonBox.ActionRole) self.connect(dialog_buttons,QtCore.SIGNAL("accepted()"),self.download) self.connect(ok_button,QtCore.SIGNAL("clicked()"),self.download) self.connect(cancel_button,QtCore.SIGNAL('clicked()'),self.InterruptAndClose) self.connect(help_button,QtCore.SIGNAL('clicked()'),self.handleHelp) self.connect(self,QtCore.SIGNAL("DownloadFinished"),self.saveDownloadedFile) self.connect(self,QtCore.SIGNAL("Error"),self.reportError) #self.connect(self.dataID,QtCore.SIGNAL("returnPressed()"),self.download) self.connect(self.viewSite,QtCore.SIGNAL("clicked()"),self.viewDatabase) self.viewSite.setToolTip('View database search tool in CCP4mg web browser') self.viewSite.setAutoDefault(0) layout = QtGui.QVBoxLayout() layout.addLayout(codeLayout) layout.addWidget(self.progressBar) layout.addWidget(self.textLabel) layout.addWidget(dialog_buttons) self.setLayout(layout) import UtilityThread self.downloadThread = UtilityThread.UtilityThread(self.downloadMain) self.setWindowModality(QtCore.Qt.ApplicationModal) def handleHelp(self): from global_definitions import HELPBROWSER HELPBROWSER().loadMgHelp('atom_typing.html#downloading') def details(self): from global_definitions import PREFERENCESWINDOW PREFERENCESWINDOW().loadNewWidget('download_preferences') def reportError(self,message=''): QtGui.QMessageBox.warning(self,'Error downloading PDB',message) self.dataID.setDisabled(0) self.progressBar.reset() self.progressBar.setRange(0,100) self.progressBar.setValue(0) def viewDatabase(self): from global_definitions import PM, HELPBROWSER site = PM('download_preferences').get('preferred_site') HELPBROWSER().loadFile(PM('download_preferences').get(site+'_Search')) def createDownloadPM(): import services pm = services.ParamsManager ( name='download_preferences', title='Download options', gui=[ 'pdb_header','preferred_site','EBI_Download_PDB','EBI_Download_CIF','EBI_Search','RCSB_Search','RCSB_Download_PDB','RCSB_Download_CIF','PDBJapan_Download_PDB','PDBJapan_Download_CIF','PDBJapan_Search','proxy_header','http_proxy','http_user','http_password'], default = { 'preferred_site' : 'EBI', 'EBI_Search' : "www.ebi.ac.uk/msd-srv/msdlite/index.html", 'RCSB_Search': "www.rcsb.org/pdb", #'RCSB_Download_PDB': "http://www.rcsb.org/pdb/cgi/export.cgi/PDBID.pdb?job=download;pdbId=PDBID;opt=show;format=PDB;pre=1&compression=gz" , 'RCSB_Download_PDB': "http://www.rcsb.org/pdb/files/PDBID.pdb" , 'RCSB_Download_CIF': "http://www.rcsb.org/pdb/files/PDBID.cif" , 'EBI_Download_PDB' : 'ftp://ftp.ebi.ac.uk/pub/databases/msd/pdb_uncompressed/pdbPDBID.ent' , 'EBI_Download_CIF' : 'http://www.ebi.ac.uk/pdbe/entry-files/download/PDBID.cif' , 'PDBJapan_Download_PDB' : 'ftp://www.pdbj.org/pdb_nc/pdbPDBID.ent', 'PDBJapan_Download_CIF' : 'ftp://ftp.pdbj.org/mmcif/PDBID.cif.gz', 'http_proxy': '', 'http_user': '', 'http_password': '', 'PDBJapan_Search' : "pdbjs3.protein.osaka-u.ac.jp/xPSSS/index.html" }, #'EBI_Download_PDB' : "'http://oca.ebi.ac.uk/oca-bin/send-x-pdb?id=' + pdbid " , definition = { 'preferred_site' : dict(type=str, label='Preferred download site',style='combobox',menu = ['EBI','RCSB','PDBJapan'],alias= ['EBI','RCSB','PDBJapan']), 'EBI_Search' : dict(type=str,label='EBI search page',style='lineedit'), 'RCSB_Search' : dict(type=str,label='RCSB search page',style='lineedit'), 'RCSB_Download_PDB' : dict(type=str,label='RSCB PDB download command',style='lineedit') , 'RCSB_Download_CIF' : dict(type=str,label='RSCB CIF download command',style='lineedit') , 'EBI_Download_PDB' : dict(type=str,label='EBI PDB download command',style='lineedit') , 'EBI_Download_CIF' : dict(type=str,label='EBI CIF download command',style='lineedit') , 'PDBJapan_Download_PDB' : dict(type=str, label='PDBJapan download command',style='lineedit'), 'PDBJapan_Download_CIF' : dict(type=str, label='PDBJapan CIF download command',style='lineedit'), 'PDBJapan_Search' : dict(type=str,label=' PDBJapan search page',style='lineedit'), 'pdb_header': dict(type=str, label='PDB download options', style='label'), 'proxy_header': dict(type=str, label='HTTP proxy options', style='label'), 'http_proxy' : dict(type=str, label='HTTP proxy',style='lineedit'), 'http_user' : dict(type=str, label='HTTP username',style='lineedit'), 'http_password' : dict(type=str, label='HTTP password',style='lineedit') }, help = 'web.html' ) return pm