def run(self): if not self.saveinput(): return env = os.environ.copy() env['OMMPROTOCOL_SLAVE'] = '1' env['PYTHONIOENCODING'] = 'latin-1' self.task = Task("OMMProtocol for {}".format(self.filename), cancelCB=self._clear_cb, statusFreq=((1, ), 1)) self.subprocess = Popen( ['ommprotocol', self.filename], stdout=PIPE, stderr=PIPE, progressCB=self._progress_cb, #universal_newlines=True, bufsize=1, env=env) self.progress = SubprocessTask("OMMProtocol", self.subprocess, task=self.task, afterCB=self._after_cb) self.task.updateStatus("Running OMMProtocol") self.queue = LifoQueue() thread = Thread(target=enqueue_output, args=(self.subprocess.stdout, self.queue)) thread.daemon = True # thread dies with the program thread.start() self.ensemble = _TrajProxy() self.molecule = self.ensemble.molecule = self.gui.ui_chimera_models.getvalue( ) self.ensemble.name = 'Trajectory for {}'.format(self.molecule.name) self.ensemble.startFrame = self.ensemble.endFrame = 1 self.movie_dialog = MovieDialog(self.ensemble, externalEnsemble=True) self.gui.Close()
def _initBlast(self, program, db, queryName, querySeq, evalue, matrix, passes): self.program = program self.db = db self.queryName = queryName self.params = (querySeq, evalue, matrix, passes) from WebServices.AppService_types import ns0 from WebServices.opal_client import OpalService inputFile = ns0.InputFileType_Def("inputFile") inputFile._name = "query.fa" inputFile._contents = self.makeFasta(queryName, querySeq) service = "BlastproteinServicePort" argList = "-P %s -d %s -i %s -o %s -e %s -M %s -p %s" % ( program, db, inputFile._name, self.outputFile, evalue, matrix, passes) try: self.opal = OpalService(service) except: import traceback, sys print "Traceback from Blast request:" traceback.print_exc(file=sys.stdout) print """ Typically, if you get a TypeError, it's a problem on the remote server and it should be fixed shortly. If you get a different error or get TypeError consistently for more than a day, please report the problem using the Report a Bug... entry in the Help menu. Please include the traceback printed above as part of the problem description.""" from chimera import NonChimeraError raise NonChimeraError("Blast web service appears " "to be down. See Reply Log " "for more details.") self.opal.launchJob(argList, _inputFile=[inputFile]) from chimera.tasks import Task self.task = Task(self._title(), self.cancelCB, self.statusCB)
def run(self, *xyz, **options): """ Launch a NCIPlot essay for specified xyz files and options. Read on self.create_nci_method documentation for further info. Notes ----- This function uses threads, queues, tasks and subprocesses, so it can be a bit difficult to understand for newcomers. `subprocess` is used to launch an external program (nciplot, in this case), and `task` is a Chimera feature to monitor that process in the tasks panels. It also allows to print status updates to the bottom bar. `task` and `subprocess` are synced with Chimera's `monitor`, which includes a very useful `afterCB` parameter: a callable that will be called when the process ends. If we needed to get it in realtime, we should add queues and threads. As a workaround, we need to get the stdout to an async queue (in realtime!) with a separate thread. >>> from threading import Thread >>> from Queue import Queue >>> def enqueue_output(out, queue): for line in iter(out.readline, b''): queue.put(line) out.close() >>> self.queue = Queue() >>> thread = Thread(target=enqueue_output, args=(self.subprocess.stdout, self.queue)) >>> thread.daemon = True # thread dies with the program >>> thread.start() Then, we can read the stdout from the queue: >>> self.queue.put(None) # Sentinel value. When iter gets this, it stops. >>> for line in iter(self.queue.get, None): >>> # do stuff Check this SO answer for more info: http://stackoverflow.com/questions/375427/ non-blocking-read-on-a-subprocess-pipe-in-python/4896288#4896288 """ nci_file = osTemporaryFile(suffix='.nci') oldworkingdir = os.getcwd() tmpdir, tmpfile = os.path.split(nci_file) if 'name' not in options or options['name'] is None: options['name'] = tmpfile[:-4] nci_input = self.create_nci_input(xyz, **options) os.chdir(tmpdir) with open(nci_file, 'w') as f: f.write(nci_input.read()) name = ', '.join(os.path.basename(f) for f in xyz) self._tmpdir = tmpdir self.task = Task("NCIPlot for {}".format(name), cancelCB=self._clear_task) self.subprocess = Popen([self.binary, nci_file], stdout=PIPE, progressCB= lambda p: 0) monitor("NCIPlot", self.subprocess, task=self.task, afterCB=self._after_cb) self.task.updateStatus("Running NCIPlot") os.chdir(oldworkingdir)
def _initSession(self, program, db, queryName, params, running, opalData): self.program = program self.db = db self.queryName = queryName self.params = params from WebServices.opal_client import OpalService self.opal = OpalService(sessionData=opalData) if not running: self.task = None else: from chimera.tasks import Task self.task = Task(self._title(), self.cancelCB, self.statusCB)
def __init__(self, queryName, querySeq, evalue, matrix, finishCB): from WebServices.AppService_types import ns0 from WebServices.opal_client import OpalService self.queryName = queryName inputFile = ns0.InputFileType_Def("inputFile") inputFile._name = "query.fa" inputFile._contents = self.makeFasta(queryName, querySeq) service = "BlastpdbServicePort" argList = "-i %s -o %s -e %s -M %s" % (self.inputFile._name, self.outputFile, evalue, matrix) self.opal = OpalService(service) self.opal.launchJob(argList, _inputFile=[inputFile]) self.finishCB = finishCB from chimera.tasks import Task self.task = Task("blastpdb %s" % queryName, self.cancelCB, self.statusCB)
def __init__(self, pdbpath, expath, name, fig): from WebServices.AppService_types import ns0 from WebServices.opal_client import OpalService self.pdbpath = pdbpath self.expath = expath self.name = name self.figure = fig pdbFile = ns0.InputFileType_Def("inputFile") pdbFile._name = "pdbfile" f = open(pdbpath) pdbFile._contents = f.read() f.close() files = [pdbFile] argList = "pdbfile" if expath: exFile = ns0.InputFileType_Def("inputFile") exFile._name = "exfile" f = open(expath) exFile._contents = f.read() f.close() files.append(exFile) argList += " exfile" try: self.opal = OpalService("SAXSService") except: import traceback, sys print "Traceback from SAXS request:" traceback.print_exc(file=sys.stdout) print """ Typically, if you get a TypeError, it's a problem on the remote server and it should be fixed shortly. If you get a different error or get TypeError consistently for more than a day, please report the problem using the Report a Bug... entry in the Help menu. Please include the traceback printed above as part of the problem description.""" from chimera import NonChimeraError raise NonChimeraError("SAXS web service appears " "to be down. See Reply Log " "for more details.") self.opal.launchJob(argList, _inputFile=files) from chimera.tasks import Task self.task = Task("SAXS " + self.name, self.cancelCB, self.statusCB)
def __init__(self, queryName, querySeq, evalue, matrix, finishCB): from WebServices.AppService_types import ns0 from WebServices.opal_client import OpalService self.queryName = queryName inputFile = ns0.InputFileType_Def("inputFile") inputFile._name = "query.fa" inputFile._contents = self.makeFasta(queryName, querySeq) service = "BlastpdbServicePort" argList = "-i %s -o %s -e %s -M %s" % ( self.inputFile._name, self.outputFile, evalue, matrix) self.opal = OpalService(service) self.opal.launchJob(argList, _inputFile=[inputFile]) self.finishCB = finishCB from chimera.tasks import Task self.task = Task("blastpdb %s" % queryName, self.cancelCB, self.statusCB)
def __init__(self, pdbpath, expath, name, fig): from WebServices.AppService_types import ns0 from WebServices.opal_client import OpalService self.pdbpath = pdbpath self.expath = expath self.name = name self.figure = fig pdbFile = ns0.InputFileType_Def("inputFile") pdbFile._name = "pdbfile" f = open(pdbpath) pdbFile._contents = f.read() f.close() files = [ pdbFile ] argList = "pdbfile" if expath: exFile = ns0.InputFileType_Def("inputFile") exFile._name = "exfile" f = open(expath) exFile._contents = f.read() f.close() files.append(exFile) argList += " exfile" try: self.opal = OpalService("SAXSService") except: import traceback, sys print "Traceback from SAXS request:" traceback.print_exc(file=sys.stdout) print """ Typically, if you get a TypeError, it's a problem on the remote server and it should be fixed shortly. If you get a different error or get TypeError consistently for more than a day, please report the problem using the Report a Bug... entry in the Help menu. Please include the traceback printed above as part of the problem description.""" from chimera import NonChimeraError raise NonChimeraError("SAXS web service appears " "to be down. See Reply Log " "for more details.") self.opal.launchJob(argList, _inputFile=files) from chimera.tasks import Task self.task = Task("SAXS " + self.name, self.cancelCB, self.statusCB)
class BlastpdbService: outputFile = "blast.out" def __init__(self, queryName, querySeq, evalue, matrix, finishCB): from WebServices.AppService_types import ns0 from WebServices.opal_client import OpalService self.queryName = queryName inputFile = ns0.InputFileType_Def("inputFile") inputFile._name = "query.fa" inputFile._contents = self.makeFasta(queryName, querySeq) service = "BlastpdbServicePort" argList = "-i %s -o %s -e %s -M %s" % (self.inputFile._name, self.outputFile, evalue, matrix) self.opal = OpalService(service) self.opal.launchJob(argList, _inputFile=[inputFile]) self.finishCB = finishCB from chimera.tasks import Task self.task = Task("blastpdb %s" % queryName, self.cancelCB, self.statusCB) def cancelCB(self): self.task = None def statusCB(self): self.task.updateStatus(self.opal.currentStatus()) if not self.opal.isFinished(): self.opal.queryStatus() return self.task = None fileMap = self.opal.getOutputs() if self.opal.isFinished() > 0: # Successful completion self.finishCB(self.getURLContent(fileMap[self.outputFile])) else: # Failed from chimera import replyobj replyobj.error("blastpdb %s failed; " "see Reply Log for more information" % self.queryName) try: self.showURLContent("blastpdb stdout", fileMap["stdout"]) except KeyError: pass try: self.showURLContent("blastpdb stderr", fileMap["stderr"]) except KeyError: pass def makeFasta(self, name, seq): output = [">QUERY\n"] maxLine = 60 for i in range(0, len(seq), maxLine): end = min(i + maxLine, len(seq)) output.append("%s\n" % seq[i:end]) return ''.join(output) def getURLContent(self, url): import urllib2 f = urllib2.urlopen(url) data = f.read() f.close() return data def showURLContent(self, title, url): from chimera import replyobj data = self.getURLContent(url) replyobj.message("%s\n-----\n%s-----\n" % (title, data))
class BlastproteinService: outputFile = "blast.out" def __init__(self, finishCB, params=None, sessionData=None): self.finishCB = finishCB if params is not None: self._initBlast(*params) else: self._initSession(*sessionData) def _initBlast(self, program, db, queryName, querySeq, evalue, matrix, passes): self.program = program self.db = db self.queryName = queryName self.params = (querySeq, evalue, matrix, passes) from WebServices.AppService_types import ns0 from WebServices.opal_client import OpalService inputFile = ns0.InputFileType_Def("inputFile") inputFile._name = "query.fa" inputFile._contents = self.makeFasta(queryName, querySeq) service = "BlastproteinServicePort" argList = "-P %s -d %s -i %s -o %s -e %s -M %s -p %s" % ( program, db, inputFile._name, self.outputFile, evalue, matrix, passes) try: self.opal = OpalService(service) except: import traceback, sys print "Traceback from Blast request:" traceback.print_exc(file=sys.stdout) print """ Typically, if you get a TypeError, it's a problem on the remote server and it should be fixed shortly. If you get a different error or get TypeError consistently for more than a day, please report the problem using the Report a Bug... entry in the Help menu. Please include the traceback printed above as part of the problem description.""" from chimera import NonChimeraError raise NonChimeraError("Blast web service appears " "to be down. See Reply Log " "for more details.") self.opal.launchJob(argList, _inputFile=[inputFile]) from chimera.tasks import Task self.task = Task(self._title(), self.cancelCB, self.statusCB) def _initSession(self, program, db, queryName, params, running, opalData): self.program = program self.db = db self.queryName = queryName self.params = params from WebServices.opal_client import OpalService self.opal = OpalService(sessionData=opalData) if not running: self.task = None else: from chimera.tasks import Task self.task = Task(self._title(), self.cancelCB, self.statusCB) def _title(self): return "%s %s: %s" % (self.program, self.db, self.queryName) def sessionData(self): return (self.program, self.db, self.queryName, self.params, self.task is not None, self.opal.sessionData()) def cancelCB(self): self.task = None def statusCB(self): self.task.updateStatus(self.opal.currentStatus()) if not self.opal.isFinished(): self.opal.queryStatus() return self.task = None fileMap = self.opal.getOutputs() if self.opal.isFinished() > 0: # Successful completion self.finishCB(self.getURLContent( fileMap[self.outputFile])) else: # Failed from chimera import replyobj replyobj.error("blast %s failed; " "see Reply Log for more information\n" % self.queryName) self.showURLContent("blast stderr", fileMap["stderr.txt"]) self.showURLContent("blast stdout", fileMap["stdout.txt"]) def makeFasta(self, name, seq): output = [ ">QUERY\n" ] maxLine = 60 for i in range(0, len(seq), maxLine): end = min(i + maxLine, len(seq)) output.append("%s\n" % seq[i:end]) return ''.join(output) def getURLContent(self, url): import urllib2 f = urllib2.urlopen(url) data = f.read() f.close() return data def showURLContent(self, title, url): from chimera import replyobj data = self.getURLContent(url) replyobj.message("%s\n-----\n%s-----\n" % (title, data))
class BlastproteinService: outputFile = "blast.out" def __init__(self, finishCB, params=None, sessionData=None): self.finishCB = finishCB if params is not None: self._initBlast(*params) else: self._initSession(*sessionData) def _initBlast(self, program, db, queryName, querySeq, evalue, matrix, passes): self.program = program self.db = db self.queryName = queryName self.params = (querySeq, evalue, matrix, passes) from WebServices.AppService_types import ns0 from WebServices.opal_client import OpalService inputFile = ns0.InputFileType_Def("inputFile") inputFile._name = "query.fa" inputFile._contents = self.makeFasta(queryName, querySeq) service = "BlastproteinServicePort" argList = "-P %s -d %s -i %s -o %s -e %s -M %s -p %s" % ( program, db, inputFile._name, self.outputFile, evalue, matrix, passes) try: self.opal = OpalService(service) except: import traceback, sys print "Traceback from Blast request:" traceback.print_exc(file=sys.stdout) print """ Typically, if you get a TypeError, it's a problem on the remote server and it should be fixed shortly. If you get a different error or get TypeError consistently for more than a day, please report the problem using the Report a Bug... entry in the Help menu. Please include the traceback printed above as part of the problem description.""" from chimera import NonChimeraError raise NonChimeraError("Blast web service appears " "to be down. See Reply Log " "for more details.") self.opal.launchJob(argList, _inputFile=[inputFile]) from chimera.tasks import Task self.task = Task(self._title(), self.cancelCB, self.statusCB) def _initSession(self, program, db, queryName, params, running, opalData): self.program = program self.db = db self.queryName = queryName self.params = params from WebServices.opal_client import OpalService self.opal = OpalService(sessionData=opalData) if not running: self.task = None else: from chimera.tasks import Task self.task = Task(self._title(), self.cancelCB, self.statusCB) def _title(self): return "%s %s: %s" % (self.program, self.db, self.queryName) def sessionData(self): return (self.program, self.db, self.queryName, self.params, self.task is not None, self.opal.sessionData()) def cancelCB(self): self.task = None def statusCB(self): self.task.updateStatus(self.opal.currentStatus()) if not self.opal.isFinished(): self.opal.queryStatus() return self.task = None fileMap = self.opal.getOutputs() if self.opal.isFinished() > 0: # Successful completion self.finishCB(self.getURLContent(fileMap[self.outputFile])) else: # Failed from chimera import replyobj replyobj.error("blast %s failed; " "see Reply Log for more information\n" % self.queryName) self.showURLContent("blast stderr", fileMap["stderr.txt"]) self.showURLContent("blast stdout", fileMap["stdout.txt"]) def makeFasta(self, name, seq): output = [">QUERY\n"] maxLine = 60 for i in range(0, len(seq), maxLine): end = min(i + maxLine, len(seq)) output.append("%s\n" % seq[i:end]) return ''.join(output) def getURLContent(self, url): import urllib2 f = urllib2.urlopen(url) data = f.read() f.close() return data def showURLContent(self, title, url): from chimera import replyobj data = self.getURLContent(url) replyobj.message("%s\n-----\n%s-----\n" % (title, data))
class NCIPlot(object): """ A wrapper around NCIPlot binary interface """ def __init__(self, binary, dat_directory, success_callback=None, clear_callback=None): self._check_paths(binary, dat_directory) self.binary = binary self.dat_directory = dat_directory os.environ['NCIPLOT_HOME'] = os.path.dirname(self.dat_directory) self.success_callback = success_callback self.clear_callback = clear_callback self.task = None self.subprocess = None self.stdout = None self.queue = None self.implementation = 'CUDA' if 'cuda' in os.path.split(self.binary)[1].lower() \ else 'CPU' self.parse_stdout = self._parse_stdout_cuda if self.implementation == 'CUDA' \ else self._parse_stdout_cpu def run(self, *xyz, **options): """ Launch a NCIPlot essay for specified xyz files and options. Read on self.create_nci_method documentation for further info. Notes ----- This function uses threads, queues, tasks and subprocesses, so it can be a bit difficult to understand for newcomers. `subprocess` is used to launch an external program (nciplot, in this case), and `task` is a Chimera feature to monitor that process in the tasks panels. It also allows to print status updates to the bottom bar. `task` and `subprocess` are synced with Chimera's `monitor`, which includes a very useful `afterCB` parameter: a callable that will be called when the process ends. If we needed to get it in realtime, we should add queues and threads. As a workaround, we need to get the stdout to an async queue (in realtime!) with a separate thread. >>> from threading import Thread >>> from Queue import Queue >>> def enqueue_output(out, queue): for line in iter(out.readline, b''): queue.put(line) out.close() >>> self.queue = Queue() >>> thread = Thread(target=enqueue_output, args=(self.subprocess.stdout, self.queue)) >>> thread.daemon = True # thread dies with the program >>> thread.start() Then, we can read the stdout from the queue: >>> self.queue.put(None) # Sentinel value. When iter gets this, it stops. >>> for line in iter(self.queue.get, None): >>> # do stuff Check this SO answer for more info: http://stackoverflow.com/questions/375427/ non-blocking-read-on-a-subprocess-pipe-in-python/4896288#4896288 """ nci_file = osTemporaryFile(suffix='.nci') oldworkingdir = os.getcwd() tmpdir, tmpfile = os.path.split(nci_file) if 'name' not in options or options['name'] is None: options['name'] = tmpfile[:-4] nci_input = self.create_nci_input(xyz, **options) os.chdir(tmpdir) with open(nci_file, 'w') as f: f.write(nci_input.read()) name = ', '.join(os.path.basename(f) for f in xyz) self._tmpdir = tmpdir self.task = Task("NCIPlot for {}".format(name), cancelCB=self._clear_task) self.subprocess = Popen([self.binary, nci_file], stdout=PIPE, progressCB= lambda p: 0) monitor("NCIPlot", self.subprocess, task=self.task, afterCB=self._after_cb) self.task.updateStatus("Running NCIPlot") os.chdir(oldworkingdir) def _after_cb(self, aborted): """ Called after the subprocess ends. """ if aborted: self._clear_task() self.clear_callback() return if self.subprocess.returncode != 0: self.task.updateStatus("NCIPlot calculation failed!") self._clear_task() self.clear_callback() return self.task.updateStatus("Parsing NCIPlot output") data = self.parse_stdout(self.subprocess.stdout) self.task.updateStatus("Loading volumes") self.success_callback(data) self.task.updateStatus("Done!") self._clear_task() def _clear_task(self): """ House cleaning """ self.task.finished() self.subprocess.stdout.close() self.task, self.subprocess, self.queue, self._tmpdir = None, None, None, None def _parse_stdout_cpu(self, stdout): """ Get useful data from NCIPlot stdout, or any file-like object. """ data = {} data['_raw'] = [] for line in stdout: if line.startswith('#') or line.startswith('---'): continue elif line.lstrip().startswith('RHO'): data['rho'] = float(line.split()[-1].strip()) elif line.lstrip().startswith('RDG'): data['rdg'] = float(line.split()[-1].strip()) elif line.rstrip().endswith('-grad.cube'): data['grad_cube'] = os.path.join(self._tmpdir, line.split('=')[-1].strip()) elif line.rstrip().endswith('-dens.cube'): data['dens_cube'] = os.path.join(self._tmpdir, line.split('=')[-1].strip()) elif 'LS x RDG' in line: data['xy_data'] = os.path.join(self._tmpdir, line.split('=')[-1].strip()) data['_raw'].append(line) return data def _parse_stdout_cuda(self, stdout): """ Get useful data from CUDA NCIPlot [1] stdout, or any file-like object. [1] A GPU accelerated implementation of NCI calculations using pro-molecular density. Rubez G, Etancelin JM, Vigouroux X, Krajecki M, Boisson JC, Henon E., J. Comput. Chem. 2017, 38, 1071 """ data = {} basedir = None data['_raw'] = [] for line in stdout: data['_raw'].append(line) line = line.strip() if not line.startswith('*'): continue line = line.strip('*') if 'MoleculeFile' in line: basedir = os.path.split(line.split(':')[1].split()[0])[0] elif basedir and 'OutPut filenam Prefix' in line: basename = line.split(':')[1].strip() data['grad_cube'] = os.path.join(basedir, basename + '-RDG.cube') data['dens_cube'] = os.path.join(basedir, basename + '-dens.cube') data['xy_data'] = os.path.join(basedir, basename + '.dat') elif '.cube rho range' in line: data['rho'] = float(line.split()[6]) elif '.dat rdg range' in line: data['rdg'] = float(line.split()[6]) return data @staticmethod def create_nci_input(paths, output_level=3, ligand=None, dat_cutoffs=(0.2, 1.0), cube_cutoffs=(0.07, 0.3), intermolecular=None, radius=None, cube=None, increments=None, name=None, **kwargs): """ Creates a file-like object with NCIPlot input options Parameters ---------- paths : list of str Paths to XYZ molecule files. # Output options name : str, optional, default=None If set, replaces the output name, which by default is the molecule name without extension. output_level : int, optional, default=3 How many files should NCI plot create. Level 1 is minimum output, level 3 creates up to 4 files. dat_cutoffs : 2-tuple of float, optional, default=(0.2, 1.0) Density and RDG cutoffs used in creating the dat file cube_cutoffs : 2-tuple of float, optional, default=(0.07, 0.3) Density (r1) and RDG (r2) cutoffs used when creating the cube files. r1 will set the cutoff for both the density and the RDG to be registered in the cube files, whereas r2 will be used for isosurfaces depiction. # Search options; If set, only a region will be explored. CHOOSE ONLY ONE! ligand : 2-tuple of float, int, optional, default=None If set, which molecule (by index) is working as a ligand, and the search radius to inspect within that molecule. intermolecular: float, optional, default=None If set, the search radius for interactions in between input molecules radius : 4-tuple of float, optional, default=None If set, first three values indicate the origin coordinates of the search sphere, and the fourth value indicates the search radius of such sphere. cube : 6-tuple of float, optional, default=None If set, search within the cube that is drawn between point A (first three floats) and point B (last three floats). increments : 3-tuple of float, optional, default=None ??? Returns ------- paths : list of str Collection of output files created by NCIPlot Notes ----- NCI input files follow this scheme. More info @ https://github.com/aoterodelaroza/nciplot <number of molecule files> <path to molecule file, xyz or wfn> <path to molecule file>... # Optional LIGAND n r #index of molecule in path list, search radius INTERMOLECULAR r # search radius RADIUS x y z r # coordinates center, radius CUBE x0 y0 z0 x1 y1 z1 # draw a cube from a to b INCREMENTS r1 r2 r3 CUTOFFS r1 r2 # density and RDG cutoffs for dat file; defaults: 0.2, 1.0 CUTPLOT r1 r2 # density and RDG cutoffs for cube file; defaults: 0.07, 0.3 ISORDG r # isosurface level; 0.3 for xyz mols, 0.5 for wfn mols OUTPUT [1-3] # level of output: 1 is minimal, 3 max ONAME str # tag name """ output = StringIO() output.write('{}\n'.format(len(paths))) for path in paths: output.write('{}\n'.format(path)) if output_level in (1, 2, 3): output.write('OUTPUT {}\n'.format(output_level)) if name: output.write('ONAME {}\n'.format(name)) if dat_cutoffs: output.write('CUTOFFS {} {}\n'.format(*dat_cutoffs[:2])) if cube_cutoffs: output.write('CUTPLOT {} {}\n'.format(*cube_cutoffs[:2])) if ligand: output.write('LIGAND {} {}\n'.format(*ligand[:2])) elif intermolecular: output.write('INTERMOLECULAR {}\n'.format(intermolecular)) elif radius: output.write('RADIUS {} {} {} {}\n'.format(*radius[:4])) elif cube: output.write('CUBE {} {} {} {} {} {}\n'.format(*cube[:6])) elif increments: output.write('INCREMENTS {} {} {}\n'.format(*increments[:3])) output.seek(0) return output def _check_paths(self, binary, dat_directory): """ Check if paths are OK, we need to bring up defaults, or if they have been never set """ if not os.path.isfile(binary): raise UserError('Specified NCIplot binary path {} does not exist'.format(binary)) if not os.path.isdir(dat_directory): raise UserError('Specified NCIplot dat library path {} does not exist'.format(dat_directory))
class ProfileOpalService: def __init__(self, pdbpath, expath, name, fig): from WebServices.AppService_types import ns0 from WebServices.opal_client import OpalService self.pdbpath = pdbpath self.expath = expath self.name = name self.figure = fig pdbFile = ns0.InputFileType_Def("inputFile") pdbFile._name = "pdbfile" f = open(pdbpath) pdbFile._contents = f.read() f.close() files = [ pdbFile ] argList = "pdbfile" if expath: exFile = ns0.InputFileType_Def("inputFile") exFile._name = "exfile" f = open(expath) exFile._contents = f.read() f.close() files.append(exFile) argList += " exfile" try: self.opal = OpalService("SAXSService") except: import traceback, sys print "Traceback from SAXS request:" traceback.print_exc(file=sys.stdout) print """ Typically, if you get a TypeError, it's a problem on the remote server and it should be fixed shortly. If you get a different error or get TypeError consistently for more than a day, please report the problem using the Report a Bug... entry in the Help menu. Please include the traceback printed above as part of the problem description.""" from chimera import NonChimeraError raise NonChimeraError("SAXS web service appears " "to be down. See Reply Log " "for more details.") self.opal.launchJob(argList, _inputFile=files) from chimera.tasks import Task self.task = Task("SAXS " + self.name, self.cancelCB, self.statusCB) def cancelCB(self): self.task = None def statusCB(self): self.task.updateStatus(self.opal.currentStatus()) if not self.opal.isFinished(): self.opal.queryStatus() return self.task = None self.filemap = self.opal.getOutputs() if self.opal.isFinished() > 0: # Successful completion self.finished() else: # Failed from chimera import replyobj replyobj.error("SAXS %s failed; see Reply Log for more information" % self.name) self.showFileContent("stdout.txt") self.showFileContent("stderr.txt") def finished(self): if self.expath: data = self.getFileContent("pdbfile_exfile.dat") p = read_profile_data(data, 3) else: data = self.getFileContent("pdbfile.dat") p = read_profile_data(data, 2) self.figure = plot_profile(p, self.name, self.figure) def getURLContent(self, url): import urllib2 f = urllib2.urlopen(url) data = f.read() f.close() return data def getFileContent(self, filename): return self.getURLContent(self.filemap[filename]) def showURLContent(self, title, url): from chimera import replyobj data = self.getURLContent(url) replyobj.message("%s\n-----\n%s-----\n" % (title, data)) def showFileContent(self, filename): try: url = self.filemap[filename] except KeyError: from chimera import replyobj replyobj.message("SAXS profile: there is no file named \"%s\"" % filename) else: self.showURLContent("SAXS profile %s" % filename, url)
def updateStatus(self, msg): chimera.statusline.show_message( '{}: {}'.format(self.title, msg), clickCallback=self._status_click_callback) Task.updateStatus(self, msg)
class Controller(object): def __init__(self, gui, model, *args, **kwargs): self.gui = gui self.model = model self.set_mvc() self.task = None self.subprocess = None self.queue = None self.progress = None self.ensemble = None self.movie_dialog = None self.molecule = None self._last_steps = 0 def set_mvc(self): self.gui.buttonWidgets['Save Input'].configure(command=self.saveinput) self.gui.buttonWidgets['Run'].configure(command=self.run) def run(self): if not self.saveinput(): return env = os.environ.copy() env['OMMPROTOCOL_SLAVE'] = '1' env['PYTHONIOENCODING'] = 'latin-1' self.task = Task("OMMProtocol for {}".format(self.filename), cancelCB=self._clear_cb, statusFreq=((1, ), 1)) self.subprocess = Popen( ['ommprotocol', self.filename], stdout=PIPE, stderr=PIPE, progressCB=self._progress_cb, #universal_newlines=True, bufsize=1, env=env) self.progress = SubprocessTask("OMMProtocol", self.subprocess, task=self.task, afterCB=self._after_cb) self.task.updateStatus("Running OMMProtocol") self.queue = LifoQueue() thread = Thread(target=enqueue_output, args=(self.subprocess.stdout, self.queue)) thread.daemon = True # thread dies with the program thread.start() self.ensemble = _TrajProxy() self.molecule = self.ensemble.molecule = self.gui.ui_chimera_models.getvalue( ) self.ensemble.name = 'Trajectory for {}'.format(self.molecule.name) self.ensemble.startFrame = self.ensemble.endFrame = 1 self.movie_dialog = MovieDialog(self.ensemble, externalEnsemble=True) self.gui.Close() def _clear_cb(self, *args): self.task.finished() self.task, self.subprocess, self.queue, self.progress, self.molecule = [ None ] * 5 if self.movie_dialog is not None: self.movie_dialog.Close() self.movie_dialog = None def _after_cb(self, aborted): if aborted: self._clear_cb() return if self.subprocess.returncode: last = self.subprocess.stderr.readlines()[-1] msg = "OMMProtocol calculation failed! Reason: {}".format(last) self._clear_cb() raise chimera.UserError(msg) self.task.finished() chimera.statusline.show_message('Yay! MD Done!') def _progress_cb(self, process): try: chunk = self.queue.get_nowait() except Empty: return self._last_steps / self.model.total_steps steps, positions = pickle.loads(chunk) if steps == self._last_steps: self._last_steps / self.model.total_steps self._last_steps = steps # Update positions in MD Movie Dialog coordinates = np.array(positions) * 10. coordsets_so_far = len(self.molecule.coordSets) cs = self.molecule.newCoordSet(coordsets_so_far) cs.load(coordinates) self.ensemble.endFrame = self.movie_dialog.endFrame = coordsets_so_far + 1 self.movie_dialog.moreFramesUpdate('', [], self.movie_dialog.endFrame) self.movie_dialog.plusCallback() return self._last_steps / self.model.total_steps def saveinput(self, path=None): self.model.parse() if path is None: path = asksaveasfilename(parent=self.gui.canvas, defaultextension='.yaml', filetypes=[('YAML', '*.yaml')]) if not path: return self.write(path) self.gui.status('Written to {}'.format(path), color='blue', blankAfter=4) return True def write(self, output): # Write input self.filename = output with open(self.filename, 'w') as f: f.write('# Yaml input for OpenMM MD\n\n') f.write('# input\n') yaml.dump(self.model.md_input, f, default_flow_style=False) f.write('\n') f.write('# output\n') yaml.dump(self.model.md_output, f, default_flow_style=False) if self.model.md_hardware: f.write('\n# hardware\n') yaml.dump(self.model.md_hardware, f, default_flow_style=False) f.write('\n# conditions\n') yaml.dump(self.model.md_conditions, f, default_flow_style=False) f.write('\n# OpenMM system options\n') yaml.dump(self.model.md_systemoptions, f, default_flow_style=False) f.write('\n\nstages:\n') for stage in self.model.stages: yaml.dump([stage], f, indent=8, default_flow_style=False) f.write('\n')
def saveImage(filename=None, width=None, height=None, format=None, units="pixels", description=None, supersample=None, master=None, printMode=None, raytrace=False, raytracePreview=None, raytraceWait=None, raytraceKeepInput=None, hideDialogs=True, statusMessages=True, raiseWindow=True, task=None): if chimera.nogui and chimera.opengl_platform() != 'OSMESA': raise chimera.UserError, "Need graphics to save images (or use headless Linux version)" if statusMessages: from replyobj import status else: def status(*args, **kw): pass if printMode is None: printMode = chimera.viewer.camera.mode() horizPixels, vertPixels, supersample = \ imageArgs(units, width, height, supersample) savedSD = None # saved screen distance if units != 'pixels': adjustFOV = preferences.get(IMAGE_SETUP, ADJUST_FOV) if adjustFOV == 1 or (adjustFOV == ONLY_STEREO_CAMERAS and printMode != 'mono'): # if image is twice as wide as screen, # screenDistance is half as much savedSD = chimera.viewer.camera.screenDistance adjust = convert[units] / convert['millimeters'] image_width = width * adjust adjust = chimera.viewer.camera.windowWidth / image_width chimera.viewer.camera.screenDistance *= adjust if raytrace: if not checkPovrayLicense(): return # TODO: make default an argument or preference if raytraceWait is None: raytraceWait = preferences.get(POVRAY_SETUP, WAIT_POVRAY) if raytraceKeepInput is None: raytraceKeepInput = preferences.get(POVRAY_SETUP, KEEP_INPUT) if raytracePreview is None: raytracePreview = preferences.get(POVRAY_SETUP, SHOW_PREVIEW) quality = DEFAULT_JPEG_QUALITY format = 'PNG' if not chimera.nogui and not filename: if not master: master = tkgui.app chooseDialog = _ChooseFileDialog(filterSet='povray', format=format) result = chooseDialog.run(master) if result is None: status("Image save cancelled.") return filename, format = result[0] quality = chooseDialog.quality.get() if not filename: replyobj.error("Need filename for POV-Ray output") return if filename.endswith('.png') or filename.endswith('.jpg'): povfilename = filename[:-4] + '.pov' inifilename = filename[:-4] + '.ini' else: povfilename = filename + '.pov' inifilename = filename + '.ini' if task is None: from chimera.tasks import Task task = Task("raytrace image", None) task.updateStatus("Generating POV-Ray data file") import exports exports.doExportCommand('POV-Ray', povfilename) task.updateStatus("Generating POV-Ray parameter file") if savedSD is not None: chimera.viewer.camera.screenDistance = savedSD import SubprocessMonitor as SM cmd = [ preferences.get(POVRAY_SETUP, POVRAY_EXE), inifilename, "+I%s" % povfilename, "+O%s" % filename, "+V" # need verbose to monitor progress ] inifile = open(inifilename, 'w') print >> inifile, ( "Width=%d\n" "Height=%d\n" # add font path, CHIMERA/share/fonts "Library_Path=\"%s\"\n" "Bounding=On\n" "Bounding_Threshold=1\n" "Split_Unions=On\n" "Remove_Bounds=On\n" "Quality=%d" ) % ( horizPixels, vertPixels, os.path.join(os.environ['CHIMERA'], 'share', 'fonts'), preferences.get(POVRAY_SETUP, POV_QUALITY) ) if not preferences.get(POVRAY_SETUP, ANTIALIAS): print >> inifile, "Antialias=Off" else: print >> inifile, ( "Antialias=On\n" "Antialias_Threshold=%f\n" "Antialias_Depth=%d\n" "Sampling_Method=%d" ) % ( preferences.get(POVRAY_SETUP, ANTIALIAS_THRESHOLD), preferences.get(POVRAY_SETUP, ANTIALIAS_DEPTH), preferences.get(POVRAY_SETUP, ANTIALIAS_METHOD) ) if not preferences.get(POVRAY_SETUP, JITTER): print >> inifile, "Jitter=Off" else: print >> inifile, ( "Jitter=On\n" "Jitter_Amount=%f\n" ) % ( preferences.get(POVRAY_SETUP, JITTER_AMOUNT), ) oa = preferences.get(POVRAY_SETUP, OUTPUT_ALPHA) if oa == 1 or (oa == 2 and chimera.bgopacity): if chimera.viewer.depthCue: replyobj.warning("Depth-cueing disables transparent background") print >> inifile, "Output_Alpha=On" if format in ('PNG', 'Stereo PNG'): print >> inifile, ("; output PNG\n" "Output_File_Type=N8") elif format in ('JPEG', 'Stereo JPEG'): print >> inifile, ("; output JPEG\n" "Output_File_Type=J%d") % quality elif format in ('PPM'): print >> inifile, ("; output PPM\n" "Output_File_Type=P") if chimera.nogui or not raytracePreview: print >> inifile, "Display=Off" else: print >> inifile, "Display=On" if not raytraceWait: print >> inifile, "Pause_when_Done=On" inifile.close() if raytraceKeepInput: inputs = [] else: inputs = [ povfilename, inifilename ] def afterCB(aborted, inputs=inputs, outputs=[filename]): import os for fn in inputs: try: os.remove(fn) except OSError: pass if aborted: for fn in outputs: try: os.remove(fn) except OSError: pass task.updateStatus("Starting POV-Ray") try: subproc = SM.Popen(cmd, stdin=None, stdout=None, stderr=SM.PIPE, daemon=True) except OSError, e: raise chimera.UserError, "Unable run POV-Ray executable: %s" % e progress = povrayProgress(subproc) progress.start() subproc.setProgress(progress) info = 'running "%s"' % '" "'.join(cmd) if not chimera.nogui and statusMessages: from chimera import dialogs, tkgui dialogs.display(tkgui._ReplyDialog.name) replyobj.info(info + '\n') task.updateStatus(info) subprog = SM.monitor('running POV-Ray', subproc, title="POV-Ray progress", task=task, afterCB=afterCB) if raytraceWait: subprog.wait() return
class BlastpdbService: outputFile = "blast.out" def __init__(self, queryName, querySeq, evalue, matrix, finishCB): from WebServices.AppService_types import ns0 from WebServices.opal_client import OpalService self.queryName = queryName inputFile = ns0.InputFileType_Def("inputFile") inputFile._name = "query.fa" inputFile._contents = self.makeFasta(queryName, querySeq) service = "BlastpdbServicePort" argList = "-i %s -o %s -e %s -M %s" % ( self.inputFile._name, self.outputFile, evalue, matrix) self.opal = OpalService(service) self.opal.launchJob(argList, _inputFile=[inputFile]) self.finishCB = finishCB from chimera.tasks import Task self.task = Task("blastpdb %s" % queryName, self.cancelCB, self.statusCB) def cancelCB(self): self.task = None def statusCB(self): self.task.updateStatus(self.opal.currentStatus()) if not self.opal.isFinished(): self.opal.queryStatus() return self.task = None fileMap = self.opal.getOutputs() if self.opal.isFinished() > 0: # Successful completion self.finishCB(self.getURLContent( fileMap[self.outputFile])) else: # Failed from chimera import replyobj replyobj.error("blastpdb %s failed; " "see Reply Log for more information" % self.queryName) try: self.showURLContent("blastpdb stdout", fileMap["stdout"]) except KeyError: pass try: self.showURLContent("blastpdb stderr", fileMap["stderr"]) except KeyError: pass def makeFasta(self, name, seq): output = [ ">QUERY\n" ] maxLine = 60 for i in range(0, len(seq), maxLine): end = min(i + maxLine, len(seq)) output.append("%s\n" % seq[i:end]) return ''.join(output) def getURLContent(self, url): import urllib2 f = urllib2.urlopen(url) data = f.read() f.close() return data def showURLContent(self, title, url): from chimera import replyobj data = self.getURLContent(url) replyobj.message("%s\n-----\n%s-----\n" % (title, data))
def start(self): self.newFrameHandle = chimera.triggers.addHandler( 'post-frame', self.captureImage, None) self.RECORDING = True from chimera.tasks import Task self.task = Task("record movie", self.cancelCB)
class ProfileOpalService: def __init__(self, pdbpath, expath, name, fig): from WebServices.AppService_types import ns0 from WebServices.opal_client import OpalService self.pdbpath = pdbpath self.expath = expath self.name = name self.figure = fig pdbFile = ns0.InputFileType_Def("inputFile") pdbFile._name = "pdbfile" f = open(pdbpath) pdbFile._contents = f.read() f.close() files = [pdbFile] argList = "pdbfile" if expath: exFile = ns0.InputFileType_Def("inputFile") exFile._name = "exfile" f = open(expath) exFile._contents = f.read() f.close() files.append(exFile) argList += " exfile" try: self.opal = OpalService("SAXSService") except: import traceback, sys print "Traceback from SAXS request:" traceback.print_exc(file=sys.stdout) print """ Typically, if you get a TypeError, it's a problem on the remote server and it should be fixed shortly. If you get a different error or get TypeError consistently for more than a day, please report the problem using the Report a Bug... entry in the Help menu. Please include the traceback printed above as part of the problem description.""" from chimera import NonChimeraError raise NonChimeraError("SAXS web service appears " "to be down. See Reply Log " "for more details.") self.opal.launchJob(argList, _inputFile=files) from chimera.tasks import Task self.task = Task("SAXS " + self.name, self.cancelCB, self.statusCB) def cancelCB(self): self.task = None def statusCB(self): self.task.updateStatus(self.opal.currentStatus()) if not self.opal.isFinished(): self.opal.queryStatus() return self.task = None self.filemap = self.opal.getOutputs() if self.opal.isFinished() > 0: # Successful completion self.finished() else: # Failed from chimera import replyobj replyobj.error( "SAXS %s failed; see Reply Log for more information" % self.name) self.showFileContent("stdout.txt") self.showFileContent("stderr.txt") def finished(self): if self.expath: data = self.getFileContent("pdbfile_exfile.dat") p = read_profile_data(data, 3) else: data = self.getFileContent("pdbfile.dat") p = read_profile_data(data, 2) self.figure = plot_profile(p, self.name, self.figure) def getURLContent(self, url): import urllib2 f = urllib2.urlopen(url) data = f.read() f.close() return data def getFileContent(self, filename): return self.getURLContent(self.filemap[filename]) def showURLContent(self, title, url): from chimera import replyobj data = self.getURLContent(url) replyobj.message("%s\n-----\n%s-----\n" % (title, data)) def showFileContent(self, filename): try: url = self.filemap[filename] except KeyError: from chimera import replyobj replyobj.message("SAXS profile: there is no file named \"%s\"" % filename) else: self.showURLContent("SAXS profile %s" % filename, url)