Mercurial > repos > rnateam > antarna
view antaRNA.py @ 1:ebc371f3c6b5 draft
planemo upload for repository https://github.com/bgruening/galaxytools/tree/master/tools/rna_tools/antarna/ commit 71414cf7f040d610afc3f02be31446efc3a82a40-dirty
author | rnateam |
---|---|
date | Wed, 13 May 2015 11:15:31 -0400 |
parents | fcf4719d3831 |
children |
line wrap: on
line source
import numpy import sys import random import subprocess import re import decimal import math import os import shutil import time import types import argparse #from argparse import RawTextHelpFormatter ############################# # FUNCTIONS def print2file(f, i, m): """ print content i to file f in mode m """ line = str(i) if m == "a": call = "echo \"" + line + "\" >> " + f elif m == "w": call = "echo \"" + line + "\" > " + f os.system(call) # checking and correcting the alphabet of the constraint sequence def checkSequenceConstraint(SC): """ Checks the Sequence constraint for illegal nucleotide characters """ out = "" for c in SC: c = c.upper() if c not in "ACGURYSWKMBDHVN": # and c!= "R" and c != "Y" and c != "S" and c != "W" and c != "K" and c != "M" and c != "B" and c != "D" and c != "H" and c != "V": if c == "T": c = "U" else: print "\tIllegal Character in the constraint sequence!" print "\tPlease use the IUPAC nomenclature for defining nucleotides in the constraint sequence!" print "\tA Adenine" print "\tC Cytosine" print "\tG Guanine" print "\tT/U Thymine/Uracil" print "\tR A or G" print "\tY C or T/U" print "\tS G or C" print "\tW A or T/U" print "\tK G or T/U" print "\tM A or C" print "\tB C or G or T/U" print "\tD A or G or T/U" print "\tH A or C or T/U" print "\tV A or C or G" print "\tN any base" exit(0) out += c return (1, out) def transform(seq): """ Transforms "U" to "T" for the processing is done on DNA alphabet """ S = "" for s in seq: if s == "T": S += "U" else: S += s return S def checkSimilarLength(s, SC): """ Compares sequence and structure constraint length """ if len(s) == len(SC): return 1 else: return 0 def isStructure(s): """ Checks if the structure constraint only contains "(", ")", and "." and legal fuzzy structure constraint characters. """ returnvalue = 1 for a in range(0,len(s)): if s[a] not in ".()[]{}<>": if s[a] not in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": returnvalue = 0 return returnvalue def isBalanced(s): """ Check if the structure s is of a balanced nature """ balance = 1 for bracket in ["()", "[]", "{}", "<>"]: counter = 0 for a in xrange(len(s)): if s[a] in bracket[0]: counter += 1 elif s[a] in bracket[1]: counter -= 1 if counter != 0: balance = 0 return balance def fulfillsHairpinRule(s): """ CHECKING FOR THE 3 nt LOOP INTERSPACE for all kind of basepairs, even wihtin the pdeudoknots """ fulfillsRules = 1 for bracket in ["()", "[]", "{}", "<>"]: last_opening_char = 0 check = 0 for a in xrange(len(s)): if s[a] == bracket[0]: last_opening_char = a check = 1 elif s[a] == bracket[1] and check == 1: check = 0 if a - last_opening_char < 4: return 0 return 1 def isValidStructure(s): """ Checks, if the structure s is a valid structure """ Structure = isStructure(s) Balanced = isBalanced(s) HairpinRule = fulfillsHairpinRule(s) if Structure == 1 and Balanced == 1 and HairpinRule == 1: return 1 else: print Structure, Balanced, HairpinRule return 0 def loadIUPACcompatibilities(IUPAC, useGU): """ Generating a hash containing all compatibilities of all IUPAC RNA NUCLEOTIDES """ compatible = {} for nuc1 in IUPAC: # ITERATING OVER THE DIFFERENT GROUPS OF IUPAC CODE sn1 = list(IUPAC[nuc1]) for nuc2 in IUPAC: # ITERATING OVER THE DIFFERENT GROUPS OF IUPAC CODE sn2 = list(IUPAC[nuc2]) compatib = 0 for c1 in sn1: # ITERATING OVER THE SINGLE NUCLEOTIDES WITHIN THE RESPECTIVE IUPAC CODE: for c2 in sn2: # ITERATING OVER THE SINGLE NUCLEOTIDES WITHIN THE RESPECTIVE IUPAC CODE: # CHECKING THEIR COMPATIBILITY if useGU == True: if (c1 == "A" and c2 == "U") or (c1 == "U" and c2 == "A") or (c1 == "C" and c2 == "G") or (c1 == "G" and c2 == "C") or (c1 == "G" and c2 == "U") or (c1 == "U" and c2 == "G"): compatib = 1 else: if (c1 == "A" and c2 == "U") or (c1 == "U" and c2 == "A") or (c1 == "C" and c2 == "G") or (c1 == "G" and c2 == "C"): compatib = 1 compatible[nuc1 + "_" + nuc2] = compatib # SAVING THE RESPECTIVE GROUP COMPATIBILITY, REVERSE SAVING IS NOT REQUIRED, SINCE ITERATING OVER ALL AGAINST ALL return compatible def isCompatibleToSet(c1, c2, IUPAC_compatibles): """ Checks compatibility of c1 wihtin c2 """ compatible = True for setmember in c2: #print setmember if isCompatible(c1, setmember, IUPAC_compatibles) == False: return False return compatible def isCompatible(c1, c2, IUPAC_compatibles): """ Checks compatibility between character c1 and c2 """ if IUPAC_compatibles[c1 + "_" + c2] == 1: return True else: return False def isStructureCompatible(lp1, lp2 ,bp): """ Checks, if the region within lp1 and lp2 is structurally balanced """ x = lp1 + 1 while (x < lp2): if (bp[x] <= lp1 or bp[x] > lp2): return False if x == bp[x]: x += 1 else: x = bp[x] + 1 return x == lp2 def checkConstaintCompatibility(basepairstack, sequenceconstraint, IUPAC_compatibles): """ Checks if the constraints are compatible to each other """ returnstring = "" compatible = 1 for id1 in basepairstack: # key = (constraint , (pos, constraint))) constr1 = basepairstack[id1][0] id2 = basepairstack[id1][1][0] constr2 = basepairstack[id1][1][1] if id1 != id2 and not isCompatible(constr1, constr2, IUPAC_compatibles): compatible = 0 returnstring += "nucleotide constraint " + str(constr1) + " at position " + str(id1) + " is not compatible with nucleotide constraint " + str(constr2) + " at position " + str(id2) + "\n" #if not isCompatible(basepairstack[basepair][0], basepairstack[basepair][1][1]): #compatible = 0 #else: #returnstring += "nucleotide constraint " + str(basepairstack[basepair][0]) + " at position " + str(basepair) + " is compatible with nucleotide constraint " + str(basepairstack[basepair][1][1]) + " at position " + str(basepairstack[basepair][1][0]) + "\n" return (compatible, returnstring) def getLP(BPSTACK): """ Retreives valid lonley base pairs from a base pair stack """ #20 ('N', (>BLOCK<, 'N')) # geting single base pairs stack = {} LP = {} if type(BPSTACK[random.choice(BPSTACK.keys())]) == types.TupleType: for i in BPSTACK.keys(): #if str(BPSTACK[i][1][0]) not in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": stack[i] = int(BPSTACK[i][1][0]) #print i , BPSTACK[i][1][0] else: for i in BPSTACK.keys(): #if str(BPSTACK[i]) not in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": stack[i] = BPSTACK[i] # removing redundant base pair indices for i in stack.keys(): if i >= stack[i]: del stack[i] # actual checking for single lonley base pairs for i in stack.keys(): if not (i-1 in stack and stack[i-1] == stack[i] + 1) and not (i+1 in stack and stack[i+1] == stack[i] - 1): LP[i] = stack[i] ##actual removal of 2er lonley base pairs for i in stack.keys(): if not (i-1 in stack and stack[i-1] == stack[i] + 1) and (i+1 in stack and stack[i+1] == stack[i] - 1) and not (i+2 in stack and stack[i+2] == stack[i] - 2): LP[i] = stack[i] LP[i+1] = stack[i+1] #if type(BPSTACK[random.choice(BPSTACK.keys())]) == types.TupleType: #for i in BPSTACK.keys(): ##if str(BPSTACK[i][1][0]) not in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": #stack[i] = int(BPSTACK[i][1][0]) ##print i , BPSTACK[i][1][0] #else: #for i in BPSTACK.keys(): ##if str(BPSTACK[i]) not in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": #stack[i] = BPSTACK[i] #for i in stack.keys(): #if i >= stack[i]: #del stack[i] return LP def getBPStack(s, seq): """ Returns a dictionary of the corresponding basepairs of the structure s and the sequence constraint seq. """ tmp_stack = {"()":[], "{}":[], "[]":[], "<>":[]} bpstack = {} for i in xrange(len(s)): # REGULAR SECONDARY STRUCTURE DETECTION if s[i] in "(){}[]<>": no = 0 ### opening if s[i] in "([{<": if s[i] == "(": tmp_stack["()"].append((i, seq[i])) elif s[i] == "[": tmp_stack["[]"].append((i, seq[i])) elif s[i] == "{": tmp_stack["{}"].append((i, seq[i])) elif s[i] == "<": tmp_stack["<>"].append((i, seq[i])) #closing elif s[i] in ")]}>": if s[i] == ")": no, constr = tmp_stack["()"].pop() elif s[i] == "]": no, constr = tmp_stack["[]"].pop() elif s[i] == "}": no, constr = tmp_stack["{}"].pop() elif s[i] == ">": no, constr = tmp_stack["<>"].pop() bpstack[no] = (constr, (i, seq[i])) bpstack[i] = (seq[i] ,(no, constr)) elif s[i] == ".": bpstack[i] = (seq[i], (i, seq[i])) elif s[i] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": bpstack[i] = (seq[i], (i, seq[i])) return (bpstack, getLP(bpstack)) def getbpStack(s): """ Returns a dictionary of the corresponding basepairs of the structure s and the sequence constraint seq. """ tmp_stack = {"()":[], "{}":[], "[]":[], "<>":[]} bpstack = {} for i in xrange(len(s)): if s[i] in "(){}[]<>": no = 0 ### opening if s[i] in "([{<": if s[i] == "(": tmp_stack["()"].append(i) elif s[i] == "[": tmp_stack["[]"].append(i) elif s[i] == "{": tmp_stack["{}"].append(i) elif s[i] == "<": tmp_stack["<>"].append(i) #closing elif s[i] in ")]}>": if s[i] == ")": no = tmp_stack["()"].pop() elif s[i] == "]": no = tmp_stack["[]"].pop() elif s[i] == "}": no = tmp_stack["{}"].pop() elif s[i] == ">": no = tmp_stack["<>"].pop() bpstack[no] = i # save basepair in the format {opening base id (opening seq constr,(closing base id, closing seq constr))} bpstack[i] = no # save basepair in the format {closing base id (closing seq constr,(opening base id, opening seq constr))} elif s[i] == ".": # no structural constaint given: produce entry, which references itself as a base pair partner.... bpstack[i] = i elif s[i] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": bpstack[i] = i #elif s[i] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": ## per position, assigned to a certain block, the target nucleotide, with whcih it should interact is marked with the specific ## block character #bpstack[i] = s[i] return (bpstack, getLP(bpstack)) def maprange( a, b, s): """ Mapping function """ (a1, a2), (b1, b2) = a, b return b1 + ((s - a1) * (b2 - b1) / (a2 - a1)) def applyGCcontributionPathAdjustment(pathlength, tmpGC, nt): """ GC path length contribution calculation. """ GCadjustment = 1.5 minimum = 0.5 upper = GCadjustment lower = minimum if nt == "A" or nt == "U": pathlength = pathlength * maprange( (0, 1) , (lower, upper), tmpGC) if nt == "G" or nt == "C": #pathlength = pathlength * (float(1-tmpGC)) pathlength = pathlength * maprange( (1, 0) , (lower, upper), tmpGC) return pathlength def getConstraint(TE, BPstack, IUPAC, IUPAC_compatibles, IUPAC_reverseComplements): """ Dependend on the situation in the constraint an the respective path section, setting wether a specific constraint can be given or not (for that path section) """ # TE :: transition element / path section under dispute # id1 :: id of the position of the caharacter to which the transition is leading to # id2 :: id of the position of the character, which is listed in the BPinformation, it can be id1 as well, when no bp is present # val :: BPstack information of the specific position # constr1 :: constraining character of pos id1 # constr2 :: constraining character of pos id2 id1 = int(TE.split(".")[0]) val = BPstack[id1] # check out the value of the destination character in the basepair/constraint stack constr1 = val[0] # getting the constraint character of position id1 id2 = int(val[1][0]) # getting position id2 constr2 = val[1][1] # getting the sequence constraint for position id2 targetNucleotide = TE.split(".")[1][-1:] # where the edge is leading to c1 = set(IUPAC[constr1]) # getting all explicit symbols of c1 c2 = set(IUPAC_reverseComplements[constr2]) # getting the reverse complement explicit symbols of c2 if targetNucleotide in c1: if id1 == id2: return 1 else: if targetNucleotide in c2: return 1 else: return 0 else: return 0 """ def getConstraint(TE, BPstack): # TE :: transition element / path section # id1 :: id of the position of the caharacter to which the transition is leading to # id2 :: id of the position of the character, which is listed in the BPinformation, it can be id1 as well, when no bp is present # val :: BPstack information of the specific position # constr1 :: constraining character of pos id1 # constr2 :: constraining character of pos id2 ### BPstack [id1] = (constr1, (id2, constr2)) id1 = TE.split(".")[0] #print id1 #id1 = TE.find(TE.strip("_")) # strip the path section and getting the position of the section #if len(TE.strip("_")) == 2: # check if the path section is from an internal and not an initial transition #id1 += 1 # increase position id1 by 1, since the last character of the section is the destination character val = BPstack[int(id1)] # check out the value of the destination character in the basepair/constraint stack constr1 = val[0] # getting the constraint character of position id1 id2 = val[1][0] # getting position id2 constr2 = val[1][1] # getting the sequence constraint for position id2 #print TE, id1, constr1, id2, constr2, #TE.split(".")[1][-1:] if id1 == id2: # both ids were the same with either character, sequential or no sequential constraint -> no basepair constraint if constr1 == TE.split(".")[1][-1:] and constr2 == TE.split(".")[1][-1:]: # case if the single base constraints on position id1 == id2 are the same as the destination character on id1 #print 1 return 1 elif constr1 == constr2 == "N": # case if the single base constraints on position id1 == id2 has no constraint #print 1 return 1 else: # single base sequence constraints differ #print 0 return 0 elif id1 != id2: # showing differentq ids, indicating a bp, (basepair structural constraint) if constr1 == "N" and constr2 == "N": # no sequence constraint #print 1 return 1 if constr1 == "N" and constr2 != "N": # c1 has no constraint, c2 has character constraint (sequence constraint of closing bases) if TE.split(".")[1][-1:] == complementBase(constr2): # the current path section destination base is equal to the complement base of the mentioned sequence constraint in constr2 #print 1 return 1 else: # case if the current path section destination base is not equeal to the mentioned complement sequence constraint in constr2 #print 0 return 0 if constr1 != "N" and constr2 == "N": # c1 has character constraint, c2 has no character constraint (sequence constraint in the opening base) if TE.split(".")[1][-1:] == constr1: # the current path section destination base is as constrained with constr1 #print 1 return 1 else: # the current path section destination base is not as constrained in constr1 #print 0 return 0 if constr1 != "N" and constr2 != "N": # both positions have sequential constraint if TE.split(".")[1][-1:] == constr1: #print 1 return 1 else: #print 0 return 0 """ def applyTerrainModification(terrain, s, tmpGC, SC, BPstack, IUPAC, IUPAC_compatibles, IUPAC_reverseComplements): #nucleotides = {'A': 0, 'C': 1,'G': 2,'T': 3} dels = [] for terrainelement in sorted(terrain): pheromone, pathlength = terrain[terrainelement] pheromone = getConstraint(terrainelement, BPstack, IUPAC, IUPAC_compatibles, IUPAC_reverseComplements) pathlength = getConstraint(terrainelement, BPstack, IUPAC, IUPAC_compatibles, IUPAC_reverseComplements) pathlength = applyGCcontributionPathAdjustment(pathlength, tmpGC,terrainelement.split(".")[1][-1:]) if pheromone * pathlength == 0: dels.append(terrainelement) terrain[terrainelement] = (pheromone, pathlength,[]) further_dels = {} for terrainelement in sorted(dels): pos, nucs = terrainelement.split(".") if int(pos) < len(s)-1: to_nt = nucs[-1:] successor_pos = int(pos) + 1 for i in ["A", "C", "G", "U"]: del_element = str(successor_pos) + "." + to_nt + i further_dels[del_element] = 1 further_dels[terrainelement] = 1 # deleting the inbound and outbound edges, which are forbidden for terrainelement in further_dels: del terrain[terrainelement] # allocate the appropriate children of edges for terrainelement in terrain: pheromone, pathlength, children = terrain[terrainelement] pos, nucs = terrainelement.split(".") if int(pos) < len(s): to_nt = nucs[-1:] successor_pos = int(pos) + 1 for i in ["A", "C", "G", "U"]: if str(successor_pos) + "." + to_nt + i in terrain: children.append(str(successor_pos) + "." + to_nt + i) terrain[terrainelement] = (pheromone, pathlength,children) starts = [] for i in ["A", "C", "G", "U"]: if str(0) + "." + i in terrain: starts.append(str(0) + "." + i) terrain["00.XY"] = (1, 1, starts) return (terrain, BPstack) def initTerrain(s): # THE CLASSIC """ Initialization of the terrain with graph like terrain... vertices are modeled implicitly """ nt = ["A","C","G","U"] nt2 = ["AA","AC","AG","AU","CA","CC","CG","CU","GA","GC","GG","GU","UA","UC","UG","UU"] # Allowed dinucleotides e = {} pathlength = 1 pheromone = 1 for p in xrange(len(s)): if p == 0: for i in nt: e["%s.%s"%(p,i)] = (pheromone, pathlength) elif p > 0: for n in nt2: e["%s.%s"%(p,n)] = (pheromone, pathlength) return e def complementBase(c): """ Returns the complement RNA character of c (without GU base pairs) """ retChar = "" if c == "A" : retChar = "U" elif c == "U": retChar = "A" elif c == "C": retChar = "G" elif c == "G": retChar = "C" return retChar def printTerrain(terrain): #print sorted(terrain.keys()) tmp_i = "0" tmp_c = 0 terrain = terrain[0] for a, i in enumerate(sorted(terrain.keys())): #print a if i.split(".")[0] != tmp_i: print "\nElements:", tmp_c,"\n#########################\n", i, terrain[i] tmp_c = 1 tmp_i = i.split(".")[0] else: print i, terrain[i] tmp_c += 1 print "\nElements:", tmp_c print "#########################" print len(terrain) def pickStep(tmp_steps, summe): """ Selects a step within the terrain """ if len(tmp_steps) == 1: return tmp_steps[0][1] # returning the nucleotide of the only present step else: rand = random.random() # draw random number mainval = 0 for choice in xrange(len(tmp_steps)): val, label = tmp_steps[choice] mainval += val/float(summe) if mainval > rand: # as soon, as the mainval gets larger than the random value the assignment is done return label def getPath(s, tmp_terrain, tmp_BPstack, alpha, beta, IUPAC, IUPAC_reverseComplements): """ Performs a walk through the terrain and assembles a sequence, while respecting the structure constraint and IUPAC base complementarity of the base pairs GU, GC and AT """ nt = ["A","C","G","U"] prev_edge = "00.XY" sequence = "" while len(sequence) < len(s): coming_from = sequence[-1:] summe = 0 steps = [] i = len(sequence) allowed_nt = "ACGU" # base pair closing case check, with subsequent delivery of a reduced allowed nt set if i > tmp_BPstack[i][1][0]: jump = tmp_BPstack[i][1][0] nuc_at_jump = sequence[jump] allowed_nt = IUPAC_reverseComplements[nuc_at_jump] #allowed_nt = complementBase(nuc_at_jump) # Checking for every possible nt if it is suitable for the selection procedure for edge in tmp_terrain[prev_edge][-1]: if edge[-1:] in allowed_nt: pheromone, PL , children = tmp_terrain[edge] #if PL > 0: value = ((float(pheromone * alpha)) + ((1/float(PL)) * beta)) summe += value steps.append((value, edge)) prev_edge = pickStep(steps, summe) sequence += prev_edge[-1:] return sequence ### # STRUCTURE PREDICTORS ### def getPKStructure(sequence, temperature, mode = "A"): """ Initialization pKiss mfe pseudoknot prediction """ p2p = "pKiss" #p2p = "/usr/local/pkiss/2014-03-17/bin/pKiss_mfe" strategy = "--strategy " t = "--temperature " + str(temperature) if mode == "A": strategy += "A" elif mode == "B": strategy += "B" elif mode == "C": strategy += "C" elif mode == "D": strategy += "D" elif mode == "P": strategy += "P" p = subprocess.Popen( ([p2p, "--mode mfe", strategy, t]), #shell = True, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, close_fds = True) #print p.stderr.readline() p.stdin.write(sequence+'\n') pks = p.communicate() structure = "".join(pks[0].split("\n")[2].split(" ")[-1:]) return structure def init_RNAfold(version, temperature, paramFile = ""): """ Initialization RNAfold listener """ p2p = "" t = "-T " + str(temperature) P = "" if paramFile != "": P = "-P " + paramFile if version == 185: p2p = "/home/rk/Software/ViennaRNA/ViennaRNA-1.8.5/Progs/RNAfold" p = subprocess.Popen( ([p2p, '--noPS', '-d 2', t, P]), shell = True, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, close_fds = True) return p elif version == 213: p2p = "RNAfold" p = subprocess.Popen( ([p2p, '--noPS', '-d 2', t, P]), #shell = True, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, close_fds = True) return p else: exit(0) def consult_RNAfold(seq, p): """ Consults RNAfold listener """ p.stdin.write(seq+'\n') out = "" for i in xrange(2): out += p.stdout.readline() return out def getRNAfoldStructure(struct2, process1): """ Retrieves folded structure of a RNAfold call """ RNAfold_pattern = re.compile('.+\n([.()]+)\s.+') #RNAdist_pattern = re.compile('.*\s([\d]+)') RNAfold_match = RNAfold_pattern.match(consult_RNAfold(struct2, process1)) current_structure = "" #if RNAfold_match: return RNAfold_match.group(1) def init_RNAdistance(): """ Initialization of RNAdistance listener """ #p2p = "/home/rk/Software/ViennaRNA/ViennaRNA-1.8.5/Progs/RNAdistance" p2p = "RNAdistance" p = subprocess.Popen( ([p2p]), #shell = True, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, close_fds = True) return p def consult_RNAdistance(s1, s2, p): """ Consulting the RNAdistance listener """ p.stdin.write(s1+'\n') p.stdin.write(s2+'\n') out = "" out_tmp = p.stdout.readline().strip() if out_tmp != "": out += out_tmp return out def getInducingSequencePositions(Cseq, degreeOfSequenceInducement): """ Delimiting the degree of structure inducement by the supplied sequence constraint. 0 : no sequence induced structure constraint 1 : "ACGT" induce structure (explicit nucleotide structure inducement level) 2 : "MWKSYR" and "ACGT" (explicit and double instances) 3 : "BDHV" , "MWKSYR" and "ACGT" (explicit, double, and triple instances) """ setOfNucleotides = "" # resembling the "0"-case if degreeOfSequenceInducement == 1: setOfNucleotides = "ACGU" elif degreeOfSequenceInducement == 2: setOfNucleotides = "ACGUMWKSYR" elif degreeOfSequenceInducement == 3: setOfNucleotides = "ACGUMWKSYRBDHV" #elif degreeOfSequenceInducement == 4: #setOfNucleotides = "ACGTMWKSYRBDHVN" tmpSeq = "" listset = setOfNucleotides for pos in Cseq: if pos not in listset: tmpSeq += "N" else: tmpSeq += pos return setOfNucleotides, tmpSeq def getBPDifferenceDistance(stack1, stack2): """ Based on the not identical amount of base pairs within both structure stacks """ d = 0 for i in stack1.keys(): # check base pairs in stack 1 if i < stack1[i] and stack1[i] != stack2[i]: d += 1 # check base pairs in stack 2 for i in stack2.keys(): if i < stack2[i] and stack1[i] != stack2[i]: d += 1 return d def getStructuralDistance(target_structure, Cseq, path, RNAfold, verbose, LP, BP, RNAfold_pattern, IUPAC_compatibles, degreeOfSequenceInducement, pseudoknots, strategy): """ Calculator for Structural Distance """ # fold the current solution's sequence to obtain the structure current_structure = "" if pseudoknots: current_structure = getPKStructure(path,strategy) else: RNAfold_match = RNAfold_pattern.match(consult_RNAfold(path, RNAfold)) current_structure = RNAfold_match.group(1) # generate the current structure's base-pair stack bp = getbpStack(current_structure)[0] # add case-dependend structural constraints in case of lonley basepairs formation tmp_target_structure_bp = getbpStack(target_structure)[0] for lp in LP: if bp[lp] == LP[lp]: # if the base pair is within the current solution structure, re-add the basepair into the constraint structure. #tmp_target_structure[lp] = "(" #tmp_target_structure[LP[lp]] = ")" tmp_target_structure_bp[lp] = LP[lp] tmp_target_structure_bp[LP[lp]] = lp # REMOVE BLOCK CONSTRAINT AND SUBSTITUTE IT WITH SINGLE STRAND INFORMATION repsective with brackets, if allowed base pairs occure # check for all allowed implicit constraint block declarators for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": occurances = [] for m in re.finditer(c, target_structure): # search for a declarator in the requested structure occurances.append(m.start()) # save the corresponding index # transform declarator into single stranded request for i in occurances: #tmp_target_structure[i] = "." tmp_target_structure_bp[i] = i # infer a base pair within the block declarated positions, if the current structure provides it. for i in occurances: for j in occurances: if i < j: if bp[i] == j: #tmp_target_structure[i] = "(" #tmp_target_structure[bp[i]] = ")" tmp_target_structure_bp[i] = bp[i] tmp_target_structure_bp[bp[i]] = i # CHECK FOR SEQUENCE CONSTRAINT WHICH INDUCES STRUCTURE CONSTRAINT IN THE MOMENTARY SITUATION #print "Checking Cseq influence and it's induced basepairs..." IUPACinducers, tmp_Cseq = getInducingSequencePositions(Cseq, degreeOfSequenceInducement) if len(Cseq.strip("N")) > 0: #print "Processing Cseq influence" # Iterate over all positions within the Base Pair stack for i in BP: # Check for each base index i if i < bp[i]: # if the current index is samller that the affiliated in the basepair stack of the current solution bp_j = bp[i] # Actual j index of the current solution BP_j = BP[i][1][0] # j index of the requested structure if (i != bp_j and i == BP_j and BP[i][0] in IUPACinducers ): # if i pairs with some other base in the current structure, and i is requested single stranded and the Sequence constraint is allowed to induce... if (BP[bp_j][1][0] == bp_j and BP[bp_j][0] in IUPACinducers):# If position j is requested singlestranded and position j nucleotide can induce base pairs #if isCompatible(bp[i][0], bp[i][1][1], IUPAC_compatibles): # If both nucleotides, i and j are actually compatible #tmp_target_structure[i] = "(" #tmp_target_structure[bp_j] = ")" tmp_target_structure_bp[i] = bp[i] tmp_target_structure_bp[bp_j] = i #tts = "".join(tmp_target_structure) dsreg = getBPDifferenceDistance(tmp_target_structure_bp, bp) # CHECK FOR ALL DETERMINED LONELY BASE PAIRS (i<j), if they are formed failLP = 0 for lp in LP: if bp[lp] != LP[lp]: isComp = isCompatible(path[lp],path[LP[lp]], IUPAC_compatibles) isStru = isStructureCompatible(lp, LP[lp] ,bp) if not ( isStru and isStru ): # check if the bases at the specific positions are compatible and check if the # basepair can be formed according to pseudoknot free restriction. If one fails, a penalty distance is raised for that base pair failLP += 1 #print dsreg, failLP, float(len(tmp_target_structure_bp)) dsLP = float(failLP) return (dsreg + dsLP) /float(len(tmp_target_structure_bp)) def getGC(sequence): """ Calculate GC content of a sequence """ GC = 0 for nt in sequence: if nt == "G" or nt == "C": GC = GC + 1 GC = GC/float(len(sequence)) return GC def getGCDistance(tGC, gc2, L): """ Calculate the pseudo GC content distance """ nt_coeff = L * tGC pc_nt = (1/float(L))*100 # d = gc2 - tGC d = d * 100 f = math.floor(nt_coeff) c = math.ceil(nt_coeff) if d < 0: # #print "case x",(abs(nt_coeff - f)), pc_nt, (abs(nt_coeff - f)) * pc_nt, d = d + (abs(nt_coeff - f)) * pc_nt elif d > 0: # case y #print "case y", abs(nt_coeff - c), pc_nt, abs(nt_coeff - c) * pc_nt, d = d - abs(nt_coeff - c) * pc_nt elif d == 0: pass d = round(d, 7) #d = max(0, abs(d)- ( max ( abs( math.ceil(nt_coeff)-(nt_coeff)) , abs(math.floor(nt_coeff)-(nt_coeff)) )/L)*100 ) return abs(d) def getSequenceEditDistance(SC, path): """ Calculate sequence edit distance of a solution to the constraint """# IUPAC = {"A":"A", "C":"C", "G":"G", "U":"U", "R":"AG", "Y":"CU", "S":"GC", "W":"AU","K":"GU", "M":"AC", "B":"CGU", "D":"AGU", "H":"ACU", "V":"ACG", "N":"ACGU"} edit = 0 for i in xrange(len(SC)): if path[i] not in IUPAC[SC[i]]: edit += 1 return edit/float(len(path)) def getTransitions(p): """ Retreive transitions of a specific path/sequence """ transitions = [] for pos in xrange(len(p)): if pos == 0: transitions.append(str(pos) + "." + p[pos]) else: insert = p[pos-1] + p[pos] transitions.append(str(pos) + "." + insert) return transitions def evaporate(t, er): """ Evaporate the terrain's pheromone trails """ terr, BP = t c = 1 for key in terr: p,l,c = terr[key] p *= (1-er) terr[key] = (p, l, c) def updateValue(distance, correction_term, omega): """ Retrieves a distance dependend pheromone value """ if correction_term == 0: return 0 else: if distance == 0: return omega * correction_term else: return (1/float(distance)) * correction_term def trailBlaze(p, c_s, s, ds, dgc, dseq, dn, t, correction_terms, BPstack, verbose): """ Pheromone Update function accorinding to the quality of the solution """ terr, BP = t bpstack, LP = getbpStack(c_s) struct_correction_term , GC_correction_term, seq_correction_term = correction_terms omega = 2.23 bs = updateValue(ds, struct_correction_term, omega) bGC = updateValue(dgc, GC_correction_term, omega) if dseq != "n.a.": bSeq = updateValue(dseq, seq_correction_term, omega) d = bs + bGC + bSeq else: d = bs + bGC transitions = getTransitions(p) for trans in xrange(len(transitions)): # for each transition in the path id1 = int(transitions[trans].split(".")[0]) tar_id2 = int(BPstack[id1][1][0]) # getting requested position id2 curr_id2 = int(bpstack[id1]) # getting the current situation multiplicator = 0 if tar_id2 == curr_id2 and id1 != tar_id2 and id1 != curr_id2: # case of a base pair, having both brackets on the correct position multiplicator = 1 elif tar_id2 == curr_id2 and id1 == tar_id2 and id1 == curr_id2: # case of a single stranded base in both structures multiplicator = 1 p, l, c = terr[transitions[trans]] # getting the pheromone and the length value of the single path transition p += d * multiplicator terr[transitions[trans]] = (p, l, c) # updating the values wihtin the terrain's t = (terr, BP) def updateTerrain(p, c_s, s, ds, dgc, dseq, dn, t, er, correction_terms, BPstack, verbose, ant_count): """ General updating function """ evaporate(t,er) trailBlaze(p, c_s, s, ds, dgc, dseq, dn, t, correction_terms, BPstack, verbose) def getUsedTime(start_time): """ Return the used time between -start time- and now. """ end_time = time.time() return end_time - start_time def good2Go(SC, L, CC, STR): """ Check, if all input is correct and runnable """ if (SC == 1 and L == 1 and CC == 1 and STR == 1): return True else: print SC,L,CC,STR return False def getPathFromSelection( aps, s, terrain, alpha, beta, RNAfold, RNAfold_pattern, GC, SC, LP, verbose, IUPAC_compatibles, degreeOfSequenceInducement, IUPAC_reverseComplements, IUPAC, pseudoknots, strategy): """ Returns the winning path from a selection of pathes... """ terr, BPs = terrain win_path = 0 for i in xrange(aps): # Generate Sequence path = getPath(s, terr, BPs, alpha, beta, IUPAC, IUPAC_reverseComplements) # Measure sequence features and transform them into singular distances distance_structural = float(getStructuralDistance(s, SC , path, RNAfold, verbose, LP, BPs, RNAfold_pattern, IUPAC_compatibles, degreeOfSequenceInducement, pseudoknots, strategy)) distance_GC = float(getGCDistance(GC,getGC(path), len(path))) distance_seq = float(getSequenceEditDistance(SC, path)) # Calculate Distance Score D = distance_structural + distance_GC + distance_seq # SELECT THE BEST-OUT-OF-k-SOLUTIONS according to distance score if i == 0: win_path = (path, D, distance_structural, distance_GC, distance_seq) else: if D < win_path[1]: win_path = (path, D, distance_structural, distance_GC, distance_seq) return win_path def substr(x, string, subst): """ Classical substring function """ s1 = string[:x-1] s2 = string[x-1:x] s3 = string[x:] #s2 = s[x+len(string)-x-1:] return s1 + subst + s3 def inConvergenceCorridor(d_struct, d_gc, BS_d_struct, BS_d_gc): """ Check if a solutions qualities are within the convergence corridor """ struct_var = ((BS_d_struct/float(4)) + 3 ) * 4 gc_var = (BS_d_gc + 1/float(100) * 5) + BS_d_gc + 1 if d_struct <= struct_var and d_gc <= gc_var: return True else: return False def getGCSamplingValue(GC, tGCmax, tGCvar): """ Returns a suitable GC value, dependend on the user input: Either returning the single GC value, which the user entered, or a smpled GC value from a designated distribution in it's interavals """ returnval = 0 if tGCmax == -1.0 and tGCvar == -1.0: # regular plain tGC value as requested return GC elif tGCmax != -1.0 and tGCvar == -1.0: # uniform distribution tGC value sampling if GC < tGCmax: tmp_GC = tGCmax tGCmax = GC GC = tmp_GC while returnval <= 0: returnval = float(numpy.random.uniform(low=GC, high=tGCmax, size=1)) return returnval elif tGCmax == -1.0 and tGCvar != -1.0: # normal distribution tGC value sampling while returnval <= 0: returnval = float(numpy.random.normal(GC, tGCvar, 1)) return returnval def reachableGC(C_struct): """ Checks if a demanded GC target content is reachable in dependence with the given sequence constraint. """ AU = 0 for i in C_struct: if i == "A" or i == "U": AU += 1 maxGC = 1 - (AU / float(len(C_struct))) # 1 - min_GC return maxGC def runColony(s, SC, objective_to_target_distance, GC, alpha, beta, evaporation_rate, correction_terms, verbose, IUPAC, IUPAC_compatibles, degreeOfSequenceInducement, IUPAC_reverseComplements, termination_convergence, convergence_count, reset_limit, improve, temperature, paramFile, pseudoknots, strategy): """ Execution function of a single ant colony finding one solution sequence """ retString = "" retString2 = [] BPstack, LP = getBPStack(s, SC) rGC = reachableGC(SC) GC_message = "" if GC > rGC: print >> sys.stderr, "WARNING: Chosen target GC %s content is not reachable due to sequence constraint! Sequence Constraint GC-content is: %s" % (GC, rGC) GC = rGC # Initial Constraint Checks prior to execution STR = isValidStructure(s) START_SC , SC = checkSequenceConstraint(str(SC)) START_LENGTH = checkSimilarLength(str(s), str(SC)) START_constraint_compatibility , CompReport = checkConstaintCompatibility(BPstack, SC, IUPAC_compatibles) g2g = good2Go(START_SC, START_LENGTH, START_constraint_compatibility, STR) if (g2g == 1): start_time = time.time() max_time = 600 # seconds #### # INITIALIZATION OF THE RNA TOOLs # RNAfold = init_RNAfold(213, temperature, paramFile) #RNAdistance = init_RNAdistance() RNAfold_pattern = re.compile('.+\n([.()]+)\s.+') #RNAdist_pattern = re.compile('.*\s([\d]+)') # #### terrain = initTerrain(s) #print len(terrain), terrain = applyTerrainModification(terrain, s, GC, SC, BPstack, IUPAC, IUPAC_compatibles, IUPAC_reverseComplements) #print len(terrain[0]) #printTerrain(terrain) #exit(0) global_ant_count = 0 global_best_ants = 0 criterion = False met = True ant_no = 1 prev_res = 0 seq = "" counter = 0 dstruct_log = [] dGC_log = [] distance_structural = 1000 distance_GC = 1000 distance_seq = 1000 convergence = convergence_count convergence_counter = 0 resets = 0 path = "" curr_structure = "" Dscore = 100000 distance_structural = 10000 distance_GC = 10000 distance_seq = 10000 best_solution = (path, curr_structure, Dscore, distance_structural, distance_GC, distance_seq) best_solution_local = (path, curr_structure, Dscore, distance_structural, distance_GC, distance_seq) best_solution_since = 0 ants_per_selection = 10 if len(LP) > 0 : for lp in LP: s = substr(lp + 1, s, ".") s = substr(LP[lp] + 1, s, ".") init = 1 while criterion != met and getUsedTime(start_time) < max_time: iteration_start = time.time() global_ant_count += 1 global_best_ants += 1 path_info = getPathFromSelection(ants_per_selection, s, terrain, alpha, beta, RNAfold, RNAfold_pattern, GC, SC, LP, verbose, IUPAC_compatibles, degreeOfSequenceInducement, IUPAC_reverseComplements, IUPAC, pseudoknots, strategy) distance_structural_prev = distance_structural distance_GC_prev = distance_GC distance_seq_prev = distance_seq path, Dscore , distance_structural, distance_GC, distance_seq = path_info curr_structure = "" if pseudoknots: curr_structure = getPKStructure(path, strategy) else: curr_structure = getRNAfoldStructure(path, RNAfold) curr_solution = (path,curr_structure, Dscore, distance_structural, distance_GC, distance_seq) # BEST SOLUTION PICKING if improve == "h": # hierarchical check # for the global best solution if distance_structural < best_solution[3] or (distance_structural == best_solution[3] and distance_GC < best_solution[4]): best_solution = curr_solution ant_no = 1 # for the local (reset) best solution if distance_structural < best_solution_local[3] or (distance_structural == best_solution_local[3] and distance_GC < best_solution_local[4]): best_solution_local = curr_solution elif improve == "s": #score based check # store best global solution if Dscore < best_solution[2]: best_solution = curr_solution ant_no = 1 # store best local solution for this reset if Dscore < best_solution_local[2]: best_solution_local = curr_solution # OLD ' BEST SOLUTION ' PICKING # if Dscore < best_solution[2]: # best_solution = (path,curr_structure, Dscore, distance_structural, distance_GC, distance_seq) # # if Dscore < best_solution_local[2]: # best_solution_local = (path,curr_structure, Dscore, distance_structural, distance_GC, distance_seq) distance_DN = 0 if verbose: print "SCORE " + str(Dscore) + " Resets " + str(resets) + " #Ant " + str(global_ant_count) + " out of " + str(ants_per_selection) + " cc " + str(convergence_counter) print s, " <- target struct" print best_solution[0] , " <- BS since ", str(best_solution_since), "Size of Terrrain:", len(terrain[0]) print best_solution[1] , " <- BS Dscore " + str(best_solution[2]) + " ds " + str(best_solution[3]) + " dGC " + str(best_solution[4]) + " dseq " + str(best_solution[5])+ " LP " + str(len(LP)) + " <- best solution stats" print curr_structure, " <- CS" print path, print " <- CS", "Dscore", str(Dscore), "ds", distance_structural, "dGC", distance_GC, "GC", getGC(path)*100, "Dseq", distance_seq #### UPDATING THE TERRAIN ACCORDING TO THE QUALITY OF THE CURRENT BESTO-OUT-OF-k SOLUTION updateTerrain(path, curr_structure, s, distance_structural,distance_GC, distance_seq, distance_DN, terrain, evaporation_rate, correction_terms, BPstack, verbose, global_ant_count) #### if verbose: print "Used time for one iteration", time.time() - iteration_start # CONVERGENCE AND TERMINATION CRITERION MANAGEMENT #print distance_structural, distance_GC, best_solution_local[3], best_solution_local[4] if inConvergenceCorridor(curr_solution[3], curr_solution[4], best_solution_local[3], best_solution_local[4]): convergence_counter += 1 if distance_structural_prev == distance_structural and distance_GC_prev == distance_GC: convergence_counter += 1 if best_solution[3] == objective_to_target_distance: if best_solution[4] == 0.0: break ant_no = ant_no + 1 convergence_counter -= 1 else: ant_no = 1 if ant_no == termination_convergence or resets >= reset_limit or global_ant_count >= 100000 or best_solution_since == 5: break # RESET if ant_no < termination_convergence and convergence_counter >= convergence: terrain = initTerrain(s) terrain = applyTerrainModification(terrain, s, GC, SC, BPstack, IUPAC, IUPAC_compatibles, IUPAC_reverseComplements) criterion = False met = True ant_no = 1 prev_res = 0 pre_path = "_" * len(s) path = "" curr_structure = "" counter = 0 Dscore = 100000 distance_structural = 1000 distance_GC = 1000 distance_seq = 1000 best_solution_local = (path, curr_structure, Dscore, distance_structural, distance_GC, distance_seq) convergence = convergence_count convergence_counter = 0 if resets == 0: sentinel_solution = best_solution best_solution_since += 1 else: if best_solution[2] < sentinel_solution[2]: sentinel_solution = best_solution best_solution_since = 0 else: best_solution_since += 1 resets += 1 duration = getUsedTime(start_time) retString += "|Ants:" + str(global_ant_count) retString += "|Resets:" + str(resets) + "/" + str(reset_limit) retString += "|AntsTC:" + str(termination_convergence) retString += "|CC:" + str(convergence_count) retString += "|IP:" + str(improve) retString += "|BSS:" + str(best_solution_since) #if GC_message != "": # retString += GC_message + "\n" sequence = best_solution[0] struct = best_solution[1] retString += "|LP:" + str(len(LP)) retString += "|ds:" + str(getStructuralDistance(s,SC, sequence, RNAfold, verbose, LP, BPstack, RNAfold_pattern, IUPAC_compatibles, degreeOfSequenceInducement, pseudoknots, strategy)) retString += "|dGC:" + str(best_solution[4]) retString += "|GC:" + str(getGC(sequence)*100) retString += "|dseq:" + str(getSequenceEditDistance(SC, sequence)) retString += "|L:" + str(len(sequence)) retString += "|Time:" + str(duration) retString2.append(struct) retString2.append(sequence) # CLOSING THE PIPES TO THE PROGRAMS RNAfold.communicate() #RNAdistance.communicate() else: # Structural premisses are not met, htherefore the program will halt with a failure message retString += "\nSome mistake detected\n" retString += "SequenceConstraintCheck: " + str(START_SC) + "\nSequenceConstraint: " + str(SC) + "\nLengthCheck: " + str(START_LENGTH) + "\nConstraintCompatibility: " + str(START_constraint_compatibility)+ "\n" + CompReport + "\n" return (retString, retString2) def findSequence(structure, Cseq, tGC, colonies, name, alpha, beta, evaporation_rate, struct_correction_term, GC_correction_term, seq_correction_term, degreeOfSequenceInducement, file_id, verbose, output_verbose, tGCmax, tGCvar, termination_convergence, convergence_count, reset_limit, improve, seed, temperature, paramFile, pseudoknots, strategy, useGU, return_mod = False): """ MAIN antaRNA - ant assembled RNA """ if seed != "none": random.seed(seed) if Cseq == "": sequenceconstraint = "N" * len(structure) else: sequenceconstraint = str(Cseq) alpha = float(alpha) beta = float(beta) tGC = float(tGC) evaporation_rate = float(evaporation_rate) struct_correction_term = float(struct_correction_term) GC_correction_term = float(GC_correction_term) seq_correction_term = float(seq_correction_term) colonies = int(colonies) file_id = str(file_id) tmp_verbose = verbose tmp_output_verbose = output_verbose verbose = tmp_output_verbose # Due to later change, this is a twistaround and a switching of purpose output_verbose = tmp_verbose # Due to later change, this is a twistaround and a switching of purpose correction_terms = struct_correction_term, GC_correction_term, seq_correction_term temperature = float(temperature) print_to_STDOUT = (file_id == "STDOUT") useGU = useGU if return_mod == False: if print_to_STDOUT == False: outfolder = '/'.join(file_id.strip().split("/")[:-1]) curr_dir = os.getcwd() if not os.path.exists(outfolder): os.makedirs(outfolder) os.chdir(outfolder) sequenceconstraint = transform(sequenceconstraint) ############################################### # Allowed deviation from the structural target: objective_to_target_distance = 0.0 # Loading the IUPAC copatibilities of nuleotides and their abstract representing symbols IUPAC = {"A":"A", "C":"C", "G":"G", "U":"U", "R":"AG", "Y":"CU", "S":"GC", "W":"AU","K":"GU", "M":"AC", "B":"CGU", "D":"AGU", "H":"ACU", "V":"ACG", "N":"ACGU"} IUPAC_compatibles = loadIUPACcompatibilities(IUPAC, useGU) IUPAC_reverseComplements = {} if useGU == False: ## Without the GU basepair IUPAC_reverseComplements = {"A":"U", "C":"G", "G":"C", "U":"A", "R":"UC", "Y":"AG", "S":"GC", "W":"UA","K":"CA", "M":"UG", "B":"AGC", "D":"ACU", "H":"UGA", "V":"UGC", "N":"ACGU"} else: ## allowing the GU basepair IUPAC_reverseComplements = {"A":"U", "C":"G", "G":"UC", "U":"AG", "R":"UC", "Y":"AG", "S":"UGC", "W":"UAG","K":"UCAG", "M":"UG", "B":"AGCU", "D":"AGCU", "H":"UGA", "V":"UGC", "N":"ACGU"} result = [] for col in xrange(colonies): # Checking the kind of taget GC value should be used GC = getGCSamplingValue(tGC, tGCmax, tGCvar) # Actual execution of a ant colony procesdure output_v, output_w = runColony(structure, sequenceconstraint, objective_to_target_distance, GC, alpha, beta, evaporation_rate, correction_terms, verbose, IUPAC, IUPAC_compatibles, degreeOfSequenceInducement, IUPAC_reverseComplements, termination_convergence, convergence_count, reset_limit, improve, temperature, paramFile, pseudoknots, strategy) # Post-Processing the output of a ant colony procedure line = ">" + name + str(col) if output_verbose: line += "|Cstr:" + structure + "|Cseq:" + sequenceconstraint + "|Alpha:" + str(alpha) + "|Beta:" + str(beta) + "|tGC:" + str(GC) + "|ER:" + str(evaporation_rate) + "|Struct_CT:" + str(struct_correction_term) + "|GC_CT:" + str(GC_correction_term) + "|Seq_CT:" + str(seq_correction_term) + output_v + "\n" + "\n".join(output_w) else: line += "\n" + output_w[1] if return_mod == False: if print_to_STDOUT: print line else: if col == 0: print2file(file_id, line, 'w') else: print2file(file_id, line, 'a') else: result.append(line) if return_mod == True: return result if print_to_STDOUT == False: os.chdir(curr_dir) def execute(args): """ CHECK AND PARSE THE COMMAND LINE STUFF """ # Checking the arguments, parsed from the shell ############################################### name = args.name structure = args.Cstr if args.Cseq == "": sequenceconstraint = "N" * len(structure) else: sequenceconstraint = args.Cseq seed = args.seed alpha = args.alpha beta = args.beta tGC = args.tGC if tGC < 0 or tGC > 1: print "Error: Chosen tGC not in range [0,1]" exit(1) evaporation_rate = args.ER struct_correction_term = args.Cstrweight GC_correction_term = args.Cgcweight seq_correction_term = args.Cseqweight colonies = args.noOfColonies degreeOfSequenceInducement = args.level file_id = args.output_file verbose = args.verbose output_verbose = args.output_verbose tGCmax = args.tGCmax tGCvar = args.tGCvar termination_convergence = args.antsTerConv convergence_count = args.ConvergenceCount temperature = args.temperature reset_limit = args.Resets improve = args.improve_procedure ### RNAfold parameterfile paramFile = args.paramFile # Using the pkiss program under user changeable parameters pseudoknots = args.pseudoknots # Loading the optimized parameters for pseudoknots and ignore user input if args.pseudoknot_parameters: alpha = 1.0 beta = 0.1 evaporation_rate = 0.2 struct_correction_term = 0.1 GC_correction_term = 1.0 seq_correction_term = 0.5 termination_convergence = 50 convergence_count = 100 strategy = args.strategy useGU = args.useGUBasePair checkForViennaTools() if pseudoknots: checkForpKiss() findSequence(structure, sequenceconstraint, tGC, colonies, name, alpha, beta, evaporation_rate, struct_correction_term, GC_correction_term, seq_correction_term, degreeOfSequenceInducement, file_id, verbose, output_verbose, tGCmax, tGCvar, termination_convergence, convergence_count, reset_limit, improve, seed, temperature, paramFile, pseudoknots, strategy, useGU) def exe(): """ MAIN EXECUTABLE WHICH PARSES THE INPUT LINE """ argument_parser = argparse.ArgumentParser( description = """ ######################################################################### # antaRNA - ant assembled RNA # # -> Ant Colony Optimized RNA Sequence Design # # ------------------------------------------------------------ # # Robert Kleinkauf (c) 2015 # # Bioinformatics, Albert-Ludwigs University Freiburg, Germany # ######################################################################### - For antaRNA only the VIENNNA RNA Package must be installed on your linux system. antaRNA will only check, if the executables of RNAfold and RNAdistance of the ViennaRNA package can be found. If those programs are not installed correctly, no output will be generated, an also no warning will be prompted. So the binary path of the Vienna Tools must be set up correctly in your system's PATH variable in order to run antaRNA correctly! - antaRNA was only tested under Linux. - For questions and remarks please feel free to contact us at http://www.bioinf.uni-freiburg.de/ """, epilog = """ Example calls: python antaRNA.py --Cstr "...(((...)))..." --tGC 0.5 -n 2 python antaRNA.py --Cstr ".........AAA(((...)))AAA........." --tGC 0.5 -n 10 --output_file /path/to/antaRNA_TESTRUN -ov python antaRNA.py --Cstr "BBBBB....AAA(((...)))AAA....BBBBB" --Cseq "NNNNANNNNNCNNNNNNNNNNNGNNNNNNUNNN" --tGC 0.5 -n 10 ######################################################################### # --- Hail to the Queen!!! All power to the swarm!!! --- # ######################################################################### """, #formatter_class=RawTextHelpFormatter ) # mandatorys argument_parser.add_argument("-Cstr", "--Cstr", help="Structure constraint using RNA dotbracket notation with fuzzy block constraint. \n(TYPE: %(type)s)\n\n", type=str, required=True) argument_parser.add_argument("-tGC", "--tGC", help="Objective target GC content in [0,1].\n(TYPE: %(type)s)\n\n", type=float, required=True) argument_parser.add_argument("-n", "--noOfColonies", help="Number of sequences which shall be produced. \n(TYPE: %(type)s)\n\n\n\n", type=int, default=1) argument_parser.add_argument("-GU", "--useGUBasePair", help="Allowing GU base pairs. \n\n", action="store_true") argument_parser.add_argument("-s", "--seed", help = "Provides a seed value for the used pseudo random number generator.\n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=str, default="none") argument_parser.add_argument("-ip", "--improve_procedure", help = "Select the improving method. h=hierarchical, s=score_based.\n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=str, default="s") argument_parser.add_argument("-r", "--Resets", help = "Amount of maximal terrain resets, until the best solution is retuned as solution.\n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=int, default=5) argument_parser.add_argument("-CC", "--ConvergenceCount", help = "Delimits the convergence count criterion for a reset.\n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=int, default=130) argument_parser.add_argument("-aTC", "--antsTerConv", help = "Delimits the amount of internal ants for termination convergence criterion for a reset.\n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=int, default=50) argument_parser.add_argument("-p", "--pseudoknots", help = "Switch to pseudoknot based prediction using pKiss. Check the pseudoknot parameter usage!!!\n\n", action="store_true") argument_parser.add_argument("-pkPar", "--pseudoknot_parameters", help = "Enable optimized parameters for the usage of pseudo knots (Further parameter input ignored).\n\n", action="store_true") argument_parser.add_argument("--strategy", help = "Defining the pKiss folding strategy.\n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=str, default="A") # Mutual Exclusiv target GC distribution variables #tGCgroup = argument_parser.add_mutually_exclusive_group() argument_parser.add_argument("-tGCmax", "--tGCmax", help = "Provides a maximum tGC value [0,1] for the case of uniform distribution sampling. The regular tGC value serves as minimum value.\n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=float, default=-1.0) argument_parser.add_argument("-tGCvar", "--tGCvar", help = "Provides a tGC variance (sigma square) for the case of normal distribution sampling. The regular tGC value serves as expectation value (mu).\n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=float, default=-1.0) argument_parser.add_argument("-t", "--temperature", help = "Provides a temperature for the folding algorithms.\n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=float, default=37.0) argument_parser.add_argument("-P", "--paramFile", help = "Changes the energy parameterfile of RNAfold. If using this explicitly, please provide a suitable energy file delivered by RNAfold. \n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=str, default="") argument_parser.add_argument("-of","--output_file", help="Provide a path and an output file, e.g. \"/path/to/the/target_file\". \n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=str, default="STDOUT") argument_parser.add_argument("-Cseq", "--Cseq", help="Sequence constraint using RNA nucleotide alphabet {A,C,G,U} and wild-card \"N\". \n(TYPE: %(type)s)\n\n", type=str, default = "") argument_parser.add_argument("-l", "--level", help="Sets the level of allowed influence of sequence constraint on the structure constraint [0:no influence; 3:extensive influence].\n(TYPE: %(type)s)\n\n", type=int, default = 1) argument_parser.add_argument("--name", help="Defines a name which is used in the sequence output. \n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=str, default="antaRNA_") argument_parser.add_argument("-a", "--alpha", help="Sets alpha, probability weight for terrain pheromone influence. [0,1] \n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=float, default=1.0) argument_parser.add_argument("-b", "--beta", help="Sets beta, probability weight for terrain path influence. [0,1]\n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=float, default=1.0) argument_parser.add_argument("-er", "--ER", help="Pheromone evaporation rate. \n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=float, default=0.2) argument_parser.add_argument("-Cstrw", "--Cstrweight", help="Structure constraint quality weighting factor. [0,1]\n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=float, default=0.5) argument_parser.add_argument("-Cgcw", "--Cgcweight", help="GC content constraint quality weighting factor. [0,1]\n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n", type=float, default=5.0) argument_parser.add_argument("-Cseqw", "--Cseqweight", help="Sequence constraint quality weighting factor. [0,1]\n(DEFAULT: %(default)s, TYPE: %(type)s)\n\n\n", type=float, default=1.0) argument_parser.add_argument("-ov", "--output_verbose", help="Displayes intermediate output.\n\n", action="store_true") argument_parser.add_argument("-v", "--verbose", help="Prints additional features and stats to the headers of the produced sequences. Also adds the structure of the sequence.\n\n", action="store_true") args = argument_parser.parse_args() execute(args) def checkForViennaTools(): """ Checking for the presence of the Vienna tools in the system by which'ing for RNAfold and RNAdistance """ RNAfold_output = subprocess.Popen(["which", "RNAfold"], stdout=subprocess.PIPE).communicate()[0].strip() if len(RNAfold_output) > 0 and RNAfold_output.find("found") == -1 and RNAfold_output.find(" no ") == -1: return True else: print "It seems the Vienna RNA Package is not installed on your machine. Please do so!" print "You can get it at http://www.tbi.univie.ac.at/" exit(0) def checkForpKiss(): """ Checking for the presence of pKiss """ pKiss_output = subprocess.Popen(["which", "pKiss"], stdout=subprocess.PIPE).communicate()[0].strip() if len(pKiss_output) > 0 and pKiss_output.find("found") == -1 and pKiss_output.find(" no ") == -1: return True else: print "It seems that pKiss is not installed on your machine. Please do so!" print "You can get it at http://bibiserv2.cebitec.uni-bielefeld.de/pkiss" exit(0) if __name__ == "__main__": exe()