"""
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