Difference between revisions of "User:Remig/plico/convert"

From Jmol
Jump to navigation Jump to search
m
(Add double-bonding options)
Line 1: Line 1:
 
'''Convert_residue''' allows the user to change polypeptide or polynucleotide residues from one type to another.  When the residue to change is selected with a mouse click, the user is prompted for the amino-acid or nucleotide to replace the selected residue.
 
'''Convert_residue''' allows the user to change polypeptide or polynucleotide residues from one type to another.  When the residue to change is selected with a mouse click, the user is prompted for the amino-acid or nucleotide to replace the selected residue.
 +
 +
The script also allows the user to double-bond or single bond all planars (aromatics, amides, etc) in an amino-acid or nucletotide chain by a shift-click or alt-shift-click respectively.  Double-bonding is useful to prevent certain distortions introduced by minimization.
  
 
'''Convert_residue''' 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:
 
'''Convert_residue''' 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:
Line 10: Line 12:
  
 
<pre>#  convert_residue - Jmol script by Ron Mignery
 
<pre>#  convert_residue - Jmol script by Ron Mignery
#  v1.1 beta    7/23/2014 -better rna detection
+
#  v1.2 beta    7/13/2015 -add double bond options
 
#
 
#
 
# Converts a selected residue base from one form to another.
 
# Converts a selected residue base from one form to another.
# Click to select a residue
+
# Alt-Click to select a residue
 
# Then enter new residue type:
 
# Then enter new residue type:
 
#  One of ACDEFGHIKLMNPQRSTUVWXY for polypeptide or
 
#  One of ACDEFGHIKLMNPQRSTUVWXY for polypeptide or
 
#  One of ACGUT for nucleotides
 
#  One of ACGUT for nucleotides
 +
# Or add or remove double bonds from aromatics, amides, and carboxyls
 +
# Click to select a chain (Shift-Click to add, Alt-Shift-Click to remove)
 +
kConvert = 1
 
gAppendNew = true
 
gAppendNew = true
 
