User:Remig/plico/hydrate

From Jmol
Jump to navigation Jump to search

Hydrate.spt allows the user to add, remove and view water molecules at appropriate places by clicking on a chain. When viewing water, a menu is presented for selecting among waters hbonded to a single oxygen, two oxygens, three oxygens, a single nitrogen, two nitrogens, three nitrogens, an oxygen and a nitrogen, an oxygen and two nitrogens, two oxygens and one nitrogen, or more than three atoms and atoms with two waters.

Hydrate 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 Hydrate
Script=script <path to your script directory>/hydrate.spt;plico_hydrate

saved as hydrate.macro in your .jmol/macros directory as described in Macro.

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

#   hydrate - Jmol script by Ron Mignery
#   v1.1 beta    4/12/2016 -require latest common includes
#
#   View waters of hydration (HOH) iteratively of any model
#    or add or delete waters on all available sites
#
#   Addition requires space where h-bonding is possible at a distance
#    of 2.3 angstrom at an angle > 100 degrees 
#
gI = 1
gSel = ""
function add_water(idx) {
    var f = _frameID/1000000
    var m = _frameID%1000000
    var iChain = {atomIndex=idx}.chain
    var ap = {atomIndex=idx}
    var pt = {0 0 0}
    var cSet = connected(ap)
    var tri = false
    if (cSet.size == 1) {
        var v = ap.xyz - cSet[1].xyz
        pt = ap.xyz + v + v
    }
    else {
        pt = get_trigonal_idx(cSet[1].atomIndex, idx, cSet[2].atomIndex, 2.3)
        tri = true
    }
    
    if (within(kCtolerance, pt).size == 0) {
        print "Hydrating " + ap 
        var ls = "data \"append addto\"\n"
        ls += format("ATOM  %5d  O   HOH %s%4d    ",
             {thisModel}.atomno.max + 1, iChain, ap.resno)
        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 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) {
                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]} @ap 5 
        } # endfor
    
        if ( i >= 360) {
            print "no room for water"
            delete ahoh
        }
    }
}

function view_hoh_mb() {
    display all
    font echo 20
    var hset = {hoh}
    color @hset pink
    o1n0 = []
    o0n1 = []
    o2n0 = [] 
    o0n2 = []
    o1n1 = []
    o2n1 = []
    o1n2 = []
    o3n0 = []
    o0n3 = []
    xgt3 = []
    wxw = []
    
    for (var i = 1; i <= hset.size; i++) {
        var ah = hset[i]
        var onset = {within(2.9, ah) and (oxygen or nitrogen) and not hoh}
        var oc = 0
        var nc = 0
        for (var j = 1; j <= onset.size; j++) {
            var cset = connected(onset[j])
            var ok = false
            if (cset) {
                ok = (angle(cset[1], onset[j], ah) > 100)
            }
            if ((ok == false) and (cset.size > 1)) {
                ok = (angle(cset[2], onset[j], ah) > 100)
            }
            if (ok) {
                if (onset[j].atomName[1]="O") {
                    oc++
                }
                else {
                    nc++
                }
            }
            wxwset = hset and within(2.9, onset[j])
            if (wxwset.size > 1) {
                wxw = wxw + onset[j]
            }
        }
        var oxnx = (((oc+nc) > 3) ? "xgt3" : format("o%dn%d", oc, nc))
        @oxnx = @oxnx + ah
    }
#print "=t"
#throw context t    
    var p1=format("O___[%2d]|OO__[%2d]|OOO_[%2d]|", o1n0.size, o2n0.size, o3n0.size)
    var p2=format("___N[%2d]|__NN[%2d]|_NNN[%2d]|", o0n1.size, o0n2.size, o0n3.size)
    var p3=fOrmat("O__N[%2d]|O_NN[%2d]|OO_N[%2d]|XGT3[%2d]|WXW [%2d]|",
        o1n1.size, o1n2.size, o2n1.size, xgt3.size, wxw.size)
    gEcho="__Menu__|"+p1+p2+p3+"QUIT VIEW"        
    set echo top left
    color echo black
    background echo lightgrey
    echo @gEcho
    unbind "ALT-LEFT-CLICK" "+:hydrate_mb";
    unbind "ALT-SHIFT-LEFT-CLICK" "+:dehydrate_mb";
    #bind "SHIFT-LEFT-CLICK" "_pickAtom";
    bind "CTRL-LEFT-CLICK" "+:tour_ctrl_click_mb";
    bind "LEFT-CLICK" "+:tour_click_mb"
    
}

