def run(self, size): """ Run CYANA using a macro created earlier. """ loki.info('A new Cyana round started for %d structures.' % size) # if no Rg check, point to something always true if self.rg_limits: check_rg = self.checkRg else: check_rg = len # run cyana as many time as needed until it completes succesfully run_cyana = "cyana < %s.cmd" % self.name todo = size while todo: # check if a new macro is needed if todo != self.__last_macro_size__: self.writeMacro(todo) self.writeScript() os.system(run_cyana) for i in range(1, todo + 1): name = '%s-%03d.pdb' % (self.name, i) if os.path.exists(name) and check_rg(name): todo -= 1 self.tally += 1 os.system('mv -f %s %s%s.pdb' % (name, self.output, str(self.tally).zfill( self.tally_digits))) else: os.system('rm -f %s' % name)
def shutdown(self): """ Perform a clean exit by deleting all temporary files. """ loki.info('Removing temporary files.') cmd = "rm -f %s*" % self.name os.system(cmd)
def checkRg(self, filename): """ Check whether a given conformation is within the limits set for radius of gyration. """ rg = calculate_rg(filename) loki.info('Rg(%s) = %f)' % (filename, rg)) if (self.rg_limits[0] != None and rg < self.rg_limits[0]) or \ (self.rg_limits[1] != None and rg > self.rg_limits[1]): return False return True
def getDCouplingVectors(self, dcouplings, include='all', exclude=[]): if include == 'all': inc = range(1, len(self) + 1) else: inc = [] for i in include: if type(i) is int: inc.append(i) else: loki.warn("discarding invalid residue '%s'", repr(i)) inc = intersection(inc, range(1, len(self) + 1)) exc = [] for i in exclude: if type(i) is int: exc.append(i) else: loki.warn("discarding invalid residue '%s'", repr(i)) include = sublist(inc, exc) loki.debug('include=' + repr(include)) dcouplings = deepcopy(dcouplings) loki.debug('dcouplings=' + repr(dcouplings)) # REMOVE record = {} for i in range(len(dcouplings)): if type(dcouplings[i]) == str: dcouplings[i] = DCouplings[dcouplings[i]] dc = dcouplings[i] record.setdefault(dc.atoms[0], {}) record.setdefault(dc.atoms[1], {}) if 'HN' in record.keys(): record.setdefault('H', {}) wanted = record.keys() for i in include: for atom in self[i-1]: if str(atom) in wanted: record[str(atom)][int(self[i-1])] = atom.position if 'H' in wanted and len(record['H'].keys()): for k in record['H'].keys(): if not record['HN'].has_key(k): record['HN'][k] = record['H'][k] loki.info('using H for HN in residue %d.', k) loki.debug('record=%s', repr(record)) table = {} for dc in dcouplings: x, y = dc.atoms residues = intersection(record[x].keys(), record[y].keys()) for i in residues: tag = (i, str(dc)) table[tag] = [m-n for m,n in zip(record[x][i], record[y][i])] tags = table.keys() tags.sort() vectors = [table[x] for x in tags] return tags, vectors
def parse_option_hash(hash, translator=None, default_keys=None, \ default_value=None, default_function=None, translator_target='mara'): """ Parse and fix/append an option hash. Arguments: hash -- an unformatted option hash or a default value translator -- a translator to format hash keys (default: as is) default_keys -- a list of keys to include (default: keys of the original hash) default_value -- a default value to use in the absense of a proper input hash default_function -- a default function to apply to values (default: as is) Returns: out -- a formatted option hash """ loki.debug('hash(in)=%s' % repr(hash)) # a do-nothing translator will be used if none given if not translator: translator = lambda x, y: x # a do-nothing function will be used if none given if not default_function: default_function = lambda x: x # translate each key & apply default function to the value if isinstance(hash, dict): out = {} for key in hash.keys(): if translator_target is not None: k = translator(key, translator_target) else: k = translator(key) out[k] = default_function(hash[key]) # or create a hash from the default keys & the given value elif hash in [int, float, str]: out = {}.fromkeys(default_keys, default_function(hash)) # or create a hash from the default keys & the default value else: loki.info('Incomprehensible hash -> using %s' % repr(default_value)) out = {}.fromkeys(default_keys, default_value) loki.debug('hash(out)=%s' % repr(out)) return out
def getSequence(self, unknown='???'): mapping = {} for coupling in self: shift1, shift2 = coupling.getType().shift if not mapping.has_key(int(coupling) + shift1): mapping[int(coupling) + shift1] = coupling.residues[0] if not mapping.has_key(int(coupling) + shift2): mapping[int(coupling) + shift2] = coupling.residues[1] keys = mapping.keys() if unknown != None: missing = 0 for i in range(min(keys) + 1, max(keys)): if not mapping.has_key(i): mapping[i] = unknown missing += 1 if missing: loki.info('Missing %d residue(s) in the sequence.' % missing) sequence = [] for i in range(min(keys), max(keys) + 1): if mapping.has_key(i): sequence.append(mapping[i]) return sequence
def writeMacro(self, size): """ Write all the required CYANA-commands into a macro. """ loki.info('A new Cyana macro required for %d structures.' % size) outf = open(self.name + '.cya', 'w') outf.write('cyanalib\n') outf.write('readdata %s\n' % self.name) # all angles in given amino acids as well as all omegas should be fixed if self.fixed_angles: outf.write('angle select *\n') outf.write('angle fix\n') outf.write('angle select -OMEGA\n') for fix in self.fixed_angles: outf.write('angle select -%s\n' % fix) outf.write('angle free\n') outf.write('read pdb %s\n' % self.name) outf.write('calc_all %d %s\n' % (size, self.__calc_end__)) outf.write('write_all %s- pdb\n' % self.name) # this could be used to find out the end seed # outf.write('system echo $seed > %s.seed'%self.name) outf.close() self.__last_macro_size__ = size
def anneal(self, amount, snippets=None, max_temp=4.0, min_temp=0.9, steps=5000): """ Anneal. """ amount = int(amount) if snippets is None: snippets = amount else: snippets = int(snippets) max_temp = float(max_temp) min_temp = float(min_temp) steps = int(steps) if snippets > amount: loki.warn('Snippet size larger than total amount. ' 'Running in one go.') snippets = amount # Current version of Cyana (2.1?) seems to be broken as tend is not # supported by anneal. FIXME when corrected. # self.__calc_end__ = 'anneal thigh=%1.3f tend=%1.3f steps=%d'%( \ # max_temp, min_temp, steps) self.__calc_end__ = 'anneal thigh=%1.3f steps=%d'%( \ max_temp, steps) if len(str(amount)) > self.tally_digits: self.tally_digits = len(str(amount)) loki.info('--- Anneal ---\nthigh=%1.3f tend=%1.3f steps=%d\n'%( \ max_temp, min_temp, steps) + '-'*14) done = 0 while done < amount: if amount - done > snippets: batch = snippets else: batch = amount - done self.run(batch) done += batch loki.info('%d structures ready' % done) loki.info('all done. Thank you for all the fish.')
def __init__(self, input, output=None, fixed_angles=None, rg_limits=None, use_limits=True, seed=None, state=None, jump=None, tally=0, tally_digits=3, name=None, verbose=False, debug=False): # store and/or process inputs self.input = str(input) self.rg_limits = rg_limits self.use_limits = bool(use_limits) self.tally = int(tally) self.tally_digits = int(tally_digits) if output != None: self.output = str(output) else: self.output = self.input + '-' self.fixed_angles = fixed_angles if fixed_angles != None: if type(fixed_angles) != list: if type(fixed_angles) == tuple: self.fixed_angles = list(fixed_angles) else: self.fixed_angles = [fixed_angles] for i in range(len(self.fixed_angles)): if type(self.fixed_angles[i]) in [list, tuple]: lo, hi = str(self.fixed_angles[i][0]), \ str(self.fixed_angles[i][1]) elif re.search('([0-9]+).+([0-9]+)', str(self.fixed_angles[i])): lo, hi = re.search('([0-9]+).+([0-9]+)', \ str(self.fixed_angles[i])).groups() else: lo = hi = str(self.fixed_angles[i]) self.fixed_angles[i] = '%s..%s' % (lo, hi) if name is None: self.name = 'temp-%d' % os.getpid() else: self.name = str(name) if debug: loki.setLevel(logging.DEBUG) elif verbose: loki.setLevel(logging.INFO) # check that required input files exist if not os.path.isfile(self.input + '.seq'): raise ArgumentError('No sequence file found.', 'Cyana') if self.fixed_angles and not os.path.isfile(self.input + '.pdb'): raise ArgumentError('No model PDB file found for angle fixes.', 'Cyana') # setup temporary files os.system('cp -f %s.seq %s.seq' % (self.input, self.name)) loki.info('Readied the sequence file for further use.') if self.use_limits: for suffix in ['lol', 'upl', 'aco', 'xplor']: if os.path.isfile(self.input + '.' + suffix): os.system('cp -f %s.%s %s.%s' % (self.input, suffix, self.name, suffix)) loki.info("Readied a '%s' file for further use." % suffix) if self.fixed_angles: os.system('cp -f %s.pdb %s.pdb' % (self.input, self.name)) # initialise the random generator self.randgen = Random(seed) if state == None: if jump != None: if sys.version < '2.2': loki.warn('Python older than 2.2. Problems may arise.') elif sys.version > '2.2' and sys.version < '2.3': # this should provide enough room for each run to be in # unique state space self.randgen.jumpahead(jump * self.amount * 1.1) else: self.randgen.jumpahead(jump) else: self.randgen.setstate(state) self.__last_macro_size__ = None
def run(self, txt=''): loki.info('arguments: %s' % txt) os.system('%s %s' % (self.command, txt))
def parse_sequence(args): """ Parse an amino acid sequence. Arguments: args -- a list of sequence items or a name of a file containing them, e.g. 'GLU PRO GLU CYS' or 'EPEC GLK C EEK' Returns: sequence -- a list of 3-letter amino acid symbols """ loki.debug('parse_sequence < %s' % repr(args)) if isinstance(args, str) and os.path.isfile(args): fname = args elif len(args) == 1 and isinstance(args[0], str): if os.path.isfile(args[0]): fname = args[0] else: if args[0].count(' '): args = args[0].split() else: args = args[0] fname = None else: fname = None if fname: f = open(fname) seq = f.read() f.close() loki.info("Read sequence from file '%s'." % fname) args = seq.strip().split() loki.debug('args=%s' % repr(args)) # sequence = [] # for aa in seq.strip().split(): # try: # sequence.append(omniTranslator(aa.capitalize(), \ # '3-letter-aminoacids')) # except KeyError: # loki.warn("Discarding unknown aminoacid '%s'." % repr(aa)) # else: # check whether all the sequence items are separated from each other args = [x.capitalize() for x in args] separated = True for a in args: if not (a in libLingua.dictionaryAmino1 or \ a in libLingua.dictionaryAmino3): separated = False loki.debug('separated=%s' % repr(separated)) sequence = [] if separated: # append each item after converting it to a 3-letter symbol for a in args: try: sequence.append(omniTranslator(a.capitalize(), \ '3-letter-aminoacids')) except KeyError: loki.warn("Discarding unknown aminoacid '%s'." % repr(a)) else: # jam all symbols together (hope they are all 1-letter symbols) aa = '' for a in args: aa += str(a) aa = aa.replace(' ', '') loki.debug('aa=%s' % repr(aa)) # append each item after converting it to a 3-letter symbol for a in list(aa): try: sequence.append(omniTranslator(a, '3-letter-aminoacids')) except KeyError: loki.warn("Discarding unknown aminoacid '%s'." % repr(a)) loki.debug('parse_sequence > %s' % repr(sequence)) return sequence