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