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

From Jmol
Jump to navigation Jump to search
(Do not var globals)
(Avoid "axis," a newly reserved word)
 
(12 intermediate revisions by the same user not shown)
Line 1: Line 1:
This script contains routines used by other scripts of the Plico suite.  It must be located in the same directory as any script that uses these routines.
+
This script contains routines used by other scripts of the Plico suite.  It must be located in the same directory as any script that uses these routines.  
  
 +
Copy and paste the following into a text editor and save in your scripts folder as plicoCommon.spt.
 
<pre>#  plicoCommon - Jmol script by Ron Mignery
 
<pre>#  plicoCommon - Jmol script by Ron Mignery
#  v1.1 beta    4/3/2014 -do not var globals for Jmol 14.0.13+
+
#  v1.12 beta    4/12/2016 -axis is now a reserved word
 
#
 
#
 
#  Routines and values common to all Plico suite scripts
 
#  Routines and values common to all Plico suite scripts
#  Must be present in the same directory as other Plico scripts
+
#  Must be present in the same directory as other Plico scripts that use it
kCommon = 1
+
kCommon = 7
 
kDtolerance = 0.1
 
kDtolerance = 0.1
kAtolerance = 5.0
 
 
kCtolerance = 1.85
 
kCtolerance = 1.85
kMtolerance = 0.8
+
gMouseX = 0
 +
gMouseY = 0
 +
gMinNo = 1
 +
gMaxNo = 9999
 +
gOK = true # global return value to work around jmol *feature*
 +
gOk2 = true # "    "
 +
gScheme = "Jmol"
 +
gAltScheme = "Rasmol"
 +
gBusy = false
 +
gEcho = ""
 +
gMenuMin = false
  
 
# Return L tetrahedron point if i1<i2<i3, else R point
 
# Return L tetrahedron point if i1<i2<i3, else R point
function getTetIdx(i1, i2, i3, dist) {
+
function get_tet_idx(i1, i2, i3, dist) {
 
     var v1 = {atomIndex=i3}.xyz - {atomIndex=i2}.xyz
 
     var v1 = {atomIndex=i3}.xyz - {atomIndex=i2}.xyz
 
     var v2 = {atomIndex=i1}.xyz - {atomIndex=i2}.xyz
 
     var v2 = {atomIndex=i1}.xyz - {atomIndex=i2}.xyz
     var axis = cross(v1, v2)
+
     var caxis = cross(v1, v2)
 
     var pma = ({atomIndex=i1}.xyz + {atomIndex=i3}.xyz)/2
 
     var pma = ({atomIndex=i1}.xyz + {atomIndex=i3}.xyz)/2
 
     var pmo = {atomIndex=i2}.xyz + {atomIndex=i2}.xyz - pma
 
     var pmo = {atomIndex=i2}.xyz + {atomIndex=i2}.xyz - pma
     var pt = pmo + (axis/axis)
+
     var pt = pmo + (caxis/caxis)
  
 
     var v = pt - {atomIndex=i2}.xyz
 
     var v = pt - {atomIndex=i2}.xyz
Line 29: Line 39:
 
}
 
}
  
function getTrigonalIdx(i1, i2, i3, dist) {
+
function get_trigonal_idx(i1, i2, i3, dist) {
 
     var v1 = {atomIndex=i1}.xyz - {atomIndex=i2}.xyz
 
     var v1 = {atomIndex=i1}.xyz - {atomIndex=i2}.xyz
 
     var v2 = {atomIndex=i3}.xyz - {atomIndex=i2}.xyz
 
     var v2 = {atomIndex=i3}.xyz - {atomIndex=i2}.xyz
Line 42: Line 52:
 
}
 
}
  
function abs( x) {
 
    if (x < 0) {
 
        x = -x
 
    }
 
    return x
 
}
 
 
# Selected must include second parameter but not the first
 
# Selected must include second parameter but not the first
function setDistanceAtoms( static, mobile, desired) {
+
# Static may be just a point
 +
function set_distance_atoms( static, mobile, desired) {
 
     try {
 
     try {
         var v = mobile.xyz - static.xyz
+
        var s = ((static.type == "point") ? static : static.xyz)       
         var dist = distance(static, mobile)
+
         var v = mobile.xyz - s
         translateSelected @{((v * (desired/dist)) - v)}
+
         var dist = distance(s, mobile)
 +
         translateSelected @{(v * (desired/dist)) - v}
 
     }
 
     }
 
     catch {
 
     catch {
 
     }
 
     }
 
}
 
}
function setDistanceIdx( staticIdx, mobileIdx, desired) {
+
function set_distance_idx( staticIdx, mobileIdx, desired) {
     setDistanceAtoms({atomIndex=staticIdx}, {atomIndex=mobileIdx}, desired)
+
     set_distance_atoms({atomIndex=staticIdx}, {atomIndex=mobileIdx}, desired)
 
}
 
}
 
  
 
# Selected must include third parameter but not the first
 
