Difference between revisions of "User:Remig/plico/remapNT"
(Jmol script to remap polynucleotides) |
m |
||
(8 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | '''RemapNT''' allows you to change the chain ID, atom numbers and/or residue numbers of a polynucleotide chain by mouse actions. It also calculates group values [nucleotide names (DU, A, etc.)]. | + | '''RemapNT''' allows you to change the chain ID, atom numbers and/or residue numbers of a polynucleotide chain by mouse actions. It also calculates group values [nucleotide names (DU, A, etc.)]. Finally it prints the resultant 1 char string to the console. |
+ | |||
+ | When you click on a polynucleotide chain, it gives the current chain ID, residue, residue number and atom number of the most 5'ward atom in that chain. You may then edit any value (except residue). Remap then remaps the entire chain based on those values by conventional increments and identifies each nucleotide residue. | ||
Note that it will also remove all waters, ligands, hydrogens and %B alternates when any chain is updated. | Note that it will also remove all waters, ligands, hydrogens and %B alternates when any chain is updated. | ||
Line 5: | Line 7: | ||
'''RemapNT''' is a member of the Plico suite of protein folding tools described [[User:Remig/plico|here]]. It may be installed and accessed as a macro with the file: | '''RemapNT''' is a member of the Plico suite of protein folding tools described [[User:Remig/plico|here]]. It may be installed and accessed as a macro with the file: | ||
− | |||
− | |||
− | |||
− | |||
− | |||
<pre># remapNT - Jmol script by Ron Mignery | <pre># remapNT - Jmol script by Ron Mignery | ||
− | # v1. | + | # v1.7 beta 4/12/2016 -require latest common includes |
# | # | ||
# Calculate or change polynucleotide chain, atom number, residue names | # Calculate or change polynucleotide chain, atom number, residue names | ||
− | # and/or residue numbers | + | # and/or residue numbers and print the resultant 1 char string |
# | # | ||
+ | gBusy = false | ||
+ | kRemapNT=2 | ||
− | function | + | function find_5_prime(pIdx) { |
while (pIdx >= 0) { | while (pIdx >= 0) { | ||
− | + | ||
# Find C3' | # Find C3' | ||
var c3pIdx = -1 | var c3pIdx = -1 | ||
Line 30: | Line 29: | ||
for (var k = 1; k <= occSet.size; k++) { | for (var k = 1; k <= occSet.size; k++) { | ||
if (connected(occSet[k]).size > 2) { | if (connected(occSet[k]).size > 2) { | ||
− | c3pIdx = occSet[k].atomIndex | + | c3pIdx = 0 + occSet[k].atomIndex |
} | } | ||
} | } | ||
} | } | ||
} | } | ||
− | + | ||
if (c3pIdx < 0) { | if (c3pIdx < 0) { | ||
return pIdx | return pIdx | ||
} | } | ||
− | |||
# Find C4' | # Find C4' | ||
var endIdx = -1 | var endIdx = -1 | ||
Line 47: | Line 45: | ||
for (var j = 1; j <= ocSet.size; j++) { | for (var j = 1; j <= ocSet.size; j++) { | ||
if (connected(ocSet[j]).size > 1) { | if (connected(ocSet[j]).size > 1) { | ||
− | endIdx = cSet[i].atomIndex | + | if (endIdx = -1) { |
+ | endIdx = 0 + cSet[i].atomIndex | ||
+ | } | ||
+ | else { | ||
+ | var Ox = connected(ocSet[j]) and not {atomindex=@{cset[i].atomIndex}} | ||
+ | if (connected(Ox) > 1) { | ||
+ | endIdx = 0 + cSet[i].atomIndex | ||
+ | } | ||
+ | |||
+ | } | ||
} | } | ||
} | } | ||
} | } | ||
− | + | ||
# Find C5' | # Find C5' | ||
var c5idx = -1 | var c5idx = -1 | ||
cSet = (connected({atomIndex=endIdx}) and not {atomIndex=c3pIdx} | cSet = (connected({atomIndex=endIdx}) and not {atomIndex=c3pIdx} | ||
and not {oxygen}) | and not {oxygen}) | ||
− | if (cSet | + | if (cSet) { |
− | c5idx = cSet[1].atomIndex | + | c5idx = 0 + cSet[1].atomIndex |
} | } | ||
− | + | ||
# Find O5' | # Find O5' | ||
var o5idx = -1 | var o5idx = -1 | ||
cSet = connected({atomIndex=c5idx}) and {oxygen} | cSet = connected({atomIndex=c5idx}) and {oxygen} | ||
− | if (cSet | + | if (cSet) { |
− | o5idx = cSet[1].atomIndex | + | o5idx = 0 + cSet[1].atomIndex |
} | } | ||
− | + | ||
if (o5idx < 0) { | if (o5idx < 0) { | ||
return c5idx | return c5idx | ||
} | } | ||
− | + | ||
# Find P | # Find P | ||
pIdx = -1 | pIdx = -1 | ||
cSet = connected({atomIndex=o5idx}) and {phosphorus} | cSet = connected({atomIndex=o5idx}) and {phosphorus} | ||
− | if (cSet | + | if (cSet) { |
− | + | Pidx = 0 + cSet[1].atomIndex | |
+ | } | ||
+ | |||
+ | if (Pidx < 0) { | ||
+ | return o5idx | ||
} | } | ||
} | } | ||
− | + | ||
− | return -1 | + | return -1 |
} | } | ||
− | function | + | function find_p_idx(idx) { |
select {atomIndex=idx} | select {atomIndex=idx} | ||
var cSet = {selected} | var cSet = {selected} | ||
− | while (cSet | + | while (cSet) { |
for (var i = 1; i <= cSet.size; i++) { | for (var i = 1; i <= cSet.size; i++) { | ||
if (cSet[i].element == "P") { | if (cSet[i].element == "P") { | ||
Line 98: | Line 109: | ||
# cSet, s, and newGreek are arrays and thus passed by reference | # cSet, s, and newGreek are arrays and thus passed by reference | ||
− | function | + | function ring_common(cSet, nIdx, s, newGreek, nextGreek) { |
if (cSet.size > 2) { | if (cSet.size > 2) { | ||
print format("Unrecognized structure with set %s", cSet) | print format("Unrecognized structure with set %s", cSet) | ||
Line 126: | Line 137: | ||
} | } | ||
− | # Bound to ALT-LEFT-CLICK by | + | # Bound to ALT-LEFT-CLICK by plico_remap_nt |
− | function | + | function remap_nt_cargo_mb() { |
− | |||
var idx =_atomPicked | var idx =_atomPicked | ||
if ({atomIndex=idx}.element == "H") { | if ({atomIndex=idx}.element == "H") { | ||
idx = connected({atomIndex=idx})[1].atomIndex | idx = connected({atomIndex=idx})[1].atomIndex | ||
} | } | ||
+ | delete {hydrogen} | ||
+ | delete {hoh} | ||
+ | delete %B | ||
+ | delete ligands | ||
+ | connect | ||
+ | |||
+ | remap_nt( idx, false, 0) | ||
+ | set echo TOP LEFT | ||
+ | echo @gEcho | ||
+ | background ECHO yellow | ||
+ | refresh | ||
+ | print_1c_chain( newChain) | ||
+ | } | ||
+ | |||
+ | function remap_nt(idx, auto, base) { | ||
+ | |||
# If P can be found | # If P can be found | ||
− | var pIdx = | + | var pIdx = find_p_idx(idx) |
− | var isValid = | + | var isValid = false |
var newResno = 1 | var newResno = 1 | ||
var newChain = "A" | var newChain = "A" | ||
Line 142: | Line 168: | ||
var t5idx = -1 | var t5idx = -1 | ||
if (pIdx >= 0) { | if (pIdx >= 0) { | ||
− | + | ||
− | t5idx = | + | t5idx = find_5_prime(pIdx) |
− | |||
if (t5idx >= 0) { | if (t5idx >= 0) { | ||
− | + | var f = {atomIndex=t5idx}.file | |
− | + | var m = {atomIndex=t5idx}.model | |
− | + | newResno = {atomIndex=t5idx}.resno | |
− | select { | + | newChain = {atomIndex=t5idx}.chain |
− | + | newAtomno = {atomIndex=t5idx}.atomno | |
+ | select {thisModel} | ||
+ | color {selected} @gScheme | ||
+ | select {(chain=newChain) and thisModel} | ||
+ | color {selected} @gAltScheme | ||
refresh | refresh | ||
+ | |||
+ | if (auto) { | ||
+ | newResno = base | ||
+ | isValid = true | ||
+ | newChain = gChain1 | ||
+ | } | ||
+ | else { | ||
− | + | # Prompt for new designators | |
− | + | var p = prompt(("Enter 5\'-terminal atom designator as\n" | |
− | + | + " <resno>:<chain>#<atomno>"), | |
− | + | format("%d:%s#%d", newResno, newChain, newAtomno))%0 | |
− | + | # If valid | |
− | + | if (p != "null") { | |
− | + | var iColon = p.find(":") | |
− | + | if (iColon > 0) { | |
− | + | var iHash = p.find("#") | |
− | + | if (iHash > 0) { | |
− | + | newResno = 0 + (p[1][iColon-1]) | |
− | + | newChain = p[iColon+1][iHash-1] | |
− | + | newAtomno = 0 + (p[iHash+1][0]) | |
− | + | if ((newResno > 0) | |
− | + | and (newChain.size == 1) | |
− | + | and (newAtomno > 0)) { | |
− | + | isValid = true | |
+ | } | ||
} | } | ||
} | } | ||
− | + | if (not isValid) { | |
− | + | prompt ("Entry not valid!") | |
− | + | } | |
} | } | ||
} | } | ||
} | } | ||
} | } | ||
− | + | ||
if (isValid) { | if (isValid) { | ||
background ECHO pink | background ECHO pink | ||
refresh | refresh | ||
− | |||
− | |||
− | |||
− | |||
− | |||
# Build inline pdb file | # Build inline pdb file | ||
− | var ls = "data \"append | + | var ls = "data \"append remapNT\"\n" # global PDB atom record |
var rs = "" | var rs = "" | ||
− | + | ||
select {atomIndex=t5idx} | select {atomIndex=t5idx} | ||
var cSet = {selected} | var cSet = {selected} | ||
var nextAtomName = {atomIndex=t5idx}.element | var nextAtomName = {atomIndex=t5idx}.element | ||
var newGroup = "UNK" | var newGroup = "UNK" | ||
− | var newGreek = array() | + | var newGreek = array("", "", "", "") |
var nIdx = t5idx | var nIdx = t5idx | ||
var c1pIdx = -1 | var c1pIdx = -1 | ||
Line 203: | Line 235: | ||
var stopIdx = -1 | var stopIdx = -1 | ||
var endIdx = -1 | var endIdx = -1 | ||
− | var isRNA = | + | var isRNA = false |
− | while (cSet | + | var first = true |
− | var s = array(1, 2, 3) | + | var psu = false |
+ | while (cSet) { | ||
+ | var s = array(1, 2, 3, 4) | ||
var iKeep = -1 | var iKeep = -1 | ||
var iDrop = -1 | var iDrop = -1 | ||
switch( nextAtomName) { | switch( nextAtomName) { | ||
case "O" : | case "O" : | ||
− | newGreek[1] = " | + | newGreek[1] = (first ? "5\'" : "P3") |
− | nextAtomName = "P" | + | nextAtomName = (first ? "C5\'" : "P") |
nIdx = cSet[1].atomIndex | nIdx = cSet[1].atomIndex | ||
break | break | ||
Line 222: | Line 256: | ||
var oc5set = ({}) | var oc5set = ({}) | ||
for (var i = 1; i <= cSet.size; i++) { | for (var i = 1; i <= cSet.size; i++) { | ||
+ | newGreek[i] = "" | ||
if (connected(cSet[i]).size > 1) { | if (connected(cSet[i]).size > 1) { | ||
− | s[ | + | s[cSet.size] = i |
− | newGreek[ | + | newGreek[cSet.size] = "5\'" |
oc5set = connected(cSet[i]) and {carbon} | oc5set = connected(cSet[i]) and {carbon} | ||
nIdx = cSet[i].atomIndex | nIdx = cSet[i].atomIndex | ||
} | } | ||
} | } | ||
− | for (var i = 1; i <= cSet.size; i++) { | + | var isP1 = false |
− | + | if (cSet.size > 3) { | |
− | + | newGreek[1] = "P1" | |
− | + | newGreek[2] = "P2" | |
− | + | newGreek[3] = "P3" | |
− | + | s[1] = 1 | |
− | + | s[2] = 2 | |
− | + | s[3] = 3 | |
− | + | } | |
− | + | else { | |
+ | for (var i = 1; i <= cSet.size; i++) { | ||
+ | if (i != s[cSet.size]) { | ||
+ | if ((isP1 == false) | ||
+ | and (abs(angle(cSet[i], {atomIndex=pIdx}, | ||
+ | cSet[s[cSet.size]], oc5set[1])) < 90.0)) { | ||
+ | s[1] = i | ||
+ | newGreek[1] = "P1" | ||
+ | isP1 = true | ||
+ | } | ||
+ | else { | ||
+ | s[2] = i | ||
+ | newGreek[2] = "P2" | ||
+ | } | ||
} | } | ||
} | } | ||
Line 260: | Line 308: | ||
s[1] = i | s[1] = i | ||
newGreek[1] = "4\'" | newGreek[1] = "4\'" | ||
− | cSet[i].selected = | + | cSet[i].selected = false |
stopIdx = cSet[i].atomIndex | stopIdx = cSet[i].atomIndex | ||
} | } | ||
Line 267: | Line 315: | ||
newGreek[2] = "3\'" | newGreek[2] = "3\'" | ||
nIdx = cSet[i].atomIndex | nIdx = cSet[i].atomIndex | ||
− | + | ||
} | } | ||
} | } | ||
Line 298: | Line 346: | ||
for (var i = 1; i <= cSet.size; i++) { | for (var i = 1; i <= cSet.size; i++) { | ||
if (cSet[i].element == "O") { | if (cSet[i].element == "O") { | ||
− | s[ | + | s[1] = i |
− | newGreek[ | + | newGreek[1] = "2\'" |
− | isRNA = | + | isRNA = true |
} | } | ||
else { | else { | ||
− | s[ | + | s[2] = i |
− | newGreek[ | + | newGreek[2] = "1\'" |
c1pIdx = cSet[i].atomIndex | c1pIdx = cSet[i].atomIndex | ||
nIdx = cSet[i].atomIndex | nIdx = cSet[i].atomIndex | ||
Line 310: | Line 358: | ||
} | } | ||
nextAtomName = "C1\'" | nextAtomName = "C1\'" | ||
− | break | + | break |
case "C1\'" : | case "C1\'" : | ||
for (var i = 1; i <= cSet.size; i++) { | for (var i = 1; i <= cSet.size; i++) { | ||
if (cSet[i].element == "N") { | if (cSet[i].element == "N") { | ||
+ | iKeep = i | ||
+ | nIdx = cSet[i].atomIndex | ||
+ | } | ||
+ | else if ((cSet[i].element == "C") and | ||
+ | ((connected(cSet[i]) and {oxygen}).size == 0)) { #PSU | ||
+ | psu = true | ||
iKeep = i | iKeep = i | ||
nIdx = cSet[i].atomIndex | nIdx = cSet[i].atomIndex | ||
} | } | ||
else { | else { | ||
− | cSet[i].selected = | + | cSet[i].selected = false |
} | } | ||
} | } | ||
Line 333: | Line 387: | ||
} | } | ||
} | } | ||
− | break | + | break |
case "N1y" : | case "N1y" : | ||
for (var i = 1; i <= cSet.size; i++) { | for (var i = 1; i <= cSet.size; i++) { | ||
Line 347: | Line 401: | ||
newGreek[1] = "2" | newGreek[1] = "2" | ||
nextAtomName = "C2" | nextAtomName = "C2" | ||
− | break | + | break |
case "N9u" : | case "N9u" : | ||
− | # Find N-C-N-C-N | + | # Find N-C-N-C-N |
for (var i = 1; i <= cSet.size; i++) { | for (var i = 1; i <= cSet.size; i++) { | ||
− | n1atom = (connected(cSet[i]) and {nitrogen} | + | var n1atom = (connected(cSet[i]) and {nitrogen} |
and not {atomIndex=nIdx}) | and not {atomIndex=nIdx}) | ||
− | c2set = connected(n1atom) and {carbon} and not cSet[i] | + | var c2set = connected(n1atom) and {carbon} and not cSet[i] |
for (var j = 1; j <= c2set.size; j++) { | for (var j = 1; j <= c2set.size; j++) { | ||
if ((connected(c2set[j]) and {nitrogen}) > 1) { | if ((connected(c2set[j]) and {nitrogen}) > 1) { | ||
Line 365: | Line 419: | ||
newGreek[1] = "8" | newGreek[1] = "8" | ||
nextAtomName = "C8" | nextAtomName = "C8" | ||
− | break | + | break |
case "C8" : | case "C8" : | ||
− | nIdx = | + | nIdx = ring_common( cSet, nIdx, s, newGreek, "7") |
nextAtomName = "N7" | nextAtomName = "N7" | ||
− | break | + | break |
case "N7" : | case "N7" : | ||
− | nIdx = | + | nIdx = ring_common( cSet, nIdx, s, newGreek, "5") |
nextAtomName = "C5" | nextAtomName = "C5" | ||
− | break | + | break |
case "C5" : | case "C5" : | ||
− | nIdx = | + | if (isRNA and (newGroup == "DU ")) { |
+ | var c5set = {atomIndex=nIdx} or connected({atomIndex=nIdx}) | ||
+ | if (angle(c5set[1], c5set[2], c5set[3]) < 114.0) { | ||
+ | newGroup = "D " | ||
+ | } | ||
+ | } | ||
+ | nIdx = ring_common( cSet, nIdx, s, newGreek, "6") | ||
if ((newGroup == "DU ") and (cSet.size > 1)) { | if ((newGroup == "DU ") and (cSet.size > 1)) { | ||
newGroup = "DT " | newGroup = "DT " | ||
} | } | ||
nextAtomName = "C6" | nextAtomName = "C6" | ||
− | break | + | break |
case "C6" : | case "C6" : | ||
if (newGroup == "PU") { | if (newGroup == "PU") { | ||
− | nIdx = | + | nIdx = ring_common( cSet, nIdx, s, newGreek, "1") |
newGroup = ((cSet[1].element == "O") ? "DG " : "DA ") | newGroup = ((cSet[1].element == "O") ? "DG " : "DA ") | ||
nextAtomName = "N1" | nextAtomName = "N1" | ||
} | } | ||
else { | else { | ||
+ | if (psu) { | ||
+ | psu = false | ||
+ | newGroup = "DU " | ||
+ | } | ||
cSet = ({}) | cSet = ({}) | ||
} | } | ||
− | break | + | break |
case "N1" : | case "N1" : | ||
− | nIdx = | + | if (connected({atomIndex=nIdx}).size > 2) { # YG |
+ | newGroup = "X " | ||
+ | } | ||
+ | nIdx = ring_common( cSet, nIdx, s, newGreek, "2") | ||
nextAtomName = "C2" | nextAtomName = "C2" | ||
− | break | + | break |
case "C2" : | case "C2" : | ||
− | nIdx = | + | nIdx = ring_common( cSet, nIdx, s, newGreek, "3") |
nextAtomName = "N3" | nextAtomName = "N3" | ||
stopIdx = -1 | stopIdx = -1 | ||
− | break | + | break |
case "N3" : | case "N3" : | ||
− | nIdx = | + | nIdx = ring_common( cSet, nIdx, s, newGreek, "4") |
nextAtomName = "C4" | nextAtomName = "C4" | ||
− | break | + | break |
case "C4" : | case "C4" : | ||
if (newGroup != "PY") { | if (newGroup != "PY") { | ||
Line 409: | Line 476: | ||
} | } | ||
else { | else { | ||
− | nIdx = | + | nIdx = ring_common( cSet, nIdx, s, newGreek, "5") |
newGroup = ((cSet[1].element == "N") ? "DC " : "DU ") | newGroup = ((cSet[1].element == "N") ? "DC " : "DU ") | ||
nextAtomName = "C5" | nextAtomName = "C5" | ||
Line 415: | Line 482: | ||
break | break | ||
} | } | ||
− | + | first = false | |
for (var i = 1; i <= cSet.size; i++) { | for (var i = 1; i <= cSet.size; i++) { | ||
rs += format("ATOM %5d %-4sUNK ", newAtomNo, | rs += format("ATOM %5d %-4sUNK ", newAtomNo, | ||
− | (cSet | + | (cSet[i].element + newGreek[s[i]])) |
− | rs += format("%s%4d %8.3f", newChain, newResno, cSet | + | rs += format("%s%4d %8.3f", newChain, newResno, cSet[i].x) |
− | rs += format("%8.3f%8.3f\n", cSet | + | rs += format("%8.3f%8.3f\n", cSet[i].y, cSet[i].z) |
newAtomno++ | newAtomno++ | ||
} | } | ||
+ | |||
cSet = (connected(cSet and not {atomIndex=stopIdx}) | cSet = (connected(cSet and not {atomIndex=stopIdx}) | ||
and not cSet and not {atomIndex=stopIdx} and not {atomIndex=endIdx}) | and not cSet and not {atomIndex=stopIdx} and not {atomIndex=endIdx}) | ||
endIdx = nIdx | endIdx = nIdx | ||
− | + | ||
if (cSet.size == 0) { | if (cSet.size == 0) { | ||
if (isRNA) { | if (isRNA) { | ||
newGroup = (newGroup.replace("DA ","A ").replace("DG ","G ") | newGroup = (newGroup.replace("DA ","A ").replace("DG ","G ") | ||
.replace("DC ","C ").replace("DT ","T ").replace("DU ","U ")) | .replace("DC ","C ").replace("DT ","T ").replace("DU ","U ")) | ||
− | } | + | } |
ls += rs.replace("UNK", newGroup) | ls += rs.replace("UNK", newGroup) | ||
rs = "" | rs = "" | ||
newResno++ | newResno++ | ||
− | + | ||
if (pIdx >= 0) { | if (pIdx >= 0) { | ||
cSet = {atomIndex=pIdx} | cSet = {atomIndex=pIdx} | ||
nextAtomName = "P" | nextAtomName = "P" | ||
newGroup = "UNK" | newGroup = "UNK" | ||
− | + | newGreek[1] = "" | |
− | newGreek[1] = | ||
c1pIdx = -1 | c1pIdx = -1 | ||
stopIdx = o3pIdx | stopIdx = o3pIdx | ||
endIdx = -1 | endIdx = -1 | ||
− | isRNA = | + | isRNA = false |
} | } | ||
else { | else { | ||
Line 451: | Line 518: | ||
} | } | ||
} | } | ||
− | } # endwhile | + | } # endwhile |
# Replace chain with new chain | # Replace chain with new chain | ||
cset = {atomIndex=idx} | cset = {atomIndex=idx} | ||
select cSet | select cSet | ||
− | while (cSet | + | while (cSet) { |
cSet = connected({selected}) and not {selected} | cSet = connected({selected}) and not {selected} | ||
select {selected} or cSet | select {selected} or cSet | ||
} | } | ||
delete {selected} | delete {selected} | ||
− | + | ||
− | ls += "end \"append | + | ls += "end \"append remapNT\"" |
+ | gAppendNew = appendNew | ||
+ | set appendNew false | ||
script inline @{ls} | script inline @{ls} | ||
− | + | set appendNew gAppendNew | |
− | + | } | |
− | + | else { | |
− | + | color {selected} @gScheme | |
− | + | } | |
+ | print_1c_chain( newChain) | ||
+ | } | ||
+ | |||
+ | function print_1c_chain(iChain) { | ||
+ | var resmin = get_resno_min(iChain) | ||
+ | var resmax = get_resno_max(iChain) | ||
+ | var rchar = (({(resno=resmin) and (chain=iChain) and thisModel}.group[0].size > 1) ? "" : "R") | ||
+ | var lcAtoms = (within(3.1, false, {(resno=resmin) and (chain=iChain) | ||
+ | and thisModel and base}) | ||
+ | and not {(resno=resmin) and (chain=iChain) and thisModel}) | ||
+ | var chain2 = "" | ||
+ | var schar = "S" | ||
+ | if (lcAtoms) { | ||
+ | chain2 = lcAtoms[1].chain | ||
+ | if (((rchar == "R") and (lcAtoms[1].group.size > 1)) | ||
+ | or ((rchar == "") and (lcAtoms[1].group.size == 1))) { | ||
+ | schar = "M" | ||
+ | } | ||
+ | else { | ||
+ | schar = "S" | ||
+ | chain2 = "" | ||
+ | } | ||
+ | } | ||
+ | var ls = format("%s%s:%s", iChain, chain2, format("%s%s", rchar, schar)) | ||
+ | for (var i = get_resno_min(iChain); i <= get_resno_max(iChain); i++) { | ||
+ | ls += ({(resno=i) and (chain=iChain) and thisModel}.group[0])[0] | ||
} | } | ||
+ | print ls | ||
} | } | ||
# Top level of Remap | # Top level of Remap | ||
− | function | + | function plico_remap_nt() { |
− | + | ||
− | # | + | # Load common functions if not already |
− | + | if (kCommon < 7) { | |
+ | script $SCRIPT_PATH$plicoCommon.spt | ||
+ | if (kCommon < 7) { | ||
+ | prompt ("A newer version of plicoCommon.SPT is required") | ||
+ | quit | ||
+ | } | ||
+ | } | ||
+ | |||
+ | gPlico = "RemapNT" | ||
+ | plico_prelim(false, true) | ||
− | + | gEcho = "_____REMAP NT_____|ALT-CLICK=select NT chain|SHIFT-DOUBLE-CLICK=exit" | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | gEcho = "_____REMAP NT_____|ALT-CLICK=select NT chain|DOUBLE-CLICK=exit" | ||
echo @gEcho | echo @gEcho | ||
− | |||
− | |||
set picking ON | set picking ON | ||
bind "ALT-LEFT-CLICK" "_pickAtom"; | bind "ALT-LEFT-CLICK" "_pickAtom"; | ||
− | bind "ALT-LEFT-CLICK" "+: | + | bind "ALT-LEFT-CLICK" "+:remap_nt_cargo_mb"; |
− | bind "DOUBLE" " | + | bind "SHIFT-DOUBLE" "plico_exit(true)"; |
− | + | bind "LEFT-CLICK" "+:plico_menu_toggle"; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
# End of REMAPNT.SPT | # End of REMAPNT.SPT | ||
</pre> | </pre> |
Latest revision as of 17:22, 12 April 2016
RemapNT allows you to change the chain ID, atom numbers and/or residue numbers of a polynucleotide chain by mouse actions. It also calculates group values [nucleotide names (DU, A, etc.)]. Finally it prints the resultant 1 char string to the console.
When you click on a polynucleotide chain, it gives the current chain ID, residue, residue number and atom number of the most 5'ward atom in that chain. You may then edit any value (except residue). Remap then remaps the entire chain based on those values by conventional increments and identifies each nucleotide residue.
Note that it will also remove all waters, ligands, hydrogens and %B alternates when any chain is updated.
RemapNT 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:
# remapNT - Jmol script by Ron Mignery # v1.7 beta 4/12/2016 -require latest common includes # # Calculate or change polynucleotide chain, atom number, residue names # and/or residue numbers and print the resultant 1 char string # gBusy = false kRemapNT=2 function find_5_prime(pIdx) { while (pIdx >= 0) { # Find C3' var c3pIdx = -1 select {atomIndex=pIdx} var cSet = {selected} for (var i = 1; i <= cSet.size; i++) { var ocSet = connected(cSet[i]) for (var j = 1; j <= ocSet.size; j++) { var occSet = connected(ocSet[j]) and not {atomIndex=pIdx} for (var k = 1; k <= occSet.size; k++) { if (connected(occSet[k]).size > 2) { c3pIdx = 0 + occSet[k].atomIndex } } } } if (c3pIdx < 0) { return pIdx } # Find C4' var endIdx = -1 cSet = connected({atomIndex=c3pIdx}) and not {oxygen} for (var i = 1; i <= cSet.size; i++) { var ocSet = connected(cSet[i]) and {oxygen} for (var j = 1; j <= ocSet.size; j++) { if (connected(ocSet[j]).size > 1) { if (endIdx = -1) { endIdx = 0 + cSet[i].atomIndex } else { var Ox = connected(ocSet[j]) and not {atomindex=@{cset[i].atomIndex}} if (connected(Ox) > 1) { endIdx = 0 + cSet[i].atomIndex } } } } } # Find C5' var c5idx = -1 cSet = (connected({atomIndex=endIdx}) and not {atomIndex=c3pIdx} and not {oxygen}) if (cSet) { c5idx = 0 + cSet[1].atomIndex } # Find O5' var o5idx = -1 cSet = connected({atomIndex=c5idx}) and {oxygen} if (cSet) { o5idx = 0 + cSet[1].atomIndex } if (o5idx < 0) { return c5idx } # Find P pIdx = -1 cSet = connected({atomIndex=o5idx}) and {phosphorus} if (cSet) { Pidx = 0 + cSet[1].atomIndex } if (Pidx < 0) { return o5idx } } return -1 } function find_p_idx(idx) { select {atomIndex=idx} var cSet = {selected} while (cSet) { for (var i = 1; i <= cSet.size; i++) { if (cSet[i].element == "P") { return cSet[i].atomIndex } } cSet = connected({selected}) and not {selected} and not {hydrogen} select {selected} or cset } return -1 } # cSet, s, and newGreek are arrays and thus passed by reference function ring_common(cSet, nIdx, s, newGreek, nextGreek) { if (cSet.size > 2) { print format("Unrecognized structure with set %s", cSet) } var oldGreek = 0 + newGreek[1] newGreek[1] = nextGreek for (var i = 1; i <= cSet.size; i++) { var ccSet = connected(cSet[i]) if (ccSet.size == 1) { if (cSet[i].element == ccSet[1].element) { s[2] = i s[1] = ((i > 1) ? 1 : 2) newGreek[i] = 1 + nextGreek newGreek[s[1]] = nextGreek return cSet[s[1]].atomIndex } else { s[1] = i s[2] = ((i > 1) ? 1 : 2) newGreek[i] = oldGreek newGreek[s[2]] = nextGreek return cSet[s[2]].atomIndex } } } return cSet[1].atomIndex } # Bound to ALT-LEFT-CLICK by plico_remap_nt function remap_nt_cargo_mb() { var idx =_atomPicked if ({atomIndex=idx}.element == "H") { idx = connected({atomIndex=idx})[1].atomIndex } delete {hydrogen} delete {hoh} delete %B delete ligands connect remap_nt( idx, false, 0) set echo TOP LEFT echo @gEcho background ECHO yellow refresh print_1c_chain( newChain) } function remap_nt(idx, auto, base) { # If P can be found var pIdx = find_p_idx(idx) var isValid = false var newResno = 1 var newChain = "A" var newAtomno = 1 var t5idx = -1 if (pIdx >= 0) { t5idx = find_5_prime(pIdx) if (t5idx >= 0) { var f = {atomIndex=t5idx}.file var m = {atomIndex=t5idx}.model newResno = {atomIndex=t5idx}.resno newChain = {atomIndex=t5idx}.chain newAtomno = {atomIndex=t5idx}.atomno select {thisModel} color {selected} @gScheme select {(chain=newChain) and thisModel} color {selected} @gAltScheme refresh if (auto) { newResno = base isValid = true newChain = gChain1 } else { # Prompt for new designators var p = prompt(("Enter 5\'-terminal atom designator as\n" + " <resno>:<chain>#<atomno>"), format("%d:%s#%d", newResno, newChain, newAtomno))%0 # If valid if (p != "null") { var iColon = p.find(":") if (iColon > 0) { var iHash = p.find("#") if (iHash > 0) { newResno = 0 + (p[1][iColon-1]) newChain = p[iColon+1][iHash-1] newAtomno = 0 + (p[iHash+1][0]) if ((newResno > 0) and (newChain.size == 1) and (newAtomno > 0)) { isValid = true } } } if (not isValid) { prompt ("Entry not valid!") } } } } } if (isValid) { background ECHO pink refresh # Build inline pdb file var ls = "data \"append remapNT\"\n" # global PDB atom record var rs = "" select {atomIndex=t5idx} var cSet = {selected} var nextAtomName = {atomIndex=t5idx}.element var newGroup = "UNK" var newGreek = array("", "", "", "") var nIdx = t5idx var c1pIdx = -1 var o3pIdx = -1 var stopIdx = -1 var endIdx = -1 var isRNA = false var first = true var psu = false while (cSet) { var s = array(1, 2, 3, 4) var iKeep = -1 var iDrop = -1 switch( nextAtomName) { case "O" : newGreek[1] = (first ? "5\'" : "P3") nextAtomName = (first ? "C5\'" : "P") nIdx = cSet[1].atomIndex break case "P" : newGreek[1] = "" nextAtomName = "OP" nIdx = cSet[1].atomIndex break case "OP" : var oc5set = ({}) for (var i = 1; i <= cSet.size; i++) { newGreek[i] = "" if (connected(cSet[i]).size > 1) { s[cSet.size] = i newGreek[cSet.size] = "5\'" oc5set = connected(cSet[i]) and {carbon} nIdx = cSet[i].atomIndex } } var isP1 = false if (cSet.size > 3) { newGreek[1] = "P1" newGreek[2] = "P2" newGreek[3] = "P3" s[1] = 1 s[2] = 2 s[3] = 3 } else { for (var i = 1; i <= cSet.size; i++) { if (i != s[cSet.size]) { if ((isP1 == false) and (abs(angle(cSet[i], {atomIndex=pIdx}, cSet[s[cSet.size]], oc5set[1])) < 90.0)) { s[1] = i newGreek[1] = "P1" isP1 = true } else { s[2] = i newGreek[2] = "P2" } } } } #nIdx = pIdx nextAtomName = "C5\'" break case "C5\'" : nIdx = cSet[1].atomIndex newGreek[1] = "5\'" nextAtomName = "C4\'" break case "C4\'" : nIdx = cSet[1].atomIndex newGreek[1] = "4\'" nextAtomName = "C3\'" break case "C3\'" : for (var i = 1; i <= cSet.size; i++) { if (cSet[i].element == "O") { s[1] = i newGreek[1] = "4\'" cSet[i].selected = false stopIdx = cSet[i].atomIndex } else { s[2] = i newGreek[2] = "3\'" nIdx = cSet[i].atomIndex } } nextAtomName = "O3\'" break case "O3\'" : for (var i = 1; i <= cSet.size; i++) { if (cSet[i].element == "O") { s[1] = i newGreek[1] = "3\'" o3pIdx = cSet[i].atomIndex } else { s[2] = i newGreek[2] = "2\'" nIdx = cSet[i].atomIndex } } nextAtomName = "C2\'" break case "C2\'" : pIdx = -1 for (var i = 1; i <= cSet.size; i++) { if (cSet[i].element == "P") { pIdx = cSet[i].atomIndex cSet = cSet and not cSet[i] break } } for (var i = 1; i <= cSet.size; i++) { if (cSet[i].element == "O") { s[1] = i newGreek[1] = "2\'" isRNA = true } else { s[2] = i newGreek[2] = "1\'" c1pIdx = cSet[i].atomIndex nIdx = cSet[i].atomIndex } } nextAtomName = "C1\'" break case "C1\'" : for (var i = 1; i <= cSet.size; i++) { if (cSet[i].element == "N") { iKeep = i nIdx = cSet[i].atomIndex } else if ((cSet[i].element == "C") and ((connected(cSet[i]) and {oxygen}).size == 0)) { #PSU psu = true iKeep = i nIdx = cSet[i].atomIndex } else { cSet[i].selected = false } } cSet = cSet[iKeep] var ccSet = connected(cSet[1]) and not {atomIndex=c1pIdx} newGreek[1] = "9" nextAtomName = "N9u" newGroup = "PU" for (var j = 1; j <= ccSet.size; j++) { if ((connected(ccSet[j]) and {oxygen}) > 0) { newGreek[1] = "1" nextAtomName = "N1y" newGroup = "PY" } } break case "N1y" : for (var i = 1; i <= cSet.size; i++) { if (connected(cSet[i]) > 2) { iKeep = i nIdx = cSet[i].atomIndex } else { stopIdx = cSet[i].atomIndex } } cSet = cSet[iKeep] newGreek[1] = "2" nextAtomName = "C2" break case "N9u" : # Find N-C-N-C-N for (var i = 1; i <= cSet.size; i++) { var n1atom = (connected(cSet[i]) and {nitrogen} and not {atomIndex=nIdx}) var c2set = connected(n1atom) and {carbon} and not cSet[i] for (var j = 1; j <= c2set.size; j++) { if ((connected(c2set[j]) and {nitrogen}) > 1) { iDrop = i } } } stopIdx = cSet[iDrop].atomIndex cSet = cSet and not cSet[iDrop] nIdx = cSet[1].atomIndex newGreek[1] = "8" nextAtomName = "C8" break case "C8" : nIdx = ring_common( cSet, nIdx, s, newGreek, "7") nextAtomName = "N7" break case "N7" : nIdx = ring_common( cSet, nIdx, s, newGreek, "5") nextAtomName = "C5" break case "C5" : if (isRNA and (newGroup == "DU ")) { var c5set = {atomIndex=nIdx} or connected({atomIndex=nIdx}) if (angle(c5set[1], c5set[2], c5set[3]) < 114.0) { newGroup = "D " } } nIdx = ring_common( cSet, nIdx, s, newGreek, "6") if ((newGroup == "DU ") and (cSet.size > 1)) { newGroup = "DT " } nextAtomName = "C6" break case "C6" : if (newGroup == "PU") { nIdx = ring_common( cSet, nIdx, s, newGreek, "1") newGroup = ((cSet[1].element == "O") ? "DG " : "DA ") nextAtomName = "N1" } else { if (psu) { psu = false newGroup = "DU " } cSet = ({}) } break case "N1" : if (connected({atomIndex=nIdx}).size > 2) { # YG newGroup = "X " } nIdx = ring_common( cSet, nIdx, s, newGreek, "2") nextAtomName = "C2" break case "C2" : nIdx = ring_common( cSet, nIdx, s, newGreek, "3") nextAtomName = "N3" stopIdx = -1 break case "N3" : nIdx = ring_common( cSet, nIdx, s, newGreek, "4") nextAtomName = "C4" break case "C4" : if (newGroup != "PY") { cSet = ({}) } else { nIdx = ring_common( cSet, nIdx, s, newGreek, "5") newGroup = ((cSet[1].element == "N") ? "DC " : "DU ") nextAtomName = "C5" } break } first = false for (var i = 1; i <= cSet.size; i++) { rs += format("ATOM %5d %-4sUNK ", newAtomNo, (cSet[i].element + newGreek[s[i]])) rs += format("%s%4d %8.3f", newChain, newResno, cSet[i].x) rs += format("%8.3f%8.3f\n", cSet[i].y, cSet[i].z) newAtomno++ } cSet = (connected(cSet and not {atomIndex=stopIdx}) and not cSet and not {atomIndex=stopIdx} and not {atomIndex=endIdx}) endIdx = nIdx if (cSet.size == 0) { if (isRNA) { newGroup = (newGroup.replace("DA ","A ").replace("DG ","G ") .replace("DC ","C ").replace("DT ","T ").replace("DU ","U ")) } ls += rs.replace("UNK", newGroup) rs = "" newResno++ if (pIdx >= 0) { cSet = {atomIndex=pIdx} nextAtomName = "P" newGroup = "UNK" newGreek[1] = "" c1pIdx = -1 stopIdx = o3pIdx endIdx = -1 isRNA = false } else { break } } } # endwhile # Replace chain with new chain cset = {atomIndex=idx} select cSet while (cSet) { cSet = connected({selected}) and not {selected} select {selected} or cSet } delete {selected} ls += "end \"append remapNT\"" gAppendNew = appendNew set appendNew false script inline @{ls} set appendNew gAppendNew } else { color {selected} @gScheme } print_1c_chain( newChain) } function print_1c_chain(iChain) { var resmin = get_resno_min(iChain) var resmax = get_resno_max(iChain) var rchar = (({(resno=resmin) and (chain=iChain) and thisModel}.group[0].size > 1) ? "" : "R") var lcAtoms = (within(3.1, false, {(resno=resmin) and (chain=iChain) and thisModel and base}) and not {(resno=resmin) and (chain=iChain) and thisModel}) var chain2 = "" var schar = "S" if (lcAtoms) { chain2 = lcAtoms[1].chain if (((rchar == "R") and (lcAtoms[1].group.size > 1)) or ((rchar == "") and (lcAtoms[1].group.size == 1))) { schar = "M" } else { schar = "S" chain2 = "" } } var ls = format("%s%s:%s", iChain, chain2, format("%s%s", rchar, schar)) for (var i = get_resno_min(iChain); i <= get_resno_max(iChain); i++) { ls += ({(resno=i) and (chain=iChain) and thisModel}.group[0])[0] } print ls } # Top level of Remap function plico_remap_nt() { # Load common functions if not already if (kCommon < 7) { script $SCRIPT_PATH$plicoCommon.spt if (kCommon < 7) { prompt ("A newer version of plicoCommon.SPT is required") quit } } gPlico = "RemapNT" plico_prelim(false, true) gEcho = "_____REMAP NT_____|ALT-CLICK=select NT chain|SHIFT-DOUBLE-CLICK=exit" echo @gEcho set picking ON bind "ALT-LEFT-CLICK" "_pickAtom"; bind "ALT-LEFT-CLICK" "+:remap_nt_cargo_mb"; bind "SHIFT-DOUBLE" "plico_exit(true)"; bind "LEFT-CLICK" "+:plico_menu_toggle"; } # End of REMAPNT.SPT