def unPause(): global paused if paused: f.runInParallel([[calculatePi, ()]]) f.runInParallel([[renderPi, ()]]) paused = False
def echoKeys(enable=False,disable=False): #change whether to let keypresses be displayed on the terminal global isEchoKeys if enable: f.runBash("stty echo") isEchoKeys=True elif disable: f.runBash("stty -echo") isEchoKeys=False else: return isEchoKeys
def buildEscape(theType, theValue): if theType == "hex" or theType == "hexadecimal": if theValue.startswith("0x"): theValue = f.withoutFirst(f.withoutFirst(theValue)) return EscapeStarters.hexadecimal + theValue elif theType == "octal" or theType == "oct": return EscapeStarters.octal + theValue elif theType == "unicode": return EscapeStarters.unicode + theValue elif theType == "esc" or theType == "escape": return EscapeStarters.hexadecimal + theValue
def keyHandler(self): self.stop=False while not self.stop: t.sleep(0.01) char=getLastChar() if not char==None: try: f.runInParallel([self.actions[char]]) except KeyError: try: f.runInParallel([[self.actions["default"],(char)]]) except KeyError: pass
def raw(enable=False,disable=False): #enable and disable raw (unbuffered) mode. useful for getting last char without newline global isRaw if enable: f.runBash(""" stty raw """) isRaw=True elif disable: f.runBash(""" stty -raw """) isRaw=False else: return isRaw
def bbGetAngle(self, r, ca, ss): import FUNC, IO import math # Elnedyn takes angles from structure, with fc=40 return (math.acos( FUNC.cos_angle([i - j for i, j in zip(ca[0], ca[1])], [i - j for i, j in zip(ca[2], ca[1])])) / IO.d2r, 40)
def main(): global paused paused = False global piGenerator, terminalSize terminalSize = tf.getTerminalSize() global dataSource dataSource = 0 global startTime startTime = t.perf_counter() getColorPallete() initScr() f.runInParallel([[calculatePi, ()]]) f.runInParallel([[renderPi, ()]]) startKeyHandler()
def bbGetAngle(self, r, ca, ss): import FUNC, IO import math # Elnedyn takes angles from structure, with fc=40 return ( math.acos(FUNC.cos_angle([i - j for i, j in zip(ca[0], ca[1])], [i - j for i, j in zip(ca[2], ca[1])])) / IO.d2r, 40, )
def handle(self): self.data = self.request.recv(1024).strip().decode() #得到一个1kb的请求 List = self.data.split('#') #用'#'分割 if List[0] == 'log in': #登陆 account = List[1] pw = List[2] flag = FUNC.login(account,pw) self.request.sendall(bytes(flag, 'utf8')) if List[0] == 'send url': userID = List[1] URL = List[2] flag = FUNC.sendURL(userID,URL) self.request.sendall(bytes(flag, 'utf8')) #这里写linux内下载命令 比如axel + url if List[0] == 'get url': userID = List[1] fileName = List[2] flag = FUNC.getURL(userID,fileName) self.request.sendall(bytes(flag, 'utf8')) #服务器的 if List[0] == 'get list': userID = List[1] flag = FUNC.getList(userID) self.request.sendall(bytes(flag, 'utf8')) if List[0] == 'register': account = List[1] pw = List[2] flag = FUNC.register(account,pw) self.request.sendall(bytes(flag, 'utf8'))
def conect(self): # Return pairs of numbers that should be CONECTed # First extract the backbone IDs cg = self.cg() bb = [i+1 for i, j in zip(range(len(cg)), cg) if j[0] == "BB"] bb = zip(bb, bb[1:]+[len(bb)]) # Set the backbone CONECTs (check whether the distance is consistent with binding) conect = [(i, j) for i, j in bb[:-1] if FUNC.distance2(cg[i-1][4:7], cg[j-1][4:7]) < 14] # Now add CONECTs for sidechains for i, j in bb: nsc = j-i-1
def fillWithSpaces(crIfRaw=True,saveCursor=True): #fill screen with spaces cursor=CursorSaver() if saveCursor: cursor.save(0) size=getTerminalSize() for line in f.fromTo(2,size["rows"]): print(" "*size["columns"],crIfRaw=crIfRaw,newline=True) if saveCursor: cursor.load(0)
def save(): global piDigits, terminalSize global lastPosition global keyHandler pause() oldKeys = keyHandler.actions keyHandler.actions = {"default": bellButItTakesArgs} t.sleep(0.02) digitChunks = f.splitString(piDigits, (len(piDigits) // 100) + 1) #split digits into a 100 chunks f.write("pi.txt", "") #delete digits that are already there tf.moveCursor(to={"row": lastPosition[1] + 1, "column": 0}) tf.clear(line=True) for digit in f.everyIndexInList(digitChunks): #save the digits f.appendTo("pi.txt", digitChunks[digit]) #append the next chunk tf.changeStyle(italic=True, invert=True, bold=True) tf.print("{}% done saving".format(digit + 1)) tf.moveCursor(to={ "row": lastPosition[1] + 1, "column": 0 }) #go to bottom left if pause: unPause() keyHandler.actions = oldKeys
def getBar(text, moveCursor=False): global lastPosition global terminalSize renderString = "" if moveCursor: renderString += tf.cursor(to={"row": lastPosition[1] + 1, "column": 1}) renderString += tf.style(reset=True) renderString += tf.style(italic=True, invert=True, bold=True) renderString += tf.clearer(line=True) renderString += f.cutString(text, terminalSize["columns"]) renderString += tf.style(reset=True) return renderString
def bbGetAngle(self,r,ca,ss): # Check is it DNA residue if r[0] in MAP.dnares3: return ca in self.dnaBbAngleDictC.keys() and self.dnaBbAngleDictC[ca] or None # RNA is not implemented properly yet elif r[0] in MAP.rnares3: return ca in self.rnaBbAngleDictC.keys() and self.rnaBbAngleDictC[ca] or None # For protein else: import FUNC,IO import math # Elnedyn takes angles from structure, with fc=40 return (math.acos(FUNC.cos_angle([i-j for i,j in zip(ca[0],ca[1])],[i-j for i,j in zip(ca[2],ca[1])]))/IO.d2r, 40)
def bbGetBond(self,r,ca,ss): # Retrieve parameters for each residue from tables defined above # Check is it DNA residue if r[0] in MAP.dnares3: return ca in self.dnaBbBondDictC.keys() and self.dnaBbBondDictC[ca] or None # RNA is not implemented properly yet elif r[0] in MAP.rnares3: return ca in self.rnaBbBondDictC.keys() and self.rnaBbBondDictC[ca] or None # If it's protein else: import FUNC import math # The 150000 forceconstant gave an error message, turning to constraints would be better. return ( math.sqrt(FUNC.distance2(ca[0],ca[1]))/10., None )
def pdbBoxString(box): # Box vectors u, v, w = box[0:3], box[3:6], box[6:9] # Box vector lengths nu, nv, nw = [math.sqrt(FUNC.norm2(i)) for i in (u, v, w)] # Box vector angles alpha = nv*nw == 0 and 90 or math.acos(FUNC.cos_angle(v, w))/d2r beta = nu*nw == 0 and 90 or math.acos(FUNC.cos_angle(u, w))/d2r gamma = nu*nv == 0 and 90 or math.acos(FUNC.cos_angle(u, v))/d2r return pdbBoxLine % (10*FUNC.norm(u), 10*FUNC.norm(v), 10*FUNC.norm(w), alpha, beta, gamma)
def add_dummy(beads, dist=0.11, n=2): # Generate a random vector in a sphere of -1 to +1, to add to the bead position v = [random.random()*2.-1, random.random()*2.-1, random.random()*2.-1] # Calculated the length of the vector and divide by the final distance of the dummy bead norm_v = FUNC.norm(v)/dist # Resize the vector vn = [i/norm_v for i in v] # m sets the direction of the added vector, currently only works when adding one or two beads. m = 1 for j in range(n): newName = 'SCD' newBead = (newName, tuple([i+(m*j) for i, j in zip(beads[-1][1], vn)]), beads[-1][2]) beads.append(newBead) m *= -2 return beads
def __str__(self): if not self.atoms or not self.parameters: return "" s = ["%5d" % i for i in self.atoms] # For exclusions, no type is defined, which equals -1 if self.type != -1: s.append(" %5d " % self.type) # Print integers and floats in proper format and neglect None terms s.extend([FUNC.formatString(i) for i in self.parameters if i is not None]) if self.comments: s.append(';') if type(self.comments) == str: s.append(self.comments) else: s.extend([str(i) for i in self.comments]) return " ".join(s)
def rubberBands(atomList, lowerBound, upperBound, decayFactor, decayPower, forceConstant, minimumForce): out = [] u2 = upperBound**2 while len(atomList) > 3: bi, xi = atomList.pop(0) for bj, xj in atomList[2:]: # Mind the nm/A conversion -- This has to be standardized! Global use of nm? d2 = FUNC.distance2(xi, xj)/100 if d2 < u2: dij = math.sqrt(d2) fscl = decayFunction(dij, lowerBound, decayFactor, decayPower) if fscl*forceConstant > minimumForce: out.append({"atoms": (bi, bj), "parameters": (dij, "RUBBER_FC*%f" % fscl)}) return out
def __str__(self): if not self.atoms or not self.parameters: return "" s = ["%5d" % i for i in self.atoms] # For exclusions, no type is defined, which equals -1 if self.type != -1: s.append(" %5d " % self.type) # Print integers and floats in proper format and neglect None terms s.extend( [FUNC.formatString(i) for i in self.parameters if i is not None]) if self.comments: s.append(';') if type(self.comments) == str: s.append(self.comments) else: s.extend([str(i) for i in self.comments]) return " ".join(s)
def rubberBands(atomList, lowerBound, upperBound, decayFactor, decayPower, forceConstant, minimumForce): out = [] u2 = upperBound**2 while len(atomList) > 3: bi, xi = atomList.pop(0) for bj, xj in atomList[2:]: # Mind the nm/A conversion -- This has to be standardized! Global use of nm? d2 = FUNC.distance2(xi, xj) / 100 if d2 < u2: dij = math.sqrt(d2) fscl = decayFunction(dij, lowerBound, decayFactor, decayPower) if fscl * forceConstant > minimumForce: out.append({ "atoms": (bi, bj), "parameters": (dij, "RUBBER_FC*%f" % fscl) }) return out
def rubberBands(atomList,lowerBound,upperBound,decayFactor,decayPower,forceConstant,minimumForce): out = [] u2 = upperBound**2 while len(atomList) > 3: bi,xi = atomList.pop(0) # This is a bit weird (=wrong I think) way of doing the cutoff... #for bj,xj in atomList[2:]: for bj,xj in atomList: # Mind the nm/A conversion -- This has to be standardized! Global use of nm? d2 = FUNC.distance2(xi,xj)/100 #if bi==73 and bj==79: # print xi, xj, d2 if d2 < u2: dij = math.sqrt(d2) fscl = decayFunction(dij,lowerBound,decayFactor,decayPower) if fscl*forceConstant > minimumForce: out.append({"atoms":(bi,bj),"parameters": (dij,"RUBBER_FC*%f"%fscl)}) return out
# dihedral definitions, which are not present for coil and termini # ss_names = { "F": "Collagenous Fiber", #@# "E": "Extended structure (beta sheet)", #@# "H": "Helix structure", #@# "1": "Helix start (H-bond donor)", #@# "2": "Helix end (H-bond acceptor)", #@# "3": "Ambivalent helix type (short helices)", #@# "T": "Turn", #@# "S": "Bend", #@# "C": "Coil", #@# } bbss = ss_names.keys() bbss = FUNC.spl(" F E H 1 2 3 T S C") # SS one letter # The following dictionary contains secondary structure types as assigned by # different programs. The corresponding Martini secondary structure types are # listed in cgss # # NOTE: # Each list of letters in the dictionary ss should exactly match the list # in cgss. # ssdefs = { "dssp": list(".HGIBETSC~"), # DSSP one letter secondary structure code #@# "pymol": list(".H...S...L"), # Pymol one letter secondary structure code #@# "gmx": list(".H...ETS.C"), # Gromacs secondary structure dump code #@# "self": list("FHHHEETSCC") # Internal CG secondary structure codes #@#
delay_ssn = np.array([]) for i, ssn_val in enumerate(ssn): if i == len(dealy): break ssn_d = ssn[-len(dealy) + i + dealy[i]] delay_ssn = np.append(delay_ssn, ssn_d) dealy_pos = np.ones(25, dtype='int') * -5 dealy_neg = np.ones(25, dtype='int') * -12 ssn_1 = df_ssn.loc[:'1980-12', 'smooth'].values ssn_2 = df_ssn.loc[:'1990-12', 'smooth'].values ssn_3 = df_ssn.loc[:'2001-05', 'smooth'].values ssn_4 = df_ssn.loc[:'2013-06', 'smooth'].values ssn_sig_1 = FUNC.PtoN(ssn_1, dealy_pos, dealy_neg) ssn_sig_2 = FUNC.PtoN(ssn_2, dealy_neg, dealy_pos) ssn_sig_3 = FUNC.PtoN(ssn_3, dealy_pos, dealy_neg) ssn_sig_4 = FUNC.PtoN(ssn_4, dealy_neg, dealy_pos) range_info['ssn_delay'] = delay_ssn """ sigmod 平滑 """ range_info.loc['1978-12-01':'1980-12-01', 'ssn_delay'] = ssn_sig_1 range_info.loc['1988-12-01':'1990-12-01', 'ssn_delay'] = ssn_sig_2 range_info.loc['1999-05-01':'2001-05-01', 'ssn_delay'] = ssn_sig_3 range_info.loc['2011-06-01':'2013-06-01', 'ssn_delay'] = ssn_sig_4 # range_info.loc['1979-01-01':'1980-12-01', 'ssn_delay'] = \
conf = CONFIG.config # settings --------------------------------- # 0 flow control OFF res = MDM.send('AT&K0\r', 0) res = MDM.receive(10) # Konfiguration laden --------------------------------------------------- res = CONFIG.initConfig() SER.set_speed(conf['COM'],'8N1') a = SER.send('\r\n***************************************************************************') a = SER.send('\r\n* Start Terminal Connection - Triptec Service *') a = SER.send('\r\n***************************************************************************\r\n') a = SER.send('\r\n- wait for connection to network ----------------\r\n') r = FUNC.openGPRS(conf['PIN_SIM'],conf['APN'],conf['GPRS_USER'],conf['GPRS_PASS']) #openGPRS(P,A,GU,GP) a = FUNC.setGPIO(CONFIG.statLED,1) a = SER.send('\r\n\r\n- wait for data input ----------------\r\n') # start Schleife -------------------------------------------------------- while 1: a = FUNC.setGPIO(CONFIG.statLED,0) MOD.sleep(10) a = FUNC.setGPIO(CONFIG.statLED,1) MOD.sleep(10) b = SER.send('\r\nYou have 10 seconds to put something in.\r\n') MOD.sleep(10) res = SER.receive(100) MOD.sleep(10)
def main(options): # Check whether to read from a gro/pdb file or from stdin # We use an iterator to wrap around the stream to allow # inferring the file type, without consuming lines already inStream = IO.streamTag(options["-f"] and options["-f"].value or sys.stdin) # The streamTag iterator first yields the file type, which # is used to specify the function for reading frames fileType = inStream.next() if fileType == "GRO": frameIterator = IO.groFrameIterator else: frameIterator = IO.pdbFrameIterator # ITERATE OVER FRAMES IN STRUCTURE FILE # # Now iterate over the frames in the stream # This should become a StructureFile class with a nice .next method model = 1 cgOutPDB = None ssTotal = [] cysteines = [] for title, atoms, box in frameIterator(inStream): if fileType == "PDB": # The PDB file can have chains, in which case we list and process them specifically # TER statements are also interpreted as chain separators # A chain may have breaks in which case the breaking residues are flagged chains = [IO.Chain(options, [i for i in IO.residues(chain)]) for chain in IO.pdbChains(atoms)] else: # The GRO file does not define chains. Here breaks in the backbone are # interpreted as chain separators. residuelist = [residue for residue in IO.residues(atoms)] # The breaks are indices to residues broken = IO.breaks(residuelist) # Reorder, such that each chain is specified with (i,j,k) # where i and j are the start and end of the chain, and # k is a chain identifier chains = zip([0]+broken, broken+[len(residuelist)], range(len(broken)+1)) chains = [IO.Chain(options, residuelist[i:j], name=chr(65+k)) for i, j, k in chains] for chain in chains: chain.multiscale = "all" in options['multi'] or chain.id in options['multi'] # Check the chain identifiers if model == 1 and len(chains) != len(set([i.id for i in chains])): # Ending down here means that non-consecutive blocks of atoms in the # PDB file have the same chain ID. The warning pertains to PDB files only, # since chains from GRO files get a unique chain identifier assigned. logging.warning("Several chains have identical chain identifiers in the PDB file.") # Check if chains are of mixed type. If so, split them. # Note that in some cases HETATM residues are part of a # chain. This will get problematic. But we cannot cover # all, probably. if not options['MixedChains']: demixedChains = [] for chain in chains: demixedChains.extend(chain.split()) chains = demixedChains n = 1 logging.info("Found %d chains:" % len(chains)) for chain in chains: logging.info(" %2d: %s (%s), %d atoms in %d residues." % (n, chain.id, chain._type, chain.natoms, len(chain))) n += 1 # Check all chains keep = [] for chain in chains: if chain.type() == "Water": logging.info("Removing %d water molecules (chain %s)." % (len(chain), chain.id)) elif chain.type() in ("Protein", "Nucleic"): keep.append(chain) # This is currently not active: elif options['RetainHETATM']: keep.append(chain) else: logging.info("Removing HETATM chain %s consisting of %d residues." % (chain.id, len(chain))) chains = keep # Here we interactively check the charge state of resides # Can be easily expanded to residues other than HIS for chain in chains: for i, resname in enumerate(chain.sequence): if resname == 'HIS' and options['chHIS']: choices = {0: 'HIH', 1: 'HIS'} choice = IO.getChargeType(resname, i, choices) chain.sequence[i] = choice # Check which chains need merging if model == 1: order, merge = IO.check_merge(chains, options['mergeList'], options['linkList'], options['CystineCheckBonds'] and options['CystineMaxDist2']) # Get the total length of the sequence seqlength = sum([len(chain) for chain in chains]) logging.info('Total size of the system: %s residues.' % seqlength) ## SECONDARY STRUCTURE ss = '' if options['Collagen']: for chain in chains: chain.set_ss("F") ss += chain.ss elif options["-ss"]: # XXX We need error-catching here, # in case the file doesn't excist, or the string contains bogus. # If the string given for the sequence consists strictly of upper case letters # and does not appear to be a file, assume it is the secondary structure ss = options["-ss"].value.replace('~', 'L').replace(' ', 'L') if ss.isalnum() and ss.isupper() and not os.path.exists(options["-ss"].value): ss = options["-ss"].value logging.info('Secondary structure read from command-line:\n'+ss) else: # There ought to be a file with the name specified ssfile = [i.strip() for i in open(options["-ss"].value)] # Try to read the file as a Gromacs Secondary Structure Dump # Those have an integer as first line if ssfile[0].isdigit(): logging.info('Will read secondary structure from file (assuming Gromacs ssdump).') ss = "".join([i for i in ssfile[1:]]) else: # Get the secondary structure type from DSSP output logging.info('Will read secondary structure from file (assuming DSSP output).') pss = re.compile(r"^([ 0-9]{4}[0-9]){2}") ss = "".join([i[16] for i in open(options["-ss"].value) if re.match(pss, i)]) # Now set the secondary structure for each of the chains sstmp = ss for chain in chains: ln = min(len(sstmp), len(chain)) chain.set_ss(sstmp[:ln]) sstmp = ss[:ln] else: if options["-dssp"]: method, executable = "dssp", options["-dssp"].value #elif options["-pymol"]: # method, executable = "pymol", options["-pymol"].value else: logging.warning("No secondary structure or determination method speficied. Protein chains will be set to 'COIL'.") method, executable = None, None for chain in chains: ss += chain.dss(method, executable) # Used to be: if method in ("dssp","pymol"): but pymol is not supported if method in ["dssp"]: logging.debug('%s determined secondary structure:\n' % method.upper()+ss) # Collect the secondary structure classifications for different frames ssTotal.append(ss) # Write the coarse grained structure if requested if options["-x"].value: logging.info("Writing coarse grained structure.") if cgOutPDB is None: cgOutPDB = open(options["-x"].value, "w") cgOutPDB.write("MODEL %8d\n" % model) cgOutPDB.write(title) cgOutPDB.write(IO.pdbBoxString(box)) atid = 1 for i in order: ci = chains[i] if ci.multiscale: for r in ci.residues: for name, resn, resi, chain, x, y, z in r: cgOutPDB.write(IO.pdbOut((name, resn[:3], resi, chain, x, y, z),i=atid)) atid += 1 coarseGrained = ci.cg(com=True) if coarseGrained: for name, resn, resi, chain, x, y, z, ssid in coarseGrained: if ci.multiscale: name = "v"+name cgOutPDB.write(IO.pdbOut((name, resn[:3], resi, chain, x, y, z),i=atid,ssid=ssid)) atid += 1 cgOutPDB.write("TER\n") else: logging.warning("No mapping for coarse graining chain %s (%s); chain is skipped." % (ci.id, ci.type())) cgOutPDB.write("ENDMDL\n") # Gather cysteine sulphur coordinates cyslist = [cys["SG"] for chain in chains for cys in chain["CYS"]] cysteines.append([cys for cys in cyslist if cys]) model += 1 # Write the index file if requested. # Mainly of interest for multiscaling. # Could be improved by adding separte groups for BB, SC, etc. if options["-n"].value: logging.info("Writing index file.") # Lists for All-atom, Virtual sites and Coarse Grain. NAA, NVZ, NCG = [], [], [] atid = 1 for i in order: ci = chains[i] coarseGrained = ci.cg(force=True) if ci.multiscale: NAA.extend([" %5d" % (a+atid) for a in range(ci.natoms)]) atid += ci.natoms if coarseGrained: if ci.multiscale: NVZ.extend([" %5d" % (a+atid) for a in range(len(coarseGrained))]) else: NCG.extend([" %5d" % (a+atid) for a in range(len(coarseGrained))]) atid += len(coarseGrained) outNDX = open(options["-n"].value, "w") outNDX.write("\n[ AA ]\n"+"\n".join([" ".join(NAA[i:i+15]) for i in range(0, len(NAA), 15)])) outNDX.write("\n[ VZ ]\n"+"\n".join([" ".join(NVZ[i:i+15]) for i in range(0, len(NVZ), 15)])) outNDX.write("\n[ CG ]\n"+"\n".join([" ".join(NCG[i:i+15]) for i in range(0, len(NCG), 15)])) outNDX.close() # Write the index file for mapping AA trajectory if requested if options["-nmap"].value: logging.info("Writing trajectory index file.") atid = 1 outNDX = open(options["-nmap"].value, "w") # Get all AA atoms as lists of atoms in residues # First we skip hetatoms and unknowns then iterate over beads # In DNA the O3' atom is mapped together with atoms from the next residue # This stores it until we get to the next residue o3_shift = '' for i_count, i in enumerate(IO.residues(atoms)): if i[0][1] in ("SOL", "HOH", "TIP"): continue if not i[0][1] in MAP.CoarseGrained.mapping.keys(): continue nra = 0 names = [j[0] for j in i] # This gives out a list of atoms in residue, each tuple has other # stuff in it that's needed elsewhere so we just take the last # element which is the atom index (in that residue) for j_count, j in enumerate(MAP.mapIndex(i)): outNDX.write('[ Bead %i of residue %i ]\n' % (j_count+1, i_count+1)) line = '' for k in j: if names[k[2]] == "O3'": line += '%s ' % (str(o3_shift)) o3_shift = k[2]+atid else: line += '%i ' % (k[2]+atid) line += '\n' nra += len(j) outNDX.write(line) atid += nra # Evertything below here we only need, if we need to write a Topology if options['-o']: # Collect the secondary structure stuff and decide what to do with it # First rearrange by the residue ssTotal = zip(*ssTotal) ssAver = [] for i in ssTotal: si = list(set(i)) if len(si) == 1: # Only one type -- consensus ssAver.append(si[0]) else: # Transitions between secondary structure types i = list(i) si = [(1.0*i.count(j)/len(i), j) for j in si] si.sort() if si[-1][0] > options["-ssc"].value: ssAver.append(si[-1][1]) else: ssAver.append(" ") ssAver = "".join(ssAver) logging.info('(Average) Secondary structure has been determined (see head of .itp-file).') # Divide the secondary structure according to the division in chains # This will set the secondary structure types to be used for the # topology. for chain in chains: chain.set_ss(ssAver[:len(chain)]) ssAver = ssAver[len(chain):] # Now the chains are complete, each consisting of a residuelist, # and a secondary structure designation if the chain is of type 'Protein'. # There may be mixed chains, there may be HETATM things. # Water has been discarded. Maybe this has to be changed at some point. # The order in the coarse grained files matches the order in the set of chains. # # If there are no merges to be done, i.e. no global Elnedyn network, no # disulphide bridges, no links, no distance restraints and no explicit merges, # then we can write out the topology, which will match the coarse grained file. # # If there are merges to be done, the order of things may be changed, in which # case the coarse grained structure will not match with the topology... # CYSTINE BRIDGES # # Extract the cysteine coordinates (for all frames) and the cysteine identifiers if options['CystineCheckBonds']: logging.info("Checking for cystine bridges, based on sulphur (SG) atoms lying closer than %.4f nm" % math.sqrt(options['CystineMaxDist2']/100)) cyscoord = zip(*[[j[4:7] for j in i] for i in cysteines]) cysteines = [i[:4] for i in cysteines[0]] bl, kb = options['ForceField'].special[(("SC1", "CYS"), ("SC1", "CYS"))] # Check the distances and add the cysteines to the link list if the # SG atoms have a distance smaller than the cutoff. rlc = range(len(cysteines)) for i in rlc[:-1]: for j in rlc[i+1:]: # Checking the minimum distance over all frames # But we could also take the maximum, or the mean d2 = min([FUNC.distance2(a, b) for a, b in zip(cyscoord[i], cyscoord[j])]) if d2 <= options['CystineMaxDist2']: a, b = cysteines[i], cysteines[j] options['linkListCG'].append((("SC1", "CYS", a[2], a[3]), ("SC1", "CYS", b[2], b[3]), bl, kb)) a, b = (a[0], a[1], a[2]-(32 << 20), a[3]), (b[0], b[1], b[2]-(32 << 20), b[3]) logging.info("Detected SS bridge between %s and %s (%f nm)" % (a, b, math.sqrt(d2)/10)) # REAL ITP STUFF # # Check whether we have identical chains, in which case we # only write the ITP for one... # This means making a distinction between chains and # moleculetypes. molecules = [tuple([chains[i] for i in j]) for j in merge] # At this point we should have a list or dictionary of chains # Each chain should be given a unique name, based on the value # of options["-o"] combined with the chain identifier and possibly # a number if there are chains with identical identifiers. # For each chain we then write an ITP file using the name for # moleculetype and name + ".itp" for the topology include file. # In addition we write a master topology file, using the value of # options["-o"], with an added extension ".top" if not given. # XXX *NOTE*: This should probably be gathered in a 'Universe' class itp = 0 moleculeTypes = {} for mi in range(len(molecules)): mol = molecules[mi] # Check if the moleculetype is already listed # If not, generate the topology from the chain definition if mol not in moleculeTypes or options['SeparateTop']: # Name of the moleculetype # XXX: The naming should be changed; now it becomes Protein_X+Protein_Y+... name = "+".join([chain.getname(options['-name'].value) for chain in mol]) moleculeTypes[mol] = name # Write the molecule type topology top = TOP.Topology(mol[0], options=options, name=name) for m in mol[1:]: top += TOP.Topology(m, options=options) # Have to add the connections, like the connecting network # Gather coordinates mcg, coords = zip(*[(j[:4], j[4:7]) for m in mol for j in m.cg(force=True)]) mcg = list(mcg) # Run through the link list and add connections (links = cys bridges or hand specified links) for atomA, atomB, bondlength, forceconst in options['linkListCG']: if bondlength == -1 and forceconst == -1: bondlength, forceconst = options['ForceField'].special[(atomA[:2], atomB[:2])] # Check whether this link applies to this group atomA = atomA in mcg and mcg.index(atomA)+1 atomB = atomB in mcg and mcg.index(atomB)+1 if atomA and atomB: cat = (forceconst is None) and "Constraint" or "Link" top.bonds.append(TOP.Bond( (atomA, atomB), options = options, type = 1, parameters = (bondlength, forceconst), category = cat, comments = "Cys-bonds/special link")) # Elastic Network # The elastic network is added after the topology is constructed, since that # is where the correct atom list with numbering and the full set of # coordinates for the merged chains are available. if options['ElasticNetwork']: rubberType = options['ForceField'].EBondType rubberList = ELN.rubberBands( [(i[0], j) for i, j in zip(top.atoms, coords) if i[4] in options['ElasticBeads']], options['ElasticLowerBound'], options['ElasticUpperBound'], options['ElasticDecayFactor'], options['ElasticDecayPower'], options['ElasticMaximumForce'], options['ElasticMinimumForce']) top.bonds.extend([TOP.Bond(i, options=options, type=rubberType, category="Rubber band") for i in rubberList]) # Write out the MoleculeType topology destination = options["-o"] and open(moleculeTypes[mol]+".itp", 'w') or sys.stdout destination.write(str(top)) itp += 1 # Check whether other chains are equal to this one # Skip this step if we are to write all chains to separate moleculetypes if not options['SeparateTop']: for j in range(mi+1, len(molecules)): if not molecules[j] in moleculeTypes and mol == molecules[j]: # Molecule j is equal to a molecule mi # Set the name of the moleculetype to the one of that molecule moleculeTypes[molecules[j]] = moleculeTypes[mol] logging.info('Written %d ITP file%s' % (itp, itp > 1 and "s" or "")) # WRITING THE MASTER TOPOLOGY # Output stream top = options["-o"] and open(options['-o'].value, 'w') or sys.stdout # ITP file listing itps = '\n'.join(['#include "%s.itp"' % molecule for molecule in set(moleculeTypes.values())]) # Molecule listing logging.info("Output contains %d molecules:" % len(molecules)) n = 1 for molecule in molecules: chainInfo = (n, moleculeTypes[molecule], len(molecule) > 1 and "s" or " ", " ".join([i.id for i in molecule])) logging.info(" %2d-> %s (chain%s %s)" % chainInfo) n += 1 molecules = '\n'.join(['%s \t 1' % moleculeTypes[molecule] for molecule in molecules]) # Set a define if we are to use rubber bands useRubber = options['ElasticNetwork'] and "#define RUBBER_BANDS" or "" # XXX Specify a better, version specific base-itp name. # Do not set a define for position restrains here, as people are more used to do it in mdp file? top.write( '''#include "martini.itp" %s %s [ system ] ; name Martini system from %s [ molecules ] ; name number %s''' % (useRubber, itps, options["-f"] and options["-f"].value or "stdin", molecules)) logging.info('Written topology files') # Maybe there are forcefield specific log messages? options['ForceField'].messages() # The following lines are always printed (if no errors occur). print "\n\tThere you are. One MARTINI. Shaken, not stirred.\n" Q = DOC.martiniq.pop(random.randint(0, len(DOC.martiniq)-1)) print "\n", Q[1], "\n%80s" % ("--"+Q[0]), "\n"
def __init__(self): import SS, FUNC, IO # parameters are defined here for the following (protein) forcefields: self.name = 'elnedyn22p' # Charged types: self.charges = { "Qd": 1, "Qa": -1, "SQd": 1, "SQa": -1, "RQd": 1, "AQa": -1 } #@# #----+---------------------+ ## A | BACKBONE PARAMETERS | #----+---------------------+ # # bbss lists the one letter secondary structure code # bbdef lists the corresponding default backbone beads # bbtyp lists the corresponding residue specific backbone beads # # bbd lists the structure specific backbone bond lengths # bbkb lists the corresponding bond force constants # # bba lists the structure specific angles # bbka lists the corresponding angle force constants # # bbd lists the structure specific dihedral angles # bbkd lists the corresponding force constants # # -=NOTE=- # if the secondary structure types differ between bonded atoms # the bond is assigned the lowest corresponding force constant # # -=NOTE=- # if proline is anywhere in the helix, the BBB angle changes for # all residues # ############################################################################################### ## BEADS ## # # F E H 1 2 3 T S C # SS one letter self.bbdef = FUNC.spl( " N0 Nda N0 Nd Na Nda Nda P5 P5" ) # Default beads #@# self.bbtyp = { # #@# "ALA": FUNC.spl(" C5 N0 C5 N0 N0 N0 N0 P4 P4" ), # ALA specific #@# "PRO": FUNC.spl(" C5 N0 C5 N0 Na N0 N0 P4 P4" ), # PRO specific #@# "HYP": FUNC.spl(" C5 N0 C5 N0 N0 N0 N0 P4 P4" ) # HYP specific #@# } # #@# ## BONDS ## # self.bbldef = (.365, .350, .350, .350, .350, .350, .350, .350, .350 ) # BB bond lengths #@# self.bbkb = (1250, 1250, 1250, 1250, 1250, 1250, 500, 400, 400 ) # BB bond kB #@# self.bbltyp = {} # #@# self.bbkbtyp = {} # #@# ## ANGLES ## # self.bbadef = (119.2, 134, 96, 96, 96, 96, 100, 130, 127 ) # BBB angles #@# self.bbka = (150, 25, 700, 700, 700, 700, 25, 25, 25 ) # BBB angle kB #@# self.bbatyp = { # #@# "PRO": (119.2, 134, 98, 98, 98, 98, 100, 130, 127), # PRO specific #@# "HYP": (119.2, 134, 98, 98, 98, 98, 100, 130, 127) # PRO specific #@# } # #@# self.bbkatyp = { # #@# "PRO": (150, 25, 100, 100, 100, 100, 25, 25, 25), # PRO specific #@# "HYP": (150, 25, 100, 100, 100, 100, 25, 25, 25) # PRO specific #@# } # #@# ## DIHEDRALS ## # self.bbddef = (90.7, 0, -120, -120, -120, -120) # BBBB dihedrals #@# self.bbkd = (100, 10, 400, 400, 400, 400) # BBBB kB #@# self.bbdmul = (1, 1, 1, 1, 1, 1) # BBBB mltplcty #@# self.bbdtyp = {} # #@# self.bbkdtyp = {} # #@# # ############################################################################################### # Some Forcefields use the Ca position to position the BB-bead (me like!) self.ca2bb = True # BBS angle, equal for all ss types # Connects BB(i-1),BB(i),SC(i), except for first residue: BB(i+1),BB(i),SC(i) # ANGLE Ka self.bbsangle = [100, 25] #@# # Bonds for extended structures (more stable than using dihedrals) # LENGTH FORCE self.ebonds = { #@# 'short': [.640, 2500], #@# 'long': [.970, 2500] #@# } #@# #----+-----------------------+ ## B | SIDE CHAIN PARAMETERS | #----+-----------------------+ # Sidechain parameters for Elnedyn. (read from cg-2.1.dat). # For HIS the order of bonds is changed and a bond with fc=0 is added. # In the elnedyn2, TRP has an extra, cross-ring constraint self.sidechains = { #RES# BEADS BONDS ANGLES DIHEDRALS V-SITES 'TRP': [ FUNC.spl("SC4 SNd SC5 SC5"), [(0.255, 73000), (0.220, None), (0.250, None), (0.280, None), (0.255, None), (0.35454, None)], [(142, 30), (143, 20), (104, 50)], [(180, 200)] ], 'TYR': [ FUNC.spl("SC4 SC4 SP1"), [(0.335, 6000), (0.335, 6000), (0.240, None), (0.310, None), (0.310, None)], [(70, 100), (130, 50)] ], 'PHE': [ FUNC.spl("SC5 SC5 SC5"), [(0.340, 7500), (0.340, 7500), (0.240, None), (0.240, None), (0.240, None)], [(70, 100), (125, 100)] ], 'HIS': [ FUNC.spl("SC4 SP1 SP1"), [(0.195, 94000), (0.193, None), (0.295, None), (0.216, None)], [(135, 100), (115, 50)] ], 'HIH': [ FUNC.spl("SC4 SP1 SQd"), [(0.195, 94000), (0.193, None), (0.295, None), (0.216, None), (0.11, None)], [(135, 100), (115, 50)] ], 'GLN': [ FUNC.spl("Nda D D"), [(0.300, 2400), (0.280, None)], [], [], [(0.5, )] ], 'ASN': [ FUNC.spl("Nda D D"), [(0.250, 61000), (0.280, None)], [], [], [(0.5, )] ], 'SER': [ FUNC.spl("N0 D D"), [(0.195, 94000), (0.280, None)], [], [], [(0.5, )] ], 'THR': [ FUNC.spl("N0 D D"), [(0.195, 94000), (0.280, None)], [], [], [(0.5, )] ], 'ARG': [ FUNC.spl("N0 Qd D"), [(0.250, 12500), (0.350, 6200), (0.110, None)], [(150, 15)] ], 'LYS': [ FUNC.spl("C3 Qd D"), [(0.250, 12500), (0.300, 9700), (0.110, None)], [(150, 20)] ], 'ASP': [FUNC.spl("Qa D"), [(0.255, None), (0.110, None)]], 'GLU': [FUNC.spl("Qa D"), [(0.310, 2500), (0.110, None)]], 'CYS': [FUNC.spl("C5"), [(0.240, None)]], 'ILE': [FUNC.spl("C1"), [(0.225, 13250)]], 'LEU': [FUNC.spl("C1"), [(0.265, None)]], 'MET': [FUNC.spl("C5"), [(0.310, 2800)]], 'PRO': [FUNC.spl("C3"), [(0.190, None)]], 'HYP': [FUNC.spl("P1"), [(0.190, None)]], 'VAL': [FUNC.spl("C2"), [(0.200, None)]], 'GLY': [], 'ALA': [], } # Not all (eg Elnedyn) forcefields use backbone-backbone-sidechain angles and BBBB-dihedrals. self.UseBBSAngles = False self.UseBBBBDihedrals = False # Martini 2.2p has polar and charged residues with seperate charges. self.polar = ["GLN", "ASN", "SER", "THR"] self.charged = ["ARG", "LYS", "ASP", "GLU", "HIH"] # If masses or charged diverge from standard (45/72 and -/+1) they are defined here. self.mass_charge = { #RES MASS CHARGE "GLN": [[0, 36, 36], [0, 0.42, -0.42]], "ASN": [[0, 36, 36], [0, 0.46, -0.46]], "SER": [[0, 36, 36], [0, 0.40, -0.40]], "THR": [[0, 36, 36], [0, 0.36, -0.36]], "ARG": [[72, 36, 36], [0, 0, 1]], "LYS": [[72, 36, 36], [0, 0, 1]], "HIH": [[72, 72, 36, 36], [0, 0, 0, 1]], "ASP": [[36, 36], [0, -1]], "GLU": [[36, 36], [0, -1]], } # Defines the connectivity between between beads # The polar sidechains have charged dummy beads, connected with a constraint # The charged sidechains have a charged dummy bead. self.connectivity = { #RES BONDS ANGLES DIHEDRALS V-SITE "TRP": [[(0, 1), (1, 2), (2, 4), (4, 3), (3, 1), (1, 4)], [(0, 1, 2), (0, 1, 4), (0, 1, 3)], [(1, 2, 3, 4)]], "TYR": [[(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)], [(0, 1, 2), (0, 1, 3)]], "PHE": [[(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)], [(0, 1, 2), (0, 1, 3)]], "HIS": [[(0, 1), (1, 2), (1, 3), (2, 3)], [(0, 1, 2), (0, 1, 3)]], "HIH": [[(0, 1), (1, 2), (1, 3), (2, 3), (3, 4)], [(0, 1, 2), (0, 1, 3)], [(0, 2, 3, 1)]], "GLN": [[(0, 1), (2, 3)], [], [], [(1, 2, 3)]], "ASN": [[(0, 1), (2, 3)], [], [], [(1, 2, 3)]], "SER": [[(0, 1), (2, 3)], [], [], [(1, 2, 3)]], "THR": [[(0, 1), (2, 3)], [], [], [(1, 2, 3)]], "ARG": [[(0, 1), (1, 2), (2, 3)], [(0, 1, 2)]], "LYS": [[(0, 1), (1, 2), (2, 3)], [(0, 1, 2)]], "ASP": [[(0, 1), (1, 2)]], "GLU": [[(0, 1), (1, 2)]], "CYS": [[(0, 1)]], "ILE": [[(0, 1)]], "LEU": [[(0, 1)]], "MET": [[(0, 1)]], "PRO": [[(0, 1)]], "HYP": [[(0, 1)]], "VAL": [[(0, 1)]], "ALA": [], "GLY": [], } #----+----------------+ ## C | SPECIAL BONDS | #----+----------------+ self.special = { # Used for sulfur bridges # ATOM 1 ATOM 2 BOND LENGTH FORCE CONSTANT (("SC1", "CYS"), ("SC1", "CYS")): (0.24, None), } # By default use an elastic network self.ElasticNetwork = True # Elastic networks bond shouldn't lead to exclusions (type 6) # But Elnedyn has been parametrized with type 1. self.EBondType = 1 #----+----------------+ ## D | INTERNAL STUFF | #----+----------------+ ## BACKBONE BEAD TYPE ## # Dictionary of default bead types (*D) self.bbBeadDictD = FUNC.hash(SS.bbss, self.bbdef) # Dictionary of dictionaries of types for specific residues (*S) self.bbBeadDictS = dict([(i, FUNC.hash(SS.bbss, self.bbtyp[i])) for i in self.bbtyp.keys()]) ## BB BOND TYPE ## # Dictionary of default abond types (*D) self.bbBondDictD = FUNC.hash(SS.bbss, zip(self.bbldef, self.bbkb)) # Dictionary of dictionaries for specific types (*S) self.bbBondDictS = dict([ (i, FUNC.hash(SS.bbss, zip(self.bbltyp[i], self.bbkbtyp[i]))) for i in self.bbltyp.keys() ]) # This is tricky to read, but it gives the right bondlength/force constant ## BBB ANGLE TYPE ## # Dictionary of default angle types (*D) self.bbAngleDictD = FUNC.hash(SS.bbss, zip(self.bbadef, self.bbka)) # Dictionary of dictionaries for specific types (*S) self.bbAngleDictS = dict([ (i, FUNC.hash(SS.bbss, zip(self.bbatyp[i], self.bbkatyp[i]))) for i in self.bbatyp.keys() ]) ## BBBB DIHEDRAL TYPE ## # Dictionary of default dihedral types (*D) self.bbDihedDictD = FUNC.hash(SS.bbss, zip(self.bbddef, self.bbkd, self.bbdmul)) # Dictionary of dictionaries for specific types (*S) self.bbDihedDictS = dict([ (i, FUNC.hash(SS.bbss, zip(self.bbdtyp[i], self.bbkdtyp[i]))) for i in self.bbdtyp.keys() ])
def bbGetBond(self, r, ca, ss): import FUNC import math # The 150000 forceconstant gave an error message, turning to constraints would be better. return (math.sqrt(FUNC.distance2(ca[0], ca[1])) / 10., None)
def main(options): # Check whether to read from a gro/pdb file or from stdin # We use an iterator to wrap around the stream to allow # inferring the file type, without consuming lines already inStream = IO.streamTag(options["-f"] and options["-f"].value or sys.stdin) # The streamTag iterator first yields the file type, which # is used to specify the function for reading frames fileType = inStream.next() if fileType == "GRO": frameIterator = IO.groFrameIterator else: frameIterator = IO.pdbFrameIterator # ITERATE OVER FRAMES IN STRUCTURE FILE # # Now iterate over the frames in the stream # This should become a StructureFile class with a nice .next method model = 1 cgOutPDB = None ssTotal = [] cysteines = [] for title, atoms, box in frameIterator(inStream): if fileType == "PDB": # The PDB file can have chains, in which case we list and process them specifically # TER statements are also interpreted as chain separators # A chain may have breaks in which case the breaking residues are flagged chains = [ IO.Chain(options, [i for i in IO.residues(chain)]) for chain in IO.pdbChains(atoms) ] else: # The GRO file does not define chains. Here breaks in the backbone are # interpreted as chain separators. residuelist = [residue for residue in IO.residues(atoms)] # The breaks are indices to residues broken = IO.breaks(residuelist) # Reorder, such that each chain is specified with (i,j,k) # where i and j are the start and end of the chain, and # k is a chain identifier chains = zip([0] + broken, broken + [len(residuelist)], range(len(broken) + 1)) chains = [ IO.Chain(options, residuelist[i:j], name=chr(65 + k)) for i, j, k in chains ] for chain in chains: chain.multiscale = "all" in options[ 'multi'] or chain.id in options['multi'] # Check the chain identifiers if model == 1 and len(chains) != len(set([i.id for i in chains])): # Ending down here means that non-consecutive blocks of atoms in the # PDB file have the same chain ID. The warning pertains to PDB files only, # since chains from GRO files get a unique chain identifier assigned. logging.warning( "Several chains have identical chain identifiers in the PDB file." ) # Check if chains are of mixed type. If so, split them. # Note that in some cases HETATM residues are part of a # chain. This will get problematic. But we cannot cover # all, probably. if not options['MixedChains']: demixedChains = [] for chain in chains: demixedChains.extend(chain.split()) chains = demixedChains n = 1 logging.info("Found %d chains:" % len(chains)) for chain in chains: logging.info(" %2d: %s (%s), %d atoms in %d residues." % (n, chain.id, chain._type, chain.natoms, len(chain))) n += 1 # Check all chains keep = [] for chain in chains: if chain.type() == "Water": logging.info("Removing %d water molecules (chain %s)." % (len(chain), chain.id)) elif chain.type() in ("Protein", "Nucleic"): keep.append(chain) # This is currently not active: elif options['RetainHETATM']: keep.append(chain) else: logging.info( "Removing HETATM chain %s consisting of %d residues." % (chain.id, len(chain))) chains = keep # Here we interactively check the charge state of resides # Can be easily expanded to residues other than HIS for chain in chains: for i, resname in enumerate(chain.sequence): if resname == 'HIS' and options['chHIS']: choices = {0: 'HIH', 1: 'HIS'} choice = IO.getChargeType(resname, i, choices) chain.sequence[i] = choice # Check which chains need merging if model == 1: order, merge = IO.check_merge( chains, options['mergeList'], options['linkList'], options['CystineCheckBonds'] and options['CystineMaxDist2']) # Get the total length of the sequence seqlength = sum([len(chain) for chain in chains]) logging.info('Total size of the system: %s residues.' % seqlength) ## SECONDARY STRUCTURE ss = '' if options['Collagen']: for chain in chains: chain.set_ss("F") ss += chain.ss elif options["-ss"]: # XXX We need error-catching here, # in case the file doesn't excist, or the string contains bogus. # If the string given for the sequence consists strictly of upper case letters # and does not appear to be a file, assume it is the secondary structure ss = options["-ss"].value.replace('~', 'L').replace(' ', 'L') if ss.isalnum() and ss.isupper() and not os.path.exists( options["-ss"].value): ss = options["-ss"].value logging.info('Secondary structure read from command-line:\n' + ss) else: # There ought to be a file with the name specified ssfile = [i.strip() for i in open(options["-ss"].value)] # Try to read the file as a Gromacs Secondary Structure Dump # Those have an integer as first line if ssfile[0].isdigit(): logging.info( 'Will read secondary structure from file (assuming Gromacs ssdump).' ) ss = "".join([i for i in ssfile[1:]]) else: # Get the secondary structure type from DSSP output logging.info( 'Will read secondary structure from file (assuming DSSP output).' ) pss = re.compile(r"^([ 0-9]{4}[0-9]){2}") ss = "".join([ i[16] for i in open(options["-ss"].value) if re.match(pss, i) ]) # Now set the secondary structure for each of the chains sstmp = ss for chain in chains: ln = min(len(sstmp), len(chain)) chain.set_ss(sstmp[:ln]) sstmp = ss[:ln] else: if options["-dssp"]: method, executable = "dssp", options["-dssp"].value #elif options["-pymol"]: # method, executable = "pymol", options["-pymol"].value else: logging.warning( "No secondary structure or determination method speficied. Protein chains will be set to 'COIL'." ) method, executable = None, None for chain in chains: ss += chain.dss(method, executable) # Used to be: if method in ("dssp","pymol"): but pymol is not supported if method in ["dssp"]: logging.debug('%s determined secondary structure:\n' % method.upper() + ss) # Collect the secondary structure classifications for different frames ssTotal.append(ss) # Write the coarse grained structure if requested if options["-x"].value: logging.info("Writing coarse grained structure.") if cgOutPDB is None: cgOutPDB = open(options["-x"].value, "w") cgOutPDB.write("MODEL %8d\n" % model) cgOutPDB.write(title) cgOutPDB.write(IO.pdbBoxString(box)) atid = 1 for i in order: ci = chains[i] if ci.multiscale: for r in ci.residues: for name, resn, resi, chain, x, y, z in r: cgOutPDB.write( IO.pdbOut( (name, resn[:3], resi, chain, x, y, z), i=atid)) atid += 1 coarseGrained = ci.cg(com=True) if coarseGrained: for name, resn, resi, chain, x, y, z, ssid in coarseGrained: if ci.multiscale: name = "v" + name cgOutPDB.write( IO.pdbOut((name, resn[:3], resi, chain, x, y, z), i=atid, ssid=ssid)) atid += 1 cgOutPDB.write("TER\n") else: logging.warning( "No mapping for coarse graining chain %s (%s); chain is skipped." % (ci.id, ci.type())) cgOutPDB.write("ENDMDL\n") # Gather cysteine sulphur coordinates cyslist = [cys["SG"] for chain in chains for cys in chain["CYS"]] cysteines.append([cys for cys in cyslist if cys]) model += 1 # Write the index file if requested. # Mainly of interest for multiscaling. # Could be improved by adding separte groups for BB, SC, etc. if options["-n"].value: logging.info("Writing index file.") # Lists for All-atom, Virtual sites and Coarse Grain. NAA, NVZ, NCG = [], [], [] atid = 1 for i in order: ci = chains[i] coarseGrained = ci.cg(force=True) if ci.multiscale: NAA.extend([" %5d" % (a + atid) for a in range(ci.natoms)]) atid += ci.natoms if coarseGrained: if ci.multiscale: NVZ.extend([ " %5d" % (a + atid) for a in range(len(coarseGrained)) ]) else: NCG.extend([ " %5d" % (a + atid) for a in range(len(coarseGrained)) ]) atid += len(coarseGrained) outNDX = open(options["-n"].value, "w") outNDX.write("\n[ AA ]\n" + "\n".join( [" ".join(NAA[i:i + 15]) for i in range(0, len(NAA), 15)])) outNDX.write("\n[ VZ ]\n" + "\n".join( [" ".join(NVZ[i:i + 15]) for i in range(0, len(NVZ), 15)])) outNDX.write("\n[ CG ]\n" + "\n".join( [" ".join(NCG[i:i + 15]) for i in range(0, len(NCG), 15)])) outNDX.close() # Write the index file for mapping AA trajectory if requested if options["-nmap"].value: logging.info("Writing trajectory index file.") atid = 1 outNDX = open(options["-nmap"].value, "w") # Get all AA atoms as lists of atoms in residues # First we skip hetatoms and unknowns then iterate over beads # In DNA the O3' atom is mapped together with atoms from the next residue # This stores it until we get to the next residue o3_shift = '' for i_count, i in enumerate(IO.residues(atoms)): if i[0][1] in ("SOL", "HOH", "TIP"): continue if not i[0][1] in MAP.CoarseGrained.mapping.keys(): continue nra = 0 names = [j[0] for j in i] # This gives out a list of atoms in residue, each tuple has other # stuff in it that's needed elsewhere so we just take the last # element which is the atom index (in that residue) for j_count, j in enumerate(MAP.mapIndex(i)): outNDX.write('[ Bead %i of residue %i ]\n' % (j_count + 1, i_count + 1)) line = '' for k in j: if names[k[2]] == "O3'": line += '%s ' % (str(o3_shift)) o3_shift = k[2] + atid else: line += '%i ' % (k[2] + atid) line += '\n' nra += len(j) outNDX.write(line) atid += nra # Evertything below here we only need, if we need to write a Topology if options['-o']: # Collect the secondary structure stuff and decide what to do with it # First rearrange by the residue ssTotal = zip(*ssTotal) ssAver = [] for i in ssTotal: si = list(set(i)) if len(si) == 1: # Only one type -- consensus ssAver.append(si[0]) else: # Transitions between secondary structure types i = list(i) si = [(1.0 * i.count(j) / len(i), j) for j in si] si.sort() if si[-1][0] > options["-ssc"].value: ssAver.append(si[-1][1]) else: ssAver.append(" ") ssAver = "".join(ssAver) logging.info( '(Average) Secondary structure has been determined (see head of .itp-file).' ) # Divide the secondary structure according to the division in chains # This will set the secondary structure types to be used for the # topology. for chain in chains: chain.set_ss(ssAver[:len(chain)]) ssAver = ssAver[len(chain):] # Now the chains are complete, each consisting of a residuelist, # and a secondary structure designation if the chain is of type 'Protein'. # There may be mixed chains, there may be HETATM things. # Water has been discarded. Maybe this has to be changed at some point. # The order in the coarse grained files matches the order in the set of chains. # # If there are no merges to be done, i.e. no global Elnedyn network, no # disulphide bridges, no links, no distance restraints and no explicit merges, # then we can write out the topology, which will match the coarse grained file. # # If there are merges to be done, the order of things may be changed, in which # case the coarse grained structure will not match with the topology... # CYSTINE BRIDGES # # Extract the cysteine coordinates (for all frames) and the cysteine identifiers if options['CystineCheckBonds']: logging.info( "Checking for cystine bridges, based on sulphur (SG) atoms lying closer than %.4f nm" % math.sqrt(options['CystineMaxDist2'] / 100)) cyscoord = zip(*[[j[4:7] for j in i] for i in cysteines]) cysteines = [i[:4] for i in cysteines[0]] bl, kb = options['ForceField'].special[(("SC1", "CYS"), ("SC1", "CYS"))] # Check the distances and add the cysteines to the link list if the # SG atoms have a distance smaller than the cutoff. rlc = range(len(cysteines)) for i in rlc[:-1]: for j in rlc[i + 1:]: # Checking the minimum distance over all frames # But we could also take the maximum, or the mean d2 = min([ FUNC.distance2(a, b) for a, b in zip(cyscoord[i], cyscoord[j]) ]) if d2 <= options['CystineMaxDist2']: a, b = cysteines[i], cysteines[j] options['linkListCG'].append( (("SC1", "CYS", a[2], a[3]), ("SC1", "CYS", b[2], b[3]), bl, kb)) a, b = (a[0], a[1], a[2] - (32 << 20), a[3]), (b[0], b[1], b[2] - (32 << 20), b[3]) logging.info( "Detected SS bridge between %s and %s (%f nm)" % (a, b, math.sqrt(d2) / 10)) # REAL ITP STUFF # # Check whether we have identical chains, in which case we # only write the ITP for one... # This means making a distinction between chains and # moleculetypes. molecules = [tuple([chains[i] for i in j]) for j in merge] # At this point we should have a list or dictionary of chains # Each chain should be given a unique name, based on the value # of options["-o"] combined with the chain identifier and possibly # a number if there are chains with identical identifiers. # For each chain we then write an ITP file using the name for # moleculetype and name + ".itp" for the topology include file. # In addition we write a master topology file, using the value of # options["-o"], with an added extension ".top" if not given. # XXX *NOTE*: This should probably be gathered in a 'Universe' class itp = 0 moleculeTypes = {} for mi in range(len(molecules)): mol = molecules[mi] # Check if the moleculetype is already listed # If not, generate the topology from the chain definition if mol not in moleculeTypes or options['SeparateTop']: # Name of the moleculetype # XXX: The naming should be changed; now it becomes Protein_X+Protein_Y+... name = "+".join( [chain.getname(options['-name'].value) for chain in mol]) moleculeTypes[mol] = name # Write the molecule type topology top = TOP.Topology(mol[0], options=options, name=name) for m in mol[1:]: top += TOP.Topology(m, options=options) # Have to add the connections, like the connecting network # Gather coordinates mcg, coords = zip(*[(j[:4], j[4:7]) for m in mol for j in m.cg(force=True)]) mcg = list(mcg) # Run through the link list and add connections (links = cys bridges or hand specified links) for atomA, atomB, bondlength, forceconst in options[ 'linkListCG']: if bondlength == -1 and forceconst == -1: bondlength, forceconst = options['ForceField'].special[ (atomA[:2], atomB[:2])] # Check whether this link applies to this group atomA = atomA in mcg and mcg.index(atomA) + 1 atomB = atomB in mcg and mcg.index(atomB) + 1 if atomA and atomB: cat = (forceconst is None) and "Constraint" or "Link" top.bonds.append( TOP.Bond((atomA, atomB), options=options, type=1, parameters=(bondlength, forceconst), category=cat, comments="Cys-bonds/special link")) # Elastic Network # The elastic network is added after the topology is constructed, since that # is where the correct atom list with numbering and the full set of # coordinates for the merged chains are available. if options['ElasticNetwork']: rubberType = options['ForceField'].EBondType rubberList = ELN.rubberBands( [(i[0], j) for i, j in zip(top.atoms, coords) if i[4] in options['ElasticBeads']], options['ElasticLowerBound'], options['ElasticUpperBound'], options['ElasticDecayFactor'], options['ElasticDecayPower'], options['ElasticMaximumForce'], options['ElasticMinimumForce']) top.bonds.extend([ TOP.Bond(i, options=options, type=rubberType, category="Rubber band") for i in rubberList ]) # Write out the MoleculeType topology destination = options["-o"] and open( moleculeTypes[mol] + ".itp", 'w') or sys.stdout destination.write(str(top)) itp += 1 # Check whether other chains are equal to this one # Skip this step if we are to write all chains to separate moleculetypes if not options['SeparateTop']: for j in range(mi + 1, len(molecules)): if not molecules[j] in moleculeTypes and mol == molecules[ j]: # Molecule j is equal to a molecule mi # Set the name of the moleculetype to the one of that molecule moleculeTypes[molecules[j]] = moleculeTypes[mol] logging.info('Written %d ITP file%s' % (itp, itp > 1 and "s" or "")) # WRITING THE MASTER TOPOLOGY # Output stream top = options["-o"] and open(options['-o'].value, 'w') or sys.stdout # ITP file listing itps = '\n'.join([ '#include "%s.itp"' % molecule for molecule in set(moleculeTypes.values()) ]) # Molecule listing logging.info("Output contains %d molecules:" % len(molecules)) n = 1 for molecule in molecules: chainInfo = (n, moleculeTypes[molecule], len(molecule) > 1 and "s" or " ", " ".join([i.id for i in molecule])) logging.info(" %2d-> %s (chain%s %s)" % chainInfo) n += 1 molecules = '\n'.join( ['%s \t 1' % moleculeTypes[molecule] for molecule in molecules]) # Set a define if we are to use rubber bands useRubber = options['ElasticNetwork'] and "#define RUBBER_BANDS" or "" # XXX Specify a better, version specific base-itp name. # Do not set a define for position restrains here, as people are more used to do it in mdp file? top.write('''#include "martini.itp" %s %s [ system ] ; name Martini system from %s [ molecules ] ; name number %s''' % (useRubber, itps, options["-f"] and options["-f"].value or "stdin", molecules)) logging.info('Written topology files') # Maybe there are forcefield specific log messages? options['ForceField'].messages() # The following lines are always printed (if no errors occur). print "\n\tThere you are. One MARTINI. Shaken, not stirred.\n" Q = DOC.martiniq.pop(random.randint(0, len(DOC.martiniq) - 1)) print "\n", Q[1], "\n%80s" % ("--" + Q[0]), "\n"
def check_merge(chains, m_list=[], l_list=[], ss_cutoff=0): chainIndex = range(len(chains)) if 'all' in m_list: logging.info("All chains will be merged in a single moleculetype.") return chainIndex, [chainIndex] chainID = [chain.id for chain in chains] # Mark the combinations of chains that need to be merged merges = [] if m_list: # Build a dictionary of chain IDs versus index # To give higher priority to top chains the lists are reversed # before building the dictionary chainIndex.reverse() chainID.reverse() dct = dict(zip(chainID, chainIndex)) chainIndex.reverse() # Convert chains in the merge_list to numeric, if necessary # NOTE The internal numbering is zero-based, while the # command line chain indexing is one-based. We have to add # one to the number in the dictionary to bring it on par with # the numbering from the command line, but then from the # result we need to subtract one again to make indexing # zero-based merges = [[(i.isdigit() and int(i) or dct[i]+1)-1 for i in j] for j in m_list] for i in merges: i.sort() # Rearrange merge list to a list of pairs pairs = [(i[j], i[k]) for i in merges for j in range(len(i)-1) for k in range(j+1, len(i))] # Check each combination of chains for connections based on # ss-bridges, links and distance restraints for i in chainIndex[:-1]: for j in chainIndex[i+1:]: if (i, j) in pairs: continue # Check whether any link links these two groups for a, b in l_list: if ((a in chains[i] and b in chains[j]) or (a in chains[j] and b in chains[i])): logging.info("Merging chains %d and %d to allow link %s" % (i+1, j+1, str((a, b)))) pairs.append(i < j and (i, j) or (j, i)) break if (i, j) in pairs: continue # Check whether any cystine bond given links these two groups #for a,b in s_list: # if ((a in chains[i] and b in chains[j]) or # (a in chains[j] and b in chains[i])): # logging.info("Merging chains %d and %d to allow cystine bridge"%(i+1,j+1)) # pairs.append( i<j and (i,j) or (j,i) ) # break #if (i,j) in pairs: # continue # Check for cystine bridges based on distance if not ss_cutoff: continue # Get SG atoms from cysteines from either chain # Check this pair of chains for cysA in chains[i]["CYS"]: for cysB in chains[j]["CYS"]: d2 = FUNC.distance2(cysA["SG"][4:7], cysB["SG"][4:7]) if d2 <= ss_cutoff: logging.info("Found SS contact linking chains %d and %d (%f nm)" % (i+1, j+1, math.sqrt(d2)/10)) pairs.append((i, j)) break if (i, j) in pairs: break # Sort the combinations pairs.sort(reverse=True) merges = [] while pairs: merges.append(set([pairs[-1][0]])) for i in range(len(pairs)-1, -1, -1): if pairs[i][0] in merges[-1]: merges[-1].add(pairs.pop(i)[1]) elif pairs[i][1] in merges[-1]: merges[-1].add(pairs.pop(i)[0]) merges = [list(i) for i in merges] for i in merges: i.sort() order = [j for i in merges for j in i] if merges: logging.warning("Merging chains.") logging.warning("This may change the order of atoms and will change the number of topology files.") logging.info("Merges: " + ", ".join([str([j+1 for j in i]) for i in merges])) if len(merges) == 1 and len(merges[0]) > 1 and set(merges[0]) == set(chainIndex): logging.info("All chains will be merged in a single moleculetype") # Determine the order for writing; merged chains go first merges.extend([[j] for j in chainIndex if j not in order]) order.extend([j for j in chainIndex if j not in order]) return order, merges
# dihedral definitions, which are not present for coil and termini # ss_names = { "F": "Collagenous Fiber", #@# "E": "Extended structure (beta sheet)", #@# "H": "Helix structure", #@# "1": "Helix start (H-bond donor)", #@# "2": "Helix end (H-bond acceptor)", #@# "3": "Ambivalent helix type (short helices)", #@# "T": "Turn", #@# "S": "Bend", #@# "C": "Coil", #@# } bbss = ss_names.keys() bbss = FUNC.spl( " F E H 1 2 3 T S C") # SS one letter # The following dictionary contains secondary structure types as assigned by # different programs. The corresponding Martini secondary structure types are # listed in cgss # # NOTE: # Each list of letters in the dictionary ss should exactly match the list # in cgss. # ssdefs = { "dssp": list(".HGIBETSC~"), # DSSP one letter secondary structure code #@# "pymol": list(".H...S...L"), # Pymol one letter secondary structure code #@# "gmx":
def contacts(atoms, cutoff=5): rla = range(len(atoms)) crd = [atom[4:] for atom in atoms] return [(i, j) for i in rla[:-1] for j in rla[i+1:] if FUNC.distance2(crd[i], crd[j]) < cutoff]
def residueDistance2(r1, r2): return min([FUNC.distance2(i, j) for i in r1 for j in r2])
def plot_pam(): pamSigphi = pd.read_csv(r'../ffm_Phi_1/output/pam_phi_sig.csv', header=0, index_col=0) pamTwopara = pd.read_csv(r'../sep_find_line_4/output/pam_info.csv', header=0, index_col=0) file = os.listdir(r'../input_data_0/pam_mon/') for i, name in enumerate(file): # 观测数据 df = pd.read_csv(r'../input_data_0/pam_mon/%s' % name, header=0, index_col=0) e = df.index.values flux = df.iloc[:, 0] # 不随能量变化的 phi 计算 出的通量 e_series = np.linspace(0.0085, 50, 1000) fluxSigpoint = FUNC.ffm_fun_all(e, pamSigphi.iloc[:, 0].values[i]) fluxSigseries = FUNC.ffm_fun_all(e_series, pamSigphi.iloc[:, 0].values[i]) # 模型计算出的 通量 Phi_point_c = FUNC.fit_obj_vary(e, pamTwopara.loc[:, 'phi_0'].values[i], pamTwopara.loc[:, 'b'].values[i]) fluxModlepoint = FUNC.ffm_fun_all(e, Phi_point_c) Phi_serier_c = FUNC.fit_obj_vary(e_series, pamTwopara.loc[:, 'phi_0'].values[i], pamTwopara.loc[:, 'b'].values[i]) fluxModleseries = FUNC.ffm_fun_all(e_series, Phi_serier_c) # SSN 计算出的结果 Phi_point_ssn = FUNC.fit_obj_vary(e, pamTwopara.loc[:, 'phi_c'].values[i], pamTwopara.loc[:, 'b_c'].values[i]) fluxSSNpoint = FUNC.ffm_fun_all(e, Phi_point_ssn) Phi_series_ssn = FUNC.fit_obj_vary( e_series, pamTwopara.loc[:, 'phi_c'].values[i], pamTwopara.loc[:, 'b_c'].values[i]) fluxSSNseries = FUNC.ffm_fun_all(e_series, Phi_series_ssn) # LIS flux_lis = FUNC.LIS_5(e_series) # 误差 sig_err_point = (fluxSigpoint - flux) / flux mod_err_point = (fluxModlepoint - flux) / flux ssn_err_point = (fluxSSNpoint - flux) / flux # 画图 plt.figure(figsize=(8, 6)) plt.style.use('fast') plt.style.use('seaborn-ticks') grid = plt.GridSpec(8, 6, hspace=0) ax_flux = plt.subplot(grid[0:5, 0:6]) plt.scatter(e, flux, marker='o', label='PAMELA', facecolors='none', edgecolor='k', alpha=0.8, s=40, zorder=100) plt.scatter(e, fluxSSNpoint, marker='D', s=15, facecolors='none', edgecolor='orange', alpha=1, label='FFM', zorder=101) plt.plot(e_series, flux_lis, 'r--', color='m', label='LIS', lw=2.5, zorder=10, alpha=0.5) plt.plot(e_series, fluxSigseries, 'r-', color='dodgerblue', label='FIT', alpha=0.8, lw=2.5, zorder=11) plt.plot(e_series, fluxModleseries, color='lime', label='MODEL', alpha=0.8, lw=2.5, zorder=1) ax_err = plt.subplot(grid[5:8, 0:6], sharex=ax_flux) plt.scatter(e, ssn_err_point * 100, marker='D', facecolor='none', edgecolors='orange', label='FFM', s=15, alpha=0.8) plt.scatter(e, sig_err_point * 100, marker='o', facecolor='none', edgecolors='dodgerblue', label='FIT', s=15, alpha=0.8) plt.scatter(e, mod_err_point * 100, marker='o', facecolor='none', edgecolors='lime', label='MODEL', s=15, alpha=0.8) ax_err.set_ylim(-30, 30) ax_err.grid(True, ls='-.', which='both', alpha=0.2) ax_err.tick_params(axis='both', direction='in', which='both') ax_err.set_ylabel(r'$(F_{pre}-F_{obs})/F_{obs}$ (%)', fontsize='10') ax_err.legend(loc='upper right') # ###################################################################### periods_list = list(pamTwopara.index) ax_flux.set_title('E-Flux Periods: %s' % periods_list[i], fontsize=10, weight='bold', style='italic') ax_err.set_xlabel('Kinetic Energy (GeV)', fontsize='10') ax_flux.set_ylabel('Flux $(m^{2}.s.sr.GeV)^{-1}$ ', fontsize='10') ax_flux.set_xscale('log') ax_flux.set_yscale('log') ax_err.set_xlim(0.0885, 115) ax_flux.set_ylim(0.2, 30000) ax_flux.tick_params(axis='both', direction='in', which='both') ax_flux.legend(loc='upper right') plt.savefig(r'./output/flux/pamela/periods_%s.png' % periods_list[i], dpi=250) plt.savefig(r'./output/flux/pamela/gif/periods_%d.png' % i, dpi=250) # 保存路径; plt.cla() plt.close("all") print('PAMELA %s' % periods_list[i], '完成 ==>') print('PAMELA 结束')
########################## ## 4 # FG -> CG MAPPING ## -> @MAP <- ########################## import FUNC dnares3 = " DA DC DG DT" dnares1 = " dA dC dG dT" rnares3 = " A C G U" rnares1 = " rA rC rG rU" # Amino acid nucleic acid codes: # The naming (AA and '3') is not strictly correct when adding DNA/RNA, but we keep it like this for consistincy. AA3 = FUNC.spl("TRP TYR PHE HIS HIH ARG LYS CYS ASP GLU ILE LEU MET ASN PRO HYP GLN SER THR VAL ALA GLY"+dnares3+rnares3) #@# AA1 = FUNC.spl(" W Y F H H R K C D E I L M N P O Q S T V A G"+dnares1+rnares1) #@# # Dictionaries for conversion from one letter code to three letter code v.v. AA123, AA321 = FUNC.hash(AA1, AA3), FUNC.hash(AA3, AA1) # Residue classes: protein = AA3[:-8] # remove eight to get rid of DNA/RNA here. water = FUNC.spl("HOH SOL TIP") lipids = FUNC.spl("DPP DHP DLP DMP DSP POP DOP DAP DUP DPP DHP DLP DMP DSP PPC DSM DSD DSS") nucleic = FUNC.spl("DAD DCY DGU DTH ADE CYT GUA THY URA DA DC DG DT") residueTypes = dict( [(i, "Protein") for i in protein ] + [(i, "Water") for i in water ] + [(i, "Lipid") for i in lipids ] + [(i, "Nucleic") for i in nucleic ] )
pam_phi = pam.iloc[:, 0].values df_ams_ssn = pd.read_csv(r'../ssn_flux_2/output/info_test.csv', header=0, index_col=0) ams_ssn = df_ams_ssn.loc['2011-06-01':'2017-03-01', 'ssn_delay'].values + fix_ssn ams_phi = ams.iloc[:, 0].values pam_log_ssn = pam_ssn**0.5 + fix_log_ssn ams_log_ssn = ams_ssn**0.5 + fix_log_ssn # print(pam_ssn) pam_end = df_alpha.loc[:'2014-01', alpha_type] pam_dealy = np.ones(len(pam_ssn), dtype='int') * -12 pam_alpha = FUNC.delay_ssn(pam_end, pam_dealy) + fix_alpha ams_end = df_alpha.loc[:'2017-03', alpha_type] ams_dealy = np.ones(len(ams_ssn), dtype='int') * -12 ams_alpha = FUNC.delay_ssn(ams_end, ams_dealy) + fix_alpha print(ams_alpha) # pam_alpha = np.log(pam_alpha) # ams_alpha = np.log(ams_alpha) df_pam = pd.DataFrame(np.vstack((pam_phi, pam_ssn, pam_log_ssn, pam_alpha)).T, columns=['phi_0', 'ssn', 'log_ssn_fix', alpha_type], index=df_pam_ssn.loc['2006-08-01':'2014-01-01', :].index) df_ams = pd.DataFrame(np.vstack((ams_phi, ams_ssn, ams_log_ssn, ams_alpha)).T, columns=['phi_0', 'ssn', 'log_ssn_fix', alpha_type], index=df_ams_ssn.loc['2011-06-01':'2017-03-01', :].index)
def __init__(self): import SS,FUNC,IO # parameters are defined here for the following (protein) forcefields: self.name = 'martini22' # Charged types: self.charges = {"Qd":1, "Qa":-1, "SQd":1, "SQa":-1, "RQd":1, "AQa":-1} #@# #----+---------------------+ ## A | BACKBONE PARAMETERS | #----+---------------------+ # # bbss lists the one letter secondary structure code # bbdef lists the corresponding default backbone beads # bbtyp lists the corresponding residue specific backbone beads # # bbd lists the structure specific backbone bond lengths # bbkb lists the corresponding bond force constants # # bba lists the structure specific angles # bbka lists the corresponding angle force constants # # bbd lists the structure specific dihedral angles # bbkd lists the corresponding force constants # # -=NOTE=- # if the secondary structure types differ between bonded atoms # the bond is assigned the lowest corresponding force constant # # -=NOTE=- # if proline is anywhere in the helix, the BBB angle changes for # all residues # ############################################################################################### ## BEADS ## # # F E H 1 2 3 T S C # SS one letter self.bbdef = FUNC.spl(" N0 Nda N0 Nd Na Nda Nda P5 P5") # Default beads #@# self.bbtyp = { # #@# "ALA": FUNC.spl(" C5 N0 C5 N0 N0 N0 N0 P4 P4"), # ALA specific #@# "PRO": FUNC.spl(" C5 N0 C5 N0 Na N0 N0 P4 P4"), # PRO specific #@# "HYP": FUNC.spl(" C5 N0 C5 N0 N0 N0 N0 P4 P4") # HYP specific #@# } # #@# ## BONDS ## # self.bbldef = (.365, .350, .310, .310, .310, .310, .350, .350, .350) # BB bond lengths #@# self.bbkb = (1250, 1250, None, None, None, None, 1250, 1250, 1250) # BB bond kB #@# self.bbltyp = {} # #@# self.bbkbtyp = {} # #@# ## ANGLES ## # self.bbadef = ( 119.2,134, 96, 96, 96, 96, 100, 130, 127) # BBB angles #@# self.bbka = ( 150, 25, 700, 700, 700, 700, 20, 20, 20) # BBB angle kB #@# self.bbatyp = { # #@# "PRO": ( 119.2,134, 98, 98, 98, 98, 100, 130, 127), # PRO specific #@# "HYP": ( 119.2,134, 98, 98, 98, 98, 100, 130, 127) # PRO specific #@# } # #@# self.bbkatyp = { # #@# "PRO": ( 150, 25, 100, 100, 100, 100, 25, 25, 25), # PRO specific #@# "HYP": ( 150, 25, 100, 100, 100, 100, 25, 25, 25) # PRO specific #@# } # #@# ## DIHEDRALS ## # self.bbddef = ( 90.7, 0, -120, -120, -120, -120) # BBBB dihedrals #@# self.bbkd = ( 100, 10, 400, 400, 400, 400) # BBBB kB #@# self.bbdmul = ( 1, 1, 1, 1, 1, 1) # BBBB mltplcty #@# self.bbdtyp = {} # #@# self.bbkdtyp = {} # #@# # ############################################################################################### # Some Forcefields use the Ca position to position the BB-bead (me like!) # martini 2.1 doesn't self.ca2bb = False # BBS angle, equal for all ss types # Connects BB(i-1),BB(i),SC(i), except for first residue: BB(i+1),BB(i),SC(i) # ANGLE Ka self.bbsangle = [ 100, 25] #@# # Bonds for extended structures (more stable than using dihedrals) # LENGTH FORCE self.ebonds = { #@# 'short': [ .640, 2500], #@# 'long' : [ .970, 2500] #@# } #@# #----+-----------------------+ ## B | SIDE CHAIN PARAMETERS | #----+-----------------------+ # To be compatible with Elnedyn, all parameters are explicitly defined, even if they are double. self.sidechains = { #RES# BEADS BONDS ANGLES DIHEDRALS # BB-SC SC-SC BB-SC-SC SC-SC-SC "TRP": [FUNC.spl("SC4 SNd SC5 SC5"),[(0.300,5000)]+[(0.270,None) for i in range(5)], [(210,50),(90,50),(90,50)], [(0,50),(0,200)]], "TYR": [FUNC.spl("SC4 SC4 SP1"), [(0.320,5000), (0.270,None), (0.270,None),(0.270,None)],[(150,50),(150,50)], [(0,50)]], "PHE": [FUNC.spl("SC5 SC5 SC5"), [(0.310,7500), (0.270,None), (0.270,None),(0.270,None)],[(150,50),(150,50)], [(0,50)]], "HIS": [FUNC.spl("SC4 SP1 SP1"), [(0.320,7500), (0.270,None), (0.270,None),(0.270,None)],[(150,50),(150,50)], [(0,50)]], "HIH": [FUNC.spl("SC4 SP1 SQd"), [(0.320,7500), (0.270,None), (0.270,None),(0.270,None)],[(150,50),(150,50)], [(0,50)]], "ARG": [FUNC.spl("N0 Qd"), [(0.330,5000), (0.340,5000)], [(180,25)]], "LYS": [FUNC.spl("C3 Qd"), [(0.330,5000), (0.280,5000)], [(180,25)]], "CYS": [FUNC.spl("C5"), [(0.310,7500)]], "ASP": [FUNC.spl("Qa"), [(0.320,7500)]], "PAS": [FUNC.spl("P3"), [(0.320,7500)]], "GLU": [FUNC.spl("Qa"), [(0.400,5000)]], "ILE": [FUNC.spl("AC1"), [(0.310,None)]], "LEU": [FUNC.spl("AC1"), [(0.330,7500)]], "MET": [FUNC.spl("C5"), [(0.400,2500)]], "ASN": [FUNC.spl("P5"), [(0.320,5000)]], "PRO": [FUNC.spl("C3"), [(0.300,7500)]], "HYP": [FUNC.spl("P1"), [(0.300,7500)]], "GLN": [FUNC.spl("P4"), [(0.400,5000)]], "SER": [FUNC.spl("P1"), [(0.250,7500)]], "THR": [FUNC.spl("P1"), [(0.260,None)]], "VAL": [FUNC.spl("AC2"), [(0.265,None)]], "ALA": [], "GLY": [], } # Not all (eg Elnedyn) forcefields use backbone-backbone-sidechain angles and BBBB-dihedrals. self.UseBBSAngles = True self.UseBBBBDihedrals = True # Martini 2.2p has polar and charged residues with seperate charges. self.polar = [] self.charged = [] # If masses or charged diverge from standard (45/72 and -/+1) they are defined here. self.mass_charge = { #RES MASS CHARGE } # Defines the connectivity between between beads self.connectivity = { #RES BONDS ANGLES DIHEDRALS V-SITE "TRP": [[(0,1),(1,2),(1,3),(2,3),(2,4),(3,4)], [(0,1,2),(0,1,3)], [(0,2,3,1),(1,2,4,3)]], "TYR": [[(0,1),(1,2),(1,3),(2,3)], [(0,1,2),(0,1,3)], [(0,2,3,1)]], "PHE": [[(0,1),(1,2),(1,3),(2,3)], [(0,1,2),(0,1,3)], [(0,2,3,1)]], "HIS": [[(0,1),(1,2),(1,3),(2,3)], [(0,1,2),(0,1,3)], [(0,2,3,1)]], "HIH": [[(0,1),(1,2),(1,3),(2,3)], [(0,1,2),(0,1,3)], [(0,2,3,1)]], "GLN": [[(0,1)]], "ASN": [[(0,1)]], "SER": [[(0,1)]], "THR": [[(0,1)]], "ARG": [[(0,1),(1,2)], [(0,1,2)]], "LYS": [[(0,1),(1,2)], [(0,1,2)]], "ASP": [[(0,1)]], "PAS": [[(0,1)]], "GLU": [[(0,1)]], "CYS": [[(0,1)]], "ILE": [[(0,1)]], "LEU": [[(0,1)]], "MET": [[(0,1)]], "PRO": [[(0,1)]], "HYP": [[(0,1)]], "VAL": [[(0,1)]], "ALA": [], "GLY": [], } #----+----------------+ ## C | SPECIAL BONDS | #----+----------------+ self.special = { # Used for sulfur bridges # ATOM 1 ATOM 2 BOND LENGTH FORCE CONSTANT (("SC1","CYS"), ("SC1","CYS")): (0.24, None), } # By default use an elastic network self.ElasticNetwork = False # Elastic networks bond shouldn't lead to exclusions (type 6) # But Elnedyn has been parametrized with type 1. self.EBondType = 6 #----+----------------+ ## D | INTERNAL STUFF | #----+----------------+ ## BACKBONE BEAD TYPE ## # Dictionary of default bead types (*D) self.bbBeadDictD = FUNC.hash(SS.bbss,self.bbdef) # Dictionary of dictionaries of types for specific residues (*S) self.bbBeadDictS = dict([(i,FUNC.hash(SS.bbss,self.bbtyp[i])) for i in self.bbtyp.keys()]) ## BB BOND TYPE ## # Dictionary of default abond types (*D) self.bbBondDictD = FUNC.hash(SS.bbss,zip(self.bbldef,self.bbkb)) # Dictionary of dictionaries for specific types (*S) self.bbBondDictS = dict([(i,FUNC.hash(SS.bbss,zip(self.bbltyp[i],self.bbkbtyp[i]))) for i in self.bbltyp.keys()]) # This is tricky to read, but it gives the right bondlength/force constant ## BBB ANGLE TYPE ## # Dictionary of default angle types (*D) self.bbAngleDictD = FUNC.hash(SS.bbss,zip(self.bbadef,self.bbka)) # Dictionary of dictionaries for specific types (*S) self.bbAngleDictS = dict([(i,FUNC.hash(SS.bbss,zip(self.bbatyp[i],self.bbkatyp[i]))) for i in self.bbatyp.keys()]) ## BBBB DIHEDRAL TYPE ## # Dictionary of default dihedral types (*D) self.bbDihedDictD = FUNC.hash(SS.bbss,zip(self.bbddef,self.bbkd,self.bbdmul)) # Dictionary of dictionaries for specific types (*S) self.bbDihedDictS = dict([(i,FUNC.hash(SS.bbss,zip(self.bbdtyp[i],self.bbkdtyp[i]))) for i in self.bbdtyp.keys()])
########################## ## 4 # FG -> CG MAPPING ## -> @MAP <- ########################## import FUNC dnares3 = " DA DC DG DT" dnares1 = " dA dC dG dT" rnares3 = " A C G U" rnares1 = " rA rC rG rU" # Amino acid nucleic acid codes: # The naming (AA and '3') is not strictly correct when adding DNA/RNA, but we keep it like this for consistincy. AA3 = FUNC.spl( "TRP TYR PHE HIS HIH ARG LYS CYS ASP GLU ILE LEU MET ASN PRO HYP GLN SER THR VAL ALA GLY" + dnares3 + rnares3) #@# AA1 = FUNC.spl( " W Y F H H R K C D E I L M N P O Q S T V A G" + dnares1 + rnares1) #@# # Dictionaries for conversion from one letter code to three letter code v.v. AA123, AA321 = FUNC.hash(AA1, AA3), FUNC.hash(AA3, AA1) # Residue classes: protein = AA3[:-8] # remove eight to get rid of DNA/RNA here. water = FUNC.spl("HOH SOL TIP") lipids = FUNC.spl( "DPP DHP DLP DMP DSP POP DOP DAP DUP DPP DHP DLP DMP DSP PPC DSM DSD DSS") nucleic = FUNC.spl("DAD DCY DGU DTH ADE CYT GUA THY URA DA DC DG DT") residueTypes = dict([(i, "Protein") for i in protein] + [(i, "Water") for i in water] +
def bbGetBond(self,r,ca,ss): import FUNC import math # The 150000 forceconstant gave an error message, turning to constraints would be better. return ( math.sqrt(FUNC.distance2(ca[0],ca[1]))/10., 150000 )
def __init__(self): import SS,FUNC,IO # parameters are defined here for the following (protein) forcefields: self.name = 'elnedyn22' # Charged types: self.charges = {"Qd":1, "Qa":-1, "SQd":1, "SQa":-1, "RQd":1, "AQa":-1} #@# #----+---------------------+ ## A | BACKBONE PARAMETERS | #----+---------------------+ # # bbss lists the one letter secondary structure code # bbdef lists the corresponding default backbone beads # bbtyp lists the corresponding residue specific backbone beads # # bbd lists the structure specific backbone bond lengths # bbkb lists the corresponding bond force constants # # bba lists the structure specific angles # bbka lists the corresponding angle force constants # # bbd lists the structure specific dihedral angles # bbkd lists the corresponding force constants # # -=NOTE=- # if the secondary structure types differ between bonded atoms # the bond is assigned the lowest corresponding force constant # # -=NOTE=- # if proline is anywhere in the helix, the BBB angle changes for # all residues # ############################################################################################### ## BEADS ## # # F E H 1 2 3 T S C # SS one letter self.bbdef = FUNC.spl(" N0 Nda N0 Nd Na Nda Nda P5 P5") # Default beads #@# self.bbtyp = { # #@# "ALA": FUNC.spl(" C5 N0 C5 N0 N0 N0 N0 P4 P4"), # ALA specific #@# "PRO": FUNC.spl(" C5 N0 C5 N0 Na N0 N0 P4 P4"), # PRO specific #@# "HYP": FUNC.spl(" C5 N0 C5 N0 N0 N0 N0 P4 P4") # HYP specific #@# } # #@# ## BONDS ## # self.bbldef = (.365, .350, .350, .350, .350, .350, .350, .350, .350) # BB bond lengths #@# self.bbkb = (1250, 1250, 1250, 1250, 1250, 1250, 500, 400, 400) # BB bond kB #@# self.bbltyp = {} # #@# self.bbkbtyp = {} # #@# ## ANGLES ## # self.bbadef = (119.2, 134, 96, 96, 96, 96, 100, 130, 127) # BBB angles #@# self.bbka = ( 150, 25, 700, 700, 700, 700, 25, 25, 25) # BBB angle kB #@# self.bbatyp = { # #@# "PRO": ( 119.2,134, 98, 98, 98, 98, 100, 130, 127), # PRO specific #@# "HYP": ( 119.2,134, 98, 98, 98, 98, 100, 130, 127) # PRO specific #@# } # #@# self.bbkatyp = { # #@# "PRO": ( 150, 25, 100, 100, 100, 100, 25, 25, 25), # PRO specific #@# "HYP": ( 150, 25, 100, 100, 100, 100, 25, 25, 25) # PRO specific #@# } # #@# ## DIHEDRALS ## # self.bbddef = (90.7, 0, -120, -120, -120, -120) # BBBB dihedrals #@# self.bbkd = ( 100, 10, 400, 400, 400, 400) # BBBB kB #@# self.bbdmul = ( 1, 1, 1, 1, 1, 1) # BBBB mltplcty #@# self.bbdtyp = {} # #@# self.bbkdtyp = {} # #@# # ############################################################################################### # Some Forcefields use the Ca position to position the BB-bead (me like!) self.ca2bb = True # BBS angle, equal for all ss types # Connects BB(i-1),BB(i),SC(i), except for first residue: BB(i+1),BB(i),SC(i) # ANGLE Ka self.bbsangle = [ 100, 25] #@# # Bonds for extended structures (more stable than using dihedrals) # LENGTH FORCE self.ebonds = { #@# 'short': [ .640, 2500], #@# 'long' : [ .970, 2500] #@# } #@# #----+-----------------------+ ## B | SIDE CHAIN PARAMETERS | #----+-----------------------+ # Sidechain parameters for Elnedyn. (read from cg-2.1.dat). # For HIS the order of bonds is changed and a bond with fc=0 is added. # In the elnedyn2, TRP has an extra, cross-ring constraint self.sidechains = { #RES# BEADS BONDS ANGLES DIHEDRALS 'TRP': [FUNC.spl("SC4 SNd SC5 SC5"), [(0.255,73000), (0.220,None), (0.250,None), (0.280,None), (0.255,None), (0.35454,None)], [(142,30), (143,20), (104,50)], [(180,200)]], 'TYR': [FUNC.spl("SC4 SC4 SP1"), [(0.335, 6000), (0.335,6000), (0.240,None), (0.310,None), (0.310,None)], [(70,100), (130, 50)]], 'PHE': [FUNC.spl("SC5 SC5 SC5"), [(0.340, 7500), (0.340,7500), (0.240,None), (0.240,None), (0.240,None)], [(70,100), (125,100)]], 'HIS': [FUNC.spl("SC4 SP1 SP1"), [(0.195, None), (0.193,None), (0.295,None), (0.216,None)], [(135,100),(115, 50)]], 'HIH': [FUNC.spl("SC4 SP1 SP1"), [(0.195, None), (0.193,None), (0.295,None), (0.216,None)], [(135,100),(115, 50)]], 'ARG': [FUNC.spl("N0 Qd"), [(0.250,12500), (0.350,6200)], [(150,15)]], 'LYS': [FUNC.spl("C3 Qd"), [(0.250,12500), (0.300,9700)], [(150,20)]], 'CYS': [FUNC.spl("C5"), [(0.240, None)]], 'ASP': [FUNC.spl("Qa"), [(0.255, None)]], 'GLU': [FUNC.spl("Qa"), [(0.310, 2500)]], 'ILE': [FUNC.spl("C1"), [(0.225,13250)]], 'LEU': [FUNC.spl("C1"), [(0.265, None)]], 'MET': [FUNC.spl("C5"), [(0.310, 2800)]], 'ASN': [FUNC.spl("P5"), [(0.250, None)]], 'PRO': [FUNC.spl("C3"), [(0.190, None)]], 'GLN': [FUNC.spl("P4"), [(0.300, 2400)]], 'SER': [FUNC.spl("P1"), [(0.195, None)]], 'THR': [FUNC.spl("P1"), [(0.195, None)]], 'VAL': [FUNC.spl("C2"), [(0.200, None)]], 'GLY': [], 'ALA': [], } # Not all (eg Elnedyn) forcefields use backbone-backbone-sidechain angles and BBBB-dihedrals. self.UseBBSAngles = False self.UseBBBBDihedrals = False # Martini 2.2p has polar and charged residues with seperate charges. self.polar = [] self.charged = [] # If masses or charged diverge from standard (45/72 and -/+1) they are defined here. self.mass_charge = { #RES MASS CHARGE } # Defines the connectivity between between beads # Connectivity records for Elnedyn (read from cg-2.1.dat). # For HIS the order of bonds is changed and a bond with fc=0 is added. self.connectivity = { #RES BONDS ANGLES DIHEDRALS V-SITE "TRP": [[(0, 1), (1, 2), (2, 4), (4, 3), (3, 1), (1, 4)],[(0, 1, 2), (0, 1, 4), (0, 1, 3)],[(1, 2, 3, 4)]], "TYR": [[(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)], [(0, 1, 2), (0, 1, 3)]], "PHE": [[(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)], [(0, 1, 2), (0, 1, 3)]], "HIS": [[(0, 1), (1, 2), (1, 3), (2, 3)], [(0, 1, 2), (0, 1, 3)]], "HIH": [[(0, 1), (1, 2), (1, 3), (2, 3)], [(0, 1, 2), (0, 1, 3)]], "GLN": [[(0,1)]], "ASN": [[(0,1)]], "SER": [[(0,1)]], "THR": [[(0,1)]], "ARG": [[(0,1),(1,2)], [(0,1,2)]], "LYS": [[(0,1),(1,2)], [(0,1,2)]], "ASP": [[(0,1)]], "GLU": [[(0,1)]], "CYS": [[(0,1)]], "ILE": [[(0,1)]], "LEU": [[(0,1)]], "MET": [[(0,1)]], "PRO": [[(0,1)]], "HYP": [[(0,1)]], "VAL": [[(0,1)]], "ALA": [], "GLY": [], } #----+----------------+ ## C | SPECIAL BONDS | #----+----------------+ self.special = { # Used for sulfur bridges # ATOM 1 ATOM 2 BOND LENGTH FORCE CONSTANT (("SC1","CYS"), ("SC1","CYS")): (0.24, None), } # By default use an elastic network self.ElasticNetwork = True # Elastic networks bond shouldn't lead to exclusions (type 6) # But Elnedyn has been parametrized with type 1. self.EBondType = 1 #----+----------------+ ## D | INTERNAL STUFF | #----+----------------+ ## BACKBONE BEAD TYPE ## # Dictionary of default bead types (*D) self.bbBeadDictD = FUNC.hash(SS.bbss,self.bbdef) # Dictionary of dictionaries of types for specific residues (*S) self.bbBeadDictS = dict([(i,FUNC.hash(SS.bbss,self.bbtyp[i])) for i in self.bbtyp.keys()]) ## BB BOND TYPE ## # Dictionary of default abond types (*D) self.bbBondDictD = FUNC.hash(SS.bbss,zip(self.bbldef,self.bbkb)) # Dictionary of dictionaries for specific types (*S) self.bbBondDictS = dict([(i,FUNC.hash(SS.bbss,zip(self.bbltyp[i],self.bbkbtyp[i]))) for i in self.bbltyp.keys()]) # This is tricky to read, but it gives the right bondlength/force constant ## BBB ANGLE TYPE ## # Dictionary of default angle types (*D) self.bbAngleDictD = FUNC.hash(SS.bbss,zip(self.bbadef,self.bbka)) # Dictionary of dictionaries for specific types (*S) self.bbAngleDictS = dict([(i,FUNC.hash(SS.bbss,zip(self.bbatyp[i],self.bbkatyp[i]))) for i in self.bbatyp.keys()]) ## BBBB DIHEDRAL TYPE ## # Dictionary of default dihedral types (*D) self.bbDihedDictD = FUNC.hash(SS.bbss,zip(self.bbddef,self.bbkd,self.bbdmul)) # Dictionary of dictionaries for specific types (*S) self.bbDihedDictS = dict([(i,FUNC.hash(SS.bbss,zip(self.bbdtyp[i],self.bbkdtyp[i]))) for i in self.bbdtyp.keys()])
class CoarseGrained: # Class for mapping an atomistic residue list to a coarsegrained one # Should get an __init__ function taking a residuelist, atomlist, Pymol selection or ChemPy model # The result should be stored in a list-type attribute # The class should have pdbstr and grostr methods # Standard mapping groups # Protein backbone bb = "N CA C O H H1 H2 H3 O1 O2" #@# # Lipid tails palmitoyl1 = FUNC.nsplit("C1B C1C C1D C1E", "C1F C1G C1H C1I", "C1J C1K C1L C1M", "C1N C1O C1P") #@# palmitoyl2 = FUNC.nsplit("C2B C2C C2D C2E", "C2F C2G C2H C2I", "C2J C2K C2L C2M", "C2N C2O C2P") #@# oleyl1 = FUNC.nsplit("C1B C1C C1D C1E", "C1F C1G C1H", "C1I C1J", "C1K C1L C1M C1N", "C1O C1P C1Q C1R") #@# oleyl2 = FUNC.nsplit("C2B C2C C2D C2E", "C2F C2G C2H", "C2I C2J", "C2K C2L C2M C2N", "C2O C2P C2Q C2R") #@# #lauroyl1 = [] #stearoyl1 = [] #arachidonoyl1 = [] #linoleyl1 = [] #hexanoyl1 = [] # Lipid head groups #phoshpatidylcholine = phosphatydilethanolamine = FUNC.nsplit("N H1 H2 H3 CA", "CB P OA OB OC OD", "CC CD OG C2A OH", "CE OE C1A OF") #@# phosphatidylglycerol = FUNC.nsplit("H1 O1 CA H2 O2 CB", "CC P OA OB OC OD", "CD CE OG C2A OH", "CF OE C1A OF") #@# #phosphatidylserine = dna_bb = "P OP1 OP2 O5' O3'", "C5' O4' C4'", "C3' O3' C2' C1'" # This is the mapping dictionary # For each residue it returns a list, each element of which # lists the atom names to be mapped to the corresponding bead. # The order should be the standard order of the coarse grained # beads for the residue. Only atom names matching with those # present in the list of atoms for the residue will be used # to determine the bead position. This adds flexibility to the # approach, as a single definition can be used for different # states of a residue (e.g., GLU/GLUH). # For convenience, the list can be specified as a set of strings, # converted into a list of lists by 'FUNC.nsplit' defined above. mapping = { "ALA": FUNC.nsplit(bb + " CB"), "CYS": FUNC.nsplit(bb, "CB SG"), "ASP": FUNC.nsplit(bb, "CB CG OD1 OD2"), "GLU": FUNC.nsplit(bb, "CB CG CD OE1 OE2"), "PHE": FUNC.nsplit(bb, "CB CG CD1 HD1", "CD2 HD2 CE2 HE2", "CE1 HE1 CZ HZ"), "GLY": FUNC.nsplit(bb), "HIS": FUNC.nsplit(bb, "CB CG", "CD2 HD2 NE2 HE2", "ND1 HD1 CE1 HE1"), "HIH": FUNC.nsplit(bb, "CB CG", "CD2 HD2 NE2 HE2", "ND1 HD1 CE1 HE1"), # Charged Histidine. "ILE": FUNC.nsplit(bb, "CB CG1 CG2 CD CD1"), "LYS": FUNC.nsplit(bb, "CB CG CD", "CE NZ HZ1 HZ2 HZ3"), "LEU": FUNC.nsplit(bb, "CB CG CD1 CD2"), "MET": FUNC.nsplit(bb, "CB CG SD CE"), "ASN": FUNC.nsplit(bb, "CB CG ND1 ND2 OD1 OD2 HD11 HD12 HD21 HD22"), "PRO": FUNC.nsplit(bb, "CB CG CD"), "HYP": FUNC.nsplit(bb, "CB CG CD OD"), "GLN": FUNC.nsplit(bb, "CB CG CD OE1 OE2 NE1 NE2 HE11 HE12 HE21 HE22"), "ARG": FUNC.nsplit(bb, "CB CG CD", "NE HE CZ NH1 NH2 HH11 HH12 HH21 HH22"), "SER": FUNC.nsplit(bb, "CB OG HG"), "THR": FUNC.nsplit(bb, "CB OG1 HG1 CG2"), "VAL": FUNC.nsplit(bb, "CB CG1 CG2"), "TRP": FUNC.nsplit(bb, "CB CG CD2", "CD1 HD1 NE1 HE1 CE2", "CE3 HE3 CZ3 HZ3", "CZ2 HZ2 CH2 HH2"), "TYR": FUNC.nsplit(bb, "CB CG CD1 HD1", "CD2 HD2 CE2 HE2", "CE1 HE1 CZ OH HH"), "POPE": phosphatydilethanolamine + palmitoyl1 + oleyl2, "DOPE": phosphatydilethanolamine + oleyl1 + oleyl2, "DPPE": phosphatydilethanolamine + palmitoyl1 + palmitoyl2, "POPG": phosphatidylglycerol + palmitoyl1 + oleyl2, "DOPG": phosphatidylglycerol + oleyl1 + oleyl2, "DPPG": phosphatidylglycerol + palmitoyl1 + palmitoyl2, "DA": FUNC.nsplit("P OP1 OP2 O5' O3' O1P O2P", "C5' O4' C4'", "C3' C2' C1'", "N9 C4", "C8 N7 C5", "C6 N6 N1", "C2 N3"), "DG": FUNC.nsplit("P OP1 OP2 O5' O3' O1P O2P", "C5' O4' C4'", "C3' C2' C1'", "N9 C4", "C8 N7 C5", "C6 O6 N1", "C2 N2 N3"), "DC": FUNC.nsplit("P OP1 OP2 O5' O3' O1P O2P", "C5' O4' C4'", "C3' C2' C1'", "N1 C6", "C5 C4 N4", "N3 C2 O2"), "DT": FUNC.nsplit("P OP1 OP2 O5' O3' O1P O2P", "C5' O4' C4'", "C3' C2' C1'", "N1 C6", "C5 C4 O4 C7 C5M", "N3 C2 O2"), } # Generic names for side chain beads residue_bead_names = FUNC.spl("BB SC1 SC2 SC3 SC4") # Generic names for DNA beads residue_bead_names_dna = FUNC.spl("BB1 BB2 BB3 SC1 SC2 SC3 SC4") # This dictionary contains the bead names for all residues, # following the order in 'mapping' names = { "POPE": "NH3 PO4 GL1 GL2 C1A C2A C3A C4A C1B C2B D3B C4B C5B".split(), "POPG": "GLC PO4 GL1 GL2 C1A C2A C3A C4A C1B C2B D3B C4B C5B".split() } # Add default bead names for all amino acids names.update([(i, ("BB", "SC1", "SC2", "SC3", "SC4")) for i in AA3]) # Add the default bead names for all DNA nucleic acids names.update([(i, ("BB1", "BB2", "BB3", "SC1", "SC2", "SC3", "SC4")) for i in nucleic]) # This dictionary allows determining four letter residue names # for ones specified with three letters, e.g., resulting from # truncation to adhere to the PDB format. # Each entry returns a prototypical test, given as a string, # and the residue name to be applied if eval(test) is True. # This is particularly handy to determine lipid types. # The test assumes there is a local or global array 'atoms' # containing the atom names of the residue in correct order. restest = { "POP": [('atoms[0] == "CA"', "POPG"), ('atoms[0] == "N"', "POPE")] } # Crude mass for weighted average. No consideration of united atoms. # This will probably give only minor deviations, while also giving less headache mass = {'H': 1, 'C': 12, 'N': 14, 'O': 16, 'S': 32, 'P': 31, 'M': 0}
def __init__(self): import SS,FUNC,IO # parameters are defined here for the following (protein) forcefields: self.name = 'martini22dna' # Charged types: self.charges = {"Qd":1, "Qa":-1, "SQd":1, "SQa":-1, "RQd":1, "AQa":-1} #@# self.bbcharges = {"BB1":-1} #@# #----+---------------------+ ## A | BACKBONE PARAMETERS | #----+---------------------+ # # bbss lists the one letter secondary structure code # bbdef lists the corresponding default backbone beads # bbtyp lists the corresponding residue specific backbone beads # # bbd lists the structure specific backbone bond lengths # bbkb lists the corresponding bond force constants # # bba lists the structure specific angles # bbka lists the corresponding angle force constants # # bbd lists the structure specific dihedral angles # bbkd lists the corresponding force constants # # -=NOTE=- # if the secondary structure types differ between bonded atoms # the bond is assigned the lowest corresponding force constant # # -=NOTE=- # if proline is anywhere in the helix, the BBB angle changes for # all residues # ############################################################################################### ## BEADS ## # # F E H 1 2 3 T S C # SS one letter self.bbdef = FUNC.spl(" N0 Nda N0 Nd Na Nda Nda P5 P5") # Default beads #@# self.bbtyp = { # #@# "ALA": FUNC.spl(" C5 N0 C5 N0 N0 N0 N0 P4 P4"), # ALA specific #@# "PRO": FUNC.spl(" C5 N0 C5 N0 Na N0 N0 P4 P4"), # PRO specific #@# "HYP": FUNC.spl(" C5 N0 C5 N0 N0 N0 N0 P4 P4") # HYP specific #@# } # #@# ## BONDS ## # self.bbldef = (.365, .350, .310, .310, .310, .310, .350, .350, .350) # BB bond lengths #@# self.bbkb = (1250, 1250, None, None, None, None, 1250, 1250, 1250) # BB bond kB #@# self.bbltyp = {} # #@# self.bbkbtyp = {} # #@# ## ANGLES ## # self.bbadef = ( 119.2,134, 96, 96, 96, 96, 100, 130, 127) # BBB angles #@# self.bbka = ( 150, 25, 700, 700, 700, 700, 20, 20, 20) # BBB angle kB #@# self.bbatyp = { # #@# "PRO": ( 119.2,134, 98, 98, 98, 98, 100, 130, 127), # PRO specific #@# "HYP": ( 119.2,134, 98, 98, 98, 98, 100, 130, 127) # PRO specific #@# } # #@# self.bbkatyp = { # #@# "PRO": ( 150, 25, 100, 100, 100, 100, 25, 25, 25), # PRO specific #@# "HYP": ( 150, 25, 100, 100, 100, 100, 25, 25, 25) # PRO specific #@# } # #@# ## DIHEDRALS ## # self.bbddef = ( 90.7, 0, -120, -120, -120, -120) # BBBB dihedrals #@# self.bbkd = ( 100, 10, 400, 400, 400, 400) # BBBB kB #@# self.bbdmul = ( 1, 1, 1, 1, 1, 1) # BBBB mltplcty #@# self.bbdtyp = {} # #@# self.bbkdtyp = {} # #@# # ############################################################################################### # Some Forcefields use the Ca position to position the BB-bead (me like!) # martini 2.1 doesn't self.ca2bb = False # BBS angle, equal for all ss types # Connects BB(i-1),BB(i),SC(i), except for first residue: BB(i+1),BB(i),SC(i) # ANGLE Ka self.bbsangle = [ 100, 25] #@# # Bonds for extended structures (more stable than using dihedrals) # LENGTH FORCE self.ebonds = { #@# 'short': [ .640, 2500], #@# 'long' : [ .970, 2500] #@# } #@# #----+-----------------------+ ## B | SIDE CHAIN PARAMETERS | #----+-----------------------+ # To be compatible with Elnedyn, all parameters are explicitly defined, even if they are double. self.sidechains = { #RES# BEADS BONDS ANGLES DIHEDRALS # BB-SC SC-SC BB-SC-SC SC-SC-SC "TRP": [FUNC.spl("SC4 SNd SC5 SC5"),[(0.300,5000)]+[(0.270,None) for i in range(5)], [(210,50),(90,50),(90,50)], [(0,50),(0,200)]], "TYR": [FUNC.spl("SC4 SC4 SP1"), [(0.320,5000), (0.270,None), (0.270,None),(0.270,None)],[(150,50),(150,50)], [(0,50)]], "PHE": [FUNC.spl("SC5 SC5 SC5"), [(0.310,7500), (0.270,None), (0.270,None),(0.270,None)],[(150,50),(150,50)], [(0,50)]], "HIS": [FUNC.spl("SC4 SP1 SP1"), [(0.320,7500), (0.270,None), (0.270,None),(0.270,None)],[(150,50),(150,50)], [(0,50)]], "HIH": [FUNC.spl("SC4 SP1 SQd"), [(0.320,7500), (0.270,None), (0.270,None),(0.270,None)],[(150,50),(150,50)], [(0,50)]], "ARG": [FUNC.spl("N0 Qd"), [(0.330,5000), (0.340,5000)], [(180,25)]], "LYS": [FUNC.spl("C3 Qd"), [(0.330,5000), (0.280,5000)], [(180,25)]], "CYS": [FUNC.spl("C5"), [(0.310,7500)]], "ASP": [FUNC.spl("Qa"), [(0.320,7500)]], "GLU": [FUNC.spl("Qa"), [(0.400,5000)]], "ILE": [FUNC.spl("AC1"), [(0.310,None)]], "LEU": [FUNC.spl("AC1"), [(0.330,7500)]], "MET": [FUNC.spl("C5"), [(0.400,2500)]], "ASN": [FUNC.spl("P5"), [(0.320,5000)]], "PRO": [FUNC.spl("C3"), [(0.300,7500)]], "HYP": [FUNC.spl("P1"), [(0.300,7500)]], "GLN": [FUNC.spl("P4"), [(0.400,5000)]], "SER": [FUNC.spl("P1"), [(0.250,7500)]], "THR": [FUNC.spl("P1"), [(0.260,None)]], "VAL": [FUNC.spl("AC2"), [(0.265,None)]], "ALA": [], "GLY": [], } # Not all (eg Elnedyn) forcefields use backbone-backbone-sidechain angles and BBBB-dihedrals. self.UseBBSAngles = True self.UseBBBBDihedrals = True # Martini 2.2p has polar and charged residues with seperate charges. self.polar = [] self.charged = [] # If masses or charged diverge from standard (45/72 and -/+1) they are defined here. self.mass_charge = { #RES MASS CHARGE } # Defines the connectivity between between beads self.aa_connectivity = { #RES BONDS ANGLES DIHEDRALS V-SITE "TRP": [[(0,1),(1,2),(1,3),(2,3),(2,4),(3,4)], [(0,1,2),(0,1,3)], [(0,2,3,1),(1,2,4,3)]], "TYR": [[(0,1),(1,2),(1,3),(2,3)], [(0,1,2),(0,1,3)], [(0,2,3,1)]], "PHE": [[(0,1),(1,2),(1,3),(2,3)], [(0,1,2),(0,1,3)], [(0,2,3,1)]], "HIS": [[(0,1),(1,2),(1,3),(2,3)], [(0,1,2),(0,1,3)], [(0,2,3,1)]], "HIH": [[(0,1),(1,2),(1,3),(2,3)], [(0,1,2),(0,1,3)], [(0,2,3,1)]], "GLN": [[(0,1)]], "ASN": [[(0,1)]], "SER": [[(0,1)]], "THR": [[(0,1)]], "ARG": [[(0,1),(1,2)], [(0,1,2)]], "LYS": [[(0,1),(1,2)], [(0,1,2)]], "ASP": [[(0,1)]], "GLU": [[(0,1)]], "CYS": [[(0,1)]], "ILE": [[(0,1)]], "LEU": [[(0,1)]], "MET": [[(0,1)]], "PRO": [[(0,1)]], "HYP": [[(0,1)]], "VAL": [[(0,1)]], "ALA": [], "GLY": [], } #----+----------------+ ## C | DNA/RNA bases | #----+----------------+ # DNA BACKBONE PARAMETERS self.dna_bb = { 'atom' : FUNC.spl("Q0 SN0 SC2"), 'bond' : [(1, 0.360, 20000), (1, 0.198, 80000), (1, 0.353, 10000)], 'angle' : [(2, 110.0, 200), (2, 102.0, 150), (2, 106.0, 75)], 'dih' : [(2, 95.0, 25), (1, 180.0, 2, 3), (9, 85.0, 2, 2, 9, 160.0, 2, 3)], 'excl' : [(), (), ()], 'pair' : [], } # DNA BACKBONE CONNECTIVITY self.dna_con = { 'bond' : [(0, 1), (1, 2), (2, 0)], 'angle' : [(0, 1, 2), (1, 2, 0), (2, 0, 1)], 'dih' : [(0, 1, 2, 0), (1, 2, 0, 1), (2, 0, 1, 2)], 'excl' : [(0, 2), (1, 0),(2, 1)], 'pair' : [], } ## FOR PLOTTING ONLY # # DNA BACKBONE PARAMETERS # self.dna_bb = { # 'atom' : FUNC.spl("Q0 SN0 SC2"), # 'bond' : [(1, 0.360, 30000), # (1, 0.400, 10000), # (1, 0.200, 50000), # (1, 0.355, 10000)], # 'angle' : [(2, 115.0, 85), # (2, 102.0, 105), # (2, 110.0, 60)], # 'dih' : [(2, 100.0, 1), # (2, -120.0, 5), # (2, 140.0, 5)], # 'excl' : [(), (), ()], # } # # DNA BACKBONE CONNECTIVITY # self.dna_con = { # 'bond' : [(0, 1), # (0, 2), # (1, 2), # (2, 0)], # 'angle' : [(0, 1, 2), # (1, 2, 0), # (2, 0, 1)], # 'dih' : [(0, 1, 2, 0), # (1, 2, 0, 1), # (2, 0, 1, 2)], # 'excl' : [(0, 2), (1, 0), (2, 1)], # } # RNA BACKBONE PARAMETERS self.rna_bb = { 'atom' : FUNC.spl("Q0 N0 C2"), 'bond' : [(0.120,5000),(0.220,5000),(0.320,5000)], 'angle' : [(10.0, 100), (20.0, 100), (30.0, 100)], 'dih' : [(100, 10), (100, 10), (100, 10),], 'excl' : [], } # RNA BACKBONE CONNECTIVITY self.rna_con = { 'bond' : [(0,1),(1,2),(2,0)], 'angle' : [(0,1,2),(1,2,0),(2,0,1)], 'dih' : [(0,1,2,0),(1,2,0,1),(2,0,1,2)], 'excl' : [], } # For bonds, angles, and dihedrals the first parameter should always # be the type. It is pretty annoying to check the connectivity from # elsewhere so we update these one base at a time. # ADENINE self.bases = { "DA": [FUNC.spl("TN0 TA2 TA3 TNa"), # TYPE EQUIL OPTS TYPE EQUIL OPTS TYPE EQUIL OPTS # [(1, 0.348, 20000), (1, 0.229, None), (1, 0.266, None), # BONDS BB3-SC1 bond lengthened by 0.048 nm. [(1, 0.300, 30000), (1, 0.229, None), (1, 0.266, None), # BONDS BB3-SC1 bond lengthened by 0.048 nm. (1, 0.326, 20000), (1, 0.288, None), (1, 0.162, None),], [(2, 94.0, 250), (2, 160.0, 200), (2, 140.0, 200), # ANGLES (1, 85.0, 200), (2, 158.0, 200), (1, 125.0, 200), (1, 74.0, 200), (1, 98.0, 200)], [(2, -90.0, 20), (2, -116.0, 0.5), (2, 98.0, 15)], # DIHEDRALS [], # IMPROPERS [], # VSITES [(), (), (), (), (), (), (), (), (), (), (), (), (), ()], # EXCLUSIONS []], # PAIRS } self.base_connectivity = { "DA": [[(2, 3), (3, 4), (4, 5), # BONDS (4, 6), (5, 6), (6, 3)], [(1, 2, 3), (2, 3, 4), (2, 3, 6), # ANGLES (3, 4, 5), (3, 2, 7), (4, 3, 6), (4, 5, 6), (5, 6, 3)], [(0, 1, 2, 3), (1, 2, 3, 4), (1, 2, 3, 6),], # DIHEDRALS [], # IMPROPERS [], # VSITES [(0, 3), (0, 4), (0, 5), # EXCLUSIONS (0, 6), (1, 3), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (2, 5), (2, 6), (3, 5), (4, 6)], []], # PAIRS } # CYTOSINE self.bases.update({ "DC": [FUNC.spl("TN0 TY2 TY3"), # TYPE EQUIL OPTS TYPE EQUIL OPTS TYPE EQUIL OPTS # [(1, 0.303, 20000), (1, 0.220, None), (1, 0.285, None), # BONDS BB3-SC1 bond lenghtened by 0.033 nm. [(1, 0.270, 30000), (1, 0.220, None), (1, 0.285, None), # BONDS BB3-SC1 bond lenghtened by 0.033 nm. (1, 0.268, None),], [(2, 95.0, 210), (2, 95.0, 300), (1, 150.0, 500), # ANGLES (1, 180.0, 30), (1, 61.0, 200), (1, 71.0, 200), (1, 47.0, 200)], [(2, -78.0, 25), (2, -90.0, 20), (2, -142.0, 50)], # DIHEDRALS #[(2, -78.0, 25), (2, -108.0, 10), (2, 40.0, 15)], # DIHEDRALS [], # IMPROPERS [], # VSITES [(), (), (), (), (), (), (), (), ()], # EXCLUSIONS []], # PAIRS }) self.base_connectivity.update({ "DC": [[(2, 3), (3, 4), (4, 5), # BONDS (5, 3)], [(1, 2, 3), (2, 3, 4), (1, 3, 5), # ANGLES (3, 2, 6), (3, 4, 5), (4, 3, 5), (4, 5, 3)], [(0, 1, 2, 3), (1, 2, 3, 4), (2, 1, 3, 5)], # DIHEDRALS [], # IMPROPERS [], # VSITES [(0, 3), (0, 4), (0, 5), # EXCLUSIONS (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5)], []], # PAIRS }) # GUANINE self.bases.update({ "DG": [FUNC.spl("TN0 TG2 TG3 TNa"), # TYPE EQUIL OPTS TYPE EQUIL OPTS TYPE EQUIL OPTS # [(1, 0.353, 20000), (1, 0.295, None), (1, 0.295, None), # BONDS BB3-SC1 bond lengthened by 0.053 nm. [(1, 0.300, 30000), (1, 0.295, None), (1, 0.295, None), # BONDS BB3-SC1 bond lengthened by 0.053 nm. (1, 0.389, 20000), (1, 0.285, None), (1, 0.161, None),], [(2, 94.5, 250), (2, 137.0, 300), (2, 130.0, 250), # ANGLES (1, 69.5, 200), (2, 157.0, 150), (1, 125.0, 200), (1, 84.0, 200), (1, 94.0, 200)], [(2, -90.0, 20), (2, -117.0, 1), (2, 92.0, 15)], # DIHEDRALS [], # IMPROPERS [], # VSITES [(), (), (), (), (), (), (), (), (), (), (), (), (), ()], # EXCLUSIONS []], # PAIRS }) self.base_connectivity.update({ "DG": [[(2, 3), (3, 4), (4, 5), # BONDS (4, 6), (5, 6), (6, 3)], [(1, 2, 3), (2, 3, 4), (2, 3, 6), # ANGLES (3, 4, 5), (3, 2, 7), (4, 3, 6), (4, 5, 6), (5, 6, 3)], [(0, 1, 2, 3), (1, 2, 3, 4), (1, 2, 3, 6),], # DIHEDRALS [], # IMPROPERS [], # VSITES [(0, 3), (0, 4), (0, 5), # EXCLUSIONS (0, 6), (1, 3), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (2, 5), (2, 6), (3, 5), (4, 6)], []], # PAIRS }) # THYMINE self.bases.update({ "DT": [FUNC.spl("TN0 TT2 TT3"), # TYPE EQUIL OPTS TYPE EQUIL OPTS TYPE EQUIL OPTS # [(1, 0.326, 20000), (1, 0.217, None), (1, 0.322, None), # BONDS BB3-SC1 bond lengthened by 0.056 nm. [(1, 0.270, 30000), (1, 0.217, None), (1, 0.322, None), # BONDS BB3-SC1 bond lengthened by 0.056 nm. (1, 0.265, None),], [(2, 92.0, 220), (2, 107.0, 300), (1, 145.0, 400), # ANGLES (1, 180.0, 30), (1, 55.0, 100), (1, 83.0, 100), (1, 42.0, 100)], [(2, -75.0, 40), (2, -110.0, 15), (2, -145.0, 65)], # DIHEDRALS [], # IMPROPERS [], # VSITES [(), (), (), (), (), (), (), (), ()], # EXCLUSIONS []], # PAIRS }) self.base_connectivity.update({ "DT": [[(2, 3), (3, 4), (4, 5), # BONDS (5, 3)], [(1, 2, 3), (2, 3, 4), (1, 3, 5), # ANGLES (3, 2, 6), (3, 4, 5), (4, 3, 5), (4, 5, 3)], [(0, 1, 2, 3), (1, 2, 3, 4), (2, 1, 3, 5)], # DIHEDRALS [], # IMPROPERS [], # VSITES [(0, 3), (0, 4), (0, 5), # EXCLUSIONS (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5)], []], # PAIRS }) ## FOR PLOTTING ONLY # # ADENINE # self.bases = { # "DA": [FUNC.spl("TN0 TA2 TA3 TNa"), # # TYPE EQUIL OPTS TYPE EQUIL OPTS TYPE EQUIL OPTS # [(1, 0.330, 30000), (1, 0.229, 30000), (1, 0.266, 30000), # BONDS BB3-SC1 bond lengthened by 0.030 nm. # (1, 0.325, 30000), (1, 0.288, 30000), (1, 0.162, 30000),], # [(2, 93.0, 250), (2, 160.0, 200), (2, 140.0, 200), # ANGLES # (2, 85.0, 200), (2, 148.0, 350), (2, 125.0, 200), # (2, 74.0, 200), (2, 98.0, 200)], # [(2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1)], # [(2, 0.0, 500)], # IMPROPERS # [], # VSITES # [(), (), (), (), (), (), (), (), (), (), (), (), (), ()]], # EXCLUSIONS # } # self.base_connectivity = { # "DA": [[(2, 3), (3, 4), (4, 5), # BONDS # (4, 6), (5, 6), (6, 3)], # [(1, 2, 3), (2, 3, 4), (2, 3, 6), # ANGLES # (3, 4, 5), (3, 2, 7), (4, 3, 6), # (4, 5, 6), (5, 6, 3)], # [(0, 1, 2, 3), (0, 2, 3, 4), (0, 2, 3, 6), # DIHEDRALS # (1, 2, 3, 4), (1, 2, 3, 6), (2, 8, 9,10), # (3, 2, 7, 8), (3, 2, 7, 9), (3, 2, 7,10), # (3, 7, 8,10), (3, 8, 9,10), (4, 2, 7, 8), # (7, 2, 3, 4), (7, 2, 3, 6)], # [(3, 4, 5, 6)], # IMPROPERS # [], # VSITES # [(0, 3), (0, 4), (0, 5), # EXCLUSIONS # (0, 6), (1, 3), (1, 4), # (1, 5), (1, 6), (2, 3), # (2, 4), (2, 5), (2, 6), # (3, 5), (4, 6)]], # } # # # CYTOSINE # self.bases.update({ # "DC": [FUNC.spl("TN0 TY2 TY3"), # # TYPE EQUIL OPTS TYPE EQUIL OPTS TYPE EQUIL OPTS # [(1, 0.290, 30000), (1, 0.220, 30000), (1, 0.285, 30000), # BONDS BB3-SC1 bond lenghtened by 0.020 nm. # (1, 0.268, 30000),], # [(2, 93.0, 200), (2, 108.0, 250), (2, 170.0, 350), # ANGLES # (2, 180.0, 1), (2, 62.0, 200), (2, 71.0, 200), # (2, 47.0, 200), (2, 100.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1)], # [(2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1)], # [], # IMPROPERS # [], # VSITES # [(), (), (), (), (), (), (), (), ()]], # EXCLUSIONS # }) # self.base_connectivity.update({ # "DC": [[(2, 3), (3, 4), (4, 5), # BONDS # (5, 3)], # [(1, 2, 3), (2, 3, 4), (2, 3, 5), # ANGLES # (3, 2, 6), (3, 4, 5), (4, 3, 5), # (4, 5, 3), (1, 3, 5), (1, 5, 3), # (2, 3, 6), (2, 1, 3), (2, 1, 5)], # [(0, 1, 2, 3), (0, 2, 3, 4), (0, 2, 3, 5), # DIHEDRALS # (1, 2, 3, 4), (1, 2, 3, 5), (2, 7, 8, 9), # (3, 2, 6, 7), (3, 2, 6, 8), (3, 2, 6, 9), # (3, 6, 7, 9), (3, 7, 8, 9), (4, 2, 6, 7), # (6, 2, 3, 4), (6, 2, 3, 5), (2, 1, 3, 5), # (2, 1, 5, 3)], # [], # IMPROPERS # [], # VSITES # [(0, 3), (0, 4), (0, 5), # EXCLUSIONS # (1, 3), (1, 4), (1, 5), # (2, 3), (2, 4), (2, 5)]], # }) # # # GUANINE # self.bases.update({ # "DG": [FUNC.spl("TN0 TG2 TG3 TNa"), # # TYPE EQUIL OPTS TYPE EQUIL OPTS TYPE EQUIL OPTS # [(1, 0.300, 30000), (1, 0.295, 30000), (1, 0.295, 30000), # BONDS BB3-SC1 bond stays the same. # (1, 0.390, 30000), (1, 0.285, 30000), (1, 0.161, 30000),], # [(2, 95.0, 250), (2, 137.0, 300), (2, 128.0, 250), # ANGLES # (2, 69.0, 200), (2, 145.0, 350), (2, 125.0, 200), # (2, 84.0, 200), (2, 94.0, 200)], # [(2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1)], # [(2, 0.0, 150)], # IMPROPERS # [], # VSITES # [(), (), (), (), (), (), (), (), (), (), (), (), (), ()]], # EXCLUSIONS # }) # self.base_connectivity.update({ # "DG": [[(2, 3), (3, 4), (4, 5), # BONDS # (4, 6), (5, 6), (6, 3)], # [(1, 2, 3), (2, 3, 4), (2, 3, 6), # ANGLES # (3, 4, 5), (3, 2, 7), (4, 3, 6), # (4, 5, 6), (5, 6, 3)], # [(0, 1, 2, 3), (0, 2, 3, 4), (0, 2, 3, 6), # DIHEDRALS # (1, 2, 3, 4), (1, 2, 3, 6), (2, 8, 9,10), # (3, 2, 7, 8), (3, 2, 7, 9), (3, 2, 7,10), # (3, 7, 8,10), (3, 8, 9,10), (4, 2, 7, 8), # (7, 2, 3, 4), (7, 2, 3, 6)], # [(3, 4, 5, 6)], # IMPROPERS # [], # VSITES # [(0, 3), (0, 4), (0, 5), # EXCLUSIONS # (0, 6), (1, 3), (1, 4), # (1, 5), (1, 6), (2, 3), # (2, 4), (2, 5), (2, 6), # (3, 5), (4, 6)]], # }) # # # THYMINE # self.bases.update({ # "DT": [FUNC.spl("TN0 TT2 TT3"), # # TYPE EQUIL OPTS TYPE EQUIL OPTS TYPE EQUIL OPTS # [(1, 0.310, 30000), (1, 0.217, 30000), (1, 0.322, 30000), # BONDS BB3-SC1 bond lengthened by 0.040 nm. # (1, 0.265, 30000),], # [(2, 93.0, 250), (2, 108.0, 350), (2, 165.0, 550), # ANGLES # (2, 165.0, 400), (2, 55.0, 200), (2, 83.0, 200), # (2, 42.0, 200), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1)], # [(2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1), # (2, 0.0, 1), (2, 0.0, 1), (2, 0.0, 1)], # [], # IMPROPERS # [], # VSITES # [(), (), (), (), (), (), (), (), ()]], # EXCLUSIONS # }) # self.base_connectivity.update({ # "DT": [[(2, 3), (3, 4), (4, 5), # BONDS # (5, 3)], # [(1, 2, 3), (2, 3, 4), (2, 3, 5), # ANGLES # (3, 2, 6), (3, 4, 5), (4, 3, 5), # (4, 5, 3), (2, 3, 6), (1, 3, 5), # (2, 1, 3), (2, 1, 5)], # [(0, 1, 2, 3), (0, 2, 3, 4), (0, 2, 3, 5), # DIHEDRALS # (1, 2, 3, 4), (1, 2, 3, 5), (2, 7, 8, 9), # (3, 2, 6, 7), (3, 2, 6, 8), (3, 2, 6, 9), # (3, 6, 7, 9), (3, 7, 8, 9), (4, 2, 6, 7), # (6, 2, 3, 4), (6, 2, 3, 5), (2, 1, 3, 5)], # [], # IMPROPERS # [], # VSITES # [(0, 3), (0, 4), (0, 5), # EXCLUSIONS # (1, 3), (1, 4), (1, 5), # (2, 3), (2, 4), (2, 5)]], # }) #----+----------------+ ## D | SPECIAL BONDS | #----+----------------+ self.special = { # Used for sulfur bridges # ATOM 1 ATOM 2 BOND LENGTH FORCE CONSTANT (("SC1","CYS"), ("SC1","CYS")): (0.39, 5000), } # By default use an elastic network self.ElasticNetwork = False # Elastic networks bond shouldn't lead to exclusions (type 6) # But Elnedyn has been parametrized with type 1. self.EBondType = 6 #----+----------------+ ## D | INTERNAL STUFF | #----+----------------+ ## BACKBONE BEAD TYPE ## # Dictionary of default bead types (*D) self.bbBeadDictD = FUNC.hash(SS.bbss,self.bbdef) # Dictionary of dictionaries of types for specific residues (*S) self.bbBeadDictS = dict([(i,FUNC.hash(SS.bbss,self.bbtyp[i])) for i in self.bbtyp.keys()]) # combine the connectivity records for different molecule types self.connectivity = dict(self.base_connectivity.items() + self.aa_connectivity.items()) # XXX No need to do that, let's just use separate for DNA for now ## BB BOND TYPE ## # Dictionary of default abond types (*D) self.bbBondDictD = FUNC.hash(SS.bbss,zip(self.bbldef,self.bbkb)) # Dictionary of dictionaries for specific types (*S) self.bbBondDictS = dict([(i,FUNC.hash(SS.bbss,zip(self.bbltyp[i],self.bbkbtyp[i]))) for i in self.bbltyp.keys()]) # This is tricky to read, but it gives the right bondlength/force constant ## BBB ANGLE TYPE ## # Dictionary of default angle types (*D) self.bbAngleDictD = FUNC.hash(SS.bbss,zip(self.bbadef,self.bbka)) # Dictionary of dictionaries for specific types (*S) self.bbAngleDictS = dict([(i,FUNC.hash(SS.bbss,zip(self.bbatyp[i],self.bbkatyp[i]))) for i in self.bbatyp.keys()]) ## BBBB DIHEDRAL TYPE ## # Dictionary of default dihedral types (*D) self.bbDihedDictD = FUNC.hash(SS.bbss,zip(self.bbddef,self.bbkd,self.bbdmul)) # Dictionary of dictionaries for specific types (*S) self.bbDihedDictS = dict([(i,FUNC.hash(SS.bbss,zip(self.bbdtyp[i],self.bbkdtyp[i]))) for i in self.bbdtyp.keys()]) ## DNA DICTIONARIES ## # Dictionary for the connectivities and parameters of bonds between DNA backbone beads self.dnaBbBondDictC = dict(zip(self.dna_con['bond'],self.dna_bb['bond'])) # Dictionary for the connectivities and parameters of angles between DNA backbone beads self.dnaBbAngleDictC = dict(zip(self.dna_con['angle'],self.dna_bb['angle'])) # Dictionary for the connectivities and parameters of dihedrals between DNA backbone beads self.dnaBbDihDictC = dict(zip(self.dna_con['dih'],self.dna_bb['dih'])) # Dictionary for exclusions for DNA backbone beads self.dnaBbExclDictC = dict(zip(self.dna_con['excl'],self.dna_bb['excl'])) # Dictionary for pairs for DNA backbone beads self.dnaBbPairDictC = dict(zip(self.dna_con['pair'],self.dna_bb['pair'])) ## RNA DICTIONARIES ## # Dictionary for the connectivities and parameters of bonds between RNA backbone beads self.rnaBbBondDictC = dict(zip(self.rna_con['bond'],self.rna_bb['bond'])) # Dictionary for the connectivities and parameters of angles between rna backbone beads self.rnaBbAngleDictC = dict(zip(self.rna_con['angle'],self.rna_bb['angle'])) # Dictionary for the connectivities and parameters of dihedrals between rna backbone beads self.rnaBbDihDictC = dict(zip(self.rna_con['dih'],self.rna_bb['dih'])) # Dictionary for exclusions for RNA backbone beads self.rnaBbExclDictC = dict(zip(self.rna_con['excl'],self.rna_bb['excl']))
def __init__(self): import SS,FUNC,IO # parameters are defined here for the following (protein) forcefields: self.name = 'martini22p' # Charged types: self.charges = {"Qd":1, "Qa":-1, "SQd":1, "SQa":-1, "RQd":1, "AQa":-1} #@# #----+---------------------+ ## A | BACKBONE PARAMETERS | #----+---------------------+ # # bbss lists the one letter secondary structure code # bbdef lists the corresponding default backbone beads # bbtyp lists the corresponding residue specific backbone beads # # bbd lists the structure specific backbone bond lengths # bbkb lists the corresponding bond force constants # # bba lists the structure specific angles # bbka lists the corresponding angle force constants # # bbd lists the structure specific dihedral angles # bbkd lists the corresponding force constants # # -=NOTE=- # if the secondary structure types differ between bonded atoms # the bond is assigned the lowest corresponding force constant # # -=NOTE=- # if proline is anywhere in the helix, the BBB angle changes for # all residues # ############################################################################################### ## BEADS ## # # F E H 1 2 3 T S C # SS one letter self.bbdef = FUNC.spl(" N0 Nda N0 Nd Na Nda Nda P5 P5") # Default beads #@# self.bbtyp = { # #@# "ALA": FUNC.spl(" C5 N0 C5 N0 N0 N0 N0 P4 P4"), # ALA specific #@# "PRO": FUNC.spl(" C5 N0 C5 N0 Na N0 N0 P4 P4"), # PRO specific #@# "HYP": FUNC.spl(" C5 N0 C5 N0 N0 N0 N0 P4 P4") # HYP specific #@# } # #@# ## BONDS ## # self.bbldef = (.365, .350, .310, .310, .310, .310, .350, .350, .350) # BB bond lengths #@# self.bbkb = (1250, 1250, None, None, None, None, 1250, 1250, 1250) # BB bond kB #@# self.bbltyp = {} # #@# self.bbkbtyp = {} # #@# ## ANGLES ## # self.bbadef = ( 119.2,134, 96, 96, 96, 96, 100, 130, 127) # BBB angles #@# self.bbka = ( 150, 25, 700, 700, 700, 700, 25, 25, 25) # BBB angle kB #@# self.bbatyp = { # #@# "PRO": ( 119.2,134, 98, 98, 98, 98, 100, 130, 127), # PRO specific #@# "HYP": ( 119.2,134, 98, 98, 98, 98, 100, 130, 127) # PRO specific #@# } # #@# self.bbkatyp = { # #@# "PRO": ( 150, 25, 100, 100, 100, 100, 25, 25, 25), # PRO specific #@# "HYP": ( 150, 25, 100, 100, 100, 100, 25, 25, 25) # PRO specific #@# } # #@# ## DIHEDRALS ## # self.bbddef = ( 90.7, 0, -120, -120, -120, -120) # BBBB dihedrals #@# self.bbkd = ( 100, 10, 400, 400, 400, 400) # BBBB kB #@# self.bbdmul = ( 1, 1, 1, 1, 1, 1) # BBBB mltplcty #@# self.bbdtyp = {} # #@# self.bbkdtyp = {} # #@# # ############################################################################################### # Some Forcefields use the Ca position to position the BB-bead (me like!) # martini 2.1 doesn't self.ca2bb = False # BBS angle, equal for all ss types # Connects BB(i-1),BB(i),SC(i), except for first residue: BB(i+1),BB(i),SC(i) # ANGLE Ka self.bbsangle = [ 100, 25] #@# # Bonds for extended structures (more stable than using dihedrals) # LENGTH FORCE self.ebonds = { #@# 'short': [ .640, 2500], #@# 'long' : [ .970, 2500] #@# } #@# #----+-----------------------+ ## B | SIDE CHAIN PARAMETERS | #----+-----------------------+ # To be compatible with Elnedyn, all parameters are explicitly defined, even if they are double. self.sidechains = { #RES# BEADS BONDS ANGLES DIHEDRALS V-SITES # BB-SC SC-SC BB-SC-SC SC-SC-SC "TRP": [FUNC.spl("SC4 SNd SC5 SC5"),[(0.300,5000)]+[(0.270,None) for i in range(5)], [(210,50),(90,50),(90,50)], [(0,50),(0,200)]], "TYR": [FUNC.spl("SC4 SC4 SP1"), [(0.320,5000), (0.270,None), (0.270,None),(0.270,None)], [(150,50),(150,50)], [(0,50)]], "PHE": [FUNC.spl("SC5 SC5 SC5"), [(0.310,7500), (0.270,None), (0.270,None),(0.270,None)], [(150,50),(150,50)], [(0,50)]], "HIS": [FUNC.spl("SC4 SP1 SP1"), [(0.320,7500), (0.270,None), (0.270,None),(0.270,None)], [(150,50),(150,50)], [(0,50)]], "HIH": [FUNC.spl("SC4 SP1 SQd D"), [(0.320,7500), (0.270,None), (0.270,None),(0.270,None),(0.11,None)],[(150,50),(150,50)], [(0,50)]], "GLN": [FUNC.spl("Nda D D"), [(0.400,5000), (0.280,None)], [], [], [(0.5,)]], "ASN": [FUNC.spl("Nda D D"), [(0.320,5000), (0.280,None)], [], [], [(0.5,)]], "SER": [FUNC.spl("N0 D D"), [(0.250,7500), (0.280,None)], [], [], [(0.5,)]], "THR": [FUNC.spl("N0 D D"), [(0.260,9000), (0.280,None)], [], [], [(0.5,)]], "ARG": [FUNC.spl("N0 Qd D"), [(0.330,5000), (0.340,5000), (0.110,None)], [(180,25)]], "LYS": [FUNC.spl("C3 Qd D"), [(0.330,5000), (0.280,5000), (0.110,None)], [(180,25)]], "ASP": [FUNC.spl("Qa D"), [(0.320,7500), (0.110,None)]], "GLU": [FUNC.spl("Qa D"), [(0.400,5000), (0.110,None)]], "CYS": [FUNC.spl("C5"), [(0.310,7500)]], "ILE": [FUNC.spl("C1"), [(0.310,None)]], "LEU": [FUNC.spl("C1"), [(0.330,7500)]], "MET": [FUNC.spl("C5"), [(0.400,2500)]], "PRO": [FUNC.spl("C3"), [(0.300,7500)]], "HYP": [FUNC.spl("P1"), [(0.300,7500)]], "VAL": [FUNC.spl("C2"), [(0.265,None)]], "ALA": [], "GLY": [], } # Not all (eg Elnedyn) forcefields use backbone-backbone-sidechain angles and BBBB-dihedrals. self.UseBBSAngles = True self.UseBBBBDihedrals = True # Martini 2.2p has polar and charged residues with seperate charges. self.polar = ["GLN","ASN","SER","THR"] self.charged = ["ARG","LYS","ASP","GLU","HIH"] # If masses or charged diverge from standard (45/72 and -/+1) they are defined here. self.mass_charge = { #RES MASS CHARGE "GLN":[[0,36,36], [0,0.42,-0.42]], "ASN":[[0,36,36], [0,0.46,-0.46]], "SER":[[0,36,36], [0,0.40,-0.40]], "THR":[[0,36,36], [0,0.36,-0.36]], "ARG":[[72,36,36], [0,0,1]], "LYS":[[72,36,36], [0,0,1]], "HIH":[[45,45,36,36], [0,0,0,1]], "ASP":[[36,36], [0,-1]], "GLU":[[36,36], [0,-1]], } self.connectivity = { #RES BONDS ANGLES DIHEDRALS V-SITE "TRP": [[(0,1),(1,2),(1,3),(2,3),(2,4),(3,4)], [(0,1,2),(0,1,3)], [(0,2,3,1),(1,2,4,3)]], "TYR": [[(0,1),(1,2),(1,3),(2,3)], [(0,1,2),(0,1,3)], [(0,2,3,1)]], "PHE": [[(0,1),(1,2),(1,3),(2,3)], [(0,1,2),(0,1,3)], [(0,2,3,1)]], "HIS": [[(0,1),(1,2),(1,3),(2,3)], [(0,1,2),(0,1,3)], [(0,2,3,1)]], "HIH": [[(0,1),(1,2),(1,3),(2,3),(3,4)], [(0,1,2),(0,1,3)], [(0,2,3,1)]], "GLN": [[(0,1),(2,3)], [], [], [(1,2,3)]], "ASN": [[(0,1),(2,3)], [], [], [(1,2,3)]], "SER": [[(0,1),(2,3)], [], [], [(1,2,3)]], "THR": [[(0,1),(2,3)], [], [], [(1,2,3)]], "ARG": [[(0,1),(1,2),(2,3)], [(0,1,2)]], "LYS": [[(0,1),(1,2),(2,3)], [(0,1,2)]], "ASP": [[(0,1),(1,2)]], "GLU": [[(0,1),(1,2)]], "CYS": [[(0,1)]], "ILE": [[(0,1)]], "LEU": [[(0,1)]], "MET": [[(0,1)]], "PRO": [[(0,1)]], "HYP": [[(0,1)]], "VAL": [[(0,1)]], "ALA": [], "GLY": [], } #----+----------------+ ## C | SPECIAL BONDS | #----+----------------+ self.special = { # Used for sulfur bridges # ATOM 1 ATOM 2 BOND LENGTH FORCE CONSTANT (("SC1","CYS"), ("SC1","CYS")): (0.24, None), } # By default use an elastic network self.ElasticNetwork = False # Elastic networks bond shouldn't lead to exclusions (type 6) # But Elnedyn has been parametrized with type 1. self.EBondType = 6 #----+----------------+ ## D | INTERNAL STUFF | #----+----------------+ ## BACKBONE BEAD TYPE ## # Dictionary of default bead types (*D) self.bbBeadDictD = FUNC.hash(SS.bbss,self.bbdef) # Dictionary of dictionaries of types for specific residues (*S) self.bbBeadDictS = dict([(i,FUNC.hash(SS.bbss,self.bbtyp[i])) for i in self.bbtyp.keys()]) ## BB BOND TYPE ## # Dictionary of default abond types (*D) self.bbBondDictD = FUNC.hash(SS.bbss,zip(self.bbldef,self.bbkb)) # Dictionary of dictionaries for specific types (*S) self.bbBondDictS = dict([(i,FUNC.hash(SS.bbss,zip(self.bbltyp[i],self.bbkbtyp[i]))) for i in self.bbltyp.keys()]) # This is tricky to read, but it gives the right bondlength/force constant ## BBB ANGLE TYPE ## # Dictionary of default angle types (*D) self.bbAngleDictD = FUNC.hash(SS.bbss,zip(self.bbadef,self.bbka)) # Dictionary of dictionaries for specific types (*S) self.bbAngleDictS = dict([(i,FUNC.hash(SS.bbss,zip(self.bbatyp[i],self.bbkatyp[i]))) for i in self.bbatyp.keys()]) ## BBBB DIHEDRAL TYPE ## # Dictionary of default dihedral types (*D) self.bbDihedDictD = FUNC.hash(SS.bbss,zip(self.bbddef,self.bbkd,self.bbdmul)) # Dictionary of dictionaries for specific types (*S) self.bbDihedDictS = dict([(i,FUNC.hash(SS.bbss,zip(self.bbdtyp[i],self.bbkdtyp[i]))) for i in self.bbdtyp.keys()])