User:Remig/plico/modify
Modify allows the user to make common amino acid and nucleotide modification by mouse actions. Hover text above each atom gives the available options including methylation on nucleosides, single-bond oxygens, and nitrogens, hydroxylation of PRO, formylation of MET, ribose/deoxyribose interconversion, phophorylation of SER, THR, TYR and HIS, and conversions to pseudouridine, dihyrouridine, inosine, and xanthine.
Some features unrelated to modification have been placed here as well to serve other Plico functions. Water molecules may be added and moved around to serve as pivot points for Tug when no other atoms are where the pivot point is wanted. Also the Jmol parameters allowMoveAtoms and allowRotateSelected are set true while modify is active to allow free rotation and translation of selected atoms.
Modify 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 Modify Script=script <path to your scripts folder>/modify.spt;plicoModify
saved as plicoModify.macro in your .jmol/macros folder as described in Macro.
Copy and paste the following to a text editor and save to your scripts folder as modify.spt:
# modify - Jmol script by Ron Mignery
# v1.0 beta 2/22/2014 for Jmol 14
#
# See atom hover text for options:
# methyl on nucleosides, single-bond oxygens, and terminal N
# OH on ribose and proline, PO3 on SER, THR, TYR and HIS (2)
# pseudouridine and dihyrouridine, inosine, xanthine
# HOH singlet anywhere for phantom pivot and target atoms
# Enable jmol move for duration
var kCtolerance = 1.85
var gAllowMoveAtoms = allowMoveAtoms
var gAllowRotateSelected = allowRotateSelected
var gSelsave = ({})
var gScheme = defaultColorScheme
var gAltScheme = ((gScheme == "Jmol") ? "Rasmol" : "Jmol")
var gIsPlanar = FALSE
# Return L tetrahedron point if i1<i2<i3, else R point
function getTet(i1, i2, i3, dist) {
print format("getTet(%d, %d, %d, dist", i1, i2, i3)
var v1 = {atomIndex=i3}.xyz - {atomIndex=i2}.xyz
var v2 = {atomIndex=i1}.xyz - {atomIndex=i2}.xyz
var axis = cross(v1, v2)
var pma = ({atomIndex=i1}.xyz + {atomIndex=i3}.xyz)/2
var pmo = {atomIndex=i2}.xyz + {atomIndex=i2}.xyz - pma
var pt = pmo + (axis/axis)
var v = pt - {atomIndex=i2}.xyz
var cdist = distance(pt, {atomIndex=i2})
var factor = (dist/cdist)
var lpt = v * factor
return lpt + {atomIndex=i2}.xyz
}
# return vector parallel to previous bond
function getTet1(pIdx, idx) {
print format("getTet1(%d, %d)", pIdx, idx)
var cset = connected({atomIndex=pIdx}) and not {atomIndex=idx}
return {atomIndex=idx}.xyz + {atomIndex=pIdx}.xyz - cset[1].xyz
}
function getTrigonal(i1, i2, i3, dist) {
var v1 = {atomIndex=i1}.xyz - {atomIndex=i2}.xyz
var v2 = {atomIndex=i3}.xyz - {atomIndex=i2}.xyz
var pt = {atomIndex=i2}.xyz - (v1 + v2)
var v = pt - {atomIndex=i2}.xyz
var cdist = distance(pt, {atomIndex=i2})
var factor = (dist/cdist)
var lpt = (v * factor)
return lpt + {atomIndex=i2}.xyz
}
# Selected must include third parameter but not the first
function setAngleIdx (statorIdx, pivotIdx, rotorIdx, toangle) {
try {
var v1={atomIndex=statorIdx}.xyz - {atomIndex=pivotIdx}.xyz
var v2={atomIndex=rotorIdx}.xyz - {atomIndex=pivotIdx}.xyz
var axis = cross(v1, v2) + {atomIndex=pivotIdx}.xyz
var curangle = angle({atomIndex=statorIdx},
{atomIndex=pivotIdx}, {atomIndex=rotorIdx})
rotateselected @axis {atomIndex = pivotIdx} @{curangle-toangle}
}
catch {
}
}
function addToIdx(idx, aElement, greek, addOs) {
print format("addToIdx(%d, %s, %s, n)", idx, aElement, greek)
var iGroup = {atomIndex=idx}.group
var iResno = {atomIndex=idx}.resno
var iChain = {atomIndex=idx}.chain
var iAtomName = {atomIndex=idx}.atomName
var iAtomno = {atomIndex=idx}.atomno
var aAtomno = {chain=iChain}.atomno.max + 1
var cset = connected({atomIndex=idx})
var pt = {0 0 0}
if ((iGroup = "HIS") or ((({atomIndex=idx} and {amino}).size == 0)
and (iAtomName[1][2] != "OP") and (iAtomName[3] != "\'"))) {
pt = getTrigonal(cSet[1].atomIndex, idx, cSet[2].atomIndex, 1.5)
}
else {
if ((cSet.size == 2) and not greek.find("\'")) {
pt = getTet(cSet[1].atomIndex, idx, cSet[2].atomIndex, 1.5)
}
else if (cSet.size > 2) {
pt = getTet(cSet[2].atomIndex, idx, cSet[1].atomIndex, 1.5)
}
else {
pt = getTet1(cSet[1].atomIndex, idx)
}
}
if (greek.size < 2) {
greek += iAtomName[2]
}
var ls = "data \"append addto\"\n"
ls += format("ATOM %5d %-4s%3s ", aAtomno, aElement + greek, iGroup)
ls += format("%s%4d %8.3f", iChain, iResno, pt.x)
ls += format("%8.3f%8.3f\n", pt.y, pt.z)
ls += "end \"append addto\""
script inline @{ls}
var aIdx = {(atomno=aAtomno) and (chain=iChain)}.atomIndex
connect {atomIndex=idx} {atomIndex=aIdx}
if (addOs > 0) {
for (var i = 1; i <= addOs; i++) {
aAtomno++
var ccSet = connected({atomIndex=aIdx})
if (addOs == 1) {
pt = ({atomIndex=aIdx}.xyz +
({atomIndex=aIdx}.xyz - {atomIndex=idx}.xyz))
}
else if (addOs == 2) {
pt = getTrigonal(ccSet[1].atomIndex, aIdx, ccSet[2].atomIndex, 1.5)
}
else {
if (ccSet.size == 2) {
pt = getTet(ccSet[1].atomIndex, aIdx, ccSet[2].atomIndex, 1.5)
}
else if (ccSet.size == 3) {
pt = getTet(ccSet[2].atomIndex, aIdx, ccSet[1].atomIndex, 1.5)
}
else {
pt = getTet1(ccSet[1].atomIndex, aIdx)
}
}
ls = "data \"append addto\"\n"
ls += format("ATOM %5d O%s%d ", aAtomno,
{atomIndex=aIdx}.AtomName[1], i)
ls += format("%3s %s%4d ", iGroup, iChain, iResno)
ls += format("%8.3f%8.3f%8.3f\n", pt.x, pt.y, pt.z)
ls += "end \"append addto\""
script inline @{ls}
oIdx = {(atomno=aAtomno) and (chain=iChain)}.atomIndex
connect {atomIndex=aIdx} {atomIndex=oIdx}
}
}
setHoverLabels()
}
function removeFromIdx(idx) {
var cSet = connected({atomIndex=idx})
if ({atomIndex=idx}.atomName[2] != "M") {
for (var i = 1; i <= cSet.size; i++) {
if ((cSet[i].atomName[2] == "P") or (cSet[i].atomName[2] == "O")) {
delete @{cSet[i]}
}
}
}
}
function toXidx(idx, newElement, newGroup) {
var cSet = {resno=@{{atomIndex=idx}.resno}}
var ls = "data \"append toX\"\n"
for (var i = 1; i <= cSet.size; i++) {
var iName = cSet[i].atomName
if (idx == cSet[i].atomIndex) {
iName[1] = newElement
}
ls += format("ATOM %5d %-3s ", cSet[i].atomno, iName)
ls += format("%3s %s%4d ", newGroup,
{atomIndex=idx}.chain, cSet[i].resno)
ls += format("%8.3f%8.3f%8.3f\n", cSet[i].x, cSet[i].y, cSet[i].z)
}
ls += "end \"append toX\""
delete cSet
script inline @{ls}
connect
}
function toPUidx(idx, undoIt) {
var iResno = {atomIndex=idx}.resno
var a1idx = {(resno=iResno) and (atomName="O2")}.atomIndex
var a2idx = {(resno=iResno) and (atomName="O4")}.atomIndex
var xyz = {0 0 0} + {atomIndex=a1idx}.xyz
{atomIndex=a1idx}.xyz = {0 0 0} + {atomIndex=a2idx}.xyz
{atomIndex=a2idx}.xyz = xyz
a1idx = {(resno=iResno) and (atomName="C2")}.atomIndex
a2idx = {(resno=iResno) and (atomName="C4")}.atomIndex
xyz = {0 0 0} + {atomIndex=a1idx}.xyz
{atomIndex=a1idx}.xyz = {0 0 0} + {atomIndex=a2idx}.xyz
{atomIndex=a2idx}.xyz = xyz
a1idx = {(resno=iResno) and (atomName="N1")}.atomIndex
a2idx = {(resno=iResno) and (atomName="C5")}.atomIndex
xyz = {0 0 0} + {atomIndex=a1idx}.xyz
{atomIndex=a1idx}.xyz = {0 0 0} + {atomIndex=a2idx}.xyz
{atomIndex=a2idx}.xyz = xyz
var a3idx = {(resno=iResno) and (atomName="c1\'")}.atomIndex
connect (atomIndex=a3idx) (atomindex=a1idx) DELETE
connect (atomIndex=a3idx) (atomindex=a2idx)
if (undoit) {
toXidx(idx, "C", "U")
}
else {
toXidx(idx, "N", "PU")
}
}
function toDidx(idx) {
print format("toDidx(%d)", idx)
delay
gIsPlanar = FALSE
var iResno = {atomIndex=idx}.resno
var iChain = {atomIndex=idx}.chain
var rSet = {(resno=iResno) and (chain=iChain)}
var n1 = {rSet and (atomName="N1")}
var c2 = {rSet and (atomName="C2")}
var o2 = {rSet and (atomName="O2")}
var n3 = {rSet and (atomName="N3")}
var c4 = {rSet and (atomName="C4")}
var o4 = {rSet and (atomName="O4")}
var c5 = {rSet and (atomName="C5")}
var c6 = {rSet and (atomName="C6")}
var a1 = angle(n1, c6, c5, c4)\10
var a2 = angle(c6, c5, c4, n3)\10
print format("a1=%d a2=%d", a1, a2)
# N1-C6-C5-C4 = 0.5 C6-C5-C4-N3 = 0.8
if ((a1 == 0) or (a1 == -1)) {
# Planar to Chair 1
axis = (c2.xyz - c6.xyz + n1.xyz)
select c2 or o2 or n3 or c4 or o4 or c5 or c6
rotateSelected @n1 @axis 40
select o2 or n3 or c4 or o4 or c5
rotateSelected @c2 @c6 40
select c4 or o4
rotateSelected @c5 @n3 40
}
# N1-C6-C5-C4 = -41.0 C6-C5-C4-N3 = -46.0
else if ((a1 == -5) and ((a2 == 5) or (a2 == 4))) {
# Chair 1 to boat 1 twist 1 `
select c4 or o4
rotateSelected @c5 @n3 -80
select o2 or n3 or c4 or o4 or c5
rotateSelected @n1 @c4 25
}
# N1-C6-C5-C4 = 41.6 C6-C5-C4-N3 = 23.3
else if (((a1 == 3) or (a1 == 4)) and (a2 == -7)) {
# Boat 1 twist 1 to boat 1 twist 2
rotateSelected @n1 @c4 -50
}
# N1-C6-C5-C4 = -40.2 C6-C5-C4-N3 = 70.0
else if (((a1 == -4) or (a1 == -5)) and ((a2 == -3) or (a2 == -2))) {
# Boat1 twist 2 to chair 2
rotateSelected @n1 @c4 25
axis = (c2.xyz - c6.xyz + n1.xyz)
select c2 or o2 or n3 or c4 or o4 or c5 or c6
rotateSelected @n1 @axis -80
select o2 or n3 or c4 or o4 or c5
rotateSelected @c2 @c6 -80
}
# N1-C6-C5-C4 = 41.8 C6-C5-C4-N3 = -44.10
else if ((a1 == 4) and (a2 == -5)) {
# Chair 2 to boat 2 twist 1` `
select c4 or o4
rotateSelected @c5 @n3 80
select o2 or n3 or c4 or o4 or c5
rotateSelected @n1 @c4 25
}
# N1-C6-C5-C4 = 41.2 C6-C5-C4-N3 = -68.5
else if ((a1 == 4) and ((a2 == 1) or (a2 == 2))) {
# Boat 2 twist 1 to boat 2 twist 2
rotateSelected @n1 @c4 -50
}
# N1-C6-C5-C4 = -41.3 C6-C5-C4-N3 = 64.5
else if ((a1 == -5) and (a2 == 6)) {
# Boat 2 twist 2 to planar
rotateSelected @n1 @c4 25
select c4 or o4
rotateSelected @c5 @n3 -40
axis = (c2.xyz - c6.xyz + n1.xyz)
select c2 or o2 or n3 or c4 or o4 or c5 or c6
#quit
rotateSelected @n1 @axis 40
select o2 or n3 or c4 or o4 or c5
rotateSelected @c2 @c6 40
gIsPlanar = TRUE
}
else {
print format("a1=%d a2=%d", a1, a2)
}
}
function setHoverLabels() {
select all
set hoverLabel "%U"
select ({(atomName="?O?")} or {(atomName="?P?") and {amino}})
set hoverLabel "%U|1: -X"
select (oxygen or sulfur) and not *.O and (bondCount = 1)
select {selected} or (nitrogen and (bondCount < 3))
set hoverLabel "%U|1: -CH3"
select (not {amino} and not oxygen and (bondCount < 3))
set hoverLabel "%U|1: -CH3"
select ({(atomName="?M?")} or {group="HOH"})
set hoverLabel "%U|1: -X"
# MET N fMET
select (MET.N and (bondCount == 1))
set hoverLabel "%U|1: -CH3|2: -CO"
select (MET.N and (bondCount == 2))
set hoverLabel "%U|1: -CH3|2: -X"
# ASP OD1 OD2 P
select ASP.OD1 or ASP.OD2 or HIS.ND1 or SER.OG or THR.OG1 OR TYR.OH
set hoverLabel "%U|1: -CH3|2: -PO3"
# PRO CG HYP
select PRO.CG
set hoverLabel "%U|1: -CH3|2: -OH"
# A N6 I
select [A].N6 or [I].O6
set hoverLabel "%U|1: -CH3|2: A <--> I"
# G N2 X
select [G].N2 or [X].O2
set hoverLabel "%U|1: -CH3|2: G <--> X"
# U N1 PU
select [U].N1 or [PU].C5
set hoverLabel "%U|1: -CH3|2: U <--> PU"
# U C5-6 HU
select [U].C6
set hoverLabel "%U|1: -CH3|2: U --> D"
# U C5-6 HU
select [D].C6
set hoverLabel "%U|1: ->Conformers|2: D --> U"
# U C5 M T
select [U].C5 OR [T].C5
set hoverLabel "%U|1: -CH3|2: U <--> T"
# *.?2' -X
select ??.?2'
set hoverLabel "%U|1: -CH3|2: X <--> DX"
refresh
}
function addWaterMB() {
var idx = _atomPicked
var iChain = {atomIndex=idx}.chain
var pt = {0 0 0}
var cSet = connected({atomIndex=idx})
if (cSet.size == 2) {
pt = getTet(cSet[1].atomIndex, idx, cSet[2].atomIndex, 2.3)
}
else if (cSet.size == 3) {
pt = getTet(cSet[2].atomIndex, idx, cSet[1].atomIndex, 2.3)
}
else {
var v = {atomIndex=idx}.xyz - cSet[1].xyz
pt = {atomIndex=idx}.xyz + v + v
}
if (within(kCtolerance, FALSE, pt).size == 0) {
var ls = "data \"append addto\"\n"
ls += format("ATOM %5d O HOH %s%4d ",
{*}.atomno.max + 1, iChain, {*}.resno.max + 1)
ls += format("%8.3f%8.3f%8.3f\n", pt.x, pt.y, pt.z)
ls += "end \"append addto\""
script inline @{ls}
setHoverLabels()
}
}
function modify1MB() {
print "modify1MB"
var idx = _atomPicked
var isAmino = ({(atomIndex=idx) and {amino}}.size > 0)
var iName = {atomIndex=idx}.atomName
var iGroup = {atomIndex=idx}.group
if (iGroup == "HOH") {
delete {atomIndex=idx}
}
else if (iGroup == "D") {
toDidx(idx)
if(gIsPlanar) {
toDidx(idx)
}
}
else if ((iName[2]="M") or (iName[2]="O")
or (isAmino and ((iName[1]="P") or (iName[2]=="P")))) {
removeFromIdx(idx)
delete {atomIndex=idx}
}
else {
if ({atomIndex=idx}.element="P") {
if (isAmino) {
removeFromIdx(idx)
}
}
else if (({atomIndex=idx}.element="O")
and ({atomIndex=idx}.atomName!="O")
and ({atomIndex=idx}.bondCount=1)) {
addToIdx(idx, "C", "M", 0)
}
else if (({atomIndex=idx}.element!="O")
and ({atomIndex=idx}.bondCount < 3)) {
addToIdx(idx, "C", "M", 0)
}
else if (isAmino) {
removeFromIdx(idx)
}
}
}
function modify2MB() {
var idx = _atomPicked
var iGroup = {atomIndex=idx}.group
var iName = {atomIndex=idx}.atomName
var iResno = {atomIndex=idx}.resno
var iChain = {atomIndex=idx}.chain
# MET.N fMET
if ((iGroup="MET") and (iName="N")) {
if ({atomIndex=idx}.bondCount == 1) {
addToIdx(idx, "C", "F", 1)
}
else {
delete {(resno=iResno) and (chain=iChain) and (atomName="CF")}
delete {(resno=iResno) and (chain=iChain) and (atomName="OC1")}
}
}
# ASP.OD1 or ASP.O or HIS.ND1 or SER.OG or THR.OG1 OR TYR.OH PO3
else if (((iGroup="HIS") and (iName="ND1"))
or ((iGroup="SER") and (iName="OG"))
or ((iGroup="THR") and (iName="OG1"))
or ((iGroup="TYR") and (iName="OH"))
or ((iGroup="ASP") and (iName[1][2]="OD"))) {
if (({atomIndex=idx}.bondCount == 1)
or ((iName="ND1") and ({atomIndex=idx}.bondCount == 2))) {
addToIdx(idx, "P", "", 3)
}
else {
removeFromIdx(idx)
}
}
# PRO.CG HYP
else if ((iGroup="PRO") and (iName="CG")) {
if ({atomIndex=idx}.bondCount == 2) {
addToIdx(idx, "O", "H", 0)
}
else {
removeFromIdx(idx)
}
}
# A.N6 I
else if ((iGroup="A") and (iName="N6")) {
toXidx(idx, "O", "I")
}
else if ((iGroup="I") and (iName="O6")) {
toXidx(idx, "N", "A")
}
# G.N2 X
else if ((iGroup="G") and (iName="N2")) {
toXidx(idx, "O", "X")
}
else if ((iGroup="X") and (iName="O2")) {
toXidx(idx, "N", "G")
}
# U.N1 PU
else if ((iGroup="U") and (iName="N1")) {
toPUidx(idx, FALSE)
}
else if ((iGroup="PU") and (iName="C5")) {
toPUidx(idx, TRUE)
}
# U.C5 T
else if ((iGroup="U") and (iName="C5")) {
addToIdx(idx, "C", "7 ", 0)
toXidx(idx, "C", "T")
}
else if ((iGroup="T") and (iName="c5")) {
delete {(resno=iResno) and (atomName="C7")}
toXidx(idx, "C", "U")
}
# U.C6 HU
else if ((iGroup="U") and ((iName="C5") or (iName="C6"))) {
toXidx(idx, "C", "D")
toDidx(idx)
}
else if ((iGroup="D") and ((iName="C5") or (iName="C6"))) {
for (var i = 0; i < 10; i++) {
toDidx(idx)
if (gIsPlanar) {
break
}
}
toXidx(idx, "C", "U")
}
# O2'
else if (iName="O2\'") {
var cIdx = connected({atomIndex=idx})[1].atomIndex
delete {atomIndex=idx}
toXidx(cIdx, "C", "D"+iGroup)
}
# C2'
else if (iName="C2\'") {
var ccSet = connected({atomIndex=idx})
if ((ccSet.size < 3) and (iGroup.size > 1)) {
addToIdx(idx, "O", "2\'", 0)
toXidx(idx, "C", iGroup[2])
}
else if (iGroup.size == 1) {
for (var i = 1; i <= ccSet.size; i++) {
if (ccSet[i].element == "O") {
delete {atomIndex=@{ccSet[i].atomIndex}}
toXidx(idx, "C", "D"+iGroup)
}
}
}
}
setHoverLabels()
print "modify2MB"
}
function selectChainMB() {
print "selectChainMB"
var cset = {atomIndex=_atomPicked}
select cSet
while (cSet.size > 0) {
cSet = connected({selected}) and not {selected}
select {selected} or cSet
}
color {selected} @gAltScheme
}
function modifyExitMB() {
unbind
set echo TOP LEFT
echo
set allowRotateSelected gAllowRotateSelected
set allowMoveAtoms gAllowMoveAtoms
set hoverDelay gHoverDelay
select all
set hoverLabel = ""
color {selected} @gScheme
select {gSelsave}
}
# Top level of Modify
function plicoModify() {
gSelsave = {selected}
gAllowMoveAtoms = allowMoveAtoms
gAllowRotateSelected = allowRotateSelected
gHoverDelay = hoverDelay
set allowMoveAtoms TRUE
set allowRotateSelected TRUE
gPlico = "MODIFY"
gScheme = defaultColorScheme
gAltScheme = ((gScheme == "Jmol") ? "Rasmol" : "Jmol")
set echo TOP LEFT
background ECHO yellow
gEcho = ("________MODIFY________|ALT-CLICK=change 1|SHIFT-CLICK=change 2|" +
"ALT-SHIFT-CLICK=select chain|ALT-CTRL-CLICK=add water|ALT-DRAG=rotate selected|" +
"ALT-SHIFT_DRAG=move selected|DOUBLE-CLICK=exit")
echo @gEcho
gChain = ""
unbind
bind "ALT-LEFT-CLICK" "_pickAtom";
bind "ALT-LEFT-CLICK" "+:modify1MB";
bind "SHIFT-LEFT-CLICK" "_pickAtom";
bind "SHIFT-LEFT-CLICK" "+:modify2MB";
bind "ALT-SHIFT-LEFT-CLICK" "_pickAtom";
bind "ALT-SHIFT-LEFT-CLICK" "+:selectChainMB";
bind "ALT-CTRL-LEFT-CLICK" "_pickAtom";
bind "ALT-CTRL-LEFT-CLICK" "+:addWaterMB";
bind "DOUBLE" "modifyExitMB";
set hoverDelay 0.001
hover on
setHoverLabels()
}
# End of MODIFY.SPT