Difference between revisions of "Recycling Corner/DNA Generator"
(lc all functions) |
(Support multiple frames) |
||
| Line 5: | Line 5: | ||
The message is a string entered by the user at a prompt. | The message is a string entered by the user at a prompt. | ||
It may be typed in or pasted in and be of any length. | It may be typed in or pasted in and be of any length. | ||
| + | If the first character is '+' then the polynucleotide is created in a new frame. | ||
If prepended with '3' then the string is considered as 3' to 5'. | If prepended with '3' then the string is considered as 3' to 5'. | ||
If prepended with 'R' then RNA is generated instead of DNA. | If prepended with 'R' then RNA is generated instead of DNA. | ||
| Line 11: | Line 12: | ||
Multiple prepends are allowed (though 'M' would be inconsistent with 'R' or 'S'). | Multiple prepends are allowed (though 'M' would be inconsistent with 'R' or 'S'). | ||
| − | If the 3d character is ':' then the two chains are labeled by the two preceding characters instead of the default 'A' and 'B'. Likewise if the 2d character is ':' then the presumably single chain is labeled by the preceding single character. | + | If the 3d character is ':' (4th if the first is '+') then the two chains are labeled by the two preceding characters instead of the default 'A' and 'B'. Likewise if the 2d character is ':' then the presumably single chain is labeled by the preceding single character. |
| − | A | + | ''With this script you can generate a polynucleotide helix chain from a sequence string in 1-char NT coding. You can optionally give it chain labels other than the default :A :B. You can also add to an existing chain(s), add new chains to an existing model or now create the chain(s) in a new frame by prepending a '+' to the sequence string.'' |
| + | |||
| + | ''Chains start from the origin and extend along the -X+Y+Z axis as they are built. If a chain with the same chain label as the new chain is at the origin, the new sequence is added to the old. If a chain with a different chain label is at the origin, all existing chains are shifted 20 angstroms to the left along the YZ axis until the origin is clear.'' | ||
| + | |||
| + | ''Note that a single chain helix could then be added to a double chain or RNA to DNA or whatever. Have fun...'' | ||
The IUPAC/IUBMB 1 letter code is used: A=Adenine C=Cytosine G=Guanine T=Thymine U=Uracil | The IUPAC/IUBMB 1 letter code is used: A=Adenine C=Cytosine G=Guanine T=Thymine U=Uracil | ||
| Line 27: | Line 32: | ||
<pre># POLYMERAZE - Jmol script by Ron Mignery | <pre># POLYMERAZE - Jmol script by Ron Mignery | ||
| − | # v1. | + | # v1.10 beta 7/11/2014 -add multi-frame support |
# | # | ||
# POLYMERAZE takes a string message encoding a nucleotide (nt) sequence | # POLYMERAZE takes a string message encoding a nucleotide (nt) sequence | ||
| Line 33: | Line 38: | ||
# 5' terminus to the 3' terminus rotating the emerging helix as it goes. | # 5' terminus to the 3' terminus rotating the emerging helix as it goes. | ||
# | # | ||
| − | # The resulting polynucleotide defaults to an open B-form. If the script "to_ab_nt" | + | # The resulting polynucleotide defaults to an open B-form. If double-stranded |
| − | + | # and the script "to_ab_nt" is available, it prompts to converts to a regular | |
| − | + | # B-form if DNA or to a regular A-form if RNA or mixed. | |
# | # | ||
# The message is a string entered by the user at a prompt. | # The message is a string entered by the user at a prompt. | ||
# It may be typed in or pasted in and be of any length | # It may be typed in or pasted in and be of any length | ||
| + | # If the 1st character is '+' then the chain is created in a new frame. | ||
# If prepended with '3' then the string is considered as 3' to 5' | # If prepended with '3' then the string is considered as 3' to 5' | ||
# If prepended with 'R' then RNA is generated instead of DNA (Ts convert to Us) | # If prepended with 'R' then RNA is generated instead of DNA (Ts convert to Us) | ||
| Line 46: | Line 52: | ||
# though 'M' is inconsistent with 'R' or 'S' | # though 'M' is inconsistent with 'R' or 'S' | ||
# | # | ||
| − | # If the 3d character is ':' then the two chains are labeled | + | # If the 3d (4th if 1st is '+') character is ':' then the two chains are labeled |
| − | # two preceding characters instead of the default 'A' and 'B' | + | # by the two preceding characters instead of the default 'A' and 'B' |
# Likewise if the 2d character is ':' then the presumably single chain is | # Likewise if the 2d character is ':' then the presumably single chain is | ||
# labeled by the single preceding character | # labeled by the single preceding character | ||
| Line 67: | Line 73: | ||
gA = "" | gA = "" | ||
gSeq = "" | gSeq = "" | ||
| + | gAppendNew = FALSE | ||
| + | gNewFrame = FALSE | ||
# Lookup 3 letter code from 1 letter code | # Lookup 3 letter code from 1 letter code | ||
| Line 225: | Line 233: | ||
# Rotate a1 on a2 in the plane of a1, a2 and a3 to the given angle | # Rotate a1 on a2 in the plane of a1, a2 and a3 to the given angle | ||
# a1 and all connected except by a2 must be selected | # a1 and all connected except by a2 must be selected | ||
| − | function | + | function set_angle_no (a1no, a2no, a3no, toangle) { |
| − | var | + | var f = (_frameID/1000000) |
| − | + | var m = (_frameID%100000) | |
| − | var | + | var c = gChain1 |
| − | + | var a1 = {(atomno=a1no) and (chain=c) and (file=f) and (model=m)} | |
| − | var axis = cross(v1, v2) + | + | var a2 = {(atomno=a2no) and (chain=c) and (file=f) and (model=m)} |
| − | var curangle = angle( | + | var a3 = {(atomno=a3no) and (chain=c) and (file=f) and (model=m)} |
| − | + | var v1 = (a1.xyz - a2.xyz) | |
| − | rotateselected @axis | + | var v2 = (a3.xyz - a2.xyz) |
| + | var axis = cross(v1, v2) + a2.xyz | ||
| + | var curangle = angle(a1, a2, a3) | ||
| + | rotateselected @axis @a2 @{curangle-toangle} | ||
} | } | ||
| Line 239: | Line 250: | ||
# a1 (or a4) and all connected except by a2 (or a3) must be selected | # a1 (or a4) and all connected except by a2 (or a3) must be selected | ||
# If selected < unselected ==> a2 < a3 and vice versa | # If selected < unselected ==> a2 < a3 and vice versa | ||
| − | function | + | function set_dihedral_no (a1no, a2no, a3no, a4no, toangle) { |
| − | var | + | var f = (_frameID/1000000) |
| − | + | var m = (_frameID%100000) | |
| − | + | var c = gChain1 | |
| − | + | var a1 = {(atomno=a1no) and (chain=c) and (file=f) and (model=m)} | |
| + | var a2 = {(atomno=a2no) and (chain=c) and (file=f) and (model=m)} | ||
| + | var a3 = {(atomno=a3no) and (chain=c) and (file=f) and (model=m)} | ||
| + | var a4 = {(atomno=a4no) and (chain=c) and (file=f) and (model=m)} | ||
| + | var curangle = angle(a1, a2, a3, a4) | ||
| + | rotateselected @a2 @a3 @{toangle-curangle} | ||
} | } | ||
| Line 257: | Line 273: | ||
# Generate a helix | # Generate a helix | ||
function gen_helix_strand(reverse, drm, double) { | function gen_helix_strand(reverse, drm, double) { | ||
| + | var f = (_frameID/1000000) | ||
| + | var m = (_frameID%100000) | ||
var cha = ":" + gChain1 | var cha = ":" + gChain1 | ||
var chb = ":" + gChain2 | var chb = ":" + gChain2 | ||
| Line 285: | Line 303: | ||
} | } | ||
| − | |||
var aResno = 1 | var aResno = 1 | ||
var pNa = 1 # previous gNa | var pNa = 1 # previous gNa | ||
| − | |||
| − | + | gAppendNew = appendNew | |
| − | + | if (gNewFrame) { | |
| − | + | appendNew = TRUE | |
| + | } | ||
| + | else { | ||
| + | appendNew = FALSE | ||
| − | + | # Get the largest atomno in frame | |
| − | + | gNa = {(file=f) and (model=m)}.atomno.max + 1 | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | # Bump up all B chain atomno and resno | + | # While there is an atom at the origin |
| − | + | while (m > 0) { | |
| − | + | var ai = {within(0.1, {0 0 0}) and (file=f) and (model=m)} | |
| − | + | if (ai.size > 0) { | |
| − | + | ||
| − | + | # If on the same chain | |
| − | + | if (ai[1].chain = gChain1) { | |
| − | + | ||
| − | + | # Add to existing strand | |
| − | + | echo "Adding to existing strand..." | |
| + | pNa = ai.atomno | ||
| + | aResno = {(chain=gChain1) and (file=f) | ||
| + | and (model=m)}.resno.max + 1 | ||
| + | gNa = {(chain=gChain1) and (file=f) | ||
| + | and (model=m)}.atomno.max + 1 | ||
| + | gNb += gNa | ||
| + | |||
| + | # Bump up all B chain atomno and resno | ||
| + | savNb = gNb | ||
| + | gNb = aAtomCount + bAtomCount + gNa | ||
| + | gA = "data \"append nt\"\n" # global PDB atom record | ||
| + | for (j = 1; j <= all.atomno.max; j++) { | ||
| + | var aj = {(atomno=j) and (file=f) and (model=m) | ||
| + | and (chain == gChain2)} | ||
| + | if (aj.size > 0) { | ||
| + | gA += gen_atom(aj.atomName, aj.group, | ||
| + | (aj.resno+seq.count+cSeq.count), | ||
| + | array(aj.x, aj.y, aj.z), true) | ||
| + | } | ||
} | } | ||
| + | gA += "end \"append nt\"" | ||
| + | delete @chb | ||
| + | script inline @{gA} # <== new atoms added here | ||
| + | gNb = savNb | ||
| + | break; | ||
| + | } | ||
| + | # Else move all from the new chain rightward on X axis | ||
| + | else { | ||
| + | select {(file=f) and (model=m) and (chain!=gChain1) | ||
| + | and (chain!=gChain2)} | ||
| + | translateselected {0, -20, -20 } | ||
} | } | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | } | + | else { |
| + | break | ||
| + | } | ||
| + | } # endwhile | ||
} | } | ||
| − | |||
var bResno = aResno + seq.count + cSeq.count - 1 | var bResno = aResno + seq.count + cSeq.count - 1 | ||
| Line 328: | Line 370: | ||
# For each NT | # For each NT | ||
| − | |||
for (var i = 1; i <= seq.count; i++) { | for (var i = 1; i <= seq.count; i++) { | ||
| Line 338: | Line 379: | ||
var pO3 = { -0.759, 0.925, 1.048} | var pO3 = { -0.759, 0.925, 1.048} | ||
if (double) { | if (double) { | ||
| − | select (@cha or @chb) | + | select ((@cha or @chb) and (file=f) and (model=m)) |
} | } | ||
else { | else { | ||
| − | select (@cha) | + | select (@cha and (file=f) and (model=m)) |
} | } | ||
if ((i + aResno) > 2) { | if ((i + aResno) > 2) { | ||
| − | var nO3 = {@cha and (atomno=@{pNa+8})}.xyz | + | var nO3 = {@cha and (atomno=@{pNa+8}) |
| + | and (file=f) and (model=m)}.xyz | ||
var xyz = @{pO3 - nO3} | var xyz = @{pO3 - nO3} | ||
translateselected @xyz | translateselected @xyz | ||
| Line 362: | Line 404: | ||
gA += "end \"append nt\"" | gA += "end \"append nt\"" | ||
script inline @{gA} # <== new atoms added here | script inline @{gA} # <== new atoms added here | ||
| + | |||
| + | f = (_frameID/1000000) | ||
| + | m = (_frameID%100000) | ||
| + | appendNew = FALSE | ||
# Flip comp to comp strand | # Flip comp to comp strand | ||
if (double) { | if (double) { | ||
| − | select @{"" + bResno + chb} | + | select @{("" + bResno + chb + "/" + f + "." + m)} |
var v1={8.238, 2.809, 6.004} | var v1={8.238, 2.809, 6.004} | ||
var v2={8.461, 4.646, 4.125} | var v2={8.461, 4.646, 4.125} | ||
| Line 373: | Line 419: | ||
# If any older NTs | # If any older NTs | ||
if ((i + aResno) > 2) { | if ((i + aResno) > 2) { | ||
| + | |||
# Set the angles between the new NT and the old NTs | # Set the angles between the new NT and the old NTs | ||
| − | select (@cha and (atomno < nNa) or (@chb and (resno != bResno))) | + | select (((@cha and (atomno < nNa)) or (@chb and (resno != bResno))) |
| − | + | and (file=f) and (model=m)) | |
| + | set_angle_no(nNa, pNa+8, pNa+7, 120.0) | ||
| + | select (((@cha and (atomno < @{nNa+3})) | ||
| + | or (@chb and (resno != bResno))) and (file=f) and (model=m)) | ||
| + | set_dihedral_no(nNa+4, nNa+3, nNa, pNa+8, kC5O5PO3) | ||
| − | select (@cha and (atomno < | + | select (((@cha and (atomno < nNa)) or (@chb and (resno != bResno))) |
| − | + | and (file=f) and (model=m)) | |
| + | set_dihedral_no(nNa+3, nNa, pNa+8, pNa+7, kO5PO3C3) | ||
| − | + | set_dihedral_no(nNa, pNa+8, pNa+7, pNa+5, kPO3C3C4) | |
| − | |||
| − | |||
| − | |||
} | } | ||
| Line 396: | Line 445: | ||
# Clean up | # Clean up | ||
| + | appendNew = gAppendNew | ||
select all | select all | ||
refresh | refresh | ||
| − | + | ||
# Convert to A-form if RNA or mixed else B-form | # Convert to A-form if RNA or mixed else B-form | ||
try { | try { | ||
| − | script $SCRIPT_PATH$ | + | script $SCRIPT_PATH$toabNT.spt |
var s = format("Convert to %s-form?", ((drm > 0) ? "A" : "B")) | var s = format("Convert to %s-form?", ((drm > 0) ? "A" : "B")) | ||
var p = prompt(s, "Yes|No", TRUE) | var p = prompt(s, "Yes|No", TRUE) | ||
| Line 432: | Line 482: | ||
print format ("Seq=%s", gSeq) | print format ("Seq=%s", gSeq) | ||
| + | gNewFrame = FALSE | ||
| + | if (gSeq[1] == '+') { | ||
| + | gNewFrame = TRUE | ||
| + | gSeq = gSeq[2][9999] | ||
| + | } | ||
if (gSeq[2] == ':') { | if (gSeq[2] == ':') { | ||
gChain1 = gSeq[1] | gChain1 = gSeq[1] | ||
| Line 463: | Line 518: | ||
} | } | ||
} | } | ||
| − | + | ||
if (drm = 1) { | if (drm = 1) { | ||
gSeq = gSeq.replace('T', 'U') | gSeq = gSeq.replace('T', 'U') | ||
| Line 470: | Line 525: | ||
gSeq = gSeq.replace('U', 'T') | gSeq = gSeq.replace('U', 'T') | ||
} | } | ||
| − | + | ||
# Generate | # Generate | ||
gen_helix_strand(reverse, drm, single ? FALSE : TRUE) | gen_helix_strand(reverse, drm, single ? FALSE : TRUE) | ||
| Line 480: | Line 535: | ||
# Get the sequence from the user | # Get the sequence from the user | ||
| − | var seq = prompt("Enter NT sequence (<3RSM>ACGTU)", "")%9999%0 | + | var seq = prompt("Enter NT sequence (<+AB:3RSM>ACGTU...)", "")%9999%0 |
if ((seq != "NULL") and (seq.count > 0)) { | if ((seq != "NULL") and (seq.count > 0)) { | ||
plico_gen_helix(seq) | plico_gen_helix(seq) | ||
Revision as of 22:45, 11 July 2014
POLYMERAZE takes a string message encoding a nucleotide (nt) sequence and generates a corresponding double helix one nt at a time from the 5' terminus to the 3' terminus rotating the emerging helix as it goes.
The resulting polynucleotide defaults to an open B-form. If the script "to_ab_nt" described here is available, it prompts to converts to a regular B-form if DNA or to a regular A-form if RNA or mixed.
The message is a string entered by the user at a prompt. It may be typed in or pasted in and be of any length. If the first character is '+' then the polynucleotide is created in a new frame. If prepended with '3' then the string is considered as 3' to 5'. If prepended with 'R' then RNA is generated instead of DNA. If prepended with 'S' then a single strand helix is produced. If prepended with 'M' then a mixed helix is produced where the first strand is DNA and the second RNA. Multiple prepends are allowed (though 'M' would be inconsistent with 'R' or 'S').
If the 3d character is ':' (4th if the first is '+') then the two chains are labeled by the two preceding characters instead of the default 'A' and 'B'. Likewise if the 2d character is ':' then the presumably single chain is labeled by the preceding single character.
With this script you can generate a polynucleotide helix chain from a sequence string in 1-char NT coding. You can optionally give it chain labels other than the default :A :B. You can also add to an existing chain(s), add new chains to an existing model or now create the chain(s) in a new frame by prepending a '+' to the sequence string.
Chains start from the origin and extend along the -X+Y+Z axis as they are built. If a chain with the same chain label as the new chain is at the origin, the new sequence is added to the old. If a chain with a different chain label is at the origin, all existing chains are shifted 20 angstroms to the left along the YZ axis until the origin is clear.
Note that a single chain helix could then be added to a double chain or RNA to DNA or whatever. Have fun...
The IUPAC/IUBMB 1 letter code is used: A=Adenine C=Cytosine G=Guanine T=Thymine U=Uracil
The top level function plicoGenNt prompts the user for input.
The top level function plicoGenHelix accepts a string as a parameter.
Polymeraze is a member of the Plico suite of protein folding tools described here. It may be installed and accessed as a macro with the file:
Title=PLICO Generate Polynucleotide Script=script <path to your script folder>/polymeraze.spt;plico_gen_nt
saved as plicoGenNT.macro in your .jmol/macros directory as described in Macro.
# POLYMERAZE - Jmol script by Ron Mignery
# v1.10 beta 7/11/2014 -add multi-frame support
#
# POLYMERAZE takes a string message encoding a nucleotide (nt) sequence
# and generates a corresponding double helix one nt at a time from the
# 5' terminus to the 3' terminus rotating the emerging helix as it goes.
#
# The resulting polynucleotide defaults to an open B-form. If double-stranded
# and the script "to_ab_nt" is available, it prompts to converts to a regular
# B-form if DNA or to a regular A-form if RNA or mixed.
#
# The message is a string entered by the user at a prompt.
# It may be typed in or pasted in and be of any length
# If the 1st character is '+' then the chain is created in a new frame.
# If prepended with '3' then the string is considered as 3' to 5'
# If prepended with 'R' then RNA is generated instead of DNA (Ts convert to Us)
# If prepended with 'S' then a single strand helix is produced
# If prepended with 'M' then a mixed helix is produced where the first
# strand is DNA and the second RNA - multiple prepends are allowed
# though 'M' is inconsistent with 'R' or 'S'
#
# If the 3d (4th if 1st is '+') character is ':' then the two chains are labeled
# by the two preceding characters instead of the default 'A' and 'B'
# Likewise if the 2d character is ':' then the presumably single chain is
# labeled by the single preceding character
#
# The IUPAC/IUBMB 1 letter code is used:
# A=Adenine C=Cytosine G=Guanine T=Thymine U=Uracil
# The following constant values determine the pitch of the helices
kC5O5PO3 = -27.0
kO5PO3C3 = -117.8
kPO3C3C4 = -171.9
kO3C3C4C5 = 121
kC3C4C5O5 = 54
kC4C5O5P = 164
kPu = 65
kPy = 52
gChain1 = 'A' # The default chain id
gChain2 = 'B' # The default complementary chain id
gA = ""
gSeq = ""
gAppendNew = FALSE
gNewFrame = FALSE
# Lookup 3 letter code from 1 letter code
kNt3from1 = {"A":" DA", "C":" DC", "G":" DG", "T":" DT", "U":" DU", "D":" DD", "X":" DX"}
kNtComp = {"A":"T", "C":"G", "G":"C", "T":"A", "U":"A", "D":"G", "X":"C"}
# Generate PDB atom record
# Writes gNa or gNb
function gen_atom(atomname, group, resno, xyz, comp) {
# Fixed column format:
#ATOM 500 O4' DA B 29 -3.745 7.211 45.474
while (atomname.size < 3) {
atomname += " ";
}
var a = format("ATOM %5d %4s %3s ", (comp ? gNb : gNa), atomname, group )
a += format("%s%4d %8.3f", (comp ? gChain2 : gChain1), resno, xyz[1] )
a += format("%8.3f%8.3f\n", xyz[2], xyz[3] )
if (comp) gNb++; else gNa++
return a
};
# Generate a PDB nucleotide record set
# Calls gen_atom that writes gNa or gNb
function gen_nt(i, nt, rna, comp) {
# From constructed nucleotides
var P0 = [0.000, 0.000, 0.000]
var OP1= [-0.973,0.363,-1.067]
var OP2= [0.297,-1.428, 0.272]
var O5p= [1.351, 0.795,-0.286]
var C5p= [1.345, 2.211,-0.125]
var C4p= [2.732, 2.786,-0.255]
var O4p= [3.413, 2.900, 1.019]
var C3p= [3.670, 2.020,-1.178]
var O3p= [4.269, 2.960,-2.051]
var C2p= [4.717, 1.445,-0.238]
var O2p= [6.046, 1.365,-0.884]
var C1p= [4.758, 2.505, 0.846]
var N1ct= [5.277, 2.056, 2.143]
var C2ct= [6.236, 2.836, 2.740]
var O2ct= [6.670, 3.853, 2.230]
var N3ct= [6.674, 2.381, 3.958]
var C4ct= [6.256, 1.245, 4.622]
var NO4ct=[6.726, 0.972, 5.728]
var C5ct= [5.255, 0.455, 3.924]
var C6ct= [4.820, 0.900, 2.737]
var nC7ct=[4.762,-0.811, 4.551]
var N9ag= [5.256, 2.091, 2.152]
var C8ag= [4.867, 1.016, 2.913]
var N7ag= [5.532, 0.894, 4.035]
var C5ag= [6.425, 1.959, 4.013]
var C6ag= [7.401, 2.391, 4.922]
var NO6ag=[7.656, 1.780, 6.081]
var N1ag= [8.118, 3.493, 4.599]
var C2ag= [7.865, 4.104, 3.438]
var nN2ag=[8.616, 5.197, 3.181]
var N3ag= [6.968, 3.796, 2.503]
var C4ag= [6.271, 2.701, 2.856]
# Build PDB atom records common to all NTs
var n3 = kNt3from1[nt]
if (n3 = "") {
n3 = " D?"
}
if (rna) {
if (n3 == " DD") {
n3 = " D"
}
else {
n3 = n3.replace('D', ' ')
}
}
var a = gen_atom(" P ", n3, i, P0, comp)
a += gen_atom(" OP1", n3, i, OP1, comp)
a += gen_atom(" OP2", n3, i, OP2, comp)
a += gen_atom(" O5'", n3, i, O5p, comp)
a += gen_atom(" C5'", n3, i, C5p, comp)
a += gen_atom(" C4'", n3, i, C4p, comp)
a += gen_atom(" O4'", n3, i, O4p, comp)
a += gen_atom(" C3'", n3, i, C3p, comp)
a += gen_atom(" O3'", n3, i, O3p, comp)
a += gen_atom(" C2'", n3, i, C2p, comp)
a += gen_atom(" C1'", n3, i, C1p, comp)
if (rna) {
a += gen_atom(" O2'", n3, i, O2p, comp)
}
# Now add NT specific atom records
switch (nt) {
case 'A' :
a += gen_atom(" N9 ", n3, i, N9ag, comp)
a += gen_atom(" C8 ", n3, i, C8ag, comp)
a += gen_atom(" N7 ", n3, i, N7ag, comp)
a += gen_atom(" C5 ", n3, i, C5ag, comp)
a += gen_atom(" C6 ", n3, i, C6ag, comp)
a += gen_atom(" N6 ", n3, i, NO6ag, comp)
a += gen_atom(" N1 ", n3, i, N1ag, comp)
a += gen_atom(" C2 ", n3, i, C2ag, comp)
a += gen_atom(" N3 ", n3, i, N3ag, comp)
a += gen_atom(" C4 ", n3, i, C4ag, comp)
break;
case 'C' :
a += gen_atom(" N1 ", n3, i, N1ct, comp)
a += gen_atom(" C2 ", n3, i, C2ct, comp)
a += gen_atom(" O2 ", n3, i, O2ct, comp)
a += gen_atom(" N3 ", n3, i, N3ct, comp)
a += gen_atom(" C4 ", n3, i, C4ct, comp)
a += gen_atom(" N4 ", n3, i, NO4ct, comp)
a += gen_atom(" C5 ", n3, i, C5ct, comp)
a += gen_atom(" C6 ", n3, i, C6ct, comp)
break;
case 'X' :
case 'G' :
a += gen_atom(" N9 ", n3, i, N9ag, comp)
a += gen_atom(" C8 ", n3, i, C8ag, comp)
a += gen_atom(" N7 ", n3, i, N7ag, comp)
a += gen_atom(" C5 ", n3, i, C5ag, comp)
a += gen_atom(" C6 ", n3, i, C6ag, comp)
a += gen_atom(" O6 ", n3, i, NO6ag, comp)
a += gen_atom(" N1 ", n3, i, N1ag, comp)
a += gen_atom(" C2 ", n3, i, C2ag, comp)
a += gen_atom(" N2 ", n3, i, nN2ag, comp)
a += gen_atom(" N3 ", n3, i, N3ag, comp)
a += gen_atom(" C4 ", n3, i, C4ag, comp)
break;
case 'T' :
a += gen_atom(" N1 ", n3, i, N1ct, comp)
a += gen_atom(" C2 ", n3, i, C2ct, comp)
a += gen_atom(" O2 ", n3, i, O2ct, comp)
a += gen_atom(" N3 ", n3, i, N3ct, comp)
a += gen_atom(" C4 ", n3, i, C4ct, comp)
a += gen_atom(" O4 ", n3, i, NO4ct, comp)
a += gen_atom(" C5 ", n3, i, C5ct, comp)
a += gen_atom(" C6 ", n3, i, C6ct, comp)
a += gen_atom(" C7 ", n3, i, nC7ct, comp)
break;
case 'D' :
case 'U' :
a += gen_atom(" N1 ", n3, i, N1ct, comp)
a += gen_atom(" C2 ", n3, i, C2ct, comp)
a += gen_atom(" O2 ", n3, i, O2ct, comp)
a += gen_atom(" N3 ", n3, i, N3ct, comp)
a += gen_atom(" C4 ", n3, i, C4ct, comp)
a += gen_atom(" O4 ", n3, i, NO4ct, comp)
a += gen_atom(" C5 ", n3, i, C5ct, comp)
a += gen_atom(" C6 ", n3, i, C6ct, comp)
break;
default :
break;
}
return a
};
# Rotate a1 on a2 in the plane of a1, a2 and a3 to the given angle
# a1 and all connected except by a2 must be selected
function set_angle_no (a1no, a2no, a3no, toangle) {
var f = (_frameID/1000000)
var m = (_frameID%100000)
var c = gChain1
var a1 = {(atomno=a1no) and (chain=c) and (file=f) and (model=m)}
var a2 = {(atomno=a2no) and (chain=c) and (file=f) and (model=m)}
var a3 = {(atomno=a3no) and (chain=c) and (file=f) and (model=m)}
var v1 = (a1.xyz - a2.xyz)
var v2 = (a3.xyz - a2.xyz)
var axis = cross(v1, v2) + a2.xyz
var curangle = angle(a1, a2, a3)
rotateselected @axis @a2 @{curangle-toangle}
}
# Set the dihedral to the given angle
# a1 (or a4) and all connected except by a2 (or a3) must be selected
# If selected < unselected ==> a2 < a3 and vice versa
function set_dihedral_no (a1no, a2no, a3no, a4no, toangle) {
var f = (_frameID/1000000)
var m = (_frameID%100000)
var c = gChain1
var a1 = {(atomno=a1no) and (chain=c) and (file=f) and (model=m)}
var a2 = {(atomno=a2no) and (chain=c) and (file=f) and (model=m)}
var a3 = {(atomno=a3no) and (chain=c) and (file=f) and (model=m)}
var a4 = {(atomno=a4no) and (chain=c) and (file=f) and (model=m)}
var curangle = angle(a1, a2, a3, a4)
rotateselected @a2 @a3 @{toangle-curangle}
}
function count_atoms(seq, rna, start, finish) {
var ntc = {"A":21, "C":20, "G":22, "T":20, "U":19}
var cnt = 0
for (var i = start; i <= finish; i++) {
cnt += (ntc[seq[i]] + (rna ? 1 : 0))
}
return cnt
}
# Generate a helix
function gen_helix_strand(reverse, drm, double) {
var f = (_frameID/1000000)
var m = (_frameID%100000)
var cha = ":" + gChain1
var chb = ":" + gChain2
var seq = ""
if (reverse) {
for (var i = gSeq.count; i > 0; i--) {
seq += gSeq[i]%9999%0
}
}
else {
seq = gSeq%9999%0
}
var cSeq = ""
if (double) {
for (var i = seq.count; i > 0; i--) {
cSeq += ((seq[i] == 'A') and (drm > 0)) ? "U" : kNtComp[seq[i]]
}
}
var aAtomCount = count_atoms(seq, (drm == 1), 1, seq.count)
var bAtomCount = count_atoms(cSeq, (drm > 0), 1, cSeq.count)
gNa = 1 # global new P atom index for chain A
gNb = 0
if (double) {
gNb = (aAtomCount + bAtomCount
- count_atoms(cSeq, (drm>0), cSeq.count, cSeq.count)) # last P in cSeq
}
var aResno = 1
var pNa = 1 # previous gNa
gAppendNew = appendNew
if (gNewFrame) {
appendNew = TRUE
}
else {
appendNew = FALSE
# Get the largest atomno in frame
gNa = {(file=f) and (model=m)}.atomno.max + 1
# While there is an atom at the origin
while (m > 0) {
var ai = {within(0.1, {0 0 0}) and (file=f) and (model=m)}
if (ai.size > 0) {
# If on the same chain
if (ai[1].chain = gChain1) {
# Add to existing strand
echo "Adding to existing strand..."
pNa = ai.atomno
aResno = {(chain=gChain1) and (file=f)
and (model=m)}.resno.max + 1
gNa = {(chain=gChain1) and (file=f)
and (model=m)}.atomno.max + 1
gNb += gNa
# Bump up all B chain atomno and resno
savNb = gNb
gNb = aAtomCount + bAtomCount + gNa
gA = "data \"append nt\"\n" # global PDB atom record
for (j = 1; j <= all.atomno.max; j++) {
var aj = {(atomno=j) and (file=f) and (model=m)
and (chain == gChain2)}
if (aj.size > 0) {
gA += gen_atom(aj.atomName, aj.group,
(aj.resno+seq.count+cSeq.count),
array(aj.x, aj.y, aj.z), true)
}
}
gA += "end \"append nt\""
delete @chb
script inline @{gA} # <== new atoms added here
gNb = savNb
break;
}
# Else move all from the new chain rightward on X axis
else {
select {(file=f) and (model=m) and (chain!=gChain1)
and (chain!=gChain2)}
translateselected {0, -20, -20 }
}
}
else {
break
}
} # endwhile
}
var bResno = aResno + seq.count + cSeq.count - 1
var nNa = gNa # new P
var nNb = 0#bBase # new comp P
# For each NT
for (var i = 1; i <= seq.count; i++) {
if (seq[i] == "") {
continue
}
# Move polynucleotide O3p to bond distance 1.59 from new nt P
var pO3 = { -0.759, 0.925, 1.048}
if (double) {
select ((@cha or @chb) and (file=f) and (model=m))
}
else {
select (@cha and (file=f) and (model=m))
}
if ((i + aResno) > 2) {
var nO3 = {@cha and (atomno=@{pNa+8})
and (file=f) and (model=m)}.xyz
var xyz = @{pO3 - nO3}
translateselected @xyz
}
# Gen NT ==================================================
gA = "data \"append nt\"\n" # global PDB atom record
gA += gen_nt(aResno, seq[i], (drm == 1), FALSE); # gNa updated
if (double) {
nNb = gNb
var nti = cSeq.count-i+1
gA += gen_nt(bResno, cSeq[nti], (drm > 0), TRUE); # gNb++
if (i > 0) {
gNb -= count_atoms(cSeq, (drm>0), nti-1, nti)
}
}
gA += "end \"append nt\""
script inline @{gA} # <== new atoms added here
f = (_frameID/1000000)
m = (_frameID%100000)
appendNew = FALSE
# Flip comp to comp strand
if (double) {
select @{("" + bResno + chb + "/" + f + "." + m)}
var v1={8.238, 2.809, 6.004}
var v2={8.461, 4.646, 4.125}
rotateSelected @v2 @v1 180.0
}
# If any older NTs
if ((i + aResno) > 2) {
# Set the angles between the new NT and the old NTs
select (((@cha and (atomno < nNa)) or (@chb and (resno != bResno)))
and (file=f) and (model=m))
set_angle_no(nNa, pNa+8, pNa+7, 120.0)
select (((@cha and (atomno < @{nNa+3}))
or (@chb and (resno != bResno))) and (file=f) and (model=m))
set_dihedral_no(nNa+4, nNa+3, nNa, pNa+8, kC5O5PO3)
select (((@cha and (atomno < nNa)) or (@chb and (resno != bResno)))
and (file=f) and (model=m))
set_dihedral_no(nNa+3, nNa, pNa+8, pNa+7, kO5PO3C3)
set_dihedral_no(nNa, pNa+8, pNa+7, pNa+5, kPO3C3C4)
}
# Step new and previous N
aResno++; bResno--
pNa = nNa
nNa = gNa; nNb = gNb
}
# Make the nucleotide bonds
connect
# Clean up
appendNew = gAppendNew
select all
refresh
# Convert to A-form if RNA or mixed else B-form
try {
script $SCRIPT_PATH$toabNT.spt
var s = format("Convert to %s-form?", ((drm > 0) ? "A" : "B"))
var p = prompt(s, "Yes|No", TRUE)
if (p = "Yes") {
to_ab_nt_auto(gChain1, (drm > 0))
}
}
catch {
}
}
# Generate a helix or two
function plico_gen_helix(seq) {
if (gPlicoRecord != "") {
var g = format("show file \"%s\"", gPlicoRecord)
var ls = script(g)
if (ls.find("FileNotFoundException")) {
ls = ""
}
ls += format("plico_gen_helix(\"%s\");", gSeq)
write var ls @gPlicoRecord
}
var single = FALSE
var reverse = FALSE
var drm = 0
var done = FALSE
gSeq = seq%9999%0
print format ("Seq=%s", gSeq)
gNewFrame = FALSE
if (gSeq[1] == '+') {
gNewFrame = TRUE
gSeq = gSeq[2][9999]
}
if (gSeq[2] == ':') {
gChain1 = gSeq[1]
gSeq = gSeq[3][9999]
}
else if (gSeq[3] == ':') {
gChain1 = gSeq[1]
gChain2 = gSeq[2]
gSeq = gSeq[4][9999]
}
while (done == FALSE) {
done = TRUE;
if (gSeq[1] == 'S') {
single = TRUE;
done = FALSE;
}
else if (gSeq[1] == '3') {
reverse = TRUE;
done = FALSE;
}
else if (gSeq[1] == 'R') {
drm = 1;
done = FALSE;
}
else if (gSeq[1] == 'M') {
drm = 2;
done = FALSE;
}
if (done == FALSE) {
gSeq = gSeq[2][9999]
}
}
if (drm = 1) {
gSeq = gSeq.replace('T', 'U')
}
else {
gSeq = gSeq.replace('U', 'T')
}
# Generate
gen_helix_strand(reverse, drm, single ? FALSE : TRUE)
}
function plico_gen_nt {
echo Generating Nucleotide Helix
# Get the sequence from the user
var seq = prompt("Enter NT sequence (<+AB:3RSM>ACGTU...)", "")%9999%0
if ((seq != "NULL") and (seq.count > 0)) {
plico_gen_helix(seq)
}
}
# end of polymeraze.spt