function hoh_tour() {
print format("x=%d y=%d", _mouseX, _mouseY)
    if ((_mouseX < 100) and ((_height-_mouseY) < 343)) {
        var line = ((_mouseX < 125) ? ((_height-_mouseY)\26) : 0)
print format("line=%d", line)        
        if (gEcho.size > 80) {
            if (line ==12) {
                select all
                halo off
                display all
                unbind
                background echo yellow
                color echo red
                measure off
                plico_hydrate()
                return 
            }
            else if (line < 1) {
                return
            }
            gI = 1
            sel = ["o1n0", "o2n0", "o3n0", "o0n1", "o0n2", "o0n3", "o1n1",
                "o1n2", "o2n1", "xgt3", "wxw"]
            gSel = sel[line]
            line = 0
        }
        
        var mx = format("%d of %d", gI, @gSel.size)
        gEcho = "__Menu__|<= prev |     next => |     back|    " + mx
        echo @gEcho
        
        if (line == 1) {
            gI--
        }
        
        else if (line == 2) {
            gI++
        }
        
        else if (line == 3) {
            view_hoh_mb()
            return
        }
        
        if (@gSel) {
            if (gI < 1) {
                gI = @gSel.size
            }
            if (gi > @gSel.size) {
                gi = 1
            }
            display_around_atom(@gSel[gI])
        }
        else {
            view_hoh_mb()
        }
    }
}

function display_around_atom(aa) {
    halo off
    center @aa
    var cset = connected(aa)
    var ccset = connected(cset) and not aa
    var nset = {(within( 2.9, aa) and (oxygen or nitrogen)
        and not ccset and not aa) or cset}
    
    select nset or aa
    halo on
    display within( 6, aa)
    measure off
    var j = 1
    for (var i = 1; i <= nset.size; i++) {
        if ((nset[i] and cset).size == 0) {
            measure @aa @{nset[i]}
        }
    
        if (ccset.size == 0) {
            var aset = connected(nset[i])
            for (var j = 1; j <= nset.size; j++) {
                measure @aa @{nset[i]} @{aset[j]}
            }
        }
    }
    
    if (nset.size > 1) {
        measure @{nset[1]} @aa @{nset[2]}
    }
    if (nset.size > 2) {
        measure @{nset[1]} @aa @{nset[3]}
        measure @{nset[2]} @aa @{nset[3]}
    }
    if (nset.size > 2) {
        measure @{nset[4]} @aa @{nset[1]}
        measure @{nset[4]} @aa @{nset[2]}
        measure @{nset[4]} @aa @{nset[3]}
    }
print "if x1=t"    
if (x1) throw context t    
    refresh
}

function tour_ctrl_click_mb() {
print _atomPicked
    var r = {atomIndex=_atomPicked}.resno
    var c = {atomIndex=_atomPicked}.chain
    var n = {atomIndex=_atomPicked}.atomName
    display add {(resno=r) and (chain=c)}
    if (n == "N") {
        r--
        display add {(resno=r) and (chain=c)}
    }
    else if (n == "C") {
        r++
        display add {(resno=r) and (chain=c)}
    }
    else if (n == "O") {
        r++
        display add {(resno=r) and (chain=c)}
    }
}

function tour_click_mb() {

    # If in menu zone
    if ((_mouseX < 100) and ((_height-_mouseY) < 343)) {
        hoh_tour()
    }
    else if (_atomPicked >= 0) {
    
        var g = {atomIndex=_atomPicked}.group
        var n = {atomIndex=_atomPicked}.atomName
        if ((g == "HOH") or (n == "N") or (n =="O")) {
            display_around_atom({atomIndex=_atomPicked})
        }
    }
}

function hydrate_mb() {
    iChain = {atomIndex=_atomPicked}.chain
    for (var r = get_resno_min(iChain); r <= get_resno_max(iChain); r++) {
        var aO = get_atom_rcn( r, iChain, "O")
        if (aO.group != "HOH") {
            add_water(aO.atomIndex)
        }
        var aN = get_atom_rcn( r, iChain, "N")
        add_water(aN.atomIndex)
    }
}

function dehydrate_mb() {
    iChain = {atomIndex=_atomPicked}.chain
    delete {hoh and (chain=iChain) and thisModel}
}

# Top level of hydrate
function plico_hydrate() {

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

    gPlico = "HYDRATE"
    plico_prelim(false, true)

    gEcho = ("________HYDRATE________|ALT-CLICK=hydrate chain|" +
        "ALT-SHIFT-CLICK=dehydrate chain|" +
        "CTRL-CLICK=view HOHs|SHIFT-DOUBLE-CLICK=exit")
    echo @gEcho

    bind "ALT-LEFT-CLICK" "_pickAtom"
    bind "ALT-LEFT-CLICK" "+:hydrate_mb"
    bind "ALT-SHIFT-LEFT-CLICK" "_pickAtom"
    bind "ALT-SHIFT-LEFT-CLICK" "+:dehydrate_mb"
    unbind "CTRL-LEFT-DOWN"
    bind "CTRL-LEFT-CLICK" "view_hoh_mb"
    bind "SHIFT-DOUBLE" "hydrate_exit"
    bind "LEFT-CLICK" "+:plico_menu_toggle"

}

function hydrate_exit() {
    if (plico_exit(true)) {
        reset gI
        reset gSel
        reset o1n0
        reset o0n1
        reset o2n0 
        reset o0n2
        reset o1n1
        reset o2n1
        reset o1n2
        reset o3n0
        reset o0n3
        reset xgt3
        reset wxw
        display all
    }
}
# End of HYDRATE.SPT

Contributors

Remig