# Selected must include third parameter but not the first
function setAngleAtoms( stator, pivot, rotor, toangle) {
+
# Stator and pivot may be just points
 +
function set_angle_atoms( stator, pivot, rotor, toangle) {
 
     try {
 
     try {
         var v1=stator.xyz - pivot.xyz
+
         var s = ((stator.type == "point") ? stator : stator.xyz)       
         var v2=rotor.xyz - pivot.xyz
+
        var p = ((pivot.type == "point") ? pivot : pivot.xyz)       
         var axis = cross(v1, v2) + pivot.xyz
+
        var v1=s - p
 +
         var v2=rotor.xyz - p
 +
         var caxis = cross(v1, v2) + p
 
         var curangle =  angle(stator, pivot, rotor)
 
         var curangle =  angle(stator, pivot, rotor)
         rotateselected @axis @pivot @{curangle-toangle}
+
         rotateselected @caxis @pivot @{curangle-toangle}
 
     }
 
     }
 
     catch {
 
     catch {
 +
        print format("unable to set_angle_atoms( stator=%s, pivot=%s, rotor=%s, toangle=%f)",
 +
            stator, pivot, rotor, toangle)
 
     }
 
     }
 
}
 
}
function setAngleIdx( statorIdx, pivotIdx, rotorIdx, toangle) {
+
function set_angle_idx( statorIdx, pivotIdx, rotorIdx, toangle) {
     setAngleAtoms({atomIndex=statorIdx}, {atomIndex=pivotIdx},
+
     set_angle_atoms({atomIndex=statorIdx}, {atomIndex=pivotIdx},
 
         {atomIndex=rotorIdx}, toangle)
 
         {atomIndex=rotorIdx}, toangle)
 
}
 
}
  
 
# Selected must include fourth parameter but not the first
 
# Selected must include fourth parameter but not the first
function setDihedralAtoms( stator1, stator2, rotor1, rotor2, toangle) {
+
function set_dihedral_atoms( stator, pivot1, pivot2, rotor, toangle) {
 
     try {
 
     try {
         var curangle =  angle(stator1, stator2, rotor1, rotor2)
+
         var curangle =  angle(stator, pivot1, pivot2, rotor)
         rotateselected {rotor1} {stator2} @{curangle-toangle}
+
         rotateselected {pivot2} {pivot1} @{curangle-toangle}
 
     }
 
     }
 
     catch {
 
     catch {
 
     }
 
     }
 
}
 
}
function setDihedralIdx( stator1idx, stator2idx, rotor1idx, rotor2idx, toangle) {
+
function set_dihedral_idx( statorIdx, pivot1idx, pivot2idx, rotorIdx, toangle) {
     setDihedralAtoms({atomIndex = stator1idx}, {atomIndex = stator2idx},
+
     set_dihedral_atoms({atomIndex = statorIdx}, {atomIndex = pivot1idx},
         {atomIndex = rotor1idx}, {atomIndex = rotor2idx}, toangle)
+
         {atomIndex = pivot2idx}, {atomIndex = rotorIdx}, toangle)
 
}
 
}
  
