Beispiel #1
0
def unPause():
    global paused

    if paused:
        f.runInParallel([[calculatePi, ()]])
        f.runInParallel([[renderPi, ()]])

    paused = False
Beispiel #2
0
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
Beispiel #3
0
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
Beispiel #4
0
	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
Beispiel #5
0
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
Beispiel #6
0
 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)
Beispiel #7
0
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,
        )
Beispiel #9
0
    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'))
Beispiel #10
0
 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
Beispiel #11
0
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)
Beispiel #12
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
Beispiel #13
0
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
Beispiel #14
0
 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)
Beispiel #15
0
 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 )
Beispiel #16
0
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)
Beispiel #17
0
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
Beispiel #18
0
 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)
Beispiel #19
0
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
Beispiel #20
0
 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)
Beispiel #21
0
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
Beispiel #22
0
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
Beispiel #23
0
# 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        #@#
Beispiel #24
0
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'] = \
Beispiel #25
0
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)
Beispiel #26
0
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"
Beispiel #27
0
    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()
        ])
Beispiel #28
0
 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)
Beispiel #29
0
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"
Beispiel #30
0
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
Beispiel #31
0
# 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":
Beispiel #32
0
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]
Beispiel #33
0
def residueDistance2(r1, r2):
    return min([FUNC.distance2(i, j) for i in r1 for j in r2])
Beispiel #34
0
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 结束')
Beispiel #35
0
##########################
## 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 ]
    )
Beispiel #36
0
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)
Beispiel #37
0
    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()])      
Beispiel #38
0
##########################
## 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()])      
Beispiel #41
0
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}
Beispiel #42
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()])