DarwinCode DarwinCode - 5 months ago 34
Python Question

How to write String template file with multiple loop elements?

I have small issue in writing for loop elements in string template as follows: when I try to make a string templete from three loop elements I can able to print only the last element not the first two elements. I beleive that the error is because of some issues in writing file but I couldnt get what is the actual problem is with my code. So If some one could you kindly help me with this.

My SCRIPT:

from string import Template
import os

AMONIOACIDS = {'A': 'ALA', 'C': 'CYS', 'E': 'GLU', 'D': 'ASP', 'G': 'GLY',
'F': 'PHE', 'I': 'ILE', 'H': 'HIS', 'K': 'LYS', 'M': 'MET',
'L': 'LEU', 'N': 'ASN', 'Q': 'GLN', 'P': 'PRO', 'S': 'SER',
'R': 'ARG', 'T': 'THR', 'W': 'TRP', 'V': 'VAL', 'Y': 'TYR'}

rPrS={'C': '102', 'A': '104','H': '12'}


a=[]
b=[]
count=1
for single, third in AMONIOACIDS.iteritems():
for rS,rP in rPrS.iteritems():
if rS == single:
a.append(["s"+str(count)+"=selection(mdl1.chains["+chain+"].residues["+rP+"])"])
b.append(["s"+str(count)+".mutate(residue_type='"+third+"')"])


str='''Loop elements\n'''
for i,j in zip (a,b):
i=''.join(i)
j=''.join(j)
str+='''$i\n'''
str+='''$j\n'''
str=Template(str)
str.substitute(i=i, j=j)
file = open(os.getcwd() + '/' + 'model.py', 'w')
file.write(str.substitute(i=i,j=j))
file.close()


Expected ouput:

Loop elements
s1=selection(mdl1.chains[A].residues[104])
s1.mutate(residue_type='ALA')
s2=selection(mdl1.chains[A].residues[102])
s2.mutate(residue_type='CYS')
s3=selection(mdl1.chains[A].residues[12])
s3.mutate(residue_type='HIS')


What I am getting :

Loop elements
s3=selection(mdl1.chains[A].residues[12])
s3.mutate(residue_type='HIS')
s3=selection(mdl1.chains[A].residues[12])
s3.mutate(residue_type='HIS')
s3=selection(mdl1.chains[A].residues[12])
s3.mutate(residue_type='HIS')

Answer

Your template is getting its substitution values from the last values of i and j from the for loop. You need to persist values from the previous iteration. How? You could use a dictionary and a count to store and distinguish values at each iteration.

You can substitute values in a template using a dictionary. I have used the count variable to create corresponding dictionary keys at each iteration: i_0, i_1, i_2, and j_0, j_1, j_2. These same names are used as identifiers in the template $i_0, $i_1, $i_2, and $j_0, $j_1, $j_2.

safe_substitute safely substitutes the value at each key into the template e.g key i_0 to the template identifier $i_0.


The dictionary stores all values of i and j at each iteration, and the substitution in your template is done taking the appropriate values at each key in the dictionary. This part should fix it:

# your previous lines of code

count = 0
d = {}
s='''Loop elements\n'''
for i,j in zip (a,b):
    d['i_{}'.format(count)] = ''.join(i)
    d['j_{}'.format(count)] = ''.join(j)
    s+='$i_{}\n'.format(count)
    s+='$j_{}\n'.format(count)
    count += 1

print(str)
print(d)
s=Template(s)
file = open(os.getcwd() + '/' + 'model.py', 'w')
file.write(s.safe_substitute(d))
file.close()

I have replaced the name str with s to avoid shadowing the builtin str. No other changes are required in the preceding code blocks before the fix.