function countCollisions(rc) {
+
function angle_idx_4( a1idx, a2idx, a3idx, a4idx) {
 +
    return angle({atomIndex=a1idx}, {atomIndex=a2idx},
 +
        {atomIndex=a3idx}, {atomIndex=a4idx})
 +
}
 +
 
 +
# First and last are BB atoms
 +
# Any side atoms in the range are also selected
 +
function select_nward_idx (firstIdx, lastIdx) {
 +
    var firstno = ((firstIdx < 0) ? {atomIndex=lastIdx}.atomno : {atomIndex=firstIdx}.atomno)
 +
    var lastno = ((lastIdx < 0) ? firstno : {atomIndex=lastIdx}.atomno)
 +
    var iChain = ((firstIdx < 0)
 +
        ? {atomIndex=lastIdx}.chain : {atomIndex=firstIdx}.chain)
 +
 
 +
    select ((atomno <= firstno) and (atomno >= lastno) and (chain = iChain)
 +
        and thisModel)
 +
    if ({(atomno=firstno) and (chain=gChain)
 +
        and thisModel}.atomName == "C") { # if psi
 +
        add_sc_to_select(firstno-1, true, true, iChain)
 +
        var a = {(atomno=@{firstno+1}) and (chain=iChain) and thisModel}
 +
        a.selected = true # add O
 +
    }
 +
    if ({(atomno=firstno) and (chain=iChain)
 +
        and thisModel}.atomName == "CA") {
 +
        add_sc_to_select(firstno, true, false, iChain)
 +
    }
 +
    if ({(atomno=lastno) and (chain=iChain)
 +
        and thisModel}.atomName == "C") { # if psi
 +
        add_sc_to_select(lastno-1, false, false, iChain)
 +
    }
 +
}
 +
 
 +
function add_sc_to_select(CAno, isAdd, addOXT, iChain) {
 +
    var res = {(atomno=CaNo) and (chain=iChain) and thisModel}.resno
 +
    var scset = {(resno=res) and (chain=iChain) and thisModel and sidechain}
 +
    if (addOXT) {
 +
        scset = scset or get_atom_rcn(res, iChain, "OXT")
 +
    }
 +
    if (isAdd) {
 +
        select add scset
 +
    }
 +
    else {
 +
        select remove scset
 +
    }
 +
}
 +
 
 +
# First and last are BB atoms
 +
# Any side atoms in the range are also selected
 +
function select_cward_idx (firstIdx, lastIdx) {
 +
    var firstno = ((firstIdx < 0) ? gMaxNo : {atomIndex=firstIdx}.atomno)
 +
    var lastno = ((lastIdx < 0) ? 1 : {atomIndex=lastIdx}.atomno)
 +
    var iChain = ((firstIdx < 0)
 +
        ? {atomIndex=lastIdx}.chain : {atomIndex=firstIdx}.chain)
 +
 
 +
    # If nWard anchor in range, begin selection with it
 +
    if ((gNanchorIdx >= 0) and ({atomIndex=gNanchorIdx}.chain == iChain))  {
 +
        var aNo = {atomIndex=gNanchorIdx}.atomno
 +
        if (aNo > firstNo) {
 +
            firstno = aNo
 +
        }
 +
    }
 +
 
 +
    # If cWard anchor in range, end selection with it
 +
    if ((gCanchorIdx >= 0) and ({atomIndex=gCanchorIdx}.chain == iChain))  {
 +
        var aNo = {atomIndex=gCanchorIdx}.atomno
 +
        if (aNo < lastNo) {
 +
            lastno = aNo
 +
        }
 +
    }
 +
 
 +
    select ((atomno >= firstno) and (atomno <= lastno) and (chain = iChain)
 +
        and thisModel)
 +
 
 +
    if ({(atomno=firstno) and (chain=iChain)
 +
        and thisModel}.atomName == "C") { # if psi
 +
        add_sc_to_select(firstno-1, false, false, iChain)
 +
    }
 +
    if ({(atomno=lastno) and (chain=iChain)
 +
        and thisModel}.atomName == "CA") {
 +
        add_sc_to_select(lastno, true, false, iChain)
 +
    }
 +
    if ({(atomno=lastno) and (chain=iChain)
 +
        and thisModel}.atomName == "C") { # if psi
 +
        add_sc_to_select(lastno-1, true, true, iChain)
 +
        var a = {(atomno=@{lastno+1}) and (chain=iChain) and thisModel}
 +
        a.selected = true # add O
 +
    }
 +
}
 +
 
 +
# tug.spt needed to handle collisions
 +
function to_handle_collisions( idx) {
 +
    # Load tug functions
 +
    if (kTug < 3) {
 +
        script $SCRIPT_PATH$tug.spt
 +
        if (kTug < 3) {
 +
            prompt ("A newer version of tug.SPT is required")
 +
            quit
 +
        }
 +
    }
 +
    handle_collisions( idx)
 +
}
 +
 
 +
function count_collisions(rc) {
 
     var cAtoms = ({})
 
     var cAtoms = ({})
     for (var idx = {*}.min.atomIndex; idx <= {*}.max.atomIndex; idx++) {
+
     for (var idx = {thisModel}.min.atomIndex;
         if ({atomIndex=idx}.size > 0) {
+
        idx <= {thisModel}.max.atomIndex; idx++) {
             var lcAtoms = (within(kCtolerance, FALSE, {atomIndex=idx})
+
         if ({atomIndex=idx} and {element!="H"}) {
                 and {atomIndex > idx}
+
             var lcAtoms = (within(kCtolerance, false, {atomIndex=idx})
                and not {rc}
+
                 and {atomIndex > idx} and {element!="H"}
 
                 and not connected({atomIndex=idx}))
 
                 and not connected({atomIndex=idx}))
             if (lcAtoms.size > 0) {
+
             if (lcAtoms) {
                 cAtoms = cAtoms or lcAtoms
+
                 cAtoms = cAtoms or lcAtoms or {atomIndex=idx}
                 if (rc == TRUE) {
+
                 for (var i = 1; i <= lcAtoms.size; i++) {
                     print format("Collision of idx=%d with %s", idx, lcAtoms)
+
                     print format("Collision of ({%d}) with %s", idx, lcAtoms[i])
 +
                    if (rc == true) {
 +
                        measure {atomindex=idx} {@{lcAtoms[i]}}
 +
                    }
 
                 }
 
                 }
 
             }
 
             }
 
         }
 
         }
 
     }
 
     }
     return cAtoms.size
+
     return cAtoms
 +
}
 +
 
 +
# Utility
 +
function get_atom_rcn( iResno, iChain, iName) {
 +
    return {(resno=iResno) and (chain=iChain) and (atomName=iName)
 +
        and thisModel}
 
}
 
}
  
# A handy debug routine
+
# Utility
function cc {
+
function atom_noc( iNo, iChain) {
     print countcollisions(TRUE)
+
     return {(atomno=iNo) and (chain=iChain) and thisModel}
 
}
 
}
  
 
# A handy debug routine
 