g1from3 = {"ALA":"A", "GLX":"B","CYS":"C", "ASP":"D","GLU":"E", "PHE":"F",
 
g1from3 = {"ALA":"A", "GLX":"B","CYS":"C", "ASP":"D","GLU":"E", "PHE":"F",
Line 24: Line 29:
  
 
function convert_aa(iResno, iChain, newres) {
 
function convert_aa(iResno, iChain, newres) {
 +
    var f = {atomIndex=_atomPicked}.file
 +
    var m = {atomIndex=_atomPicked}.model
 
     gBusy = true
 
     gBusy = true
 
     background ECHO pink
 
     background ECHO pink
 
     refresh
 
     refresh
 
     gCHAIN = iChain
 
     gCHAIN = iChain
 
+
   
     # Collect data
+
     # Collect orientation
     var f = {atomIndex=_atomPicked}.file
+
     var aO = get_atom_rcn(iResno, iChain, "O")
    var m = {atomIndex=_atomPicked}.model
+
     var aC = get_atom_rcn(iResno, iChain, "C")
    var topno = {(resno=iResno) and (chain=iChain)
+
     var aCA = get_atom_rcn(iResno, iChain, "CA")
        and (file=f) and (model=m)}.atomno.max + 0
+
     var aN = get_atom_rcn(iResno, iChain, "N")
     var idmax = {(file=f) and (model=m)}.atomIndex.max
+
     var aNp = {connected(aC) and (atomname="N")}
    var aN = atom_rcn(iResno, iChain, "N")
+
     var aCAp = {connected(aNp) and (atomname="CA")}
     var aCA = atom_rcn(iResno, iChain, "CA")
 
     var aC = atom_rcn(iResno, iChain, "C")
 
     var aO = atom_rcn(iResno, iChain, "O")
 
     var aNxyz = aN.xyz + {0 0 0}
 
    var aCAxyz = aCA.xyz + {0 0 0}
 
 
     var aCxyz = aC.xyz + {0 0 0}
 
     var aCxyz = aC.xyz + {0 0 0}
 
     var aOxyz = aO.xyz + {0 0 0}
 
     var aOxyz = aO.xyz + {0 0 0}
 +
    var angC = angle(aNp, aC, aCA)
 +
    var dihedralC = angle(aCAp, aNp, aC, aCA)
 +
    var psi = angle(aNp, aC, aCA, aN)
 
     gN = aN.atomno
 
     gN = aN.atomno
  
Line 48: Line 53:
 
     delete {(resno=iResno) and (chain=iChain) and (file=f) and (model=m)}
 
     delete {(resno=iResno) and (chain=iChain) and (file=f) and (model=m)}
  
     # Gen AA ==================================================
+
     # Make a new AA  
    gAppendNew = appendNew
 
    set appendNew false
 
 
     gA = "data \"append aa\"\n"
 
     gA = "data \"append aa\"\n"
 +
   
 +
    # Call gen_aa in ribozyme.spt
 
     gA += gen_aa(iResno, newres);
 
     gA += gen_aa(iResno, newres);
 
     gA += "end \"append aa\""
 
     gA += "end \"append aa\""
 +
    gAppendNew = appendNew
 +
    set appendNew false
 
     script inline @{gA}
 
     script inline @{gA}
 
     appendNew = gAppendNew
 
     appendNew = gAppendNew
 
+
   
 
     # Recollect data and move backbone to coords of old aa
 
     # Recollect data and move backbone to coords of old aa
     aN = atom_rcn(iResno, iChain, "N")
+
     aO = get_atom_rcn(iResno, iChain, "O")
     aCA = atom_rcn(iResno, iChain, "CA")
+
     aC = get_atom_rcn(iResno, iChain, "C")
     aC = atom_rcn(iResno, iChain, "C")
+
     aCA = get_atom_rcn(iResno, iChain, "CA")
     aO = atom_rcn(iResno, iChain, "O")
+
     aN = get_atom_rcn(iResno, iChain, "N")
     var aCB = atom_rcn(iResno, iChain, "CB")
+
      
     aN.xyz = aNxyz
+
    select {(chain=iChain) and (resno=iResno) and (file=f) and (model=m)}
     aCA.xyz = aCAxyz
+
     var v = aCxyz - aC.xyz
     aC.xyz = aCxyz
+
    translate Selected @v
 +
    var v1=aNp.xyz - aC.xyz
 +
     var v2=aCA.xyz - aC.xyz
 +
     var axis = cross(v1, v2) + aC.xyz
 +
    var curangle =  angle(aNp, aC, aCA)
 +
    rotateselected @aC @axis @{angC-curangle}
 +
    curangle =  angle(aCAp, aNp, aC, aCA)
 +
    rotateselected @aNp @aC @{dihedralC-curangle}
 +
    curangle = angle(aNp, aC, aCA, aN)
 +
    rotateselected @aC @aCA @{psi-curangle}
 
     aO.xyz = aOxyz
 
     aO.xyz = aOxyz
 
+
      
     # Reconstruct side-chain position on backbone
 
    select ((atomIndex > idmax) and sidechain and (file=f) and (model=m))
 
    color {selected} @gAltScheme
 
    if (aCB.size > 0) {
 
        set_distance_atoms( aCA, aCB, 1.5)
 
        set_angle_atoms( aC, aCA, aCB, 115.9)
 
        set_dihedral_atoms( aO, aC, aCA, aCB, -100.2)
 
        var aCG = atom_rcn(iResno, iChain, "*G*")
 
        if (aCG.size > 0) {
 
            var nno = aCG[0].atomno+1
 
            set_dihedral_atoms( aC, aCA, aCB, aCG[1], -172.9)
 
            set_angle_atoms( aCA, aCB, aCG[1], 113.2)
 
            aCD = {(atomno=nno) and (chain=iChain) and (file=f) and (model=m)}
 
            if (aCD.size > 0) {
 
                set_dihedral_atoms( aCA, aCB, aCG[1], aCD, 179.4)
 
            }
 
        }
 
    }
 
 
 
 
     # Connect the new AA
 
     # Connect the new AA
     var aCm = atom_rcn(iResno-1, iChain, "C")
+
     var aCm = get_atom_rcn(iResno-1, iChain, "C")
    var aNp = atom_rcn(iResno+1, iChain, "N")
 
 
     connect @aN @aCm
 
     connect @aN @aCm
 
     connect @aC @aNp
 
     connect @aC @aNp
Line 107: Line 103:
 
     refresh
 
     refresh
 
     gBusy = false
 
     gBusy = false
 +
 
}
 
}
  
 
function atom_rcn_xyz(iResno, iChain, iName, xyz) {
 
function atom_rcn_xyz(iResno, iChain, iName, xyz) {
     var a = atom_rcn(iResno, iChain, iName)
+
     var a = get_atom_rcn(iResno, iChain, iName)
 
     a.xyz = xyz
 
     a.xyz = xyz
 
}
 
}
  
 
function convert_nt(iResno, iChain, newres) {
 
function convert_nt(iResno, iChain, newres) {
    gBusy = true
 
    background ECHO pink
 
    refresh
 
 
     gChain1 = iChain
 
     gChain1 = iChain
     var f = {atomIndex=_atomPicked}.file
+
     var f = {chain=iChain}.file
     var m = {atomIndex=_atomPicked}.model
+
     var m = {chain=iChain}.model
  
 
     # Collect data
 
     # Collect data
Line 126: Line 120:
 
         and (file=f) and (model=m)}.atomno.max + 0
 
         and (file=f) and (model=m)}.atomno.max + 0
 
     var idmax = {(file=f) and (model=m)}.atomIndex.max
 
     var idmax = {(file=f) and (model=m)}.atomIndex.max
     var aO4 = atom_rcn(iResno, iChain, "O4\'")
+
     var aO4 = get_atom_rcn(iResno, iChain, "O4\'")
     var aC1 = atom_rcn(iResno, iChain, "C1\'")
+
    if (newres = "") {
     var aC4 = atom_rcn(iResno, iChain, "C4\'")
+
        newres = aO4.group
     var aP = atom_rcn(iResno, iChain, "P")
+
    }
 +
     var aC1 = get_atom_rcn(iResno, iChain, "C1\'")
 +
     var aC4 = get_atom_rcn(iResno, iChain, "C4\'")
 +
     var aP = get_atom_rcn(iResno, iChain, "P")
 
     var aPxyz = aP.xyz + {0 0 0}
 
     var aPxyz = aP.xyz + {0 0 0}
     var aOP1xyz = atom_rcn(iResno, iChain, "OP1").xyz + {0 0 0}
+
     var aOP1xyz = get_atom_rcn(iResno, iChain, "OP1").xyz + {0 0 0}
     var aOP2xyz = atom_rcn(iResno, iChain, "OP2").xyz + {0 0 0}
+
     var aOP2xyz = get_atom_rcn(iResno, iChain, "OP2").xyz + {0 0 0}
 
     var aC1xyz = aC1.xyz + {0 0 0}
 
     var aC1xyz = aC1.xyz + {0 0 0}
 
     var aO4xyz = aO4.xyz + {0 0 0}
 
     var aO4xyz = aO4.xyz + {0 0 0}
     var aO3xyz = atom_rcn(iResno, iChain, "O3\'").xyz + {0 0 0}
+
     var aO3xyz = get_atom_rcn(iResno, iChain, "O3\'").xyz + {0 0 0}
     var aC3xyz = atom_rcn(iResno, iChain, "C3\'").xyz + {0 0 0}
+
     var aC3xyz = get_atom_rcn(iResno, iChain, "C3\'").xyz + {0 0 0}
     var aC2xyz = atom_rcn(iResno, iChain, "C2\'").xyz + {0 0 0}
+
     var aC2xyz = get_atom_rcn(iResno, iChain, "C2\'").xyz + {0 0 0}
     var aO2xyz = atom_rcn(iResno, iChain, "O2\'").xyz + {0 0 0}
+
     var aO2xyz = get_atom_rcn(iResno, iChain, "O2\'").xyz + {0 0 0}
 
     var aC4xyz = aC4.xyz + {0 0 0}
 
     var aC4xyz = aC4.xyz + {0 0 0}
     var aC5xyz = atom_rcn(iResno, iChain, "C5\'").xyz + {0 0 0}
+
     var aC5xyz = get_atom_rcn(iResno, iChain, "C5\'").xyz + {0 0 0}
     var aO5xyz = atom_rcn(iResno, iChain, "O5\'").xyz + {0 0 0}
+
     var aO5xyz = get_atom_rcn(iResno, iChain, "O5\'").xyz + {0 0 0}
 
     var isR  = ((aC1 and {purine}).size > 0)
 
     var isR  = ((aC1 and {purine}).size > 0)
 
     var N1or9 = (isR ? "N9" : "N1")
 
     var N1or9 = (isR ? "N9" : "N1")
 
     var C6or8 = (isR ? "C8" : "C6")
 
     var C6or8 = (isR ? "C8" : "C6")
     if (aC1.group="PSU") {
+
     if (aC1.group = "PSU") {
 
         N1or9 = "C5"
 
         N1or9 = "C5"
 
     }
 
     }
     var aN = atom_rcn(iResno, iChain, N1or9)
+
     var aN = get_atom_rcn(iResno, iChain, N1or9)
     var aC = atom_rcn(iResno, iChain, C6or8)
+
     var aC = get_atom_rcn(iResno, iChain, C6or8)
 
     var chi = angle(aO4, aC1, aN, aC)
 
     var chi = angle(aO4, aC1, aN, aC)
 
     var dist = distance( aC1, aN)
 
     var dist = distance( aC1, aN)
Line 155: Line 152:
 
     var bdh = angle( aC4, aO4, aC1, aN)
 
     var bdh = angle( aC4, aO4, aC1, aN)
 
     gNa = aP.atomno
 
     gNa = aP.atomno
 
 
     # Delete the original
 
     # Delete the original
 
     delete {(resno=iResno) and (chain=iChain) and (file=f) and (model=m)}
 
     delete {(resno=iResno) and (chain=iChain) and (file=f) and (model=m)}
    refresh
 
 
      
 
      
 
     # Gen NT ==================================================
 
     # Gen NT ==================================================
     var isRna = (aO2xyz != {0 0 0})
+
     var isRna = (aO2xyz != -1)
 +
    gA = "data \"append nt\"\n"
 +
    gA += gen_nt(iResno, newres, isRna, false); # CALL
 +
    gA += "end \"append nt\""
 
     gAppendNew = appendNew
 
     gAppendNew = appendNew
 
     set appendNew false
 
     set appendNew false
    gA = "data \"append nt\"\n"
 
    gA += gen_nt(iResno, newres, isRna, false);
 
    gA += "end \"append nt\""
 
 
     script inline @{gA}
 
     script inline @{gA}
 
     appendNew = gAppendNew
 
     appendNew = gAppendNew
Line 174: Line 169:
 
     N1or9 = (isR ? "N9" : "N1")
 
     N1or9 = (isR ? "N9" : "N1")
 
     C6or8 = (isR ? "C8" : "C6")
 
     C6or8 = (isR ? "C8" : "C6")
     N3or7 = (isR ? "N7" : "N3")
+
     var N3or7 = (isR ? "N7" : "N3")
     aN = atom_rcn(iResno, iChain, N1or9)
+
     aN = get_atom_rcn(iResno, iChain, N1or9)
     aC = atom_rcn(iResno, iChain, C6or8)
+
     aC = get_atom_rcn(iResno, iChain, C6or8)
     var aN3or7 = atom_rcn(iResno, iChain, N3or7)
+
     var aN3or7 = get_atom_rcn(iResno, iChain, N3or7)
     var aC4 = atom_rcn(iResno, iChain, "C4\'")
+
     var aC4 = get_atom_rcn(iResno, iChain, "C4\'")
     aO4 = atom_rcn(iResno, iChain, "O4\'")
+
     aO4 = get_atom_rcn(iResno, iChain, "O4\'")
     aC1 = atom_rcn(iResno, iChain, "C1\'")
+
     aC1 = get_atom_rcn(iResno, iChain, "C1\'")
     aP = atom_rcn(iResno, iChain, "P")
+
     aP = get_atom_rcn(iResno, iChain, "P")
     var aO3 = atom_rcn(iResno, iChain, "O3\'")
+
     var aO3 = get_atom_rcn(iResno, iChain, "O3\'")
     aP.xyz = aPxyz
+
     if (aPxyz != -1) {
    atom_rcn_xyz(iResno, iChain, "OP1", aOP1xyz)
+
        aP.xyz = aPxyz
    atom_rcn_xyz(iResno, iChain, "OP2", aOP2xyz)
+
        atom_rcn_xyz(iResno, iChain, "OP1", aOP1xyz)
 +
        atom_rcn_xyz(iResno, iChain, "OP2", aOP2xyz)
 +
    }
 +
    else {
 +
        delete aP
 +
        aP = get_atom_rcn(iResno, iChain, "OP1")
 +
        delete aP
 +
        aP = get_atom_rcn(iResno, iChain, "OP2")
 +
        delete aP
 +
    }
 
     aC1.xyz = aC1xyz
 
     aC1.xyz = aC1xyz
 
     aO4.xyz = aO4xyz
 
     aO4.xyz = aO4xyz
Line 195: Line 199:
 
     atom_rcn_xyz(iResno, iChain, "C5\'", aC5xyz)
 
     atom_rcn_xyz(iResno, iChain, "C5\'", aC5xyz)
 
     atom_rcn_xyz(iResno, iChain, "O5\'", aO5xyz)
 
     atom_rcn_xyz(iResno, iChain, "O5\'", aO5xyz)
 
+
   
 
     # Reconstruct base position on backbone
 
     # Reconstruct base position on backbone
 
     select ((atomIndex > idmax) and base and (file=f) and (model=m))
 
     select ((atomIndex > idmax) and base and (file=f) and (model=m))
Line 208: Line 212:
  
 
     # Connect the new NT
 
     # Connect the new NT
     var aO3m = atom_rcn(iResno-1, iChain, "O3\'")
+
     var aO3m = get_atom_rcn(iResno-1, iChain, "O3\'")
     var aPp = atom_rcn(iResno+1, iChain, "P")
+
     var aPp = get_atom_rcn(iResno+1, iChain, "P")
 
     connect @aP @aO3m
 
     connect @aP @aO3m
 
     connect @aO3 @aPp
 
     connect @aO3 @aPp
 
    # Update atomnos
 
    topdif = {(resno=iResno) and (chain=iChain)
 
        and (file=f) and (model=m)}.atomno.max - topno
 
    if (topdif != 0) {
 
        topmax = {(chain=iChain) and (file=f) and (model=m)}.atomno.max
 
        for (var i=(topno+1); i <= topmax; i++) {
 
            {(atomno=i) and (chain=iChain) and (file=f)
 
                and (model=m)}.atomno += topdif
 
        }
 
    }
 
 
    set echo TOP LEFT
 
    background ECHO yellow
 
 
     refresh
 
     refresh
 +
   
 
     gBusy = false
 
     gBusy = false
 
}
 
}
Line 256: Line 247:
 
             }
 
             }
 
             sels = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
 
             sels = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
             selp = "  (enter 1 or 3 characters)"
