#!/usr/bin/python '''Utility classes with implementation details that are common to wrapping NEXUS-based programs''' import os from PIPRes.basic import writeTreesBlock, writeNexusDataMatrix from PIPRes.wrap.external_program import * import threading _LOG = cipresGetLogger('pipres.wrap.nexus_program_server.py') class WrapNexusProgram(WrapExternalProgram): '''This class implements the intersection of functionality between the mb and paup wrappers.''' def _createTempDataFile(self, **kwargs): '''returns (tempDirectory, fileName, openFileStream, toExternalTranslation, treeTaxLabels) with the matrix and tree already written to the fileStream. kwargs can contain: tree matrix writeMatrix (boolean def = True) writeTree (boolean def = True) supportsTaxaSubsets (boolean def = False) dirPref filename (default = data.nex) writePoundNexus (boolean def = True) The field self.mappedTree will be overwritten. ''' tree = kwargs.get('tree') matrix = kwargs.get('matrix') dirPref = kwargs.get('dirPref', 'wrap') supportsTaxaSubsets = kwargs.get('supportsTaxaSubsets', False) if tree is not None and not supportsTaxaSubsets: self.mappedTree, treeTaxLabels, rows, fromExternalTranslation = mapTreeToLeafSubset(tree) else: self.mappedTree, treeTaxLabels, rows, fromExternalTranslation = None, [], None, None tempDirectory = makeCipresTempDir(prefix=dirPref) _LOG.debug('created directory %s' % tempDirectory) filename = kwargs.get('filename', 'data' + os.path.extsep + 'nex') filePath = os.path.join(tempDirectory, filename) f = open(filePath, 'w') if kwargs.get('writePoundNexus', True): f.write('#NEXUS\n') if matrix is not None and kwargs.get('writeData', True): _LOG.debug('writing matrix to ' + filename) writeNexusDataMatrix(matrix, f, rowSlice = rows) if tree is not None and kwargs.get('writeTree', True): treeToWrite = supportsTaxaSubsets and tree or self.mappedTree writeTreesBlock(f, [treeToWrite], treeTaxLabels) return ExternalInvocationContext( tempDir=tempDirectory, filename=filename, fileObj=f, fromExternalTranslation=fromExternalTranslation, treeTaxLabels=treeTaxLabels) class SimpleNexusWrapperServer(SimpleServer, WrapNexusProgram): def __init__(self, registry): SimpleServer.__init__(self, registry) self.nexusReader = None self.runningProcesses = [] #children to be killed on exit self.exiting = False self.nexusReaderLock = threading.Lock() def getUIXml(self): return '' def __del__(self): try: self.nexusReaderLock.acquire() except: sys.exit('YIKES') try: self.exiting = True _LOG.debug('__del__() called') self.removeServants() finally: self.nexusReaderLock.release() def remove(self): try: self.nexusReaderLock.acquire() except: sys.exit('YIKES') try: self.exiting = True _LOG.debug('remove() called') self.removeServants() finally: self.nexusReaderLock.release() SimpleServer.remove(self) def removeServants(self): _LOG.debug('removeServants()') if self.nexusReader is not None: try: _LOG.debug('Releasing NexusReader') self.nexusReader.remove() self.nexusReader = None except: logException(_LOG) WrapExternalProgram.killChildProcesses(self.runningProcesses) def userCommands(self): '''Returns a string that is a concatenation of all of the commands sent using "execute()". This is simply self.userConfigCmdList joined with spaces.''' return ' '.join(self.userConfigCmdList)