# A handy debug routine
 
function hi {
 
function hi {
     var selsave = {selected}
+
    hover "%D %U"
    select all
+
}
    set hoverlabel "%D %U"
+
 
     select {selsave}
+
function plico_menu_toggle() {
 +
     var yr = _height-25
 +
    if ((_mouseY > (_height-25)) and (_mouseX < 300)) {
 +
        if (gMenuMin) {
 +
            echo @gEcho
 +
        }
 +
        else {
 +
            var p = gEcho.find("|")
 +
            if (p > 0) {
 +
                echo @{gEcho[1][p-1]}
 +
            }
 +
            else {
 +
                echo
 +
            }
 +
        }
 +
        gMenuMin = !gMenuMin
 +
     }
 +
    gBusy = false
 
}
 
}
  
function plicoPrelim() {
+
function plico_prelim(repair, backup) {
  
 
     # Push selected
 
     # Push selected
 
     gSelSaves = {selected}
 
     gSelSaves = {selected}
     select all
+
     select (thisModel)
      
+
     gBusy=false
 +
 
 
     # Bad idea to proceed when collisions present
 
     # Bad idea to proceed when collisions present
     while (TRUE) {
+
     while (repair) {
         var cc = countCollisions(({}))
+
         var cc = count_collisions(({})).size
 
         if (cc > 0) {
 
         if (cc > 0) {
 
             var p = prompt(format("%d collision%s present!\nProceed anyway?",
 
             var p = prompt(format("%d collision%s present!\nProceed anyway?",
                 cc, ((cc > 1) ? "s" : "")), "OK|Cancel|Repair", TRUE)
+
                 cc, ((cc > 1) ? "s" : "")), "OK|Cancel|Repair", true)
 
             if (p == "Cancel") {
 
             if (p == "Cancel") {
 
                 quit
 
                 quit
 
             }
 
             }
 
             else if (p == "Repair") {
 
             else if (p == "Repair") {
                 select all
+
                 select (thisModel)
 
                 allSet = {selected}
 
                 allSet = {selected}
 
                 gChain = "XX"
 
                 gChain = "XX"
Line 149: Line 287:
 
                     if ({atomIndex=idx}.chain != gChain) {
 
                     if ({atomIndex=idx}.chain != gChain) {
 
                         gChain = {atomIndex=idx}.chain
 
                         gChain = {atomIndex=idx}.chain
                         select {chain=gChain}
+
                         select {(chain=gChain) and thisModel}
                         handleCollisions2( idx)
+
                         to_handle_collisions( idx)
 
                     }
 
                     }
 
                 }
 
                 }
Line 165: Line 303:
 
     gZoom = script("show zoom")
 
     gZoom = script("show zoom")
 
     gRotate = script("show rotation")
 
     gRotate = script("show rotation")
     write tugsave.pdb
+
     if (backup) {
 +
        write plico_save.pdb
 +
    }
 
     select none
 
     select none
   
+
 
 
     gScheme = defaultColorScheme
 
     gScheme = defaultColorScheme
 
     gAltScheme = ((gScheme == "jmol") ? "rasmol" : "jmol")
 
     gAltScheme = ((gScheme == "jmol") ? "rasmol" : "jmol")
Line 173: Line 313:
 
     background ECHO yellow
 
     background ECHO yellow
 
     gChain = ""
 
     gChain = ""
 +
    gMenuMin = false
 
     unbind
 
     unbind
 
}
 
}
  
function plicoExit() {
+
# gPlicoRecord is maintained by the macro plicoRecord
 +
function plico_record(s) {
 +
    var g = format("show file \"%s\"", gPlicoRecord)
 +
    var ls = script(g)
 +
    if (ls.find("FileNotFoundException") > 0) {
 +
        ls = ""
 +
    }
 +
    ls += s
 +
    write var ls @gPlicoRecord
 +
}
 +
 
 +
function plico_exit(undo) {
 
     var p = ""
 
     var p = ""
     if (gPlico.size > 0) {
+
    var done = false
         p = prompt(format("Exit %s?", gPlico), "Yes|No|Undo", TRUE)
+
     if (gPlico) {
         if (p == "Undo") {
+
         p = prompt(format("Exit %s?", gPlico),
             load tugsave.pdb
+
            "Yes|No"+(undo ? "|Undo all" : ""), true)
 +
         if (p == "Undo all") {
 +
             load plico_save.pdb
 
             script inline gZoom
 
             script inline gZoom
 
             rotate @gRotate
 
             rotate @gRotate
             echo Tug session undone
+
             echo Session undone
 
             if (gPlicoRecord != "") {
 
             if (gPlicoRecord != "") {
                 plicoRecord("load tugsave.pdb;")
+
                 plico_record("load plico_save.pdb;")
 
             }
 
             }
 +
            reset gPlotEcho
 +
            set AnimFrameCallback NONE
 
         }
 
         }
 
     }
 
     }
Line 193: Line 349:
 
         unbind
 
         unbind
 
         halo off
 
         halo off
        echo
+
         select (thisModel)
         select all
 
 
         halo off
 
         halo off
 
         star off
 
         star off
 
         color {selected} @gScheme
 
         color {selected} @gScheme
 
         draw gSCcircle DELETE
 
         draw gSCcircle DELETE
         gBusy = FALSE
+
         gBusy = false
 +
        gEcho = ""
 +
        set echo TOP LEFT
 
         background ECHO yellow
 
         background ECHO yellow
 +
        echo @gEcho
 +
        gMenuMin = false
 +
        done = true
  
 
         # Pop selected
 
         # Pop selected
 
         select gSelSaves
 
         select gSelSaves
 +
    }
 +
    return done
 +
}
 +
 +
function add_hydrogens(addh) {
 +
    delete hydrogen
 +
    connect {*} {*} aromatic modify
 +
    if (addh) {
 +
        calculate hydrogens
 +
    }
 +
    calculate aromatic
 +
}
 +
 +
# Prevents minimization from disrespecting planar elements
 +
# and allows calculate hydrogens to place hydrogens correctly
 +
function double_bond_planars(iChain, undo) {
 +
print format("double_bond_planars(%s, %s)", iChain, undo)
 +
    for (var i = get_resno_min(iChain); i <= get_resno_max(iChain); i++) {
 +
        var aa = {resno=i}.group[0]
 +
        var bps = ["O","C"]
 +
        switch (aa) {
 +
        case 'ARG' :
 +
            bps += ["CZ","NH1"]
 +
            break
 +
        case 'ASN' :
 +
        case 'ASP' :
 +
            bps += ["OD1","CG"]
 +
            break
 +
        case 'GLN' :
 +
        case 'GLU' :
 +
            bps += ["OE1","CD"]
 +
            break
 +
        case 'HIS' :
 +
            bps += ["CG","CD2","CE1","NE2"]
 +
            break
 +
        case 'PHE' :
 +
        case 'TYR' :
 +
            bps += ["CG","CD1","CD2","CE2","CE1","CZ"]
 +
            break
 +
        case 'TRP' :
 +
            bps += ["CG","CD1","CD2","CE2","CE3","CZ3","CZ2","CH2"]
 +
            break
 +
        case 'A' :
 +
        case 'G' :
 +
        case 'DA' :
 +
        case 'DG' :
 +
            bps = ["N7","C8","C4","C5","N3","C2", ((aa = "A") ? "N1" : "O6"), "C6"]
 +
            break
 +
        case 'C' :
 +
        case 'U' :
 +
        case 'T' :
 +
        case 'DC' :
 +
        case 'DT' :
 +
        case 'DU' :
 +
            bps = ["C5","C6","C2","O2","C4","CZ",((aa = "C") ? "N3" : "O4")]
 +
            break
 +
        }
 +
        for (var j = 1; j <= bps.size; j += 2) {
 +
            var a1 = get_atom_rcn( i, iChain, bps[j])
 +
            var a2 = get_atom_rcn( i, iChain, bps[j+1])
 +
            if (undo) {
 +
                connect @a1 @a2 single
 +
            }
 +
            else {
 +
                connect @a1 @a2 double
 +
            }
 +
        }
 +
        var a1 = get_atom_rcn(get_resno_max(iChain), iChain, "O")
 +
        var a2 = get_atom_rcn(get_resno_max(iChain), iChain, "C")
 +
        if (undo) {
 +
            connect @a1 @a2 single
 +
        }
 +
        else {
 +
            connect @a1 @a2 double
 +
        }
 +
    } # endfor
 +
   
 +
    if (_version > 1402015) {
 +
        set multipleBondBananas true
 +
    }
 +
}
 +
 +
function get_resno_max( iChain) {
 +
    return {not hoh and not ligand and (chain=iChain) and thisModel}.resno.max
 +
}
 +
 +
function get_resno_min( iChain) {
 +
    return {not hoh and not ligand and (chain=iChain) and thisModel}.resno.min
 +
}
 +
 +
function plico_minimize( aset) {
 +
    try {
 +
        var savemt = useMinimizationThread
 +
        set useMinimizationThread false
 +
        var ms = minimizationSilent
 +
        set minimizationSilent true
 +
        minimize @aset
 +
       
 +
        set useMinimizationThread savemt
 +
        set minimizationSilent ms
 +
    }
 +
    catch {
 +
        print "minimization error"
 +
    }
 +
}
 +
 +
function p(s) {
 +
    print s
 +
}
 +
 +
function delete_from_array( a, item) {
 +
    for (var i = 1; i <= a.size; i++) {
 +
        if (a[i] = item) {
 +
            if (i == 1) {
 +
                a = a[i+1][0]
 +
            }
 +
            else {
 +
                a = a[1][i-1]+a[i+1][0]
 +
            }
 +
        }
 
     }
 
     }
 
}
 
}
# end of plicoCommon.spt
+
 
</pre>
+
# end of plicocommon.spt</pre>

Latest revision as of 17:08, 12 April 2016

This script contains routines used by other scripts of the Plico suite. It must be located in the same directory as any script that uses these routines.

Copy and paste the following into a text editor and save in your scripts folder as plicoCommon.spt.

#   plicoCommon - Jmol script by Ron Mignery
#   v1.12 beta    4/12/2016 -axis is now a reserved word
#
#   Routines and values common to all Plico suite scripts
#   Must be present in the same directory as other Plico scripts that use it
kCommon = 7
kDtolerance = 0.1
kCtolerance = 1.85
gMouseX = 0
gMouseY = 0
gMinNo = 1
gMaxNo = 9999
gOK = true # global return value to work around jmol *feature*
gOk2 = true # "    "
gScheme = "Jmol"
gAltScheme = "Rasmol"
gBusy = false
gEcho = ""
gMenuMin = false

# Return L tetrahedron point if i1<i2<i3, else R point
function get_tet_idx(i1, i2, i3, dist) {
    var v1 = {atomIndex=i3}.xyz - {atomIndex=i2}.xyz
    var v2 = {atomIndex=i1}.xyz - {atomIndex=i2}.xyz
    var caxis = cross(v1, v2)
    var pma = ({atomIndex=i1}.xyz + {atomIndex=i3}.xyz)/2
    var pmo = {atomIndex=i2}.xyz + {atomIndex=i2}.xyz - pma
    var pt = pmo + (caxis/caxis)

    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
}

function get_trigonal_idx(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 second parameter but not the first
# Static may be just a point
function set_distance_atoms( static, mobile, desired) {
    try {
        var s = ((static.type == "point") ? static : static.xyz)        
        var v = mobile.xyz - s
        var dist = distance(s, mobile)
        translateSelected @{(v * (desired/dist)) - v}
    }
    catch {
    }
}
function set_distance_idx( staticIdx, mobileIdx, desired) {
    set_distance_atoms({atomIndex=staticIdx}, {atomIndex=mobileIdx}, desired)
}

# Selected must include third parameter but not the first
# Stator and pivot may be just points
function set_angle_atoms( stator, pivot, rotor, toangle) {
    try {
        var s = ((stator.type == "point") ? stator : stator.xyz)        
        var p = ((pivot.type == "point") ? pivot : pivot.xyz)        
        var v1=s - p
        var v2=rotor.xyz - p
        var caxis = cross(v1, v2) + p
        var curangle =  angle(stator, pivot, rotor)
        rotateselected @caxis @pivot @{curangle-toangle}
    }
    catch {
        print format("unable to set_angle_atoms( stator=%s, pivot=%s, rotor=%s, toangle=%f)",
            stator, pivot, rotor, toangle)
    }
}
function set_angle_idx( statorIdx, pivotIdx, rotorIdx, toangle) {
    set_angle_atoms({atomIndex=statorIdx}, {atomIndex=pivotIdx},
        {atomIndex=rotorIdx}, toangle)
}

# Selected must include fourth parameter but not the first
function set_dihedral_atoms( stator, pivot1, pivot2, rotor, toangle) {
    try {
        var curangle =  angle(stator, pivot1, pivot2, rotor)
        rotateselected {pivot2} {pivot1} @{curangle-toangle}
    }
    catch {
    }
}
function set_dihedral_idx( statorIdx, pivot1idx, pivot2idx, rotorIdx, toangle) {
    set_dihedral_atoms({atomIndex = statorIdx}, {atomIndex = pivot1idx},
        {atomIndex = pivot2idx}, {atomIndex = rotorIdx}, toangle)
}

function angle_idx_4( a1idx, a2idx, a3idx, a4idx) {
    return angle({atomIndex=a1idx}, {atomIndex=a2idx},
        {atomIndex=a3idx}, {atomIndex=a4idx})
}

# First and last are BB atoms
# Any side atoms in the range are also selected
function select_nward_idx (firstIdx, lastIdx) {
    var firstno = ((firstIdx < 0) ? {atomIndex=lastIdx}.atomno : {atomIndex=firstIdx}.atomno)
    var lastno = ((lastIdx < 0) ? firstno : {atomIndex=lastIdx}.atomno)
    var iChain = ((firstIdx < 0)
        ? {atomIndex=lastIdx}.chain : {atomIndex=firstIdx}.chain)

    select ((atomno <= firstno) and (atomno >= lastno) and (chain = iChain)
        and thisModel)
    if ({(atomno=firstno) and (chain=gChain)
        and thisModel}.atomName == "C") { # if psi
        add_sc_to_select(firstno-1, true, true, iChain)
        var a = {(atomno=@{firstno+1}) and (chain=iChain) and thisModel}
        a.selected = true # add O
    }
    if ({(atomno=firstno) and (chain=iChain)
        and thisModel}.atomName == "CA") {
        add_sc_to_select(firstno, true, false, iChain)
    }
    if ({(atomno=lastno) and (chain=iChain)
        and thisModel}.atomName == "C") { # if psi
        add_sc_to_select(lastno-1, false, false, iChain)
    }
}

function add_sc_to_select(CAno, isAdd, addOXT, iChain) {
    var res = {(atomno=CaNo) and (chain=iChain) and thisModel}.resno
    var scset = {(resno=res) and (chain=iChain) and thisModel and sidechain}
    if (addOXT) {
        scset = scset or get_atom_rcn(res, iChain, "OXT")
    }
    if (isAdd) {
        select add scset
    }
    else {
        select remove scset
    }
}

# First and last are BB atoms
# Any side atoms in the range are also selected
function select_cward_idx (firstIdx, lastIdx) {
    var firstno = ((firstIdx < 0) ? gMaxNo : {atomIndex=firstIdx}.atomno)
    var lastno = ((lastIdx < 0) ? 1 : {atomIndex=lastIdx}.atomno)
    var iChain = ((firstIdx < 0)
        ? {atomIndex=lastIdx}.chain : {atomIndex=firstIdx}.chain)

    # If nWard anchor in range, begin selection with it
    if ((gNanchorIdx >= 0) and ({atomIndex=gNanchorIdx}.chain == iChain))  {
        var aNo = {atomIndex=gNanchorIdx}.atomno
        if (aNo > firstNo) {
            firstno = aNo
        }
    }

    # If cWard anchor in range, end selection with it
    if ((gCanchorIdx >= 0) and ({atomIndex=gCanchorIdx}.chain == iChain))  {
        var aNo = {atomIndex=gCanchorIdx}.atomno
        if (aNo < lastNo) {
            lastno = aNo
        }
    }

    select ((atomno >= firstno) and (atomno <= lastno) and (chain = iChain)
        and thisModel)

    if ({(atomno=firstno) and (chain=iChain)
        and thisModel}.atomName == "C") { # if psi
        add_sc_to_select(firstno-1, false, false, iChain)
    }
    if ({(atomno=lastno) and (chain=iChain)
        and thisModel}.atomName == "CA") {
        add_sc_to_select(lastno, true, false, iChain)
    }
    if ({(atomno=lastno) and (chain=iChain)
        and thisModel}.atomName == "C") { # if psi
        add_sc_to_select(lastno-1, true, true, iChain)
        var a = {(atomno=@{lastno+1}) and (chain=iChain) and thisModel}
        a.selected = true # add O
    }
}

# tug.spt needed to handle collisions
function to_handle_collisions( idx) {
    # Load tug functions
    if (kTug < 3) {
        script $SCRIPT_PATH$tug.spt
        if (kTug < 3) {
            prompt ("A newer version of tug.SPT is required")
            quit
        }
    }
    handle_collisions( idx)
}

function count_collisions(rc) {
    var cAtoms = ({})
    for (var idx = {thisModel}.min.atomIndex;
        idx <= {thisModel}.max.atomIndex; idx++) {
        if ({atomIndex=idx} and {element!="H"}) {
            var lcAtoms = (within(kCtolerance, false, {atomIndex=idx})
                and {atomIndex > idx} and {element!="H"}
                and not connected({atomIndex=idx}))
            if (lcAtoms) {
                cAtoms = cAtoms or lcAtoms or {atomIndex=idx}
                for (var i = 1; i <= lcAtoms.size; i++) {
                    print format("Collision of ({%d}) with %s", idx, lcAtoms[i])
                    if (rc == true) {
                        measure {atomindex=idx} {@{lcAtoms[i]}}
                    }
                }
            }
        }
    }
    return cAtoms
}

# Utility
function get_atom_rcn( iResno, iChain, iName) {
    return {(resno=iResno) and (chain=iChain) and (atomName=iName)
        and thisModel}
}

# Utility
function atom_noc( iNo, iChain) {
    return {(atomno=iNo) and (chain=iChain) and thisModel}
}

# A handy debug routine
function hi {
    hover "%D %U"
}

function plico_menu_toggle() {
    var yr = _height-25
    if ((_mouseY > (_height-25)) and (_mouseX < 300)) {
        if (gMenuMin) {
            echo @gEcho
        }
        else {
            var p = gEcho.find("|")
            if (p > 0) {
                echo @{gEcho[1][p-1]}
            }
            else {
                echo
            }
        }
        gMenuMin = !gMenuMin
    }
    gBusy = false
}

function plico_prelim(repair, backup) {

    # Push selected
    gSelSaves = {selected}
    select (thisModel)
    gBusy=false

    # Bad idea to proceed when collisions present
    while (repair) {
        var cc = count_collisions(({})).size
        if (cc > 0) {
            var p = prompt(format("%d collision%s present!\nProceed anyway?",
                cc, ((cc > 1) ? "s" : "")), "OK|Cancel|Repair", true)
            if (p == "Cancel") {
                quit
            }
            else if (p == "Repair") {
                select (thisModel)
                allSet = {selected}
                gChain = "XX"
                for (var idx = {allSet}.atomIndex.min;
                    idx <= {allSet}.atomIndex.max; idx++) {
                    if ({atomIndex=idx}.chain != gChain) {
                        gChain = {atomIndex=idx}.chain
                        select {(chain=gChain) and thisModel}
                        to_handle_collisions( idx)
                    }
                }
            }
            else {
                break
            }
        }
        else {
            break
        }
    } # endwhile

    gZoom = script("show zoom")
    gRotate = script("show rotation")
    if (backup) {
        write plico_save.pdb
    }
    select none

    gScheme = defaultColorScheme
    gAltScheme = ((gScheme == "jmol") ? "rasmol" : "jmol")
    set echo TOP LEFT
    background ECHO yellow
    gChain = ""
    gMenuMin = false
    unbind
}

# gPlicoRecord is maintained by the macro plicoRecord
function plico_record(s) {
    var g = format("show file \"%s\"", gPlicoRecord)
    var ls = script(g)
    if (ls.find("FileNotFoundException") > 0) {
        ls = ""
    }
    ls += s
    write var ls @gPlicoRecord
}

function plico_exit(undo) {
    var p = ""
    var done = false
    if (gPlico) {
        p = prompt(format("Exit %s?", gPlico),
            "Yes|No"+(undo ? "|Undo all" : ""), true)
        if (p == "Undo all") {
            load plico_save.pdb
            script inline gZoom
            rotate @gRotate
            echo Session undone
            if (gPlicoRecord != "") {
                plico_record("load plico_save.pdb;")
            }
            reset gPlotEcho
            set AnimFrameCallback NONE
        }
    }
    if (p != "No") {
        unbind
        halo off
        select (thisModel)
        halo off
        star off
        color {selected} @gScheme
        draw gSCcircle DELETE
        gBusy = false
        gEcho = ""
        set echo TOP LEFT
        background ECHO yellow
        echo @gEcho
        gMenuMin = false
        done = true

        # Pop selected
        select gSelSaves
    }
    return done
}

function add_hydrogens(addh) {
    delete hydrogen
    connect {*} {*} aromatic modify
    if (addh) {
        calculate hydrogens
    }
    calculate aromatic
}

# Prevents minimization from disrespecting planar elements
# and allows calculate hydrogens to place hydrogens correctly
function double_bond_planars(iChain, undo) {
print format("double_bond_planars(%s, %s)", iChain, undo)
    for (var i = get_resno_min(iChain); i <= get_resno_max(iChain); i++) {
        var aa = {resno=i}.group[0]
        var bps = ["O","C"]
        switch (aa) {
        case 'ARG' :
            bps += ["CZ","NH1"]
            break
        case 'ASN' :
        case 'ASP' :
            bps += ["OD1","CG"]
            break
        case 'GLN' :
        case 'GLU' :
            bps += ["OE1","CD"]
            break
        case 'HIS' :
            bps += ["CG","CD2","CE1","NE2"]
            break
        case 'PHE' :
        case 'TYR' :
            bps += ["CG","CD1","CD2","CE2","CE1","CZ"]
            break
        case 'TRP' :
            bps += ["CG","CD1","CD2","CE2","CE3","CZ3","CZ2","CH2"]
            break
        case 'A' :
        case 'G' :
        case 'DA' :
        case 'DG' :
            bps = ["N7","C8","C4","C5","N3","C2", ((aa = "A") ? "N1" : "O6"), "C6"]
            break
        case 'C' :
        case 'U' :
        case 'T' :
        case 'DC' :
        case 'DT' :
        case 'DU' :
            bps = ["C5","C6","C2","O2","C4","CZ",((aa = "C") ? "N3" : "O4")]
            break
        }
        for (var j = 1; j <= bps.size; j += 2) {
            var a1 = get_atom_rcn( i, iChain, bps[j])
            var a2 = get_atom_rcn( i, iChain, bps[j+1])
            if (undo) {
                connect @a1 @a2 single
            }
            else {
                connect @a1 @a2 double
            }
        }
        var a1 = get_atom_rcn(get_resno_max(iChain), iChain, "O")
        var a2 = get_atom_rcn(get_resno_max(iChain), iChain, "C")
        if (undo) {
            connect @a1 @a2 single
        }
        else {
            connect @a1 @a2 double
        }
    } # endfor
    
    if (_version > 1402015) {
        set multipleBondBananas true
    }
}

function get_resno_max( iChain) {
    return {not hoh and not ligand and (chain=iChain) and thisModel}.resno.max
}

function get_resno_min( iChain) {
    return {not hoh and not ligand and (chain=iChain) and thisModel}.resno.min
}

function plico_minimize( aset) {
    try {
        var savemt = useMinimizationThread
        set useMinimizationThread false
        var ms = minimizationSilent
        set minimizationSilent true
        minimize @aset
        
        set useMinimizationThread savemt
        set minimizationSilent ms
    }
    catch {
        print "minimization error"
    }
}

function p(s) {
    print s
}

function delete_from_array( a, item) {
    for (var i = 1; i <= a.size; i++) {
        if (a[i] = item) {
            if (i == 1) {
                a = a[i+1][0]
            }
            else {
                a = a[1][i-1]+a[i+1][0]
            }
        }
    }
}

# end of plicocommon.spt

Contributors

Remig