+
             var selp = "  (enter 1 or 3 characters)"
 
         }
 
         }
 
         else if (isNT) {
 
         else if (isNT) {
             if (kPu.size == 0) {
+
             if (kPolymeraze < 1) {
 
                 script $SCRIPT_PATH$polymeraze.spt
 
                 script $SCRIPT_PATH$polymeraze.spt
                 if (kPu.size == 0) {
+
                 if (kPolymeraze < 1) {
                     prompt ("The Plico script polymeraze.spt is required")
+
                     prompt ("The Plico script polymeraze.spt (1.14+) is required")
 
                     quit
 
                     quit
 
                 }
 
                 }
Line 272: Line 263:
 
             var ps = format("Change residue %d from %s to ?\n%s",
 
             var ps = format("Change residue %d from %s to ?\n%s",
 
                 iResno, iGroup, selp)
 
                 iResno, iGroup, selp)
             newres = prompt(ps, "")%9999%0
+
             var newres = prompt(ps, "")%9999%0
 
             if (isAmino and (newres.size==3)) {
 
             if (isAmino and (newres.size==3)) {
 
                 newres = g1from3[newres]
 
                 newres = g1from3[newres]
Line 281: Line 272:
 
             if ((newres != "") and (newres != "NULL")) {
 
             if ((newres != "") and (newres != "NULL")) {
 
                 if (sels.find(newres[1]) > 0) {
 
                 if (sels.find(newres[1]) > 0) {
 +
                    gBusy = true
 +
                    background ECHO pink
 +
                    refresh
 
                     if (isAmino) {
 
                     if (isAmino) {
 
                         convert_aa(iResno, iChain, newres[1])
 
                         convert_aa(iResno, iChain, newres[1])
Line 287: Line 281:
 
                         convert_nt(iResno, iChain, newres[1])
 
                         convert_nt(iResno, iChain, newres[1])
 
                     }
 
                     }
 +
                    update_atomnos(iChain)
 +
                    set echo TOP LEFT
 +
                    background ECHO yellow
 +
                    refresh
 
                 }
 
                 }
 
                 else {
 
                 else {
Line 299: Line 297:
 
         halo off
 
         halo off
 
     }
 
     }
 +
}
 +
 +
function double_mb() {
 +
    var idx = _atomPicked
 +
    var iChain = {atomIndex=idx}.chain
 +
    background ECHO pink
 +
    refresh
 +
    double_bond_planars(iChain, false)
 +
    background ECHO yellow
 +
    refresh
 +
}
 +
 +
function undouble_mb() {
 +
    var idx = _atomPicked
 +
    var iChain = {atomIndex=idx}.chain
 +
    background ECHO pink
 +
    refresh
 +
    double_bond_planars(iChain, true)
 +
    background ECHO yellow
 +
    refresh
 
}
 
}
  
Line 340: Line 358:
 
     background ECHO yellow
 
     background ECHO yellow
  
     gEcho = ("____CONVERT_RESIDUE____|ALT-CLICK=select|DOUBLE-CLICK=exit")
+
     gEcho = ("____CONVERT_RESIDUE____|ALT-CLICK=select residue"+
 +
        "|SHIFT-CLICK=add double bonds to chain"+
 +
        "|ALT-SHIFT-CLICK=remove double bonds|DOUBLE-CLICK=exit")
 
     echo @gEcho
 
     echo @gEcho
 
     gChain = ""
 
     gChain = ""
Line 347: Line 367:
 
     bind "ALT-LEFT-CLICK" "_pickAtom";
 
     bind "ALT-LEFT-CLICK" "_pickAtom";
 
     bind "ALT-LEFT-CLICK" "+:convert_mb";
 
     bind "ALT-LEFT-CLICK" "+:convert_mb";
 +
    bind "SHIFT-LEFT-CLICK" "_pickAtom";
 +
    bind "SHIFT-LEFT-CLICK" "+:double_mb";
 +
    bind "ALT-SHIFT-LEFT-CLICK" "_pickAtom";
 +
    bind "ALT-SHIFT-LEFT-CLICK" "+:undouble_mb";
 +
    bind "ALT-CTRL-LEFT-CLICK" "align_trna";
 
     bind "DOUBLE" "convert_exit_mb";
 
     bind "DOUBLE" "convert_exit_mb";
  
 
}
 
}
  
 +
function connect_res_nt( r5, r3, iChain, del) {
 +
    var aO3 = get_atom_rcn(r5, iChain, "O3\'")
 +
    var aP = get_atom_rcn(r3, iChain, "P")
 +
    if (del) {
 +
        connect @aO3 @aP DELETE
 +
    }
 +
    else {
 +
        connect @aO3 @aP
 +
        fix_p_res(r3, iChain, false)
 +
    }
 +
}
 
# End of CONVERT_RESIDUE.SPT
 
# End of CONVERT_RESIDUE.SPT
 
</pre>
 
</pre>

Revision as of 18:29, 13 July 2015

Convert_residue allows the user to change polypeptide or polynucleotide residues from one type to another. When the residue to change is selected with a mouse click, the user is prompted for the amino-acid or nucleotide to replace the selected residue.

The script also allows the user to double-bond or single bond all planars (aromatics, amides, etc) in an amino-acid or nucletotide chain by a shift-click or alt-shift-click respectively. Double-bonding is useful to prevent certain distortions introduced by minimization.

Convert_residue 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 Convert residue
Script=script <path to your scripts directory>/convert_residue.spt;plico_convert

saved as plicoConvert.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 convert_residue.spt:

#   convert_residue - Jmol script by Ron Mignery
#   v1.2 beta    7/13/2015 -add double bond options
#
# Converts a selected residue base from one form to another.
# Alt-Click to select a residue
# Then enter new residue type:
#   One of ACDEFGHIKLMNPQRSTUVWXY for polypeptide or
#   One of ACGUT for nucleotides
# Or add or remove double bonds from aromatics, amides, and carboxyls
# Click to select a chain (Shift-Click to add, Alt-Shift-Click to remove)
kConvert = 1
gAppendNew = true
g1from3 = {"ALA":"A", "GLX":"B","CYS":"C", "ASP":"D","GLU":"E", "PHE":"F",
    "GLY":"G", "HIS":"H","ILE":"I", "LYS":"K","LEU":"L", "MET":"M",
    "ASN":"N", "PYL":"O","PRO":"P", "GLN":"Q","ARG":"R", "SER":"S",
    "THR":"T", "SEC":"U","VAL":"V", "TRP":"W","UNK":"X", "TYR":"Y", "ASX":"Z"}

function convert_aa(iResno, iChain, newres) {
    var f = {atomIndex=_atomPicked}.file
    var m = {atomIndex=_atomPicked}.model
    gBusy = true
    background ECHO pink
    refresh
    gCHAIN = iChain
    
    # Collect orientation
    var aO = get_atom_rcn(iResno, iChain, "O")
    var aC = get_atom_rcn(iResno, iChain, "C")
    var aCA = get_atom_rcn(iResno, iChain, "CA")
    var aN = get_atom_rcn(iResno, iChain, "N")
    var aNp = {connected(aC) and (atomname="N")}
    var aCAp = {connected(aNp) and (atomname="CA")}
    var aCxyz = aC.xyz + {0 0 0}
    var aOxyz = aO.xyz + {0 0 0}
    var angC = angle(aNp, aC, aCA)
    var dihedralC = angle(aCAp, aNp, aC, aCA)
    var psi = angle(aNp, aC, aCA, aN)
    gN = aN.atomno

    # Delete the original
    delete {(resno=iResno) and (chain=iChain) and (file=f) and (model=m)}

    # Make a new AA    
    gA = "data \"append aa\"\n"
    
    # Call gen_aa in ribozyme.spt
    gA += gen_aa(iResno, newres);
    gA += "end \"append aa\""
    gAppendNew = appendNew
    set appendNew false
    script inline @{gA}
    appendNew = gAppendNew
    
    # Recollect data and move backbone to coords of old aa
    aO = get_atom_rcn(iResno, iChain, "O")
    aC = get_atom_rcn(iResno, iChain, "C")
    aCA = get_atom_rcn(iResno, iChain, "CA")
    aN = get_atom_rcn(iResno, iChain, "N")
    
    select {(chain=iChain) and (resno=iResno) and (file=f) and (model=m)}
    var v = aCxyz - aC.xyz
    translate Selected @v
    var v1=aNp.xyz - aC.xyz
    var v2=aCA.xyz - aC.xyz
    var axis = cross(v1, v2) + aC.xyz
    var curangle =  angle(aNp, aC, aCA)
    rotateselected @aC @axis @{angC-curangle}
    curangle =  angle(aCAp, aNp, aC, aCA)
    rotateselected @aNp @aC @{dihedralC-curangle}
    curangle =  angle(aNp, aC, aCA, aN)
    rotateselected @aC @aCA @{psi-curangle}
    aO.xyz = aOxyz
    
    # Connect the new AA
    var aCm = get_atom_rcn(iResno-1, iChain, "C")
    connect @aN @aCm
    connect @aC @aNp

    # Update atomnos
    var topdif = {(resno=iResno) and (chain=iChain)
        and (file=f) and (model=m)}.atomno.max - topno
    if (topdif != 0) {
        topmax = {(chain=iChain) and (file=f) and (model=m)}.atomno.max
        for (var i=(topno+1); i <= topmax; i++) {
            {(atomno=i) and (chain=iChain) and (file=f) and (model=m)}.atomno += topdif
        }
    }

    set echo TOP LEFT
    background ECHO yellow
    refresh
    gBusy = false

}

function atom_rcn_xyz(iResno, iChain, iName, xyz) {
    var a = get_atom_rcn(iResno, iChain, iName)
    a.xyz = xyz
}

function convert_nt(iResno, iChain, newres) {
    gChain1 = iChain
    var f = {chain=iChain}.file
    var m = {chain=iChain}.model

    # Collect data
    var topno = {(resno=iResno) and (chain=iChain)
        and (file=f) and (model=m)}.atomno.max + 0
    var idmax = {(file=f) and (model=m)}.atomIndex.max
    var aO4 = get_atom_rcn(iResno, iChain, "O4\'")
    if (newres = "") {
        newres = aO4.group
    }
    var aC1 = get_atom_rcn(iResno, iChain, "C1\'")
    var aC4 = get_atom_rcn(iResno, iChain, "C4\'")
    var aP = get_atom_rcn(iResno, iChain, "P")
    var aPxyz = aP.xyz + {0 0 0}
    var aOP1xyz = get_atom_rcn(iResno, iChain, "OP1").xyz + {0 0 0}
    var aOP2xyz = get_atom_rcn(iResno, iChain, "OP2").xyz + {0 0 0}
    var aC1xyz = aC1.xyz + {0 0 0}
    var aO4xyz = aO4.xyz + {0 0 0}
    var aO3xyz = get_atom_rcn(iResno, iChain, "O3\'").xyz + {0 0 0}
    var aC3xyz = get_atom_rcn(iResno, iChain, "C3\'").xyz + {0 0 0}
    var aC2xyz = get_atom_rcn(iResno, iChain, "C2\'").xyz + {0 0 0}
    var aO2xyz = get_atom_rcn(iResno, iChain, "O2\'").xyz + {0 0 0}
    var aC4xyz = aC4.xyz + {0 0 0}
    var aC5xyz = get_atom_rcn(iResno, iChain, "C5\'").xyz + {0 0 0}
    var aO5xyz = get_atom_rcn(iResno, iChain, "O5\'").xyz + {0 0 0}
    var isR  = ((aC1 and {purine}).size > 0)
    var N1or9 = (isR ? "N9" : "N1")
    var C6or8 = (isR ? "C8" : "C6")
    if (aC1.group = "PSU") {
        N1or9 = "C5"
    }
    var aN = get_atom_rcn(iResno, iChain, N1or9)
    var aC = get_atom_rcn(iResno, iChain, C6or8)
    var chi = angle(aO4, aC1, aN, aC)
    var dist = distance( aC1, aN)
    var bang = angle( aO4, aC1, aN)
    var bdh = angle( aC4, aO4, aC1, aN)
    gNa = aP.atomno
    # Delete the original
    delete {(resno=iResno) and (chain=iChain) and (file=f) and (model=m)}
    
    # Gen NT ==================================================
    var isRna = (aO2xyz != -1)
    gA = "data \"append nt\"\n"
    gA += gen_nt(iResno, newres, isRna, false); # CALL
    gA += "end \"append nt\""
    gAppendNew = appendNew
    set appendNew false
    script inline @{gA}
    appendNew = gAppendNew

    # Recollect data and move new NT to coords of old
    isR  = ((newres="A") or (newres="G"))
    N1or9 = (isR ? "N9" : "N1")
    C6or8 = (isR ? "C8" : "C6")
    var N3or7 = (isR ? "N7" : "N3")
    aN = get_atom_rcn(iResno, iChain, N1or9)
    aC = get_atom_rcn(iResno, iChain, C6or8)
    var aN3or7 = get_atom_rcn(iResno, iChain, N3or7)
    var aC4 = get_atom_rcn(iResno, iChain, "C4\'")
    aO4 = get_atom_rcn(iResno, iChain, "O4\'")
    aC1 = get_atom_rcn(iResno, iChain, "C1\'")
    aP = get_atom_rcn(iResno, iChain, "P")
    var aO3 = get_atom_rcn(iResno, iChain, "O3\'")
    if (aPxyz != -1) {
        aP.xyz = aPxyz
        atom_rcn_xyz(iResno, iChain, "OP1", aOP1xyz)
        atom_rcn_xyz(iResno, iChain, "OP2", aOP2xyz)
    }
    else {
        delete aP
        aP = get_atom_rcn(iResno, iChain, "OP1")
        delete aP
        aP = get_atom_rcn(iResno, iChain, "OP2")
        delete aP
    }
    aC1.xyz = aC1xyz
    aO4.xyz = aO4xyz
    aO3.xyz = aO3xyz
    atom_rcn_xyz(iResno, iChain, "C3\'", aC3xyz)
    atom_rcn_xyz(iResno, iChain, "C2\'", aC2xyz)
    atom_rcn_xyz(iResno, iChain, "O2\'", aO2xyz)
    aC4.xyz = aC4xyz
    atom_rcn_xyz(iResno, iChain, "C5\'", aC5xyz)
    atom_rcn_xyz(iResno, iChain, "O5\'", aO5xyz)
    
    # Reconstruct base position on backbone
    select ((atomIndex > idmax) and base and (file=f) and (model=m))
    color {selected} @gAltScheme
    set_distance_atoms( aC1, aN, dist)
    set_angle_atoms( aO4, aC1, aN, bang)
    set_dihedral_atoms( aC4, aO4, aC1, aN, bdh)

    set_angle_atoms( aC1, aN, aC, (isR ? 128.5 : 121.4))
    set_dihedral_atoms( aC1, aN, aC, aN3or7, 180.0)
    set_dihedral_atoms( aO4, aC1, aN, aC, chi)

    # Connect the new NT
    var aO3m = get_atom_rcn(iResno-1, iChain, "O3\'")
    var aPp = get_atom_rcn(iResno+1, iChain, "P")
    connect @aP @aO3m
    connect @aO3 @aPp
    refresh
    
    gBusy = false
}

function convert_mb() {
    if (gBusy == false) {
        var idx = _atomPicked
        var isAmino = (({(atomIndex=idx) and amino}.size > 0)
            or ({atomIndex=idx}.group="SEC")
            or ({atomIndex=idx}.group="PYL"))
        var isNT = ({(atomIndex=idx) and (rna or dna)}.size > 0)
        var iResno = {atomIndex=idx}.resno
        var iGroup = {atomIndex=idx}.group
        var iChain = {atomIndex=idx}.chain
        var f = {atomIndex=idx}.file
        var m = {atomIndex=idx}.model
        var sels = ""
        select {(resno=iResno) and (chain=iChain) and (file=f) and (model=m)}
        halo on
        refresh

        if (isAmino) {
            if (kPHI.size == 0) {
                script $SCRIPT_PATH$ribozome.spt
                if (kPHI.size == 0) {
                    prompt ("The Plico script ribozome.spt is required")
                    quit
                }
            }
            sels = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
            var selp = "   (enter 1 or 3 characters)"
        }
        else if (isNT) {
            if (kPolymeraze < 1) {
                script $SCRIPT_PATH$polymeraze.spt
                if (kPolymeraze < 1) {
                    prompt ("The Plico script polymeraze.spt (1.14+) is required")
                    quit
                }
            }
            sels = "ACGTU"
            selp = "   (enter A, C, G, T, or U)"
        }
        if (sels.size > 0) {
            var ps = format("Change residue %d from %s to ?\n%s",
                iResno, iGroup, selp)
            var newres = prompt(ps, "")%9999%0
            if (isAmino and (newres.size==3)) {
                newres = g1from3[newres]
            }
            else if (newres.size==2) {
                newres = newres[2]
            }
            if ((newres != "") and (newres != "NULL")) {
                if (sels.find(newres[1]) > 0) {
                    gBusy = true
                    background ECHO pink
                    refresh
                    if (isAmino) {
                        convert_aa(iResno, iChain, newres[1])
                    }
                    else {
                        convert_nt(iResno, iChain, newres[1])
                    }
                    update_atomnos(iChain)
                    set echo TOP LEFT
                    background ECHO yellow
                    refresh
                }
                else {
                    prompt("Invalid entry")
                }
            }
        }
        else {
            prompt("Not a polypeptide or polynucleotide")
        }
        select {(resno=iResno) and (chain=iChain) and (file=f) and (model=m)}
        halo off
    }
}

function double_mb() {
    var idx = _atomPicked
    var iChain = {atomIndex=idx}.chain
    background ECHO pink
    refresh
    double_bond_planars(iChain, false)
    background ECHO yellow
    refresh
}

function undouble_mb() {
    var idx = _atomPicked
    var iChain = {atomIndex=idx}.chain
    background ECHO pink
    refresh
    double_bond_planars(iChain, true)
    background ECHO yellow
    refresh
}

function convert_exit_mb() {
    var f = (_frameID/1000000)
    var m = (_frameID%1000000)
    unbind
    set echo TOP LEFT
    echo
    set allowRotateSelected gAllowRotateSelected
    set allowMoveAtoms gAllowMoveAtoms
    select ((file=f) and (model=m))
    color {selected} @gScheme
    select {gSelsave}
}

# Top level of Modify
function plico_convert() {
    gBusy = false
    gSelsave = {selected}
    gPlico = "CONVERT RESIDUE"

    # Load common functions if not already
    if (kCommon < 3) {
        script $SCRIPT_PATH$plicoCommon.spt
        if (kCommon < 3) {
            prompt ("A newer version of plicoCommon.SPT is required")
            quit
        }
    }
    if (kNTcommon < 4) {
        script $SCRIPT_PATH$plicoNTcommon.spt
        if (kNTcommon < 4) {
            prompt ("A newer version of plicoNTcommon.SPT is required")
            quit
        }
    }


    set echo TOP LEFT
    background ECHO yellow

    gEcho = ("____CONVERT_RESIDUE____|ALT-CLICK=select residue"+
        "|SHIFT-CLICK=add double bonds to chain"+
        "|ALT-SHIFT-CLICK=remove double bonds|DOUBLE-CLICK=exit")
    echo @gEcho
    gChain = ""
    unbind

    bind "ALT-LEFT-CLICK" "_pickAtom";
    bind "ALT-LEFT-CLICK" "+:convert_mb";
    bind "SHIFT-LEFT-CLICK" "_pickAtom";
    bind "SHIFT-LEFT-CLICK" "+:double_mb";
    bind "ALT-SHIFT-LEFT-CLICK" "_pickAtom";
    bind "ALT-SHIFT-LEFT-CLICK" "+:undouble_mb";
    bind "ALT-CTRL-LEFT-CLICK" "align_trna";
    bind "DOUBLE" "convert_exit_mb";

}

function connect_res_nt( r5, r3, iChain, del) {
    var aO3 = get_atom_rcn(r5, iChain, "O3\'")
    var aP = get_atom_rcn(r3, iChain, "P")
    if (del) {
        connect @aO3 @aP DELETE
    }
    else {
        connect @aO3 @aP
        fix_p_res(r3, iChain, false)
    }
}
# End of CONVERT_RESIDUE.SPT

Contributors

Remig