User:Remig/plico/modify
Modify allows the user to make common amino acid and nucleotide modifications by mouse actions. Hover text above each atom gives the available options if any including methylation on nucleosides, single-bond oxygens, and nitrogens, hydroxylation of PRO, formylation of MET, ribose/deoxyribose interconversion, phosphorylation of SER, THR, TYR and HIS, and nucleotide modifications to generate pseudouridine, dihyrouridine, inosine, and xanthine.
Modifications indicated with 1: are performed with ALT-CLICK on the atom. Modifications indicated with 2: are performed with SHIFT-CLICK on the atom.
See Convert for a script to replace one amino-acid with another or one nucleotide with another.
After a modification adding atoms, the hover text on those atoms includes 'X' to remove the modification. Note also that the desired modification may be presented in the hover text on only just one or a few of the atoms of the residue to be modified and you may have to look around to find it.
Some features unrelated to modification have been placed here as well to serve other Plico functions. Water molecules may be added and moved around perhaps to serve as pivot points for Tug when no other atoms are where the pivot point is wanted.
Also the Jmol parameters allowMoveAtoms, allowRotateSelected, and dragSelected are set true while modify is active to allow free rotation and translation of selected atoms where ALT-DRAG rotates the selection and ALT-SHIFT-DRAG moves it. Note that the select chain option in Modify selects all atoms connected to the clicked atom, not those sharing the chain label with the clicked atom.
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 directory>/modify.spt;plico_modify
saved as plicoModify.macro in your .jmol/macros directory as described in Macro.
Copy and paste the following to a text editor and save to your scripts directory as modify.spt:
# modify - Jmol script by Ron Mignery
# v1.11 beta 9/11/2015 -use thisModel
#
# 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
gAllowMoveAtoms = allowMoveAtoms
gAllowRotateSelected = allowRotateSelected
gDragSelected = dragSelected
gSelsave = ({})
gScheme = defaultColorScheme
gAltScheme = ((gScheme == "Jmol") ? "Rasmol" : "Jmol")
gIsPlanar = false
gAppendNew = false
gHoverLabel = ""
# return vector parallel to previous bond
function get_tet_1(pIdx, idx) {
var cset = connected({atomIndex=pIdx}) and not {atomIndex=idx}
return {atomIndex=idx}.xyz + {atomIndex=pIdx}.xyz - cset[1].xyz
}
function add_to_idx(idx, aElement, greek, addOs) {
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) and thisModel}.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] != "\'")
and (cset.size > 1))) {
pt = get_trigonal_idx(cSet[1].atomIndex, idx, cSet[2].atomIndex, 1.5)
}
else {
if ((cSet.size == 2) and not greek.find("\'")) {
pt = get_tet_idx(cSet[1].atomIndex, idx, cSet[2].atomIndex, 1.5)
}
else if (cSet.size > 2) {
pt = get_tet_idx(cSet[2].atomIndex, idx, cSet[1].atomIndex, 1.5)
}
else {
pt = get_tet_1(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\""
gAppendNew = appendNew
appendNew = false
script inline @{ls}
appendNew = gAppendNew
var aIdx = {(atomno=aAtomno) and (chain=iChain)
and thisModel}.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 = get_trigonal_idx(ccSet[1].atomIndex, aIdx, ccSet[2].atomIndex, 1.5)
}
else {
if (ccSet.size == 2) {
pt = get_tet_idx(ccSet[1].atomIndex, aIdx, ccSet[2].atomIndex, 1.5)
}
else if (ccSet.size == 3) {
pt = get_tet_idx(ccSet[2].atomIndex, aIdx, ccSet[1].atomIndex, 1.5)
}
else {
pt = get_tet_1(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\""
gAppendNew = appendNew
appendNew = false
script inline @{ls}
appendNew = gAppendNew
oIdx = {(atomno=aAtomno) and (chain=iChain)
and thisModel}.atomIndex
connect {atomIndex=aIdx} {atomIndex=oIdx}
}
}
set_hover_labels()
}
function remove_from_idx(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 to_x_idx(idx, newElement, newGroup) {
var r = {atomIndex=idx}.resno
var cSet = {(resno=r) and thisModel}
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
gAppendNew = appendNew
appendNew = false
script inline @{ls}
appendNew = gAppendNew
var aP = get_atom_rcn(r, iChain, "P")
var aO3p = get_atom_rcn(r-1, iChain, "O3\'")
connect @aP @aO3p
var aO3 = get_atom_rcn(r, iChain, "O3\'")
var aPn = get_atom_rcn(r+1, iChain, "P")
connect @aO3 @aPn
}
function to_pu_idx(idx, undoIt) {
var iResno = {atomIndex=idx}.resno
var iChain = {atomIndex=idx}.chain
var a1 = get_atom_rcn(iResno, iChain, "O2")
var a2 = get_atom_rcn(iResno, iChain, "O4")
var xyz = {0 0 0} + a1.xyz
a1.xyz = {0 0 0} + a2.xyz
a2.xyz = xyz
a1 = get_atom_rcn(iResno, iChain, "C2")
a2 = get_atom_rcn(iResno, iChain, "C4")
xyz = {0 0 0} + a1.xyz
a1.xyz = {0 0 0} + a2.xyz
a2.xyz = xyz
a1 = get_atom_rcn(iResno, iChain, "N1")
a2 = get_atom_rcn(iResno, iChain, "C5")
xyz = {0 0 0} + a1.xyz
a1.xyz = {0 0 0} + a2.xyz
a2.xyz = xyz
var a3 = get_atom_rcn(iResno, iChain, "C1\'")
connect @a3 @a1 DELETE
connect @a3 @a2
if (undoit) {
to_x_idx(idx, "C", "U")
}
else {
to_x_idx(idx, "N", "PSU")
}
}
function to_d_idx(idx) {
delay
gIsPlanar = false
var iResno = {atomIndex=idx}.resno
var iChain = {atomIndex=idx}.chain
var n1 = get_atom_rcn(iResno, iChain, "N1")
var c2 = get_atom_rcn(iResno, iChain, "C2")
var o2 = get_atom_rcn(iResno, iChain, "O2")
var n3 = get_atom_rcn(iResno, iChain, "N3")
var c4 = get_atom_rcn(iResno, iChain, "C4")
var o4 = get_atom_rcn(iResno, iChain, "O4")
var c5 = get_atom_rcn(iResno, iChain, "C5")
var c6 = get_atom_rcn(iResno, iChain, "C6")
var a1 = angle(n1, c6, c5, c4)\10
var a2 = angle(c6, c5, c4, n3)\10
# 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
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 set_hover_labels() {
select (thisModel)
set hoverLabel "%U"
select ({(atomName="?O?")} or {(atomName="?P?") and {amino}}
and thisModel)
set hoverLabel "%U|1: -X"
select ((((oxygen or sulfur) and not *.O and (bondCount = 1))
or (nitrogen and (bondCount < 3))) and thisModel)
set hoverLabel "%U|1: -CH3"
select (not amino and not oxygen and (bondCount < 3)
and thisModel)
set hoverLabel "%U|1: -CH3"
select (((atomName="?M?") or (group="HOH")) and thisModel)
set hoverLabel "%U|1: -X"
# MET N fMET
select (MET.N and (bondCount == 1) and thisModel)
set hoverLabel "%U|1: -CH3|2: -CO"
select (MET.N and (bondCount == 2) and thisModel)
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)
and thisModel)
set hoverLabel "%U|1: -CH3|2: -PO3"
# PRO CG HYP
select PRO.CG and thisModel
set hoverLabel "%U|1: -CH3|2: -OH"
# A N6 I
select ([A].N6 or [I].O6) and thisModel
set hoverLabel "%U|1: -CH3|2: A <--> I"
# G N2 X
select ([G].N2 or [X].O2) and thisModel
set hoverLabel "%U|1: -CH3|2: G <--> X"
# U N1 PU
select ([U].N1 or [PU].C5) and thisModel
set hoverLabel "%U|1: -CH3|2: U <--> PU"
# U C5-6 HU
select [U].C6 and thisModel
set hoverLabel "%U|1: -CH3|2: U --> D"
# U C5-6 HU
select [D].C6 and thisModel
set hoverLabel "%U|1: ->Conformers|2: D --> U"
# U C5 M T
select ([U].C5 OR [T].C5) and thisModel
set hoverLabel "%U|1: -CH3|2: U <--> T"
# *.?2' -X
select ??.?2' and thisModel
set hoverLabel "%U|1: -CH3|2: X <--> DX"
select (thisModel)
refresh
}
function add_water_mb() {
f = _frameID/1000000
m = _frameID%1000000
var idx = _atomPicked
var iChain = {atomIndex=idx}.chain
var pt = {0 0 0}
var cSet = connected({atomIndex=idx})
var tri = false
if (cSet.size == 1) {
var v = {atomIndex=idx}.xyz - cSet[1].xyz
pt = {atomIndex=idx}.xyz + v + v
}
else {
pt = get_trigonal_idx(cSet[1].atomIndex, idx, cSet[2].atomIndex, 2.3)
tri = true
}
var ls = "data \"append addto\"\n"
ls += format("ATOM %5d O HOH %s%4d ",
{(chain=iChain) andthisModel}.atomno.max + 1, iChain,
get_resno_max(iChain) + 1)
ls += format("%8.3f%8.3f%8.3f\n", pt.x, pt.y, pt.z)
ls += "end \"append addto\""
gAppendNew = appendNew
appendNew = false
script inline @{ls}
appendNew = gAppendNew
var ap = {atomIndex=idx}
var ahoh = {(group="HOH") and within(2.9, ap)}
select @ahoh
color pink
set_distance_atoms(ap, ahoh, 2.3)
if (tri = false) {
var hidx = ahoh.atomIndex
var ccSet = connected(cSet[1])
set_angle_idx(cSet[1].atomIndex, idx, hidx, 120)
set_dihedral_idx(ccSet[1].atomIndex, cSet[1].atomIndex, idx, hidx, 180)
var xset = within(kCtolerance, ahoh) and not ahoh
if ( xset) {
set_dihedral_idx(ccSet[1].atomIndex, cSet[1].atomIndex, idx, hidx, 0)
}
}
var i = 0
for (; i < 360; i += 5) {
var xset = within(kCtolerance, ahoh) and not ahoh
if (xset.size == 0) {
set_hover_labels()
break
}
else if ((xset.size == 1) and (xset[1].group == "HOH")) {
print "share it TBD"
i = 360
break
}
else if (tri) {
i = 360
break
}
rotateSelected @{cset[1]} {atomIndex=idx} 5
} # endfor
if ( i >= 360) {
print "no room for water"
delete ahoh
}
}
function modify_1_mb() {
var idx = _atomPicked
var isAmino = ({(atomIndex=idx) and {amino}})
var iName = {atomIndex=idx}.atomName
var iGroup = {atomIndex=idx}.group
if (iGroup == "HOH") {
delete {atomIndex=idx}
}
else if (iGroup == "D") {
to_d_idx(idx)
if(gIsPlanar) {
to_d_idx(idx)
}
}
else if ((iName[2]="M") or (iName[2]="O")
or (isAmino and ((iName[1]="P") or (iName[2]=="P")))) {
remove_from_idx(idx)
delete {atomIndex=idx}
}
else {
if ({atomIndex=idx}.element="P") {
if (isAmino) {
remove_from_idx(idx)
}
}
else if (({atomIndex=idx}.element="O")
and ({atomIndex=idx}.atomName!="O")
and ({atomIndex=idx}.bondCount=1)) {
add_to_idx(idx, "C", "M", 0)
}
else if (({atomIndex=idx}.element!="O")
and ({atomIndex=idx}.bondCount < 3)) {
add_to_idx(idx, "C", "M", 0)
}
else if (isAmino) {
remove_from_idx(idx)
}
}
}
function modify_2_mb() {
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) {
add_to_idx(idx, "C", "F", 1)
}
else {
delete get_atom_rcn(iResno, iChain, "CF")
delete get_atom_rcn(iResno, iChain, "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))) {
add_to_idx(idx, "P", "", 3)
}
else {
remove_from_idx(idx)
}
}
# PRO.CG HYP
else if ((iGroup="PRO") and (iName="CG")) {
if ({atomIndex=idx}.bondCount == 2) {
add_to_idx(idx, "O", "H", 0)
}
else {
remove_from_idx(idx)
}
}
# A.N6 I
else if ((iGroup="A") and (iName="N6")) {
to_x_idx(idx, "O", "I")
}
else if ((iGroup="I") and (iName="O6")) {
to_x_idx(idx, "N", "A")
}
# G.N2 X
else if ((iGroup="G") and (iName="N2")) {
to_x_idx(idx, "O", "X")
}
else if ((iGroup="X") and (iName="O2")) {
to_x_idx(idx, "N", "G")
}
# U.N1 PU
else if ((iGroup="U") and (iName="N1")) {
to_pu_idx(idx, false)
}
else if ((iGroup="PSU") and (iName="C5")) {
to_pu_idx(idx, true)
}
# U.C5 T
else if ((iGroup="U") and (iName="C5")) {
add_to_idx(idx, "C", "7 ", 0)
to_x_idx(idx, "C", "T")
}
else if ((iGroup="T") and (iName="c5")) {
delete get_atom_rcn(iResno, iChain, "C7")
to_x_idx(idx, "C", "U")
}
# U.C6 HU
else if ((iGroup="U") and ((iName="C5") or (iName="C6"))) {
to_x_idx(idx, "C", "D")
to_d_idx(idx)
}
else if ((iGroup="D") and ((iName="C5") or (iName="C6"))) {
for (var i = 0; i < 10; i++) {
to_d_idx(idx)
if (gIsPlanar) {
break
}
}
to_x_idx(idx, "C", "U")
}
# O2'
else if (iName="O2\'") {
var cIdx = connected({atomIndex=idx})[1].atomIndex
delete {atomIndex=idx}
to_x_idx(cIdx, "C", "D"+iGroup)
}
# C2'
else if (iName="C2\'") {
var ccSet = connected({atomIndex=idx})
if ((ccSet.size < 3) and (iGroup.size > 1)) {
add_to_idx(idx, "O", "2\'", 0)
to_x_idx(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}}
to_x_idx(idx, "C", "D"+iGroup)
}
}
}
}
set_hover_labels()
}
function select_chain_mb() {
var cset = {atomIndex=_atomPicked}
select cSet
while (cSet) {
cSet = connected({selected}) and not {selected}
select {selected} or cSet
}
color {selected} @gAltScheme
color {selected and oxygen} pink
}
function modify_exit_mb() {
if (plico_exit(true)) {
set allowRotateSelected gAllowRotateSelected
set allowMoveAtoms gAllowMoveAtoms
set dragSelected gDragSelected
set hoverDelay gHoverDelay
set AnimFrameCallback none
hoverLabel = gHoverLabel
set hoverLabel gHoverLabel
}
}
# Top level of Modify
function plico_modify() {
# Load common functions if not already
if (kCommon < 6) {
script $SCRIPT_PATH$plicoCommon.spt
if (kCommon < 6) {
prompt ("A newer version of plicoCommon.SPT is required")
quit
}
}
gPlico = "MODIFY"
plico_prelim(false, true)
gAllowMoveAtoms = allowMoveAtoms
gAllowRotateSelected = allowRotateSelected
gDragSelected = dragSelected
gHoverDelay = hoverDelay
gHoverLabel = hoverLabel
set allowMoveAtoms true
set allowRotateSelected true
set dragSelected true
set AnimFrameCallback "jmolscript:set_hover_labels"
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|SHIFT-DOUBLE-CLICK=exit")
echo @gEcho
bind "ALT-LEFT-CLICK" "_pickAtom";
bind "ALT-LEFT-CLICK" "+:modify_1_mb";
bind "SHIFT-LEFT-CLICK" "_pickAtom";
bind "SHIFT-LEFT-CLICK" "+:modify_2_mb";
bind "ALT-SHIFT-LEFT-CLICK" "_pickAtom";
bind "ALT-SHIFT-LEFT-CLICK" "+:select_chain_mb";
bind "ALT-CTRL-LEFT-CLICK" "_pickAtom";
bind "ALT-CTRL-LEFT-CLICK" "+:add_water_mb";
bind "SHIFT-DOUBLE" "modify_exit_mb";
bind "LEFT-CLICK" "+:plico_menu_toggle";
set hoverDelay 0.001
hover on
set_hover_labels()
}
# End of MODIFY.SPT