Difference between revisions of "User:Remig/plico/tug"
< User:Remig | plico
Jump to navigation
Jump to search
(Use plico) |
(Avoid "axis," a newly reserved word) |
||
| (10 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
| − | '''Tug''' allows the user to pull or push by mouse actions to move or rotate one part of a polypeptide against the rest by rotation on its psi and phi bonds with collision detection and restriction. It also allows the user to move an entire chain to nest against another chain. | + | '''Tug''' allows the user to pull or push by mouse actions to move or rotate one part of a polypeptide against the rest by rotation on its psi and phi bonds with collision detection and restriction. It also allows the user to move an entire chain to nest against another chain. A full description of its capabilities can be found [[User:Remig/plico/tugManual|here]]. |
'''Tug''' is a member of the Plico suite of protein folding tools described in [[User:Remig/plico]] . It may be installed and accessed as a macro with the file: | '''Tug''' is a member of the Plico suite of protein folding tools described in [[User:Remig/plico]] . It may be installed and accessed as a macro with the file: | ||
<pre>Title=PLICO Tug | <pre>Title=PLICO Tug | ||
| − | Script=script <path to your scripts | + | Script=script <path to your scripts directory>/tug.spt;plico_tug</pre> |
saved as plicotug.macro in your .jmol/macros directory as described in [[Macro]]. | saved as plicotug.macro in your .jmol/macros directory as described in [[Macro]]. | ||
| − | Copy and paste the following into a text editor and save in your scripts | + | Copy and paste the following into a text editor and save in your scripts directory as tug.spt. |
<pre># tug - Jmol script by Ron Mignery | <pre># tug - Jmol script by Ron Mignery | ||
| − | # v1. | + | # v1.20 beta 4/12/2016 -axis is now a reserved word |
# | # | ||
# Translate or rotate a stretch of a polypeptide against itself | # Translate or rotate a stretch of a polypeptide against itself | ||
# or against other chains by mouse actions | # or against other chains by mouse actions | ||
# | # | ||
| − | + | kTug = 3 | |
| − | + | gCanchorIdx = -1 | |
| − | + | gCanchorNo = -1 | |
| − | + | gPlico = "TUG" | |
| − | + | gNanchorIdx = -1 | |
| − | + | gNanchorNo = -1 | |
| − | + | gCcargoIdx = -1 | |
| − | + | gNcargoIdx = -1 | |
| − | + | gCcargoNo = -1 | |
| − | + | gNcargoNo = -1 | |
| − | + | gDestAtomIdx = -1 | |
| − | + | g1pivotIdx = -1 | |
| − | + | g2pivotIdx = -1 | |
| − | + | gSelSaves = ({}) | |
| − | + | gCrotors = array() | |
| − | + | gNrotors = array() | |
| − | + | gOkCollide = ({}) | |
| − | + | gChain = "" | |
| − | + | gMinNo = 1 | |
| − | + | gMaxNo = 9999 | |
| − | + | gCargoSet = ({}) | |
| − | + | gMovingSet = ({}) | |
| − | + | gBusy = false | |
| − | + | gSCidx = -1 | |
| − | + | gSCcircle = -1 | |
| − | + | gSCpt = {0 0 0} | |
| − | + | gTargetPt = {0 0 0} | |
| − | + | gNewDrag = false | |
| − | + | gTow = false | |
| − | + | g1dynamicIdx = -1 | |
| − | + | g2dynamicIdx = -1 | |
| − | + | gSCcheck = true | |
| − | + | gBondPicking = false | |
| − | + | gFreeze = array() | |
| − | + | gToab = false | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | function | + | function get_cp_idx (idx) { |
| − | while (( | + | var no = {atomIndex=idx}.atomno |
| − | + | while ((no < gMaxNo) and ({(atomno=no) and (chain=gChain) | |
| + | and thisModel}.atomName != "C")) { | ||
| + | no++ | ||
} | } | ||
| − | return | + | return ({(atomno=no) and (chain=gChain) and thisModel}.atomIndex) |
} | } | ||
| − | function | + | function get_cm_no (iNo) { |
| − | + | while ((iNo > 0) and ({(atomno=iNo) and (chain=gChain) | |
| − | + | and thisModel}.atomName != "C")) { | |
| − | + | iNo-- | |
| − | |||
| − | |||
| − | |||
| − | while ((iNo | ||
| − | iNo | ||
} | } | ||
return iNo | return iNo | ||
} | } | ||
| − | function | + | function get_nm_idx (idx) { |
| − | var no = {atomIndex=idx and (chain=gChain)}. | + | var no = {atomIndex=idx}.atomno |
| − | + | while ((no > 0) and ({(atomno=no) and (chain=gChain) | |
| − | return ({(atomno=no) and (chain=gChain)}.atomIndex) | + | and thisModel}.atomName != "N")) { |
| + | no-- | ||
| + | } | ||
| + | return ({(atomno=no) and (chain=gChain) and thisModel}.atomIndex) | ||
} | } | ||
| − | function | + | function get_np_no (iNo) { |
| − | while ((iNo < gMaxNo) and ({(atomno=iNo) and (chain=gChain)}.atomName != " | + | while ((iNo < gMaxNo) and ({(atomno=iNo) and (chain=gChain) |
| + | and thisModel}.atomName != "N")) { | ||
iNo++ | iNo++ | ||
} | } | ||
| Line 89: | Line 84: | ||
} | } | ||
| − | function | + | function get_cb_idx (BBidx) { |
| − | var no = {atomIndex= | + | var no = {atomIndex=BBidx}.atomno |
| − | + | var i = 1 | |
| − | return | + | for (; i < 5; i++) { |
| + | if ({(atomno=@{no+i}) and (chain=gChain) | ||
| + | and thisModel}.atomName == "CB") { | ||
| + | break | ||
| + | } | ||
| + | } | ||
| + | return {(atomno=@{no+i}) and (chain=gChain) and thisModel}.atomIndex | ||
} | } | ||
| − | function | + | function get_o_idx (BBidx) { |
| − | + | var no = {atomIndex=BBidx}.atomno | |
| − | + | var i = 1 | |
| + | for (; i < 4; i++) { | ||
| + | if ({(atomno=@{no+i}) and (chain=gChain) | ||
| + | and thisModel}.atomName == "O") { | ||
| + | break | ||
| + | } | ||
} | } | ||
| − | return | + | return {(atomno=@{no+i}) and (chain=gChain) and thisModel}.atomIndex |
} | } | ||
| − | function | + | function get_nward_bb_idx (idx, iChain) { |
| − | var no = {atomIndex=idx and (chain= | + | var no = {atomIndex=idx}.atomno - 1 |
| − | + | for (; no >= 0; no--) { | |
| − | return ({(atomno=no) and (chain= | + | var atomName = {(atomno=no) and (chain=iChain) |
| + | and thisModel}.atomName | ||
| + | if ((atomName = "N") or (atomName = "C") or (atomName = "CA")) { | ||
| + | break | ||
| + | } | ||
| + | } | ||
| + | return ((no >= 0) ? ({(atomno=no) and (chain=iChain) | ||
| + | and thisModel}.atomIndex) : -1) | ||
} | } | ||
| − | function | + | function get_cward_bb_idx (idx, iChain) { |
| − | + | var no = {atomIndex=idx}.atomno + 1 | |
| − | + | for (; no < gMaxNo; no++) { | |
| + | var atomName = {(atomno=no) and (chain=iChain) | ||
| + | and thisModel}.atomName | ||
| + | if ((atomName = "N") or (atomName = "C") or (atomName = "CA")) { | ||
| + | break | ||
| + | } | ||
} | } | ||
| − | return | + | return ((no >= 0) ? ({(atomno=no) and (chain=iChain) |
| + | and thisModel}.atomIndex) : -1) | ||
} | } | ||
| − | function | + | function get_sc_set (scIdx, iChain) { |
| − | var | + | var scSet = ({}) |
| − | + | var idx = get_sc_bb_idx(scIdx, iChain) | |
| − | + | var iNo = {atomIndex=idx}.atomno + 3 | |
| − | |||
| − | + | for (var i = 1; i < 20; i++) { | |
| − | + | idx = {(atomno=@{iNo+i}) and (chain=iChain) | |
| − | + | and thisModel}.atomIndex | |
| + | if (is_bb_idx(idx)) { | ||
| + | break | ||
| + | } | ||
| + | scSet = scSet or {atomIndex=idx} | ||
} | } | ||
| − | return | + | return scSet |
} | } | ||
| − | function | + | function get_sc_bb_idx (idx, iChain) { |
var no = {atomIndex=idx}.atomno | var no = {atomIndex=idx}.atomno | ||
| − | no | + | for (; no > 0; no--) { |
| − | + | if ({(atomno=no) and (chain=iChain) | |
| − | + | and thisModel}.atomName == "CA") { | |
| − | + | break | |
| − | + | } | |
| − | + | else if ({(atomno=no) and (chain=iChain) | |
| − | + | and thisModel}.atomName == "C") { | |
| − | |||
| − | if ({(atomno= | ||
break | break | ||
} | } | ||
| − | + | else if ({(atomno=no) and (chain=iChain) | |
| − | + | and thisModel}.atomName == "N") { | |
| − | + | break | |
| − | + | } | |
| − | + | else if ({(atomno=no) and (chain=iChain) | |
| − | + | and thisModel}.atomName == "CB") { | |
| − | + | no -= 3 | |
| − | |||
| − | if ({(atomno= | ||
break | break | ||
} | } | ||
} | } | ||
| − | return {(atomno= | + | return {(atomno=no) and (chain=iChain) and thisModel}.atomIndex |
} | } | ||
| − | function | + | function is_bb_idx(aIdx) { |
| − | + | var ret = false | |
| − | + | switch({atomIndex=aIdx}.atomName) { | |
| − | + | case "N": | |
| − | + | case "CA": | |
| − | + | case "C": | |
| + | ret = true | ||
| + | break | ||
} | } | ||
| − | return | + | return ret |
} | } | ||
| − | function | + | function is_sc_idx(aIdx) { |
| − | var | + | |
| − | + | var ret = false | |
| − | + | if (not is_bb_idx(aIDx)) { | |
| − | |||
| − | + | ret = true | |
| − | + | switch({atomIndex=aIdx}.atomName) { | |
| − | ({ | + | case "O": |
| − | + | case "CB": | |
| − | + | ret = false | |
| − | + | break | |
| + | } | ||
} | } | ||
| − | return | + | return ret |
} | } | ||
| − | function | + | function select_add_sc(fromIdx) { |
| − | var | + | var iNo = {atomIndex=fromIdx}.atomno |
| − | + | var iChain = {atomIndex=fromIdx}.chain | |
| − | + | select none | |
| + | while ({(atomno=iNo) and (chain=iChain) | ||
| + | and thisModel and sidechain}) { | ||
| + | var a = {(atomno=iNo) and (chain=iChain)and thisModel} | ||
| + | a.selected = true | ||
| + | iNo++ | ||
| + | } | ||
} | } | ||
| − | function | + | # Resolve collisions on selection |
| − | + | function handle_collisions( targetIdx) { | |
| − | + | ||
| − | + | # For all selected atoms | |
| − | + | for (var iNo = {selected}.min.atomno; iNo <= {selected}.max.atomno; iNo++) { | |
| − | + | var idx = {(atomno=iNo) and (chain=gchain) | |
| − | idx = {(atomno= | + | and thisModel}.atomIndex |
| − | if ( | + | if ({atomindex=idx}.selected) { |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # Collect local colliders | |
| − | + | var lcAtoms = (within(kCtolerance, false, {atomIndex=idx}) | |
| − | + | and not {atomIndex=idx} | |
| − | + | and not {gOkCollide} | |
| − | + | and not connected({atomIndex=idx})) | |
| − | + | if (lcAtoms) { | |
| − | + | # Ignore kinked BB | |
| − | + | try { | |
| − | + | if (is_bb_idx(idx) and (angle( | |
| − | + | {atomIndex=@{get_cward_bb_idx(idx, gChain)}}, {atomIndex=idx}, | |
| − | + | {atomIndex=@{get_nward_bb_idx(idx, gChain)}}) < 100.0)) { | |
| − | + | continue | |
| − | + | } | |
| − | + | } | |
| − | + | catch { | |
| − | + | } | |
| − | |||
| − | |||
| − | } | ||
| − | + | # For all local colliders | |
| − | + | for (var c = 1; c <= lcAtoms.size; c++ ) { | |
| − | + | var cidx = lcAtoms[c].atomIndex | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # If it is with water, delete it | |
| + | if (lcAtoms[c].group = "HOH") { | ||
| + | delete {atomIndex=cidx} | ||
| + | } | ||
| − | + | # else if it is with side chain not proline, fix it | |
| − | + | else if (is_sc_idx(cidx) and ({atomIndex=cidx}.group != "PRO")) { | |
| + | fix_sc_collision_2(cidx) | ||
| + | |||
| + | # If not fixed, exit fail | ||
| + | if (not gOk2) { | ||
| + | return # early exit (break n jmol bug) | ||
| + | } | ||
| + | } | ||
| − | + | # else if it is itself a side chain not proline, fix it | |
| − | + | else if (is_sc_idx(idx) and ({atomIndex=idx}.group != "PRO")) { | |
| − | + | fix_sc_collision_2(idx) | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # If not fixed, exit fail | |
| − | + | if (not gOk2) { | |
| − | + | return # early exit (break n jmol bug) | |
| − | + | } | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | } | ||
| − | + | # Else if it is with O, counter-rotate | |
| − | + | else if (lcAtoms[c].atomName = "O") { | |
| − | + | counter_rotate_2(lcAtoms[c].atomIndex, | |
| − | + | {atomIndex=idx}.xyz, targetIdx, false) | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | # | + | # If not fixed, exit fail |
| − | + | if (not gOk2) { | |
| − | + | return # early exit (break n jmol bug) | |
| − | + | } | |
| − | + | } | |
| − | |||
| − | |||
| − | + | # Else if it is itself O, counter-rotate | |
| + | else if ({atomIndex=idx}.atomName = "O") { | ||
| + | counter_rotate_2(idx, lcAtoms[c].xyz, targetIdx, false) | ||
| − | + | # If not fixed, exit fail | |
| − | + | if (not gOk2) { | |
| − | + | return # early exit (break n jmol bug) | |
| − | + | } | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | } | ||
| − | # | + | else { # Else not fixed, exit fail |
| − | + | gOk2 = false | |
| − | + | return # early exit (break n jmol bug) | |
| − | + | } | |
| − | + | } # endfor | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | } | + | } # endfor iNo |
| + | } | ||
| − | + | # Rotate rotor set to move target atom to its proper place | |
| − | + | function tug_track_idx(targetIdx, targetPt, nWard, cDetect) { | |
| − | + | gOK = false | |
| − | + | var pt = targetPt | |
| − | + | var dist = distance(pt, {atomIndex=targetIdx}.xyz) | |
| − | |||
| − | |||
| − | + | var rotors = (nWard ? gNrotors : gCrotors) | |
| − | + | # For a number of passes | |
| − | + | for (var pass1 = 0; pass1 < 20; pass1++) { | |
| − | + | var blocked = ({}) | |
| − | + | for (var pass2 = 0; pass2 < (rotors.size/4); pass2++) { | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| + | var v1 = {atomIndex=targetIdx}.xyz - pt | ||
| − | # | + | # Find the most orthgonal unused rotor |
| − | + | var imax = 0 | |
| + | var smax = 0.5 | ||
| + | for (var i = 1; i < rotors.size; i += 4) { | ||
| + | var i2 = rotors[i+1] | ||
| + | var i3 = rotors[i+2] | ||
| + | var i4 = rotors[i+3] | ||
| + | if ((i2 != targetIdx) and (i3 != targetIdx) and (i4 != targetIdx)) { | ||
| + | if ({blocked and {atomIndex=i2}}.count == 0) { | ||
| + | var v2 = {atomIndex=i3}.xyz - {atomIndex=i2}.xyz | ||
| − | + | var s = sin(abs(angle(v1, {0 0 0}, v2))) | |
| − | + | if (s > smax) { | |
| − | + | smax = s | |
| − | + | imax = i | |
| + | } | ||
| + | } | ||
| + | } | ||
| + | } | ||
| − | # | + | # If no more rotors, break to next full try |
| − | var | + | if (imax == 0) { |
| − | + | break | |
| − | + | } | |
| − | + | var i1 = rotors[imax+0] | |
| − | if ( | + | var i2 = rotors[imax+1] |
| + | var i3 = rotors[imax+2] | ||
| + | var i4 = rotors[imax+3] | ||
| + | |||
| + | # Get dihedral of rotor with target point | ||
| + | var dt = angle({atomIndex=targetIdx}, {atomIndex=i2}, {atomIndex=i3}, pt) | ||
| + | var dh = angle({atomIndex=i1}, {atomIndex=i2}, {atomIndex=i3}, {atomIndex=i4}) | ||
| + | if (abs(dh).type == "string") { | ||
| + | dh = -50 | ||
| + | } | ||
| + | var psi = dh + dt | ||
| + | var phi = dh + dt | ||
| − | + | # Compute resultant psi and phi | |
| − | if ( | + | # and select from target atom to first half of rotor |
| − | {atomIndex= | + | var movePt = false |
| − | + | if (nWard) { | |
| + | if ({atomIndex=i2}.atomName="CA") { | ||
| + | psi = angle({atomIndex=@{get_cward_bb_idx(i1, gChain)}}, {atomIndex=i1}, | ||
| + | {atomIndex=i2}, {atomIndex=i3}) + dt | ||
| + | } | ||
| + | else { | ||
| + | phi = angle({atomIndex=i1}, {atomIndex=i2}, | ||
| + | {atomIndex=i3}, {atomIndex=@{get_nward_bb_idx(i3, gChain)}}) + dt | ||
} | } | ||
| − | + | if ({atomIndex=i2}.atomno > {atomIndex=targetIdx}.atomno) { | |
| − | + | movePt = true | |
| − | + | select_nward_idx(i3, get_cward_bb_idx(targetIdx, gChain)) | |
| + | {atomIndex=targetIdx}.selected = true | ||
| + | } | ||
| + | else { | ||
| + | select_cward_idx(i2, targetIdx) | ||
| + | } | ||
| + | } | ||
| + | else { | ||
| + | if (({atomIndex=i2}.atomName="CA")) { | ||
| + | phi = angle({atomIndex=@{get_nward_bb_idx(i1, gChain)}}, {atomIndex=i1}, | ||
| + | {atomIndex=i2}, {atomIndex=i3}) + dt | ||
| + | } | ||
| + | else { | ||
| + | psi = angle({atomIndex=i2}, {atomIndex=i3}, | ||
| + | {atomIndex=i4}, {atomIndex=@{get_cward_bb_idx(i4, gChain)}}) + dt | ||
| + | } | ||
| − | + | if ({atomIndex=i2}.atomno < {atomIndex=targetIdx}.atomno) { | |
| − | + | movePt = true | |
| − | + | select_cward_idx(i3, get_nward_bb_idx(targetIdx, gChain)) | |
| − | } | + | {atomIndex=targetIdx}.selected = true |
| + | } | ||
| + | else { | ||
| + | select_nward_idx(i2, targetIdx) | ||
| + | } | ||
| + | } | ||
| − | + | # Relax rules if desperate | |
| − | + | if (pass1 > 10) { | |
| − | + | phi = -50 | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # If rotation within ramachandran limits | |
| − | + | if ((abs(dt) >= 0.1) and | |
| − | + | (({atomIndex=i2}.group=="GLY") or (phi < 0))) { | |
| − | |||
| − | + | # If moving target point, put the target atom there | |
| − | + | var cp = {atomIndex=targetIdx}.xyz | |
| − | + | if (movePt) { | |
| − | + | dt = -dt | |
| − | + | {atomIndex=targetIdx}.xyz = pt | |
| + | } | ||
| − | + | # Rotate to minimize vector ==================== | |
| − | + | rotateSelected {atomIndex=i2} {atomIndex=i3} @dt | |
| − | |||
| − | |||
| − | + | # If collision checking | |
| + | if (cDetect) { | ||
| + | |||
| + | # If collision, back off by eighths | ||
| + | var wasCollision = false | ||
| + | for (var ci = 0; ci < 4; ci++) { | ||
| + | if (ci < 3) { | ||
| + | dt /= 2 | ||
| + | } | ||
| + | handle_collisions( targetIdx) | ||
if (not gOk2) { | if (not gOk2) { | ||
| − | + | wasCollision = true | |
| + | rotateSelected {atomIndex=i2} {atomIndex=i3} @{-dt} | ||
| + | } | ||
| + | else if (wasCollision) { | ||
| + | if (ci <3) { | ||
| + | rotateSelected {atomIndex=i2} {atomIndex=i3} @{dt} | ||
| + | } | ||
} | } | ||
| − | + | else { | |
| − | + | break | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | |||
| − | + | if (dt < 0.01) { | |
| − | + | break | |
| − | + | } | |
| − | + | } # endfor | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | } | ||
| − | # | + | # If moving target point, put the target atom back |
| − | + | if (movePt) { | |
| − | + | pt = {atomIndex=targetIdx}.xyz | |
| − | + | {atomIndex=targetIdx}.xyz = cp | |
| − | + | } | |
| − | + | } | |
| − | + | # If close enough, stop | |
| − | + | if (distance(pt, {atomIndex=targetIdx}) < kDtolerance) { | |
| − | + | gOK = true | |
| − | + | gTargetPt = pt | |
| + | break | ||
| + | } | ||
| − | + | # Block rotor | |
| + | blocked |= {atomIndex=i2} | ||
| − | + | } # endfor num rotors passes | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | if (gOK) { | |
| − | + | break | |
| − | + | } | |
| − | + | } # endfor 20 passes | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | + | # Counter rotate bonds on either side of a BB O | |
| − | + | function do_counter_rotate(caPhiIdx, nIdx, cIdx, oIdx, caPsiIdx, dir, nWard) { | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # Rotate psi | |
| − | + | {atomIndex=nIdx}.selected = nWard | |
| − | + | {atomIndex=cIdx}.selected = nWard | |
| − | + | {atomIndex=oIdx}.selected = nward | |
| − | + | rotateSelected {atomIndex=caPsiIdx} {atomIndex=cIdx} @{dir} | |
| − | + | ||
| − | + | # Counter-rotate phi | |
| − | + | {atomIndex=nIdx}.selected = not nWard | |
| + | {atomIndex=cIdx}.selected = not nWard | ||
| + | {atomIndex=oIdx}.selected = not nward | ||
| + | rotateSelected {atomIndex=nIdx} {atomIndex=caPhiIdx} @{-dir} | ||
| + | } | ||
| + | |||
| + | function counter_rotate(oIdx, dir, nWard) { | ||
| − | + | var iChain = {atomIndex=oIdx}.chain | |
| − | + | var selsave = {selected} | |
| − | + | var cIdx = get_sc_bb_idx(oIdx, iChain) | |
| − | + | var nIdx = get_cward_bb_idx(cIdx, iChain) | |
| − | + | var caPhiIdx = get_cward_bb_idx(nIdx, iChain) | |
| − | + | var caPsiIdx = get_nward_bb_idx(cIdx, iChain) | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | if (nWard) { | |
| − | + | var nNo = {(chain=iChain) and thisModel}.atomno.min | |
| − | + | select_nward_idx(caPsiIdx, {(atomno=nNo) and (chain=iChain) | |
| − | + | and thisModel}.atomIndex) | |
| − | + | } | |
| − | + | else { | |
| − | + | var cNo = {(chain=iChain) and thisModel}.atomno.max | |
| − | + | select_cward_idx(caPhiIdx, {(atomno=cNo) and (chain=iChain) | |
| − | + | and thisModel}.atomIndex) | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # Counter-rotate | |
| − | + | do_counter_rotate(caPhiIdx, nIdx, cIdx, oIdx, caPsiIdx, dir, not nWard) | |
| − | + | select selsave | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | function counter_rotate_2(oIdx, toPt, terminalIdx, oDrag) { | |
| − | |||
| − | |||
| − | |||
| − | + | var iChain = {atomIndex=oIdx}.chain | |
| − | + | var selsave = {selected} | |
| − | + | var gOk2 = true | |
| + | var cIdx = get_sc_bb_idx(oIdx, iChain) | ||
| + | var nIdx = get_cward_bb_idx(cIdx, iChain) | ||
| + | var caPhiIdx = get_cward_bb_idx(nIdx, iChain) | ||
| + | var caPsiIdx = get_nward_bb_idx(cIdx, iChain) | ||
| − | + | var nTward = ({atomIndex=oIdx}.atomno < {atomIndex=terminalIdx}.atomno) | |
| − | + | if (nTward) { | |
| − | + | select_cward_idx(cIdx, terminalIdx) | |
| − | + | } | |
| − | + | else { | |
| − | + | select_nward_idx(nIdx, terminalIdx) | |
| + | } | ||
| − | + | # Until all collisions cancelled | |
| − | + | var dir = 5 | |
| + | var ang = angle(toPt, {atomIndex=oIdx}, {atomIndex=cIdx}) | ||
| + | var tcount = 0 | ||
| + | while (oDrag or (within(kCtolerance, false, {atomIndex=oIdx}) | ||
| + | and not {atomIndex=oIdx} and not connected({atomIndex=oIdx}) | ||
| + | and not {gOkCollide} > 0)) { | ||
| − | + | # Counter-rotate | |
| − | + | do_counter_rotate(caPhiIdx, nIdx, cIdx, oIdx, caPsiIdx, dir, nTward) | |
| + | var newang = angle(toPt, {atomIndex=oIdx}, {atomIndex=cIdx}) | ||
| − | + | # If wrong direction once, undo and reverse | |
| − | + | if (newang > ang) { | |
| − | + | do_counter_rotate(caPhiIDx, nIdx, cIdx, oIdx, caPsiIdx, -dir, nTward) | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| + | # If first time, continue in opposite direction | ||
| + | dir *= -1 | ||
| + | if (dir < 0) { | ||
| + | continue | ||
} | } | ||
| + | } | ||
| − | + | if (oDrag) { | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | if ( | ||
break | break | ||
} | } | ||
| − | |||
| − | |||
| − | # | + | # If no go, undo and exit |
| − | + | tcount++ | |
| + | if (tcount > (360/abs(dir))) { | ||
| + | gOk2 = false | ||
| + | break | ||
| + | } | ||
| − | # | + | } # endwhile |
| − | + | select selsave | |
| − | + | } | |
| − | |||
| − | |||
| − | + | # Repair proline | |
| − | {atomIndex= | + | function repair_proline(BBidx) { |
| − | { | + | var cbidx = get_cb_idx(BBidx) |
| − | { | + | var cbno = {atomIndex=cbidx}.atomno |
| − | + | var cgidx = {(atomno=@{cbno+1}) and (chain=gChain) | |
| − | } | + | and thisModel}.atomIndex |
| + | var cdidx = {(atomno=@{cbno+2}) and (chain=gChain) | ||
| + | and thisModel}.atomIndex | ||
| + | var caidx = {(atomno=@{cbno-3}) and (chain=gChain) | ||
| + | and thisModel}.atomIndex | ||
| + | var nidx = {(atomno=@{cbno-4}) and (chain=gChain) | ||
| + | and thisModel}.atomIndex | ||
| − | + | select {atomIndex=cbidx} | |
| + | set_angle_idx(nidx, caidx, cbidx, 109.5) | ||
| − | + | select {atomIndex=cdidx} | |
| − | + | set_distance_idx(nidx, cdidx, 1.47) | |
| − | + | set_angle_idx(caidx, nidx, cdidx, 102.7) | |
| − | + | set_dihedral_idx(cbidx, caidx, nidx, cdidx, 16.2) | |
| − | |||
| − | |||
| − | + | select {atomIndex=cgidx} | |
| − | + | set_distance_idx(cdidx, cgidx, 1.51) | |
| − | + | set_angle_idx(nidx, cdidx, cgidx, 106.4) | |
| − | + | set_dihedral_idx(caidx, nidx, cdidx, cgidx, 16.2) | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | function | + | # Repair side chain |
| + | function repair_sc(targetIdx, nWard) { | ||
| − | var | + | var idx = (nWard ? get_cward_bb_idx(targetIdx, gChain) : get_nward_bb_idx(targetIdx, gChain)) |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | var | + | if (({atomIndex=targetIdx}.atomName == "CA") |
| − | + | and ({atomIndex=targetIdx}.group != "GLY")) { | |
| − | + | var cbidx = get_cb_idx(targetIdx) | |
| + | select none | ||
| + | select_add_sc(cbidx) | ||
| + | set_angle_idx(idx, targetIdx, cbidx, 110.0) | ||
| + | set_distance_idx(targetIdx, cbidx, 1.5) | ||
| + | if ({atomIndex=targetIdx}.group != "PRO") { | ||
| + | var colliders = (within(kCtolerance, false, {selected}) | ||
| + | and not {atomIndex=targetIdx} and not {selected}) | ||
| + | if (colliders) { | ||
| + | if ({atomIndex=targetIdx}.group != "ALA") { | ||
| + | fix_sc_collision_2(cbidx) | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | else { | ||
| + | if (nWard) { | ||
| + | } | ||
| + | else { | ||
| + | set_dihedral_idx(get_nward_bb_idx(idx, gChain), idx, targetIdx, cbidx, 174.2) | ||
| + | } | ||
| + | } | ||
} | } | ||
| − | else { | + | |
| − | + | else if ({atomIndex=targetIdx}.atomName == "C") { | |
| + | var oidx = get_o_idx(targetIdx) | ||
| + | select {atomIndex=oidx} | ||
| + | set_angle_idx(idx, targetIdx, oidx, 120.0) | ||
| + | set_distance_idx(targetIdx, oidx, 1.21) | ||
| + | if (nWard) { | ||
| + | set_dihedral_idx(get_cward_bb_idx(idx, gChain), idx, targetIdx, oidx, 0.0) | ||
| + | } | ||
| + | if ({atomIndex=idx}.group == "PRO") { | ||
| + | repair_proline(idx) | ||
| + | var dNo = {atomIndex=targetIdx}.atomno + 4 | ||
| + | var dIdx = {(atomno=dNO) and (chain=gChain) | ||
| + | and thisModel}.atomIndex | ||
| + | var colliders = (within(kCtolerance, false, {atomIndex=dIdx}) | ||
| + | and not connected({atomIndex=dIdx}) | ||
| + | and not {atomIndex=dIdx}) | ||
| + | for (var i = 1; i <= colliders.size; i++) { | ||
| + | if (colliders[i].atomName == "O") { | ||
| + | counter_rotate_2(colliders[i].atomIndex, | ||
| + | {atomIndex=dIdx}.xyz, targetIdx, false) | ||
| + | } | ||
| + | } | ||
| + | } | ||
} | } | ||
| + | } | ||
| − | + | # Rebuild Cward rotors set | |
| − | + | function tug_track_c() { | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # For all bb atoms cWard of cargo | |
| − | + | var targetIdx = gCcargoIdx | |
| − | + | var okCount = 0 | |
| − | + | # Allow collisions with cargo | |
| − | + | gOkCollide = gCargoSet | |
| − | + | var tcount = 0 | |
| + | while (targetIdx != gNanchorIdx) { | ||
| − | + | # Step to next atom | |
| − | + | targetIdx = get_cward_bb_idx(targetIdx, gChain) | |
| − | + | if (targetIdx < 0) { | |
| − | + | break | |
| − | |||
} | } | ||
| − | if ( | + | # No collision with cargo allowed after two atoms placed |
| − | + | if (tcount == 2) { | |
| + | gOkCollide = ({}) | ||
} | } | ||
| − | |||
| − | |||
tcount++ | tcount++ | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | } # | + | # Compute targets desired coords |
| − | select | + | try { |
| − | } | + | var c1idx = get_cward_bb_idx(targetIdx, gChain) |
| + | var n1idx = get_nward_bb_idx(targetIdx, gChain ) | ||
| + | var n2idx = get_nward_bb_idx(n1Idx, gChain) | ||
| + | var n3idx = get_nward_bb_idx(n2Idx, gChain) | ||
| + | var pt = {0 0 0} | ||
| + | if ({atomIndex=targetIdx}.atomName == "N") { | ||
| + | var oidx = get_o_idx(n1idx) | ||
| + | select {atomIndex=oidx} | ||
| + | |||
| + | # Desired target location is trigonal O | ||
| + | set_distance_idx(n1idx, oidx, 1.5) | ||
| + | pt = get_trigonal_idx(n2idx, n1idx, oidx, 1.37) | ||
| + | set_distance_idx(n1idx, oidx, 1.21) | ||
| + | } | ||
| + | else if (({atomIndex=targetIdx}.atomName == "C") | ||
| + | and ({atomIndex=targetIdx}.group != "GLY")) { | ||
| + | |||
| + | # Desired target location is tetragonal CB | ||
| + | var cbidx = get_cb_idx(n1idx) | ||
| + | pt = get_tet_idx(n2idx, n1idx, cbidx, 1.5) | ||
| + | } | ||
| + | else { # CA (or GLY C) | ||
| + | |||
| + | # Save current target coords | ||
| + | var cp = {atomIndex=targetIdx}.xyz | ||
| + | |||
| + | # Set target atom at desired distance and angle | ||
| + | select {atomIndex=targetIdx} | ||
| + | set_distance_idx(n1idx, targetIdx, 1.5) | ||
| + | set_angle_idx(n2idx, n1idx, targetIdx, 120.0) | ||
| + | if ({atomIndex=targetIdx}.atomName == "CA") { | ||
| + | set_dihedral_idx(n3idx, n2idx, n1idx, targetIdx, 180) | ||
| + | } | ||
| + | |||
| + | # Record and restore target | ||
| + | pt = {atomIndex=targetIdx}.xyz | ||
| + | {atomIndex=targetIdx}.xyz = cp | ||
| + | } | ||
| + | |||
| + | # If target not at desired location | ||
| + | if (distance(pt, {atomIndex=targetIdx}) > kDtolerance) { | ||
| + | okCount = 0 | ||
| + | gTargetPt = pt | ||
| + | var xcount = 0 | ||
| + | gOK = false | ||
| + | while ((xcount < 20) and (not gOK)) { | ||
| + | |||
| + | # Rotate on cWard rotor set to move it there | ||
| + | tug_track_idx(targetIdx, pt, false, false) | ||
| + | xcount++ | ||
| + | } | ||
| + | } | ||
| + | else { | ||
| + | gOK = true | ||
| + | okCount++ | ||
| + | } | ||
| + | } | ||
| + | catch { | ||
| + | } | ||
| − | # | + | # If successful |
| − | + | if (gOK == true) { | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # Adust any side atoms | |
| − | + | repair_sc(targetIdx, false) | |
| + | } | ||
| − | + | # Else fail | |
| − | + | else { | |
| − | + | break | |
| − | + | } | |
| − | + | # If no movement in 4 tries, we are done | |
| − | + | if (okCount > 3) { | |
| − | + | break | |
| − | + | } | |
| + | } # endwhile (targetIdx != gCanchorIdx) { | ||
} | } | ||
| − | # | + | # Rebuild Nward rotors set |
| − | function | + | function tug_track_n() { |
| − | + | gOK = true | |
| − | + | # For all bb atoms nWard of cargo | |
| − | + | var targetIdx = gNcargoIdx | |
| − | + | var okCount = 0 | |
| − | + | ||
| − | + | # Allow collisions with cargo | |
| − | + | gOkCollide = gCargoSet | |
| − | + | var tcount = 0 | |
| − | if ( | + | while (targetIdx != gNanchorIdx) { |
| − | + | ||
| − | + | # Step to next atom | |
| − | + | targetIdx = get_nward_bb_idx(targetIdx, gChain) | |
| − | + | if (targetIdx < 0) { | |
| − | + | break | |
| − | |||
| − | |||
} | } | ||
| − | + | ||
| − | + | # No collision with cargo allowed after two atoms placed | |
| − | + | if (tcount == 2) { | |
| − | + | gOkCollide = ({}) | |
| − | |||
| − | |||
} | } | ||
| − | + | tcount++ | |
| + | |||
| + | # Compute targets desired coords | ||
| + | var n1idx = get_nward_bb_idx(targetIdx, gChain) | ||
| + | var c1idx = get_cward_bb_idx(targetIdx, gChain) | ||
| + | var c2idx = get_cward_bb_idx(c1idx, gChain) | ||
| + | var c3idx = get_cward_bb_idx(c2idx, gChain) | ||
| + | var pt = {0 0 0} | ||
| + | if ({atomIndex=targetIdx}.atomName == "CA") { | ||
| − | + | # Desired target location is trigonal O | |
| − | + | var oidx = get_o_idx(c1idx) | |
| − | + | select {atomIndex=oidx} | |
| − | + | set_distance_idx(c1idx, oidx, 1.39) | |
| − | + | pt = get_trigonal_idx(c2idx, c1idx, oidx, 1.41) | |
| − | + | set_distance_idx(c1idx, oidx, 1.21) | |
| − | |||
} | } | ||
| − | if ({atomIndex= | + | else if (({atomIndex=targetIdx}.atomName == "N") |
| − | + | and ({atomIndex=targetIdx}.group != "GLY")) { | |
| − | + | ||
| − | + | # Desired target location is r-tetragonal CB | |
| − | + | var cbidx = get_cb_idx(c1idx) | |
| − | + | pt = get_tet_idx(cbidx, c1idx, c2idx, 1.5) | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | + | else { # C | |
| − | |||
| − | # | + | # Save current target coords |
| − | + | var cp = {atomIndex=targetIdx}.xyz | |
| − | + | # Set target atom at desired distance and angle | |
| − | + | select {atomIndex=targetIdx} | |
| − | + | set_distance_idx(c1idx, targetIdx, 1.37) | |
| + | set_angle_idx(c2idx, c1idx, targetIdx, 110.0) | ||
| − | + | if ({atomIndex=targetIdx}.group == "PRO") { | |
| − | + | set_dihedral_idx(c3idx, c2idx, c1idx, targetIdx, -57.0) | |
| − | + | } | |
| − | |||
| − | + | # Record and restore target | |
| − | + | pt = {atomIndex=targetIdx}.xyz | |
| − | + | {atomIndex=targetIdx}.xyz = cp | |
| − | |||
| − | |||
| − | |||
} | } | ||
| − | |||
| − | # | + | # If target not at desired location |
| − | + | if (distance(pt, {atomIndex=targetIdx}) > kDtolerance) { | |
| − | + | var okCount = 0 | |
| − | + | gTargetPt = pt | |
| − | + | var xcount = 0 | |
| − | + | gOK = false | |
| − | + | while ((xcount < 20) and (not gOK)) { | |
| − | |||
| − | |||
| − | + | # Rotate on nWard rotor set to move it there | |
| − | + | tug_track_idx(targetIdx, pt, true, false) | |
| − | + | xcount++ | |
| − | + | } | |
} | } | ||
| − | else | + | else { |
| − | + | gOK = true | |
| − | + | okCount++ | |
| − | |||
| − | |||
| − | |||
} | } | ||
| − | |||
| − | + | # If sucessful | |
| − | + | if (gOK == true) { | |
| − | # | + | # Adust any side atoms |
| − | + | repair_sc(targetIdx, true) | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # Else fail | |
| − | + | else { | |
| − | + | break | |
} | } | ||
| − | # If | + | # If no movement in 4 tries, we are done |
| − | if ( | + | if (okCount > 3) { |
| − | + | break | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | + | } # endwhile (targetIdx != gNanchorIdx) { | |
| − | + | } | |
| − | + | # gPlicoRecord is maintained by the macro pilcoRecord | |
| − | + | function translate_selected_record(pt) { | |
| − | + | if (gPlicoRecord != "") { | |
| + | plico_record(format("select %s;translateSelected %s;", {selected}, pt)) | ||
| + | } | ||
| + | translateSelected @pt | ||
| + | } | ||
| − | + | # gPlicoRecord is maintained by the macro pilcoRecord | |
| − | + | function rotate_selected_record(pivotIdx, caxis, a) { | |
| − | + | if (gPlicoRecord != "") { | |
| − | + | plico_record(format("select %s;", {selected})) | |
| + | plico_record(format("rotateSelected {atomIndex=%d} @%s @%s;", | ||
| + | pivotIdx, caxis, a)) | ||
| + | } | ||
| + | rotateSelected {atomIndex=pivotIdx} @caxis @a | ||
| + | } | ||
| − | # | + | function collect_sc_rotors(no, iChain) { |
| − | + | var scBondIdxs = array() | |
| + | for (var iNo = no; iNo >= 0; iNo--) { | ||
| + | var ile = 0 | ||
| + | switch ({(atomno=iNo) and (chain=iChain) | ||
| + | and thisModel}.atomName) { | ||
| + | case "CA" : | ||
| + | return scBondIdxs # Early exit since break 1 appears broken | ||
| + | case "CZ" : | ||
| + | if ({(atomno=iNo) and (chain=iChain) | ||
| + | and thisModel}.group == "TYR") { | ||
| + | break | ||
| + | } | ||
| + | case "CE" : | ||
| + | if ({(atomno=iNo) and (chain=iChain) | ||
| + | and thisModel}.group == "MET") { | ||
| + | break | ||
| + | } | ||
| + | case "CG1" : | ||
| + | if ({(atomno=iNo) and (chain=iChain) | ||
| + | and thisModel}.group == "VAL") { | ||
| + | break | ||
| + | } | ||
| + | if ({(atomno=iNo) and (chain=iChain) | ||
| + | and thisModel}.group == "ILE") { | ||
| + | ile = 1 | ||
| + | } | ||
| + | case "NE" : | ||
| + | case "CD" : | ||
| + | case "SD" : | ||
| + | case "CG" : | ||
| + | case "CB" : | ||
| + | scBondIdxs += {(atomno=@{iNo+1+ile}) and (chain=iChain) | ||
| + | and thisModel}.atomIndex | ||
| + | scBondIdxs += {(atomno=@{iNo+0}) and (chain=iChain) | ||
| + | and thisModel}.atomIndex | ||
| + | if ({(atomno=iNo) and (chain=iChain) | ||
| + | and thisModel}.atomName%2 == "CG") { | ||
| + | scBondIdxs += {(atomno=@{iNo-1}) and (chain=iChain) | ||
| + | and thisModel}.atomIndex | ||
| + | scBondIdxs += {(atomno=@{iNo-4}) and (chain=iChain) | ||
| + | and thisModel}.atomIndex | ||
| + | } | ||
| + | else if ({(atomno=iNo) and (chain=iChain) | ||
| + | and thisModel}.atomName == "CB") { | ||
| + | scBondIdxs += {(atomno=@{iNo-3}) and (chain=iChain) | ||
| + | and thisModel}.atomIndex | ||
| + | scBondIdxs += {(atomno=@{iNo-4}) and (chain=iChain) | ||
| + | and thisModel}.atomIndex | ||
| + | } | ||
| + | else { | ||
| + | scBondIdxs += {(atomno=@{iNo-1}) and (chain=iChain) | ||
| + | and thisModel}.atomIndex | ||
| + | scBondIdxs += {(atomno=@{iNo-2}) and (chain=iChain) | ||
| + | and thisModel}.atomIndex | ||
| + | } | ||
break | break | ||
} | } | ||
| − | } | + | |
| + | } | ||
| + | |||
| + | return scBondIdxs | ||
} | } | ||
| − | # | + | # Drag Side Chain |
| − | function | + | function drag_sc() { |
| + | var iNo = {atomIndex=gSCidx}.atomno | ||
| + | var iChain = {atomIndex=gSCidx}.chain | ||
| + | if ({atomIndex=gSCidx}.group != "PRO") { | ||
| − | + | var scBondIdxs = collect_sc_rotors( iNo, iChain) | |
| + | var numChi = scBondIdxs.size / 4 | ||
| + | var dist = distance({atomIndex=gSCidx}.xyz, gSCpt) | ||
| + | var scSet = get_sc_set(gSCidx, iChain) | ||
| − | + | # For all rotor combinations | |
| − | + | var dh = array() | |
| − | + | for (var i = 0; i < numChi; i++) { | |
| − | + | dh += angle({atomIndex=@{scBondIdxs[4+(4*i)]}}, | |
| − | + | {atomIndex=@{scBondIdxs[3+(4*i)]}}, | |
| − | + | {atomIndex=@{scBondIdxs[2+(4*i)]}}, | |
| − | + | {atomIndex=@{scBondIdxs[1+(4*i)]}}) | |
| − | + | } | |
| + | for (var i = 0; i < numChi; i++) { | ||
| + | var rot = -120 | ||
| + | for (var j = 0; j < 6; j++) { | ||
| + | rot += 60*j | ||
| + | select_add_sc(scBondIdxs[1+(4*i)]) | ||
| + | set_dihedral_idx(scBondIdxs[4+(4*i)], scBondIdxs[3+(4*i)], | ||
| + | scBondIdxs[2+(4*i)], scBondIdxs[1+(4*i)], rot) | ||
| + | var newDist = distance({atomIndex=gSCidx}.xyz, gSCpt) | ||
| + | if (gSCcheck) { | ||
| + | var colliders = (within(kCtolerance, false, scSet) | ||
| + | and not connected(scSet) and not {scSet}) | ||
| + | if (colliders) { | ||
| + | continue | ||
| + | } | ||
| + | } | ||
| − | + | # Find the best | |
| − | + | if (newDist < dist) { | |
| + | dist = newDist | ||
| + | for (var k = 0; k < numChi; k++) { | ||
| + | dh[k+1] = angle({atomIndex=@{scBondIdxs[4+(4*k)]}}, | ||
| + | {atomIndex=@{scBondIdxs[3+(4*k)]}}, | ||
| + | {atomIndex=@{scBondIdxs[2+(4*k)]}}, | ||
| + | {atomIndex=@{scBondIdxs[1+(4*k)]}}) | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | } | ||
| − | # | + | # Now set the best |
| − | if ( | + | for (var i = 0; i < numChi; i++) { |
| − | + | select_add_sc(scBondIdxs[1+(4*i)]) | |
| + | set_dihedral_idx(scBondIdxs[4+(4*i)], scBondIdxs[3+(4*i)], | ||
| + | scBondIdxs[2+(4*i)], scBondIdxs[1+(4*i)], dh[i+1]) | ||
| + | } | ||
| + | |||
| + | if (gSCcheck = false) { | ||
| + | plico_minimize( scSet) | ||
} | } | ||
| − | + | } | |
| + | else { # PRO - toggle between puckers up and down | ||
| + | var icd = {(atomno=@{iNo+1}) and (chain=iChain) | ||
| + | and thisModel}.atomIndex | ||
| + | var icb = {(atomno=@{iNo-1}) and (chain=iChain) | ||
| + | and thisModel}.atomIndex | ||
| + | var ica = {(atomno=@{iNo-4}) and (chain=iChain) | ||
| + | and thisModel}.atomIndex | ||
| + | var in = {(atomno=@{iNo-5}) and (chain=iChain) | ||
| + | and thisModel}.atomIndex | ||
| + | select {atomIndex=gSCidx} | ||
| − | + | if (angle({atomIndex=ica}, {atomIndex=in}, | |
| − | + | {atomIndex=icd}, {atomIndex=gSCidx}) < -10.0) { | |
| − | + | set_dihedral_idx(ica, in, icd, gSCidx, 8.7) | |
| − | + | set_angle_idx(in, icd, gSCidx, 110.0) | |
| − | + | set_distance_idx(icd, gSCidx, 1.5) | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | else | + | else { |
| − | + | set_dihedral_idx(ica, in, icd, gSCidx, -29.5) | |
| − | + | set_angle_idx(in, icd, gSCidx, 108.8) | |
| − | + | set_distance_idx(icd, gSCidx, 1.5) | |
| − | |||
| − | |||
} | } | ||
| − | + | } | |
| − | + | draw gSCcircle CIRCLE {atomIndex=gSCidx} MESH NOFILL | |
| − | + | gSCpt = {atomIndex=gSCidx}.xyz | |
| + | } | ||
| − | + | # Fix side chain collisions | |
| − | + | function fix_sc_collision_2(idx) { | |
| − | + | gOk2 = false | |
| − | + | var iNo = {atomIndex=idx}.atomno | |
| + | var iChain = {atomIndex=idx}.chain | ||
| + | var resno = {(atomno=iNo) and (chain=iChain) | ||
| + | and thisModel}.resno | ||
| − | + | # Get SC terminus | |
| − | + | while (resno == {(atomno=iNo) and (chain=iChain) | |
| − | + | and thisModel}.resno) { | |
| + | iNo++ | ||
| + | } | ||
| + | iNo-- | ||
| − | + | var sc = array() | |
| − | + | var iBno = iNo | |
| − | { | + | while ({(atomno=iBno) and (chain=iChain) |
| − | } | + | and thisModel}.atomName != "CB") { |
| + | sc += {(atomno=iBno) and (chain=iChain) | ||
| + | and thisModel} | ||
| + | iBno-- | ||
| + | } | ||
| + | var cbidx = {(atomno=iBno) and (chain=iChain) | ||
| + | and thisModel}.atomIndex | ||
| − | + | var scBondIdxs = collect_sc_rotors( iNo, iChain) | |
| − | + | var numChi = scBondIdxs.size / 4 | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # For all rotor combinations | |
| − | + | for (var i = 0; i < numChi; i++) { | |
| − | + | var rot = -120 | |
| − | + | for (var j = 0; j < 6; j++) { | |
| − | + | rot += 60 | |
| − | + | select_add_sc(scBondIdxs[1+(4*i)]) | |
| − | + | set_dihedral_idx(scBondIdxs[1+(4*i)], scBondIdxs[2+(4*i)], | |
| − | + | scBondIdxs[3+(4*i)], scBondIdxs[4+(4*i)], rot) | |
| − | |||
| − | + | # If no collision, exit | |
| − | + | var colliders = (within(kCtolerance, false, {sc}) | |
| + | and not {atomIndex=cbidx} and not {sc}) | ||
| − | # | + | # If it is with water, delete the water |
| − | + | for (var c = 1; c < colliders.size; c++ ) { | |
| − | + | if (colliders[c].group = "HOH") { | |
| + | delete {atomIndex=@{colliders[c].atomIndex}} | ||
| + | colliders = {colliders and not @{colliders[c]}} | ||
| + | } | ||
| + | } | ||
| − | + | if (colliders.size == 0) { | |
| − | + | gOk2 = true | |
| − | + | return # Early exit since break 1 appears broken | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
} | } | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | |||
| − | |||
} | } | ||
| − | + | function is_moveable_sc(aIdx) { | |
| − | function | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | var ret = (({atomIndex=aIdx}.group != "PRO") | |
| − | + | or ({atomIndex=aIdx}.atomName == "CG")) | |
| − | + | switch({atomIndex=aIdx}.atomName) { | |
| − | + | case "N": | |
| − | + | case "CA": | |
| − | + | case "C": | |
| + | case "CB": | ||
| + | case "O": | ||
| + | case "O4\'": | ||
| + | ret = false | ||
| + | break | ||
} | } | ||
| − | + | return ret | |
} | } | ||
| − | function | + | function is_rotor_avail(i1idx, i2idx) { |
| − | var | + | var ret = true |
| − | + | if (i1idx > i2idx) { # frozen bonds are kept as lo-hi | |
| − | var | + | var idx = @i1idx |
| − | + | i1idx = @i2idx | |
| − | + | i2idx = @idx | |
| − | + | } | |
| − | + | ||
| − | + | for (var i = 1; i <= gFreeze.size; i += 2) { | |
| − | + | if ((gFreeze[i] == i1idx) and (gFreeze[i+1] == i2idx)) { | |
| − | + | ret = false | |
| − | + | break | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | break | ||
} | } | ||
| − | |||
} | } | ||
| − | return | + | return ret |
} | } | ||
| − | + | function xcollect_bb_rotors(nWard) { | |
| − | function | + | var anchorNo = (nWard |
| − | + | ? ((gNanchorIdx >= 0) ? {atomIndex=gNanchorIdx}.atomno : gMinNo) | |
| − | var | + | : ((gCanchorIdx >= 0) ? {atomIndex=gCanchorIdx}.atomno : gMaxNo)) |
| − | var | + | var cargoNo = (nWard |
| + | ? ((gNcargoIdx >= 0) ? {atomIndex=gNcargoIdx}.atomno | ||
| + | : {atomIndex=gCcargoIdx}.atomno) | ||
| + | : {atomIndex=gCcargoIdx}.atomno) | ||
| + | var rotors = array() | ||
| + | if (cargoNo < anchorNo) { | ||
| − | + | for (var iNo = cargoNo; iNo <= anchorNo; iNo++) { | |
| + | if ({(atomno=iNo) and (chain=gChain) | ||
| + | and thisModel}.atomName == "CA") { | ||
| + | if (is_rotor_avail(iNo)) {# xxx | ||
| + | if (({(atomno=iNo) and (chain=gChain) | ||
| + | and thisModel}.group != "PRO") and (iNo > cargoNo)) { # phi | ||
| + | rotors += [{(atomno=@{get_cm_no(iNo-1)}) and (chain=gChain) | ||
| + | and thisModel}.atomIndex, | ||
| + | {(atomno=@{iNo-1}) and (chain=gChain) | ||
| + | and thisModel}.atomIndex] | ||
| + | rotors += [{(atomno=@{iNo}) and (chain=gChain) | ||
| + | and thisModel}.atomIndex, | ||
| + | {(atomno=@{iNo+1}) and (chain=gChain) | ||
| + | and thisModel}.atomIndex] | ||
| + | } | ||
| + | if (iNo != (anchorNo-1)) { # psi | ||
| + | rotors += [{(atomno=@{iNo-1}) and (chain=gChain) | ||
| + | and thisModel}.atomIndex, | ||
| + | {(atomno=@{iNo}) and (chain=gChain) | ||
| + | and thisModel}.atomIndex] | ||
| + | rotors += [{(atomno=@{iNo+1}) and (chain=gChain) | ||
| + | and thisModel}.atomIndex, | ||
| + | {(atomno=@{get_np_no(iNo+2)}) and (chain=gChain) | ||
| + | and thisModel}.atomIndex] | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | else { | ||
| − | var | + | for (var iNo = cargoNo; iNo >= anchorNo; iNo--) { |
| − | + | if ({(atomno=iNo) and (chain=gChain) | |
| − | + | and thisModel}.atomName == "CA") { | |
| − | + | if (is_rotor_avail(iNo)) { | |
| − | + | if ((iNo != (anchorNo-1)) and (iNo < cargoNo)) { # psi | |
| − | + | rotors += [{(atomno=@{get_np_no(iNo+2)}) and (chain=gChain) | |
| − | + | and thisModel}.atomIndex, | |
| − | + | {(atomno=@{iNo+1}) and (chain=gChain) | |
| − | + | and thisModel}.atomIndex] | |
| − | + | rotors += [{(atomno=@{iNo}) and (chain=gChain) | |
| − | + | and thisModel}.atomIndex, | |
| − | + | {(atomno=@{iNo-1}) and (chain=gChain) | |
| − | + | and thisModel}.atomIndex] | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | + | if ({(atomno=iNo) and (chain=gChain) | |
| − | + | and thisModel}.group != "PRO") { # phi | |
| − | + | rotors += [{(atomno=@{iNo+1}) and (chain=gChain) | |
| − | + | and thisModel}.atomIndex, | |
| − | + | {(atomno=@{iNo}) and (chain=gChain) | |
| − | + | and thisModel}.atomIndex] | |
| − | + | rotors += [{(atomno=@{iNo-1}) and (chain=gChain) | |
| − | + | and thisModel}.atomIndex, | |
| − | { | + | {(atomno=@{get_cm_no(iNo-1)}) and (chain=gChain) |
| − | + | and thisModel}.atomIndex] | |
} | } | ||
} | } | ||
} | } | ||
} | } | ||
| + | } | ||
| − | + | if (nWard) { | |
| − | + | gNrotors = rotors | |
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | else { | + | else { |
| − | var | + | gCrotors = rotors |
| − | var | + | } |
| − | + | } | |
| − | + | function collect_bb_rotors(nWard) { | |
| − | + | if (nWard) { | |
| − | + | gNrotors = array() | |
| − | + | var nres = {atomIndex=gNcargoIdx}.resno | |
| − | {atomIndex= | + | var nname = {atomIndex=gNcargoIdx}.atomName |
| − | + | var ares = get_resno_min(gChain) | |
| − | + | var aA = get_atom_rcn( ares, gChain, "N") | |
| − | + | if (gNanchorIdx >= 0) { | |
| − | + | aA = {atomIndex=gNanchorIdx} | |
| − | + | } | |
| − | + | var aname = aA.atomName | |
| − | + | for (var r = nres; r >= ares; r--) { | |
| − | + | var aCp = get_atom_rcn( r-1, gChain, "C") | |
| − | } | + | var aN = get_atom_rcn( r, gChain, "N") |
| + | var aCa = get_atom_rcn( r, gChain, "CA") | ||
| + | var aC = get_atom_rcn( r, gChain, "C") | ||
| + | var aNn = get_atom_rcn( r+1, gChain, "N") | ||
| + | if (aCp.size < 1) { | ||
| + | aCp = aNn | ||
| + | } | ||
| + | # psi | ||
| + | if (((r < nres) and (r > ares)) | ||
| + | or ((r == nres) and (nname == "C")) | ||
| + | or ((r == ares) and (aname != "C"))) { | ||
| + | if (is_rotor_avail(aCa.atomIndex, aC.atomIndex)) { | ||
| + | gNrotors += aNn.atomIndex | ||
| + | gNrotors += aC.atomIndex | ||
| + | gNrotors += aCa.atomIndex | ||
| + | gNrotors += aN.atomIndex | ||
| + | } | ||
| + | } | ||
| + | |||
| + | # phi | ||
| + | if (aCa.group != "PRO") { | ||
| + | if (((r <= nres) and (r > ares)) | ||
| + | or ((r == ares) and (aname == "N"))) { | ||
| + | if (is_rotor_avail(aCa.atomIndex, aN.atomIndex)) { | ||
| + | gNrotors += aC.atomIndex | ||
| + | gNrotors += aCa.atomIndex | ||
| + | gNrotors += aN.atomIndex | ||
| + | gNrotors += aCp.atomIndex | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | } # endfor | ||
| + | } | ||
| + | else { | ||
| + | gCrotors = array() | ||
| + | var cres = {atomIndex=gCcargoIdx}.resno | ||
| + | var cname = {atomIndex=gCcargoIdx}.atomName | ||
| + | var ares = get_resno_max(gChain) | ||
| + | var aA = get_atom_rcn( ares, gChain, "C") | ||
| + | if (gCanchorIdx >= 0) { | ||
| + | aA = {atomIndex=gCanchorIdx} | ||
| + | } | ||
| + | var aname = aA.atomName | ||
| + | for (var r = cres; r <= ares; r++) { | ||
| + | var aCp = get_atom_rcn( r-1, gChain, "C") | ||
| + | var aN = get_atom_rcn( r, gChain, "N") | ||
| + | var aCa = get_atom_rcn( r, gChain, "CA") | ||
| + | var aC = get_atom_rcn( r, gChain, "C") | ||
| + | var aNn = get_atom_rcn( r+1, gChain, "N") | ||
| + | if (aNn.size < 1) { | ||
| + | aNn = aCp | ||
| + | } | ||
| + | |||
| + | # phi | ||
| + | if (aCa.group != "PRO") { | ||
| + | if (((r > cres) and (r < ares)) | ||
| + | or ((r == cres) and (aname == "N")) | ||
| + | or ((r == ares) and (aname != "N"))) { | ||
| + | if (is_rotor_avail(aN.atomIndex, aCa.atomIndex)) { | ||
| + | gCrotors += aCp.atomIndex | ||
| + | gCrotors += aN.atomIndex | ||
| + | gCrotors += aCa.atomIndex | ||
| + | gCrotors += aC.atomIndex | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | # psi | ||
| + | if (((r >= cres) and (r < ares)) | ||
| + | or ((r == cres) and (aname != "C")) | ||
| + | or ((r == ares) and (aname == "C"))) { | ||
| + | if (is_rotor_avail(aCa.atomIndex, aC.atomIndex)) { | ||
| + | gCrotors += aN.atomIndex | ||
| + | gCrotors += aCa.atomIndex | ||
| + | gCrotors += aC.atomIndex | ||
| + | gCrotors += aNn.atomIndex | ||
| + | } | ||
| + | } | ||
| + | } # endfor | ||
} | } | ||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | + | function collect_rotors() { | |
| − | function | + | collect_bb_rotors(false) |
| − | + | collect_bb_rotors(true) | |
| − | + | } | |
| − | |||
| − | |||
| − | + | function tug_sc(pt) { | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # If destination atom defined | |
| − | + | if (gDestAtomIdx >= 0) { | |
| − | + | var v = {atomIndex=gDestAtomIdx}.xyz - {atomIndex=gSCidx}.xyz | |
| − | + | if (abs(angle({atomIndex=gDestAtomIdx}.xyz, {0 0 0}, pt)) < 90) { | |
| − | + | pt = -v/20.0 | |
| + | } | ||
| + | else { | ||
| + | pt = v/20.0 | ||
| + | } | ||
} | } | ||
| − | + | gSCpt += pt | |
| + | draw arrow {atomIndex=gSCidx} @gSCpt | ||
| + | } | ||
| − | + | function set_colors() { | |
| − | + | select (thisModel) | |
| + | color {selected} @gScheme | ||
| + | color {atomIndex=g1pivotIdx} green | ||
| + | color {atomIndex=g2pivotIdx} green | ||
| + | color @gCargoSet @gAltScheme | ||
| + | color {gCargoSet and oxygen} pink | ||
| + | select {(atomIndex=gCcargoIdx) or (atomIndex=gNcargoIdx) | ||
| + | or (atomIndex=gCanchorIdx) or (atomIndex=gNanchorIdx)} | ||
| + | halo on | ||
| + | select {atomIndex=gDestAtomIdx} | ||
| + | star on | ||
| + | select none | ||
| + | } | ||
| − | + | function clear_atom_idxs() { | |
| − | + | gCcargoIdx = -1 | |
| − | + | gNcargoIdx = -1 | |
| − | + | gCanchorIdx = -1 | |
| − | + | gNanchorIdx = -1 | |
| − | + | g1pivotIdx = -1 | |
| − | + | g2pivotIdx = -1 | |
| − | + | g1dynamicIdx = -1 | |
| − | + | g2dynamicIdx = -1 | |
| − | + | gDestAtomIdx = -1 | |
| − | + | gSCidx = -1 | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| + | function timed_out (s) { | ||
| + | timeout ID"tug" OFF | ||
| + | refresh | ||
| + | if (prompt(format("%s - Undo?", s), "Yes|No", true) == "Yes") { | ||
| + | gBusy = false | ||
| + | restore state gState | ||
| + | connect | ||
| + | select gCargoSet | ||
| + | set bondPicking true | ||
| + | refresh | ||
| + | for (var i = 1; i <= gFreeze.size; i+=2) { | ||
| + | select {atomIndex=@{gFreeze[i]}} or {atomIndex=@{gFreeze[i+1]}} | ||
| + | color bonds lightblue | ||
} | } | ||
| + | background ECHO yellow | ||
| + | echo @gEcho | ||
| + | select all | ||
| + | quit | ||
} | } | ||
} | } | ||
| − | function | + | function record_drag() { |
| − | + | var ls = format("select %s;", {selected}) | |
| − | var | + | ls += format("gCanchorIdx = %d;", gCanchorIdx) |
| − | + | ls += format("gCanchorNo = %d;", gCanchorNo) | |
| − | + | ls += format("gNanchorIdx = %d;", gNanchorIdx) | |
| − | + | ls += format("gNanchorNo = %d;", gNanchorNo) | |
| − | + | ls += format("gCcargoIdx = %d;", gCcargoIdx) | |
| − | + | ls += format("gNcargoIdx = %d;", gNcargoIdx) | |
| − | + | ls += format("gCcargoNo = %d;", gCcargoNo) | |
| − | + | ls += format("gNcargoNo = %d;", gNcargoNo) | |
| − | + | ls += format("gDestAtomIdx = %d;", gDestAtomIdx) | |
| − | + | ls += format("g1pivotIdx = %d;", g1pivotIdx) | |
| − | + | ls += format("g2pivotIdx = %d;", g2pivotIdx) | |
| − | + | ls += format("gOkCollide = %s;", gOkCollide) | |
| − | + | ls += format("gChain = \"%s\";", gChain) | |
| + | ls += format("gMinNo = %d;", gMinNo) | ||
| + | ls += format("gMaxNo = %d;", gMaxNo) | ||
| + | ls += format("gCargoSet = %s;", gCargoSet) | ||
| + | ls += format("gSCidx = %d;", gSCidx) | ||
| + | ls += format("gSCcircle = %d;", gSCcircle) | ||
| + | ls += format("gSCpt = %s;", gSCpt) | ||
| + | ls += "collect_rotors();" | ||
| + | ls += "tug_drag_done_mb();" | ||
| + | plico_record(ls) | ||
} | } | ||
| − | function | + | # Pick call-back for freeze |
| − | + | function tug_pick_cb() { | |
| − | if ( | + | if (_pickInfo[3][6] == "bond") { |
| − | var | + | var sel = {selected} |
| − | + | var i = _pickInfo.find(":") | |
| − | + | var iChain = _pickInfo[i+1] | |
| − | + | i = _pickInfo.find("#") | |
| − | + | var a1no = 0 + _pickInfo[i+1][i+3] | |
| − | + | var j = _pickInfo[i+1][9999].find("#") | |
| − | if (( | + | var a2no = 0 + _pickInfo[i+j+1][i+j+3] |
| − | + | var i1idx = {(atomno=a1no) and (chain=iChain) | |
| − | + | and thisModel}.atomIndex | |
| − | + | var i2idx = {(atomno=a2no) and (chain=iChain) | |
| − | + | and thisModel}.atomIndex | |
| − | + | if (({atomIndex=i1idx}.atomName == "CA") | |
| − | + | or ({atomIndex=i2idx}.atomName == "CA")) { | |
| − | } | + | if (({atomIndex=i1idx}.atomName != "CB") |
| + | and ({atomIndex=i2idx}.atomName != "CB")) { | ||
| + | if (i1idx > i2idx) { | ||
| + | var idx = 0 + i1idx | ||
| + | i1idx = 0 + i2idx | ||
| + | i2idx = 0 + idx | ||
| + | } | ||
| + | select {atomIndex=i1idx} or {atomIndex=i2idx} | ||
| − | + | for (i = 1; i <= gFreeze.size; i += 2) { | |
| − | + | if ((gFreeze[i] == i1idx) and (gFreeze[i+1] == i2idx)) { | |
| − | + | if (i > 1) { | |
| − | + | if (gFreeze.size = (i+1)) { | |
| − | + | gFreeze = gFreeze[1][i-1] | |
| − | + | } | |
| − | + | else { | |
| − | + | gFreeze = gFreeze[1][i-1] + gFreeze[i+2][0] | |
| − | + | } | |
| − | + | } | |
| − | + | else { | |
| − | + | gFreeze = gFreeze[i+2][0] | |
| − | + | } | |
| − | + | color bonds NONE | |
| − | + | i = 0 | |
| − | + | break | |
| − | |||
| − | |||
| − | { | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| + | } | ||
| + | if (i > gFreeze.size) { | ||
| + | gFreeze += i1idx | ||
| + | gFreeze += i2idx | ||
| + | color bonds lightblue | ||
} | } | ||
} | } | ||
} | } | ||
| + | select {sel} | ||
} | } | ||
| − | + | } | |
| − | + | # Bound to LEFT-UP by tug_enable_drag | |
| − | + | function tug_drag_done_mb() { | |
| − | + | if (not gBusy) { | |
| − | + | if (gPlicoRecord != "") { | |
| − | + | record_drag() | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | |||
| − | + | # Move by rotation on rotor sets, smallest first | |
| − | + | gBusy = true | |
| − | + | background ECHO pink | |
| − | + | refresh | |
| − | |||
| − | |||
| − | |||
| − | + | # If side chain mode | |
| − | + | if (gSCidx >= 0) { | |
| − | + | drag_sc() | |
| − | } | + | } |
| − | + | # Else | |
| − | + | else if (not gTow) { | |
| − | + | gOK = true | |
| − | + | timeout ID"tug" 20.0 "timed_out(\"Tug timed out\")" | |
| − | + | if ((gCrotors.size < gNrotors.size) or (gNanchorIdx < 0)) { | |
| − | + | if (gCrotors.size > 4) { | |
| − | + | tug_track_c() | |
| − | + | } | |
| − | + | if (gOK and (gNrotors.size > 4)) { | |
| − | + | tug_track_n() | |
| − | + | } | |
| − | + | } | |
| − | + | else { | |
| − | + | if (gNrotors.size > 4) { | |
| − | } | + | tug_track_n() |
| + | } | ||
| + | if (gOK and (gCrotors.size > 4)) { | ||
| + | tug_track_c() | ||
| + | } | ||
| + | } | ||
| + | timeout ID"tug" OFF | ||
| − | + | # If anchor angles acute, fail | |
| − | + | if (gOK == true) { | |
| − | + | if (gCanchorIdx >= 0) { | |
| − | + | var ic = get_cward_bb_idx(gCanchorIdx, gChain) | |
| − | + | var in = get_nward_bb_idx(gCanchorIdx, gChain) | |
| − | + | if ((ic >= 0) and | |
| − | + | angle({atomIndex=ic}, {atomIndex=gCanchorIdx}, {atomIndex=in}) | |
| − | + | < 100.0) { | |
| − | + | gOK = false | |
| − | + | } | |
| − | + | } | |
| − | + | if (gNanchorIdx >= 0) { | |
| − | } | + | var ic = get_cward_bb_idx(gNanchorIdx, gChain) |
| + | var in = get_nward_bb_idx(gNanchorIdx, gChain) | ||
| + | if ((in >= 0) and | ||
| + | angle({atomIndex=ic}, {atomIndex=gNanchorIdx}, {atomIndex=in}) | ||
| + | < 100.0) { | ||
| + | gOK = false | ||
| + | } | ||
| + | } | ||
| + | } | ||
| − | + | # If too far | |
| − | + | if (not gOK) { | |
| − | + | timed_out("TUG TOO FAR!") | |
| − | + | } | |
| − | + | ||
| − | + | # Else OK | |
| − | + | else { | |
| − | + | ||
| − | + | var idx = { | |
| − | + | (atomno=@{{(chain=gChain) and thisModel}.atomno.min}) | |
| − | + | and (chain=gChain) and thisModel}.atomIndex | |
| − | } | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | var ihc = 0 | |
| − | + | for (ihc = 0; ihc < 10; ihc++) { | |
| − | + | select ((atomno >= gNanchorNo) and (atomno <= gCanchorNo) | |
| − | + | and (chain = gChain) and thisModel) | |
| − | + | handle_collisions( idx) | |
| − | + | if (count_collisions(({})).size == 0) { | |
| − | + | break | |
| − | + | } | |
| − | + | } | |
| − | + | if (ihc == 10) { | |
| − | + | timed_out("Unable to handle all collisions!") | |
| − | + | } | |
| − | + | } | |
| − | + | } | |
| − | + | select {gCargoSet} | |
| − | + | gBusy = false | |
| − | + | background ECHO yellow | |
| − | + | set bondPicking true | |
| − | + | refresh | |
| − | + | } | |
| − | + | } | |
| − | + | ||
| − | + | # Bound to ALT-SHIFT-LEFT-DRAG by tug_enable_drag | |
| − | + | function tug_drag_2_mb() { | |
| + | tug_drag_mb(true) | ||
} | } | ||
| − | # | + | # Bound to ALT-LEFT-DRAG by tug_enable_drag |
| − | function | + | function tug_drag_mb(alt) { |
| + | if (not gBusy) { | ||
| + | gBusy = true | ||
| + | var dx = (40.0 * (_mouseX - gMouseX))/_width | ||
| + | var dy = (40.0 * (_mouseY - gMouseY))/_height | ||
| + | var q = quaternion() | ||
| + | var ptd = {@dx @dy 0} | ||
| + | var pt = (!q)%ptd | ||
| + | var caxis = {0 0 0} | ||
| + | if (distance(pt, {0 0 0}) > 0.004) { | ||
| + | # If sidechain mode | ||
| + | if (gSCidx >= 0) { | ||
| + | if ({atomIndex=gSCidx}.atomName == "O") { | ||
| + | if ({atomIndex=gSCidx}.group != "PRO") { | ||
| + | var dir = ((abs(dx) > abs(dy)) | ||
| + | ? ((dx < 0) ? 10 : -10) | ||
| + | : ((dy < 0) ? 1 : -1)) | ||
| + | counter_rotate(gSCidx, dir, not alt) | ||
| + | } | ||
| + | } | ||
| + | else { | ||
| + | gSCcheck = not alt | ||
| + | tug_sc(pt) | ||
| + | } | ||
| + | } | ||
| − | + | # Else | |
| − | + | else { | |
| − | + | ||
| − | + | # If new drag | |
| − | + | if (gNewDrag) { | |
| − | + | gNewDrag = false | |
| − | + | save state gState | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | if ( | ||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | + | ||
| − | + | # If destination atom defined | |
| − | + | if (gDestAtomIdx >= 0) { | |
| − | if (( | + | var v = {atomIndex=gDestAtomIdx}.xyz - {selected}.xyz |
| − | + | if (abs(angle({atomIndex=gDestAtomIdx}.xyz, {0 0 0}, pt)) < 90) { | |
| − | + | pt = -v/20.0 | |
| − | + | } | |
| + | else { | ||
| + | pt = v/20.0 | ||
} | } | ||
} | } | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | # | + | # Move the cargo |
| − | + | select {gCargoSet} | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # If pivots defined, rotate it | |
| − | + | if (g1pivotIdx >= 0) { | |
| − | |||
| − | |||
| − | + | # If two pivots | |
| − | + | if (g2pivotIdx >= 0) { | |
| − | + | caxis = {atomIndex=g2pivotIdx} | |
| − | + | } | |
| + | |||
| + | # Else | ||
| + | else { | ||
| + | caxis = cross(pt, {0 0 0}) + {atomIndex=g1pivotIdx}.xyz | ||
| + | } | ||
| + | |||
| + | var dir = ((abs(dx) > abs(dy)) | ||
| + | ? ((dx < 0) ? 2 : -2) | ||
| + | : ((dy < 0) ? 2 : -2)) | ||
| + | rotate_selected_record(g1pivotIdx, caxis, dir) | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | + | ||
| − | + | # Else translate it | |
| + | else { | ||
| + | translate_selected_record(pt) | ||
} | } | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # If collisions | |
| − | + | var cNotSels = (within(kCtolerance, false, {selected}) | |
| − | + | and not {gMovingSet}) | |
| − | + | if ((cNotSels) and (not alt)) { | |
| − | + | gOk2 = true | |
| − | + | for (var i = 1; i <= cNotSels.size; i++) { | |
| − | + | ||
| − | + | # If net collision vector same as move vector | |
| − | + | var cSels = (within(kCtolerance, false, cNotSels[i]) and {selected}) | |
| − | + | for (var j = 1; j <= cSels.size; j++) { | |
| − | + | var v1 = cNotSels[i].xyz - cSels[j].xyz | |
| − | + | if (abs(angle(v1, {0 0 0}, pt)) < 90) { | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # If tow mode | |
| − | + | if (gTow) { | |
| − | |||
| − | |||
| − | + | # Make a dynamic pivot | |
| − | + | if (g1pivotIdx < 0) { | |
| − | + | g1pivotIdx = cSels[j].atomIndex | |
| − | + | g1dynamicIdx = cNotSels[i].atomIndex | |
| − | + | color {atomIndex=g1pivotIdx} lightgreen | |
| − | + | set_distance_idx(cNotSels[i].atomIndex, | |
| − | + | cSels[j].atomIndex, | |
| + | kCtolerance + kDtolerance) | ||
| + | } | ||
| + | else if (g2pivotIdx < 0) { | ||
| + | g2pivotIdx = cSels[j].atomIndex | ||
| + | g2dynamicIdx = cNotSels[i].atomIndex | ||
| + | color {atomIndex=g2pivotIdx} lightgreen | ||
| + | set_distance_idx(cNotSels[i].atomIndex, | ||
| + | cSels[j].atomIndex, | ||
| + | kCtolerance + kDtolerance) | ||
| + | } | ||
| + | else { | ||
| + | gOk2 = false | ||
| + | } | ||
| + | } | ||
| + | else { | ||
| + | # Try to resolve | ||
| + | select @{cSels[j]} | ||
| + | var idx = {(atomno=@{{(chain=gChain) | ||
| + | and thisModel}.atomno.min}) | ||
| + | and (chain=gChain) and thisModel}.atomIndex | ||
| + | handle_collisions( idx) | ||
| + | } | ||
| + | } | ||
| + | } # endfor | ||
| + | if (not gOk2) { | ||
| + | break | ||
| + | } | ||
| + | } # endfor | ||
| − | + | # If unable | |
| − | + | if (not gOk2) { | |
| − | + | ||
| − | + | # Back off | |
| − | + | background ECHO pink | |
| + | delay 1 | ||
| + | if (g1pivotIdx >= 0) { | ||
| + | rotate_selected_record(g1pivotIdx, caxis, -a) | ||
| + | } | ||
| + | else { | ||
| + | translate_selected_record(-pt) | ||
| + | } | ||
| + | background ECHO yellow | ||
| + | set bondPicking true | ||
} | } | ||
| − | |||
| − | |||
| − | |||
} | } | ||
} | } | ||
| − | } | + | |
| − | select {gCargoSet} | + | # If dynamic pivots |
| − | gBusy = | + | if (g1dynamicIdx >= 0) { |
| − | + | var v1 = {atomIndex=g1dynamicIdx}.xyz - {atomIndex=g1pivotIdx}.xyz | |
| − | + | if (abs(angle(v1, {0 0 0}, pt)) > 90) { | |
| + | color {atomIndex=g1pivotIdx} @gAltScheme | ||
| + | g1pivotIdx = -1 | ||
| + | g1dynamicIdx = -1 | ||
| + | |||
| + | } | ||
| + | } | ||
| + | if (g2dynamicIdx >= 0) { | ||
| + | var v1 = {atomIndex=g2dynamicIdx}.xyz - {atomIndex=g2pivotIdx}.xyz | ||
| + | if (abs(angle(v1, {0 0 0}, pt)) > 90) { | ||
| + | color {atomIndex=g2pivotIdx} @gAltScheme | ||
| + | g2pivotIdx = -1 | ||
| + | g2dynamicIdx = -1 | ||
| + | } | ||
| + | } | ||
| + | |||
| + | gMouseX = _mouseX | ||
| + | gMouseY = _mouseY | ||
| + | } | ||
| + | select {gCargoSet} | ||
| + | gBusy = false | ||
} | } | ||
} | } | ||
| − | # Bound to ALT | + | # Bound to ALT-LEFT-DOWN by tug_enable_drag |
| − | function | + | function tug_mark_mb() { |
| − | + | gMouseX = _mouseX | |
| + | gMouseY = _mouseY | ||
| + | gNewDrag = true | ||
} | } | ||
| − | # | + | # Called by tug_cargo_mb |
| − | function | + | function tug_enable_drag() { |
| − | + | gEcho = "__________TUG__________|ALT-CLICK=mark block|SHIFT-CLICK=anchors" + | |
| − | + | "|ALT-CTRL-CLICK=pivots|ALT-SHIFT-CLICK=dest atom|ALT-DRAG=move" + | |
| − | + | "|ALT-SHIFT-DRAG=alt move|CLICK bond=freeze|ALT-DOUBLE-CLICK=undo" + | |
| − | + | "|SHIFT-DOUBLE-CLICK=exit" | |
| − | + | echo @gEcho | |
| − | + | ||
| − | + | # Allow atoms to be dragged | |
| − | + | bind "ALT-LEFT-DOWN" "tug_mark_mb"; | |
| − | + | bind "ALT-LEFT-UP" "tug_drag_done_mb"; | |
| − | + | bind "ALT-SHIFT-LEFT-DOWN" "tug_mark_mb"; | |
| − | + | bind "ALT-LEFT-DRAG" "tug_drag_mb"; | |
| − | + | bind "ALT-SHIFT-LEFT-DRAG" "tug_drag_2_mb"; | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | unbind "SHIFT-LEFT-CLICK" | |
| − | + | bind "SHIFT-LEFT-CLICK" "_pickAtom"; | |
| + | bind "SHIFT-LEFT-CLICK" "+:tug_anchor_mb"; | ||
| − | + | bind "ALT-CTRL-LEFT-CLICK" "_pickAtom"; | |
| − | + | bind "ALT-CTRL-LEFT-CLICK" "+:tug_pivot_mb"; | |
| − | |||
| − | |||
| − | |||
| − | + | bind "ALT-SHIFT-LEFT-CLICK" "_pickAtom"; | |
| − | + | bind "ALT-SHIFT-LEFT-CLICK" "+:tug_dest_atom_mb"; | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # Bound to SHIFT-LEFT-CLICK by tug_cargo_mb | |
| − | + | function tug_anchor_mb() { | |
| + | if ({atomIndex=_atomPicked}.chain == gChain) { | ||
| + | var aPidx = get_sc_bb_idx( _atomPicked, gChain) | ||
| − | + | var pno = {atomIndex=aPidx}.atomno | |
| − | + | if (pno > {atomIndex=gCcargoIdx}.atomno) { | |
| − | + | select {atomIndex=gCanchorIdx} | |
| − | + | halo off | |
| − | + | if (gCanchorIdx == aPidx) { | |
| − | + | gCanchorIdx = -1 | |
| − | + | gCanchorNo = gMaxNo + 1 | |
| − | + | } | |
| − | + | else { | |
| − | + | gCanchorIdx = aPidx | |
| − | + | gCanchorNo = {atomIndex=gCanchorIdx}.atomno | |
| − | + | select {atomIndex=gCanchorIdx} | |
| − | + | halo on | |
| − | + | } | |
| − | + | collect_bb_rotors(false) | |
| − | + | } | |
| − | + | else if (pno < {atomIndex=gNcargoIdx}.atomno) { | |
| − | + | select {atomIndex=gNanchorIdx} | |
| − | } | + | halo off |
| − | + | if (gNanchorIdx == aPidx) { | |
| − | + | gNanchorIdx = -1 | |
| − | + | gNanchorNo = gMinNo - 1 | |
| − | + | } | |
| − | + | else { | |
| + | gNanchorIdx = aPidx | ||
| + | gNanchorNo = {atomIndex=gNanchorIdx}.atomno | ||
| + | select {atomIndex=gNanchorIdx} | ||
| + | halo on | ||
| + | } | ||
| + | collect_bb_rotors(true) | ||
| + | } | ||
| + | else { | ||
| + | tow_cargo_mb() | ||
| + | } | ||
| − | + | # Get moving atoms set | |
| − | + | gMovingSet = {((atomno < gCanchorNo) and (atomno > gNanchorNo) | |
| − | + | and (chain=gChain) and thisModel)} | |
| − | + | } | |
| − | + | select {gCargoSet} | |
| − | + | } | |
| − | + | # Bound to ALT-SHIFT-LEFT-CLICK by tug_cargo_mb | |
| − | + | function tug_dest_atom_mb() { | |
| − | + | var aOk = true | |
| − | + | if ({atomIndex=_atomPicked}.chain == gChain) { | |
| − | |||
| − | + | var pno = {atomIndex=_atomPicked}.atomno | |
| − | + | if ((pno <= {atomIndex=gCcargoIdx}.atomno) | |
| + | and (pno >= {atomIndex=gNcargoIdx}.atomno)) { | ||
| + | aOk = false | ||
| + | } | ||
| + | } | ||
| + | if (aOk) { | ||
| + | select {atomIndex=gDestAtomIdx} | ||
| + | star off | ||
| + | if (gDestAtomIdx == _atomPicked) { | ||
| + | gDestAtomIdx = -1 | ||
| + | } | ||
| + | else { | ||
| + | gDestAtomIdx = _atomPicked | ||
| + | select {atomIndex=gDestAtomIdx} | ||
| + | star on | ||
| + | } | ||
| + | select {gCargoSet} | ||
| + | } | ||
| + | } | ||
| − | + | # Bound to CTRL-LEFT-CLICK by tug_cargo_mb | |
| − | + | function tug_pivot_mb() { | |
| − | + | if (g1pivotIdx == _atomPicked) { | |
| − | + | color {atomIndex=g1pivotIdx} @gScheme | |
| − | + | if (g2pivotIdx >= 0) { | |
| − | + | g1pivotIdx = g2pivotIdx | |
| − | + | g2pivotIdx = -1 | |
| − | + | g2dynamicIdx = -1 | |
| − | + | } | |
| − | + | else { | |
| − | + | g1pivotIdx = -1 | |
| − | + | g1dynamicIdx = -1 | |
| − | + | } | |
| − | + | } | |
| − | + | else if (g2pivotIdx == _atomPicked) { | |
| − | + | color {atomIndex=g2pivotIdx} @gScheme | |
| − | + | g2pivotIdx = -1 | |
| − | + | g2dynamicIdx = -1 | |
| − | + | } | |
| − | + | else if (g1pivotIdx >= 0) { | |
| − | + | if (g2pivotIdx >= 0) { | |
| − | + | color {atomIndex=g2pivotIdx} @gScheme | |
| + | } | ||
| − | + | g2pivotIdx = _atomPicked | |
| − | + | g2dynamicIdx = -1 | |
| − | + | color {atomIndex=g2pivotIdx} green | |
| − | + | } | |
| − | + | else { | |
| − | + | g1pivotIdx = _atomPicked | |
| − | + | g1dynamicIdx = -1 | |
| − | + | color {atomIndex=g1pivotIdx} green | |
| − | + | } | |
| − | + | select {gCargoSet} | |
| − | + | } | |
| − | |||
| − | + | # Bound to SHIFT-LEFT-CLICK by plico_tug | |
| − | + | function tow_cargo_mb() { | |
| + | gTow = true | ||
| + | gChain = {atomIndex=_atomPicked}.chain | ||
| + | gMinNo = {(chain=gChain) and thisModel}.atomno.min | ||
| + | gMaxNo = {(chain=gChain) and thisModel}.atomno.max | ||
| + | gCcargoIdx = -1 | ||
| + | gNcargoIdx = -1 | ||
| + | gCanchorIdx = -1 | ||
| + | gCanchorNo = gMaxNo + 1 | ||
| + | gNanchorIdx = -1 | ||
| + | gNanchorNo = gMinNo - 1 | ||
| − | + | # Highlight cargo cluster | |
| − | + | select {(chain=gChain) and thisModel} | |
| − | + | gCargoSet = {selected} | |
| − | + | gMovingSet = {selected} | |
| − | + | set_colors() | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # Enable dragging | |
| − | + | tug_enable_drag() | |
| − | + | select {gCargoSet} | |
| − | + | halo off | |
| − | + | var es = gEcho.replace("anchors","mark chain") | |
| − | + | echo @es | |
| − | + | unbind "SHIFT-LEFT-CLICK" | |
| + | bind "SHIFT-LEFT-CLICK" "_pickAtom"; | ||
| + | bind "SHIFT-LEFT-CLICK" "+:tow_cargo_mb"; | ||
| + | } | ||
| − | + | # Bound to ALT-LEFT-CLICK by plico_tug or called by plicotoab.toabCargoMB | |
| − | + | function tug_cargo_mb() { | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # If O or movable side chain atom picked | |
| − | + | if ((({atomIndex=_atomPicked}.atomName = "O") | |
| + | and ({atomIndex=_atomPicked}.group != "PRO")) | ||
| + | or (is_moveable_sc( _atomPicked))) { | ||
| + | if (gSCidx >= 0) { | ||
| + | draw gSCcircle DELETE | ||
| + | } | ||
| + | if (gSCidx == _atomPicked) { | ||
| + | gSCidx = -1 | ||
| + | } | ||
| + | else { | ||
| + | gSCidx = _atomPicked | ||
| + | gSCpt = {atomIndex=gSCidx}.xyz | ||
| + | draw gSCcircle CIRCLE {atomIndex=gSCidx} MESH NOFILL | ||
} | } | ||
| − | |||
| − | |||
} | } | ||
| − | } | + | else { |
| − | + | if ({atomIndex=_atomPicked}.chain != gChain) { | |
| − | + | if (gTow) { | |
| − | + | select {(chain=gChain) and thisModel} | |
| − | + | color {selected} @gScheme | |
| − | + | } | |
| − | + | gChain = {atomIndex=_atomPicked}.chain | |
| − | } | + | select ({atomIndex=gCcargoIdx} or {atomIndex=gNcargoIdx} |
| − | + | or {atomIndex=gCanchorIdx} or {atomIndex=gNanchorIdx}) | |
| − | + | halo off | |
| − | + | gCcargoIdx = -1 | |
| − | + | gNcargoIdx = -1 | |
| − | + | gCanchorIdx = -1 | |
| − | + | gNanchorIdx = -1 | |
| − | + | } | |
| + | gTow = false | ||
| + | gMinNo = {(chain=gChain) and thisModel}.atomno.min | ||
| + | gMaxNo = {(chain=gChain) and thisModel}.atomno.max | ||
| + | if (gNanchorIdx < 0) { | ||
| + | gNanchorNo = gMinNo - 1 | ||
| + | } | ||
| + | if (gCanchorIdx < 0) { | ||
| + | gCanchorNo = gMaxNo + 1 | ||
| + | } | ||
| + | var aPidx = get_sc_bb_idx( _atomPicked, gChain) | ||
| − | + | gSCidx = -1 | |
| − | + | draw gSCcircle DELETE | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # If existing cWard cargo picked | |
| − | + | if (gCcargoIdx == aPidx) { | |
| − | |||
| − | + | # Clear the highlight | |
| − | + | select {atomIndex=gCcargoIdx} | |
| + | halo off | ||
| − | + | # If nWard cargo exists, mark it as the cWard cargo | |
| − | + | if (gNcargoIdx != gCcargoIdx) { | |
| − | + | gCcargoIdx = get_cp_idx(gNcargoIdx) | |
| − | + | gCcargoNo = {atomIndex=gCcargoIdx}.atomno | |
| − | # | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
else { | else { | ||
| − | + | gCcargoIdx = -1 | |
| − | + | gNcargoIdx = -1 | |
| − | |||
| − | |||
} | } | ||
| − | |||
} | } | ||
| − | else if ( | + | else if (gNcargoIdx == aPidx) { |
| − | select {atomIndex= | + | select {atomIndex=gNcargoIdx} |
halo off | halo off | ||
| − | + | gNcargoIdx = get_nm_idx(gCcargoIdx) | |
| − | + | gNcargoNo = {atomIndex=gNcargoIdx}.atomno | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| + | else if (gCcargoIdx >= 0) { | ||
| − | + | var no = {atomIndex=aPidx}.atomno | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | } | ||
| − | # | + | # If pick is nWard of it |
| − | + | if (no < {atomIndex=gCcargoIdx}.atomno) { | |
| − | |||
| − | |||
| − | + | # If exists, clear its highlight | |
| − | + | if (gNcargoIdx != gCcargoIdx) { | |
| − | + | select {atomIndex=gNcargoIdx} | |
| − | + | halo off | |
| − | + | } | |
| − | + | ||
| − | + | # Set new nWard cargo and highlight it | |
| − | + | gNcargoIdx = get_nm_idx(aPidx) | |
| − | + | gNcargoNo = {atomIndex=gNcargoIdx}.atomno | |
| − | + | } | |
| − | + | ||
| − | + | # Else cWard | |
| − | + | else { | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | # | + | # Clear its old highlight |
| − | + | select {atomIndex=gCcargoIdx} | |
| − | + | if (gNcargoIdx != gCcargoIdx) { | |
| − | + | halo off | |
| − | + | } | |
| − | + | ||
| − | + | # Set new cWard cargo and highlight | |
| − | + | gCcargoIdx = get_cp_idx(aPidx) | |
| + | gCcargoNo = {atomIndex=gCcargoIdx}.atomno | ||
| + | } | ||
} | } | ||
| + | |||
| + | # Else no cWard cargo | ||
else { | else { | ||
| − | + | ||
| − | + | # Set new cWard cargo and highlight | |
| + | gCcargoIdx = get_cp_idx(aPidx) | ||
| + | gCcargoNo = {atomIndex=gCcargoIdx}.atomno | ||
| + | gNcargoIdx = get_nm_idx(gCcargoIdx) | ||
| + | gNcargoNo = {atomIndex=gNcargoIdx}.atomno | ||
} | } | ||
| − | + | ||
| − | + | # If any anchor now inside cargo cluster, kill it | |
| − | + | if ({atomIndex=gCanchorIdx}.atomno <= {atomIndex=gCcargoIdx}.atomno) { | |
| − | + | gCanchorIdx = -1 | |
| − | + | gCanchorNo = gMaxNo + 1 | |
| − | + | } | |
| − | + | if ({atomIndex=gNanchorIdx}.atomno >= {atomIndex=gNcargoIdx}.atomno) { | |
| − | + | gNanchorIdx = -1 | |
| − | + | gNanchorNo = gMinNo - 1 | |
} | } | ||
| − | + | # Highlight cargo cluster | |
| − | + | select_nward_idx(gCcargoIdx, gNcargoIdx) | |
| − | + | gCargoSet = {selected} | |
| + | set_colors() | ||
| + | |||
| + | # Collect the rotor sets | ||
| + | collect_rotors() | ||
| + | |||
| + | # Get moving atoms set | ||
| + | gMovingSet = {((atomno < gCanchorNo) and (atomno > gNanchorNo) | ||
| + | and (chain=gChain) and thisModel)} | ||
| + | } | ||
| + | |||
| + | # Enable dragging | ||
| + | if (gToab) { | ||
| + | to_ab_enable_drag() | ||
} | } | ||
else { | else { | ||
| − | + | tug_enable_drag() | |
| − | |||
| − | |||
} | } | ||
| + | |||
select {gCargoSet} | select {gCargoSet} | ||
} | } | ||
| − | + | function tug_undo_mb() { | |
| − | function | + | if (prompt("Undo", "Yes|No", true) == "Yes") { |
| − | + | restore state gState | |
| − | + | } | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | # Top level of Tug | |
| − | + | function plico_tug() { | |
| − | |||
| − | |||
| − | |||
| − | # | + | # 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") | |
| − | echo @ | + | quit |
| − | + | } | |
| + | } | ||
| + | |||
| + | gPlico = "TUG" | ||
| + | plico_prelim(true, true) | ||
| + | |||
| + | gBondPicking = bondPicking | ||
| + | set bondPicking true | ||
| + | set PickCallback "jmolscript:tug_pick_cb" | ||
| + | |||
| + | gEcho = ("_________TUG_________|ALT-CLICK=mark block|SHIFT-CLICK=mark chain" + | ||
| + | "|CLICK bond=freeze|ALT-DOUBLE-CLICK=undo|SHIFT-DOUBLE-CLICK=exit") | ||
| + | echo @gEcho | ||
| + | gCrotors = array() | ||
| + | gNrotors = array() | ||
| + | clear_atom_idxs() | ||
| + | gToab = false | ||
| + | |||
| + | bind "ALT-LEFT-CLICK" "_pickAtom"; | ||
| + | bind "ALT-LEFT-CLICK" "+:tug_cargo_mb"; | ||
bind "SHIFT-LEFT-CLICK" "_pickAtom"; | bind "SHIFT-LEFT-CLICK" "_pickAtom"; | ||
| − | bind "SHIFT-LEFT-CLICK" "+: | + | bind "SHIFT-LEFT-CLICK" "+:tow_cargo_mb"; |
| + | bind "ALT-LEFT-DOUBLE" "tug_undo_mb"; | ||
| + | bind "SHIFT-DOUBLE" "tug_exit(true)"; | ||
| + | bind "LEFT-CLICK" "+:plico_menu_toggle"; | ||
} | } | ||
| − | # Bound to | + | # Bound to DOUBLE by plico_tug |
| − | function | + | function tug_exit() { |
| − | + | if (plico_exit()) { | |
| − | + | set bondPicking gBondPicking | |
| − | if (( | + | set PickCallback NONE |
| − | + | select all | |
| − | + | color bonds none | |
| − | + | ||
| − | + | reset kTug | |
| − | + | reset gCanchorIdx | |
| − | + | reset gCanchorNo | |
| − | + | reset gPlico | |
| − | + | reset gNanchorIdx | |
| − | + | reset gNanchorNo | |
| − | + | reset gCcargoIdx | |
| − | + | reset gNcargoIdx | |
| − | + | reset gCcargoNo | |
| − | + | reset gNcargoNo | |
| − | + | reset gDestAtomIdx | |
| − | + | reset g1pivotIdx | |
| − | + | reset g2pivotIdx | |
| − | + | reset gSelSaves | |
| − | + | reset gCrotors | |
| − | + | reset gNrotors | |
| − | + | reset gOkCollide | |
| − | + | reset gChain | |
| − | + | reset gMinNo | |
| − | + | reset gMaxNo | |
| − | + | reset gCargoSet | |
| − | + | reset gMovingSet | |
| − | + | reset gSCidx | |
| − | + | reset gSCcircle | |
| − | + | reset gSCpt | |
| − | + | reset gTargetPt | |
| − | + | reset gNewDrag | |
| − | + | reset gTow | |
| − | + | reset g1dynamicIdx | |
| − | + | reset g2dynamicIdx | |
| − | + | reset gSCcheck | |
| − | + | reset gBondPicking | |
| − | + | reset gFreeze | |
| − | + | reset gToab | |
| − | + | reset function "get_cp_idx" | |
| − | + | reset function "get_cm_no" | |
| − | gSCidx | + | reset function "get_nm_idx" |
| − | + | reset function "get_np_no" | |
| − | + | reset function "get_cb_idx" | |
| − | + | reset function "get_o_idx" | |
| − | + | reset function "get_nward_bb_idx" | |
| − | + | reset function "get_cward_bb_idx" | |
| − | + | reset function "get_sc_set" | |
| − | + | reset function "get_sc_bb_idx" | |
| − | + | reset function "is_bb_idx" | |
| − | + | reset function "is_sc_idx" | |
| − | + | reset function "select_add_sc" | |
| − | + | reset function "handle_collisions" | |
| − | + | reset function "tug_track_idx" | |
| − | + | reset function "do_counter_rotate" | |
| − | + | reset function "counter_rotate" | |
| − | + | reset function "counter_rotate_2" | |
| − | + | reset function "repair_proline" | |
| − | + | reset function "repair_sc" | |
| − | + | reset function "tug_track_c" | |
| − | + | reset function "tug_track_n" | |
| − | + | reset function "translate_selected_record" | |
| − | + | reset function "rotate_selected_record" | |
| − | + | reset function "collect_sc_rotors" | |
| − | + | reset function "drag_sc" | |
| − | + | reset function "fix_sc_collision_2" | |
| − | + | reset function "is_moveable_sc" | |
| − | + | reset function "is_rotor_avail" | |
| − | + | reset function "xcollect_bb_rotors" | |
| − | + | reset function "collect_bb_rotors" | |
| − | + | reset function "collect_rotors" | |
| − | + | reset function "tug_sc" | |
| − | + | reset function "set_colors" | |
| − | + | reset function "clear_atom_idxs" | |
| − | + | reset function "timed_out" | |
| − | + | reset function "record_drag" | |
| − | + | reset function "tug_pick_cb" | |
| − | + | reset function "tug_drag_done_mb" | |
| − | + | reset function "tug_drag_2_mb" | |
| − | + | reset function "tug_drag_mb" | |
| − | + | reset function "tug_mark_mb" | |
| − | + | reset function "tug_anchor_mb" | |
| − | + | reset function "tug_enable_drag" | |
| − | + | reset function "tug_dest_atom_mb" | |
| − | + | reset function "tug_pivot_mb" | |
| − | + | reset function "tow_cargo_mb" | |
| − | + | reset function "tug_cargo_mb" | |
| − | + | reset function "tug_undo_mb" | |
| − | + | reset function "plico_tug" | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | # End of TUG.SPT</pre> | + | # End of TUG.SPT |
| + | </pre> | ||
Latest revision as of 17:15, 12 April 2016
Tug allows the user to pull or push by mouse actions to move or rotate one part of a polypeptide against the rest by rotation on its psi and phi bonds with collision detection and restriction. It also allows the user to move an entire chain to nest against another chain. A full description of its capabilities can be found here.
Tug is a member of the Plico suite of protein folding tools described in User:Remig/plico . It may be installed and accessed as a macro with the file:
Title=PLICO Tug Script=script <path to your scripts directory>/tug.spt;plico_tug
saved as plicotug.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 tug.spt.
# tug - Jmol script by Ron Mignery
# v1.20 beta 4/12/2016 -axis is now a reserved word
#
# Translate or rotate a stretch of a polypeptide against itself
# or against other chains by mouse actions
#
kTug = 3
gCanchorIdx = -1
gCanchorNo = -1
gPlico = "TUG"
gNanchorIdx = -1
gNanchorNo = -1
gCcargoIdx = -1
gNcargoIdx = -1
gCcargoNo = -1
gNcargoNo = -1
gDestAtomIdx = -1
g1pivotIdx = -1
g2pivotIdx = -1
gSelSaves = ({})
gCrotors = array()
gNrotors = array()
gOkCollide = ({})
gChain = ""
gMinNo = 1
gMaxNo = 9999
gCargoSet = ({})
gMovingSet = ({})
gBusy = false
gSCidx = -1
gSCcircle = -1
gSCpt = {0 0 0}
gTargetPt = {0 0 0}
gNewDrag = false
gTow = false
g1dynamicIdx = -1
g2dynamicIdx = -1
gSCcheck = true
gBondPicking = false
gFreeze = array()
gToab = false
function get_cp_idx (idx) {
var no = {atomIndex=idx}.atomno
while ((no < gMaxNo) and ({(atomno=no) and (chain=gChain)
and thisModel}.atomName != "C")) {
no++
}
return ({(atomno=no) and (chain=gChain) and thisModel}.atomIndex)
}
function get_cm_no (iNo) {
while ((iNo > 0) and ({(atomno=iNo) and (chain=gChain)
and thisModel}.atomName != "C")) {
iNo--
}
return iNo
}
function get_nm_idx (idx) {
var no = {atomIndex=idx}.atomno
while ((no > 0) and ({(atomno=no) and (chain=gChain)
and thisModel}.atomName != "N")) {
no--
}
return ({(atomno=no) and (chain=gChain) and thisModel}.atomIndex)
}
function get_np_no (iNo) {
while ((iNo < gMaxNo) and ({(atomno=iNo) and (chain=gChain)
and thisModel}.atomName != "N")) {
iNo++
}
return iNo
}
function get_cb_idx (BBidx) {
var no = {atomIndex=BBidx}.atomno
var i = 1
for (; i < 5; i++) {
if ({(atomno=@{no+i}) and (chain=gChain)
and thisModel}.atomName == "CB") {
break
}
}
return {(atomno=@{no+i}) and (chain=gChain) and thisModel}.atomIndex
}
function get_o_idx (BBidx) {
var no = {atomIndex=BBidx}.atomno
var i = 1
for (; i < 4; i++) {
if ({(atomno=@{no+i}) and (chain=gChain)
and thisModel}.atomName == "O") {
break
}
}
return {(atomno=@{no+i}) and (chain=gChain) and thisModel}.atomIndex
}
function get_nward_bb_idx (idx, iChain) {
var no = {atomIndex=idx}.atomno - 1
for (; no >= 0; no--) {
var atomName = {(atomno=no) and (chain=iChain)
and thisModel}.atomName
if ((atomName = "N") or (atomName = "C") or (atomName = "CA")) {
break
}
}
return ((no >= 0) ? ({(atomno=no) and (chain=iChain)
and thisModel}.atomIndex) : -1)
}
function get_cward_bb_idx (idx, iChain) {
var no = {atomIndex=idx}.atomno + 1
for (; no < gMaxNo; no++) {
var atomName = {(atomno=no) and (chain=iChain)
and thisModel}.atomName
if ((atomName = "N") or (atomName = "C") or (atomName = "CA")) {
break
}
}
return ((no >= 0) ? ({(atomno=no) and (chain=iChain)
and thisModel}.atomIndex) : -1)
}
function get_sc_set (scIdx, iChain) {
var scSet = ({})
var idx = get_sc_bb_idx(scIdx, iChain)
var iNo = {atomIndex=idx}.atomno + 3
for (var i = 1; i < 20; i++) {
idx = {(atomno=@{iNo+i}) and (chain=iChain)
and thisModel}.atomIndex
if (is_bb_idx(idx)) {
break
}
scSet = scSet or {atomIndex=idx}
}
return scSet
}
function get_sc_bb_idx (idx, iChain) {
var no = {atomIndex=idx}.atomno
for (; no > 0; no--) {
if ({(atomno=no) and (chain=iChain)
and thisModel}.atomName == "CA") {
break
}
else if ({(atomno=no) and (chain=iChain)
and thisModel}.atomName == "C") {
break
}
else if ({(atomno=no) and (chain=iChain)
and thisModel}.atomName == "N") {
break
}
else if ({(atomno=no) and (chain=iChain)
and thisModel}.atomName == "CB") {
no -= 3
break
}
}
return {(atomno=no) and (chain=iChain) and thisModel}.atomIndex
}
function is_bb_idx(aIdx) {
var ret = false
switch({atomIndex=aIdx}.atomName) {
case "N":
case "CA":
case "C":
ret = true
break
}
return ret
}
function is_sc_idx(aIdx) {
var ret = false
if (not is_bb_idx(aIDx)) {
ret = true
switch({atomIndex=aIdx}.atomName) {
case "O":
case "CB":
ret = false
break
}
}
return ret
}
function select_add_sc(fromIdx) {
var iNo = {atomIndex=fromIdx}.atomno
var iChain = {atomIndex=fromIdx}.chain
select none
while ({(atomno=iNo) and (chain=iChain)
and thisModel and sidechain}) {
var a = {(atomno=iNo) and (chain=iChain)and thisModel}
a.selected = true
iNo++
}
}
# Resolve collisions on selection
function handle_collisions( targetIdx) {
# For all selected atoms
for (var iNo = {selected}.min.atomno; iNo <= {selected}.max.atomno; iNo++) {
var idx = {(atomno=iNo) and (chain=gchain)
and thisModel}.atomIndex
if ({atomindex=idx}.selected) {
# Collect local colliders
var lcAtoms = (within(kCtolerance, false, {atomIndex=idx})
and not {atomIndex=idx}
and not {gOkCollide}
and not connected({atomIndex=idx}))
if (lcAtoms) {
# Ignore kinked BB
try {
if (is_bb_idx(idx) and (angle(
{atomIndex=@{get_cward_bb_idx(idx, gChain)}}, {atomIndex=idx},
{atomIndex=@{get_nward_bb_idx(idx, gChain)}}) < 100.0)) {
continue
}
}
catch {
}
# For all local colliders
for (var c = 1; c <= lcAtoms.size; c++ ) {
var cidx = lcAtoms[c].atomIndex
# If it is with water, delete it
if (lcAtoms[c].group = "HOH") {
delete {atomIndex=cidx}
}
# else if it is with side chain not proline, fix it
else if (is_sc_idx(cidx) and ({atomIndex=cidx}.group != "PRO")) {
fix_sc_collision_2(cidx)
# If not fixed, exit fail
if (not gOk2) {
return # early exit (break n jmol bug)
}
}
# else if it is itself a side chain not proline, fix it
else if (is_sc_idx(idx) and ({atomIndex=idx}.group != "PRO")) {
fix_sc_collision_2(idx)
# If not fixed, exit fail
if (not gOk2) {
return # early exit (break n jmol bug)
}
}
# Else if it is with O, counter-rotate
else if (lcAtoms[c].atomName = "O") {
counter_rotate_2(lcAtoms[c].atomIndex,
{atomIndex=idx}.xyz, targetIdx, false)
# If not fixed, exit fail
if (not gOk2) {
return # early exit (break n jmol bug)
}
}
# Else if it is itself O, counter-rotate
else if ({atomIndex=idx}.atomName = "O") {
counter_rotate_2(idx, lcAtoms[c].xyz, targetIdx, false)
# If not fixed, exit fail
if (not gOk2) {
return # early exit (break n jmol bug)
}
}
else { # Else not fixed, exit fail
gOk2 = false
return # early exit (break n jmol bug)
}
} # endfor
}
}
} # endfor iNo
}
# Rotate rotor set to move target atom to its proper place
function tug_track_idx(targetIdx, targetPt, nWard, cDetect) {
gOK = false
var pt = targetPt
var dist = distance(pt, {atomIndex=targetIdx}.xyz)
var rotors = (nWard ? gNrotors : gCrotors)
# For a number of passes
for (var pass1 = 0; pass1 < 20; pass1++) {
var blocked = ({})
for (var pass2 = 0; pass2 < (rotors.size/4); pass2++) {
var v1 = {atomIndex=targetIdx}.xyz - pt
# Find the most orthgonal unused rotor
var imax = 0
var smax = 0.5
for (var i = 1; i < rotors.size; i += 4) {
var i2 = rotors[i+1]
var i3 = rotors[i+2]
var i4 = rotors[i+3]
if ((i2 != targetIdx) and (i3 != targetIdx) and (i4 != targetIdx)) {
if ({blocked and {atomIndex=i2}}.count == 0) {
var v2 = {atomIndex=i3}.xyz - {atomIndex=i2}.xyz
var s = sin(abs(angle(v1, {0 0 0}, v2)))
if (s > smax) {
smax = s
imax = i
}
}
}
}
# If no more rotors, break to next full try
if (imax == 0) {
break
}
var i1 = rotors[imax+0]
var i2 = rotors[imax+1]
var i3 = rotors[imax+2]
var i4 = rotors[imax+3]
# Get dihedral of rotor with target point
var dt = angle({atomIndex=targetIdx}, {atomIndex=i2}, {atomIndex=i3}, pt)
var dh = angle({atomIndex=i1}, {atomIndex=i2}, {atomIndex=i3}, {atomIndex=i4})
if (abs(dh).type == "string") {
dh = -50
}
var psi = dh + dt
var phi = dh + dt
# Compute resultant psi and phi
# and select from target atom to first half of rotor
var movePt = false
if (nWard) {
if ({atomIndex=i2}.atomName="CA") {
psi = angle({atomIndex=@{get_cward_bb_idx(i1, gChain)}}, {atomIndex=i1},
{atomIndex=i2}, {atomIndex=i3}) + dt
}
else {
phi = angle({atomIndex=i1}, {atomIndex=i2},
{atomIndex=i3}, {atomIndex=@{get_nward_bb_idx(i3, gChain)}}) + dt
}
if ({atomIndex=i2}.atomno > {atomIndex=targetIdx}.atomno) {
movePt = true
select_nward_idx(i3, get_cward_bb_idx(targetIdx, gChain))
{atomIndex=targetIdx}.selected = true
}
else {
select_cward_idx(i2, targetIdx)
}
}
else {
if (({atomIndex=i2}.atomName="CA")) {
phi = angle({atomIndex=@{get_nward_bb_idx(i1, gChain)}}, {atomIndex=i1},
{atomIndex=i2}, {atomIndex=i3}) + dt
}
else {
psi = angle({atomIndex=i2}, {atomIndex=i3},
{atomIndex=i4}, {atomIndex=@{get_cward_bb_idx(i4, gChain)}}) + dt
}
if ({atomIndex=i2}.atomno < {atomIndex=targetIdx}.atomno) {
movePt = true
select_cward_idx(i3, get_nward_bb_idx(targetIdx, gChain))
{atomIndex=targetIdx}.selected = true
}
else {
select_nward_idx(i2, targetIdx)
}
}
# Relax rules if desperate
if (pass1 > 10) {
phi = -50
}
# If rotation within ramachandran limits
if ((abs(dt) >= 0.1) and
(({atomIndex=i2}.group=="GLY") or (phi < 0))) {
# If moving target point, put the target atom there
var cp = {atomIndex=targetIdx}.xyz
if (movePt) {
dt = -dt
{atomIndex=targetIdx}.xyz = pt
}
# Rotate to minimize vector ====================
rotateSelected {atomIndex=i2} {atomIndex=i3} @dt
# If collision checking
if (cDetect) {
# If collision, back off by eighths
var wasCollision = false
for (var ci = 0; ci < 4; ci++) {
if (ci < 3) {
dt /= 2
}
handle_collisions( targetIdx)
if (not gOk2) {
wasCollision = true
rotateSelected {atomIndex=i2} {atomIndex=i3} @{-dt}
}
else if (wasCollision) {
if (ci <3) {
rotateSelected {atomIndex=i2} {atomIndex=i3} @{dt}
}
}
else {
break
}
if (dt < 0.01) {
break
}
} # endfor
}
# If moving target point, put the target atom back
if (movePt) {
pt = {atomIndex=targetIdx}.xyz
{atomIndex=targetIdx}.xyz = cp
}
}
# If close enough, stop
if (distance(pt, {atomIndex=targetIdx}) < kDtolerance) {
gOK = true
gTargetPt = pt
break
}
# Block rotor
blocked |= {atomIndex=i2}
} # endfor num rotors passes
if (gOK) {
break
}
} # endfor 20 passes
}
# Counter rotate bonds on either side of a BB O
function do_counter_rotate(caPhiIdx, nIdx, cIdx, oIdx, caPsiIdx, dir, nWard) {
# Rotate psi
{atomIndex=nIdx}.selected = nWard
{atomIndex=cIdx}.selected = nWard
{atomIndex=oIdx}.selected = nward
rotateSelected {atomIndex=caPsiIdx} {atomIndex=cIdx} @{dir}
# Counter-rotate phi
{atomIndex=nIdx}.selected = not nWard
{atomIndex=cIdx}.selected = not nWard
{atomIndex=oIdx}.selected = not nward
rotateSelected {atomIndex=nIdx} {atomIndex=caPhiIdx} @{-dir}
}
function counter_rotate(oIdx, dir, nWard) {
var iChain = {atomIndex=oIdx}.chain
var selsave = {selected}
var cIdx = get_sc_bb_idx(oIdx, iChain)
var nIdx = get_cward_bb_idx(cIdx, iChain)
var caPhiIdx = get_cward_bb_idx(nIdx, iChain)
var caPsiIdx = get_nward_bb_idx(cIdx, iChain)
if (nWard) {
var nNo = {(chain=iChain) and thisModel}.atomno.min
select_nward_idx(caPsiIdx, {(atomno=nNo) and (chain=iChain)
and thisModel}.atomIndex)
}
else {
var cNo = {(chain=iChain) and thisModel}.atomno.max
select_cward_idx(caPhiIdx, {(atomno=cNo) and (chain=iChain)
and thisModel}.atomIndex)
}
# Counter-rotate
do_counter_rotate(caPhiIdx, nIdx, cIdx, oIdx, caPsiIdx, dir, not nWard)
select selsave
}
function counter_rotate_2(oIdx, toPt, terminalIdx, oDrag) {
var iChain = {atomIndex=oIdx}.chain
var selsave = {selected}
var gOk2 = true
var cIdx = get_sc_bb_idx(oIdx, iChain)
var nIdx = get_cward_bb_idx(cIdx, iChain)
var caPhiIdx = get_cward_bb_idx(nIdx, iChain)
var caPsiIdx = get_nward_bb_idx(cIdx, iChain)
var nTward = ({atomIndex=oIdx}.atomno < {atomIndex=terminalIdx}.atomno)
if (nTward) {
select_cward_idx(cIdx, terminalIdx)
}
else {
select_nward_idx(nIdx, terminalIdx)
}
# Until all collisions cancelled
var dir = 5
var ang = angle(toPt, {atomIndex=oIdx}, {atomIndex=cIdx})
var tcount = 0
while (oDrag or (within(kCtolerance, false, {atomIndex=oIdx})
and not {atomIndex=oIdx} and not connected({atomIndex=oIdx})
and not {gOkCollide} > 0)) {
# Counter-rotate
do_counter_rotate(caPhiIdx, nIdx, cIdx, oIdx, caPsiIdx, dir, nTward)
var newang = angle(toPt, {atomIndex=oIdx}, {atomIndex=cIdx})
# If wrong direction once, undo and reverse
if (newang > ang) {
do_counter_rotate(caPhiIDx, nIdx, cIdx, oIdx, caPsiIdx, -dir, nTward)
# If first time, continue in opposite direction
dir *= -1
if (dir < 0) {
continue
}
}
if (oDrag) {
break
}
# If no go, undo and exit
tcount++
if (tcount > (360/abs(dir))) {
gOk2 = false
break
}
} # endwhile
select selsave
}
# Repair proline
function repair_proline(BBidx) {
var cbidx = get_cb_idx(BBidx)
var cbno = {atomIndex=cbidx}.atomno
var cgidx = {(atomno=@{cbno+1}) and (chain=gChain)
and thisModel}.atomIndex
var cdidx = {(atomno=@{cbno+2}) and (chain=gChain)
and thisModel}.atomIndex
var caidx = {(atomno=@{cbno-3}) and (chain=gChain)
and thisModel}.atomIndex
var nidx = {(atomno=@{cbno-4}) and (chain=gChain)
and thisModel}.atomIndex
select {atomIndex=cbidx}
set_angle_idx(nidx, caidx, cbidx, 109.5)
select {atomIndex=cdidx}
set_distance_idx(nidx, cdidx, 1.47)
set_angle_idx(caidx, nidx, cdidx, 102.7)
set_dihedral_idx(cbidx, caidx, nidx, cdidx, 16.2)
select {atomIndex=cgidx}
set_distance_idx(cdidx, cgidx, 1.51)
set_angle_idx(nidx, cdidx, cgidx, 106.4)
set_dihedral_idx(caidx, nidx, cdidx, cgidx, 16.2)
}
# Repair side chain
function repair_sc(targetIdx, nWard) {
var idx = (nWard ? get_cward_bb_idx(targetIdx, gChain) : get_nward_bb_idx(targetIdx, gChain))
if (({atomIndex=targetIdx}.atomName == "CA")
and ({atomIndex=targetIdx}.group != "GLY")) {
var cbidx = get_cb_idx(targetIdx)
select none
select_add_sc(cbidx)
set_angle_idx(idx, targetIdx, cbidx, 110.0)
set_distance_idx(targetIdx, cbidx, 1.5)
if ({atomIndex=targetIdx}.group != "PRO") {
var colliders = (within(kCtolerance, false, {selected})
and not {atomIndex=targetIdx} and not {selected})
if (colliders) {
if ({atomIndex=targetIdx}.group != "ALA") {
fix_sc_collision_2(cbidx)
}
}
}
else {
if (nWard) {
}
else {
set_dihedral_idx(get_nward_bb_idx(idx, gChain), idx, targetIdx, cbidx, 174.2)
}
}
}
else if ({atomIndex=targetIdx}.atomName == "C") {
var oidx = get_o_idx(targetIdx)
select {atomIndex=oidx}
set_angle_idx(idx, targetIdx, oidx, 120.0)
set_distance_idx(targetIdx, oidx, 1.21)
if (nWard) {
set_dihedral_idx(get_cward_bb_idx(idx, gChain), idx, targetIdx, oidx, 0.0)
}
if ({atomIndex=idx}.group == "PRO") {
repair_proline(idx)
var dNo = {atomIndex=targetIdx}.atomno + 4
var dIdx = {(atomno=dNO) and (chain=gChain)
and thisModel}.atomIndex
var colliders = (within(kCtolerance, false, {atomIndex=dIdx})
and not connected({atomIndex=dIdx})
and not {atomIndex=dIdx})
for (var i = 1; i <= colliders.size; i++) {
if (colliders[i].atomName == "O") {
counter_rotate_2(colliders[i].atomIndex,
{atomIndex=dIdx}.xyz, targetIdx, false)
}
}
}
}
}
# Rebuild Cward rotors set
function tug_track_c() {
# For all bb atoms cWard of cargo
var targetIdx = gCcargoIdx
var okCount = 0
# Allow collisions with cargo
gOkCollide = gCargoSet
var tcount = 0
while (targetIdx != gNanchorIdx) {
# Step to next atom
targetIdx = get_cward_bb_idx(targetIdx, gChain)
if (targetIdx < 0) {
break
}
# No collision with cargo allowed after two atoms placed
if (tcount == 2) {
gOkCollide = ({})
}
tcount++
# Compute targets desired coords
try {
var c1idx = get_cward_bb_idx(targetIdx, gChain)
var n1idx = get_nward_bb_idx(targetIdx, gChain )
var n2idx = get_nward_bb_idx(n1Idx, gChain)
var n3idx = get_nward_bb_idx(n2Idx, gChain)
var pt = {0 0 0}
if ({atomIndex=targetIdx}.atomName == "N") {
var oidx = get_o_idx(n1idx)
select {atomIndex=oidx}
# Desired target location is trigonal O
set_distance_idx(n1idx, oidx, 1.5)
pt = get_trigonal_idx(n2idx, n1idx, oidx, 1.37)
set_distance_idx(n1idx, oidx, 1.21)
}
else if (({atomIndex=targetIdx}.atomName == "C")
and ({atomIndex=targetIdx}.group != "GLY")) {
# Desired target location is tetragonal CB
var cbidx = get_cb_idx(n1idx)
pt = get_tet_idx(n2idx, n1idx, cbidx, 1.5)
}
else { # CA (or GLY C)
# Save current target coords
var cp = {atomIndex=targetIdx}.xyz
# Set target atom at desired distance and angle
select {atomIndex=targetIdx}
set_distance_idx(n1idx, targetIdx, 1.5)
set_angle_idx(n2idx, n1idx, targetIdx, 120.0)
if ({atomIndex=targetIdx}.atomName == "CA") {
set_dihedral_idx(n3idx, n2idx, n1idx, targetIdx, 180)
}
# Record and restore target
pt = {atomIndex=targetIdx}.xyz
{atomIndex=targetIdx}.xyz = cp
}
# If target not at desired location
if (distance(pt, {atomIndex=targetIdx}) > kDtolerance) {
okCount = 0
gTargetPt = pt
var xcount = 0
gOK = false
while ((xcount < 20) and (not gOK)) {
# Rotate on cWard rotor set to move it there
tug_track_idx(targetIdx, pt, false, false)
xcount++
}
}
else {
gOK = true
okCount++
}
}
catch {
}
# If successful
if (gOK == true) {
# Adust any side atoms
repair_sc(targetIdx, false)
}
# Else fail
else {
break
}
# If no movement in 4 tries, we are done
if (okCount > 3) {
break
}
} # endwhile (targetIdx != gCanchorIdx) {
}
# Rebuild Nward rotors set
function tug_track_n() {
gOK = true
# For all bb atoms nWard of cargo
var targetIdx = gNcargoIdx
var okCount = 0
# Allow collisions with cargo
gOkCollide = gCargoSet
var tcount = 0
while (targetIdx != gNanchorIdx) {
# Step to next atom
targetIdx = get_nward_bb_idx(targetIdx, gChain)
if (targetIdx < 0) {
break
}
# No collision with cargo allowed after two atoms placed
if (tcount == 2) {
gOkCollide = ({})
}
tcount++
# Compute targets desired coords
var n1idx = get_nward_bb_idx(targetIdx, gChain)
var c1idx = get_cward_bb_idx(targetIdx, gChain)
var c2idx = get_cward_bb_idx(c1idx, gChain)
var c3idx = get_cward_bb_idx(c2idx, gChain)
var pt = {0 0 0}
if ({atomIndex=targetIdx}.atomName == "CA") {
# Desired target location is trigonal O
var oidx = get_o_idx(c1idx)
select {atomIndex=oidx}
set_distance_idx(c1idx, oidx, 1.39)
pt = get_trigonal_idx(c2idx, c1idx, oidx, 1.41)
set_distance_idx(c1idx, oidx, 1.21)
}
else if (({atomIndex=targetIdx}.atomName == "N")
and ({atomIndex=targetIdx}.group != "GLY")) {
# Desired target location is r-tetragonal CB
var cbidx = get_cb_idx(c1idx)
pt = get_tet_idx(cbidx, c1idx, c2idx, 1.5)
}
else { # C
# Save current target coords
var cp = {atomIndex=targetIdx}.xyz
# Set target atom at desired distance and angle
select {atomIndex=targetIdx}
set_distance_idx(c1idx, targetIdx, 1.37)
set_angle_idx(c2idx, c1idx, targetIdx, 110.0)
if ({atomIndex=targetIdx}.group == "PRO") {
set_dihedral_idx(c3idx, c2idx, c1idx, targetIdx, -57.0)
}
# Record and restore target
pt = {atomIndex=targetIdx}.xyz
{atomIndex=targetIdx}.xyz = cp
}
# If target not at desired location
if (distance(pt, {atomIndex=targetIdx}) > kDtolerance) {
var okCount = 0
gTargetPt = pt
var xcount = 0
gOK = false
while ((xcount < 20) and (not gOK)) {
# Rotate on nWard rotor set to move it there
tug_track_idx(targetIdx, pt, true, false)
xcount++
}
}
else {
gOK = true
okCount++
}
# If sucessful
if (gOK == true) {
# Adust any side atoms
repair_sc(targetIdx, true)
}
# Else fail
else {
break
}
# If no movement in 4 tries, we are done
if (okCount > 3) {
break
}
} # endwhile (targetIdx != gNanchorIdx) {
}
# gPlicoRecord is maintained by the macro pilcoRecord
function translate_selected_record(pt) {
if (gPlicoRecord != "") {
plico_record(format("select %s;translateSelected %s;", {selected}, pt))
}
translateSelected @pt
}
# gPlicoRecord is maintained by the macro pilcoRecord
function rotate_selected_record(pivotIdx, caxis, a) {
if (gPlicoRecord != "") {
plico_record(format("select %s;", {selected}))
plico_record(format("rotateSelected {atomIndex=%d} @%s @%s;",
pivotIdx, caxis, a))
}
rotateSelected {atomIndex=pivotIdx} @caxis @a
}
function collect_sc_rotors(no, iChain) {
var scBondIdxs = array()
for (var iNo = no; iNo >= 0; iNo--) {
var ile = 0
switch ({(atomno=iNo) and (chain=iChain)
and thisModel}.atomName) {
case "CA" :
return scBondIdxs # Early exit since break 1 appears broken
case "CZ" :
if ({(atomno=iNo) and (chain=iChain)
and thisModel}.group == "TYR") {
break
}
case "CE" :
if ({(atomno=iNo) and (chain=iChain)
and thisModel}.group == "MET") {
break
}
case "CG1" :
if ({(atomno=iNo) and (chain=iChain)
and thisModel}.group == "VAL") {
break
}
if ({(atomno=iNo) and (chain=iChain)
and thisModel}.group == "ILE") {
ile = 1
}
case "NE" :
case "CD" :
case "SD" :
case "CG" :
case "CB" :
scBondIdxs += {(atomno=@{iNo+1+ile}) and (chain=iChain)
and thisModel}.atomIndex
scBondIdxs += {(atomno=@{iNo+0}) and (chain=iChain)
and thisModel}.atomIndex
if ({(atomno=iNo) and (chain=iChain)
and thisModel}.atomName%2 == "CG") {
scBondIdxs += {(atomno=@{iNo-1}) and (chain=iChain)
and thisModel}.atomIndex
scBondIdxs += {(atomno=@{iNo-4}) and (chain=iChain)
and thisModel}.atomIndex
}
else if ({(atomno=iNo) and (chain=iChain)
and thisModel}.atomName == "CB") {
scBondIdxs += {(atomno=@{iNo-3}) and (chain=iChain)
and thisModel}.atomIndex
scBondIdxs += {(atomno=@{iNo-4}) and (chain=iChain)
and thisModel}.atomIndex
}
else {
scBondIdxs += {(atomno=@{iNo-1}) and (chain=iChain)
and thisModel}.atomIndex
scBondIdxs += {(atomno=@{iNo-2}) and (chain=iChain)
and thisModel}.atomIndex
}
break
}
}
return scBondIdxs
}
# Drag Side Chain
function drag_sc() {
var iNo = {atomIndex=gSCidx}.atomno
var iChain = {atomIndex=gSCidx}.chain
if ({atomIndex=gSCidx}.group != "PRO") {
var scBondIdxs = collect_sc_rotors( iNo, iChain)
var numChi = scBondIdxs.size / 4
var dist = distance({atomIndex=gSCidx}.xyz, gSCpt)
var scSet = get_sc_set(gSCidx, iChain)
# For all rotor combinations
var dh = array()
for (var i = 0; i < numChi; i++) {
dh += angle({atomIndex=@{scBondIdxs[4+(4*i)]}},
{atomIndex=@{scBondIdxs[3+(4*i)]}},
{atomIndex=@{scBondIdxs[2+(4*i)]}},
{atomIndex=@{scBondIdxs[1+(4*i)]}})
}
for (var i = 0; i < numChi; i++) {
var rot = -120
for (var j = 0; j < 6; j++) {
rot += 60*j
select_add_sc(scBondIdxs[1+(4*i)])
set_dihedral_idx(scBondIdxs[4+(4*i)], scBondIdxs[3+(4*i)],
scBondIdxs[2+(4*i)], scBondIdxs[1+(4*i)], rot)
var newDist = distance({atomIndex=gSCidx}.xyz, gSCpt)
if (gSCcheck) {
var colliders = (within(kCtolerance, false, scSet)
and not connected(scSet) and not {scSet})
if (colliders) {
continue
}
}
# Find the best
if (newDist < dist) {
dist = newDist
for (var k = 0; k < numChi; k++) {
dh[k+1] = angle({atomIndex=@{scBondIdxs[4+(4*k)]}},
{atomIndex=@{scBondIdxs[3+(4*k)]}},
{atomIndex=@{scBondIdxs[2+(4*k)]}},
{atomIndex=@{scBondIdxs[1+(4*k)]}})
}
}
}
}
# Now set the best
for (var i = 0; i < numChi; i++) {
select_add_sc(scBondIdxs[1+(4*i)])
set_dihedral_idx(scBondIdxs[4+(4*i)], scBondIdxs[3+(4*i)],
scBondIdxs[2+(4*i)], scBondIdxs[1+(4*i)], dh[i+1])
}
if (gSCcheck = false) {
plico_minimize( scSet)
}
}
else { # PRO - toggle between puckers up and down
var icd = {(atomno=@{iNo+1}) and (chain=iChain)
and thisModel}.atomIndex
var icb = {(atomno=@{iNo-1}) and (chain=iChain)
and thisModel}.atomIndex
var ica = {(atomno=@{iNo-4}) and (chain=iChain)
and thisModel}.atomIndex
var in = {(atomno=@{iNo-5}) and (chain=iChain)
and thisModel}.atomIndex
select {atomIndex=gSCidx}
if (angle({atomIndex=ica}, {atomIndex=in},
{atomIndex=icd}, {atomIndex=gSCidx}) < -10.0) {
set_dihedral_idx(ica, in, icd, gSCidx, 8.7)
set_angle_idx(in, icd, gSCidx, 110.0)
set_distance_idx(icd, gSCidx, 1.5)
}
else {
set_dihedral_idx(ica, in, icd, gSCidx, -29.5)
set_angle_idx(in, icd, gSCidx, 108.8)
set_distance_idx(icd, gSCidx, 1.5)
}
}
draw gSCcircle CIRCLE {atomIndex=gSCidx} MESH NOFILL
gSCpt = {atomIndex=gSCidx}.xyz
}
# Fix side chain collisions
function fix_sc_collision_2(idx) {
gOk2 = false
var iNo = {atomIndex=idx}.atomno
var iChain = {atomIndex=idx}.chain
var resno = {(atomno=iNo) and (chain=iChain)
and thisModel}.resno
# Get SC terminus
while (resno == {(atomno=iNo) and (chain=iChain)
and thisModel}.resno) {
iNo++
}
iNo--
var sc = array()
var iBno = iNo
while ({(atomno=iBno) and (chain=iChain)
and thisModel}.atomName != "CB") {
sc += {(atomno=iBno) and (chain=iChain)
and thisModel}
iBno--
}
var cbidx = {(atomno=iBno) and (chain=iChain)
and thisModel}.atomIndex
var scBondIdxs = collect_sc_rotors( iNo, iChain)
var numChi = scBondIdxs.size / 4
# For all rotor combinations
for (var i = 0; i < numChi; i++) {
var rot = -120
for (var j = 0; j < 6; j++) {
rot += 60
select_add_sc(scBondIdxs[1+(4*i)])
set_dihedral_idx(scBondIdxs[1+(4*i)], scBondIdxs[2+(4*i)],
scBondIdxs[3+(4*i)], scBondIdxs[4+(4*i)], rot)
# If no collision, exit
var colliders = (within(kCtolerance, false, {sc})
and not {atomIndex=cbidx} and not {sc})
# If it is with water, delete the water
for (var c = 1; c < colliders.size; c++ ) {
if (colliders[c].group = "HOH") {
delete {atomIndex=@{colliders[c].atomIndex}}
colliders = {colliders and not @{colliders[c]}}
}
}
if (colliders.size == 0) {
gOk2 = true
return # Early exit since break 1 appears broken
}
}
}
}
function is_moveable_sc(aIdx) {
var ret = (({atomIndex=aIdx}.group != "PRO")
or ({atomIndex=aIdx}.atomName == "CG"))
switch({atomIndex=aIdx}.atomName) {
case "N":
case "CA":
case "C":
case "CB":
case "O":
case "O4\'":
ret = false
break
}
return ret
}
function is_rotor_avail(i1idx, i2idx) {
var ret = true
if (i1idx > i2idx) { # frozen bonds are kept as lo-hi
var idx = @i1idx
i1idx = @i2idx
i2idx = @idx
}
for (var i = 1; i <= gFreeze.size; i += 2) {
if ((gFreeze[i] == i1idx) and (gFreeze[i+1] == i2idx)) {
ret = false
break
}
}
return ret
}
function xcollect_bb_rotors(nWard) {
var anchorNo = (nWard
? ((gNanchorIdx >= 0) ? {atomIndex=gNanchorIdx}.atomno : gMinNo)
: ((gCanchorIdx >= 0) ? {atomIndex=gCanchorIdx}.atomno : gMaxNo))
var cargoNo = (nWard
? ((gNcargoIdx >= 0) ? {atomIndex=gNcargoIdx}.atomno
: {atomIndex=gCcargoIdx}.atomno)
: {atomIndex=gCcargoIdx}.atomno)
var rotors = array()
if (cargoNo < anchorNo) {
for (var iNo = cargoNo; iNo <= anchorNo; iNo++) {
if ({(atomno=iNo) and (chain=gChain)
and thisModel}.atomName == "CA") {
if (is_rotor_avail(iNo)) {# xxx
if (({(atomno=iNo) and (chain=gChain)
and thisModel}.group != "PRO") and (iNo > cargoNo)) { # phi
rotors += [{(atomno=@{get_cm_no(iNo-1)}) and (chain=gChain)
and thisModel}.atomIndex,
{(atomno=@{iNo-1}) and (chain=gChain)
and thisModel}.atomIndex]
rotors += [{(atomno=@{iNo}) and (chain=gChain)
and thisModel}.atomIndex,
{(atomno=@{iNo+1}) and (chain=gChain)
and thisModel}.atomIndex]
}
if (iNo != (anchorNo-1)) { # psi
rotors += [{(atomno=@{iNo-1}) and (chain=gChain)
and thisModel}.atomIndex,
{(atomno=@{iNo}) and (chain=gChain)
and thisModel}.atomIndex]
rotors += [{(atomno=@{iNo+1}) and (chain=gChain)
and thisModel}.atomIndex,
{(atomno=@{get_np_no(iNo+2)}) and (chain=gChain)
and thisModel}.atomIndex]
}
}
}
}
}
else {
for (var iNo = cargoNo; iNo >= anchorNo; iNo--) {
if ({(atomno=iNo) and (chain=gChain)
and thisModel}.atomName == "CA") {
if (is_rotor_avail(iNo)) {
if ((iNo != (anchorNo-1)) and (iNo < cargoNo)) { # psi
rotors += [{(atomno=@{get_np_no(iNo+2)}) and (chain=gChain)
and thisModel}.atomIndex,
{(atomno=@{iNo+1}) and (chain=gChain)
and thisModel}.atomIndex]
rotors += [{(atomno=@{iNo}) and (chain=gChain)
and thisModel}.atomIndex,
{(atomno=@{iNo-1}) and (chain=gChain)
and thisModel}.atomIndex]
}
if ({(atomno=iNo) and (chain=gChain)
and thisModel}.group != "PRO") { # phi
rotors += [{(atomno=@{iNo+1}) and (chain=gChain)
and thisModel}.atomIndex,
{(atomno=@{iNo}) and (chain=gChain)
and thisModel}.atomIndex]
rotors += [{(atomno=@{iNo-1}) and (chain=gChain)
and thisModel}.atomIndex,
{(atomno=@{get_cm_no(iNo-1)}) and (chain=gChain)
and thisModel}.atomIndex]
}
}
}
}
}
if (nWard) {
gNrotors = rotors
}
else {
gCrotors = rotors
}
}
function collect_bb_rotors(nWard) {
if (nWard) {
gNrotors = array()
var nres = {atomIndex=gNcargoIdx}.resno
var nname = {atomIndex=gNcargoIdx}.atomName
var ares = get_resno_min(gChain)
var aA = get_atom_rcn( ares, gChain, "N")
if (gNanchorIdx >= 0) {
aA = {atomIndex=gNanchorIdx}
}
var aname = aA.atomName
for (var r = nres; r >= ares; r--) {
var aCp = get_atom_rcn( r-1, gChain, "C")
var aN = get_atom_rcn( r, gChain, "N")
var aCa = get_atom_rcn( r, gChain, "CA")
var aC = get_atom_rcn( r, gChain, "C")
var aNn = get_atom_rcn( r+1, gChain, "N")
if (aCp.size < 1) {
aCp = aNn
}
# psi
if (((r < nres) and (r > ares))
or ((r == nres) and (nname == "C"))
or ((r == ares) and (aname != "C"))) {
if (is_rotor_avail(aCa.atomIndex, aC.atomIndex)) {
gNrotors += aNn.atomIndex
gNrotors += aC.atomIndex
gNrotors += aCa.atomIndex
gNrotors += aN.atomIndex
}
}
# phi
if (aCa.group != "PRO") {
if (((r <= nres) and (r > ares))
or ((r == ares) and (aname == "N"))) {
if (is_rotor_avail(aCa.atomIndex, aN.atomIndex)) {
gNrotors += aC.atomIndex
gNrotors += aCa.atomIndex
gNrotors += aN.atomIndex
gNrotors += aCp.atomIndex
}
}
}
} # endfor
}
else {
gCrotors = array()
var cres = {atomIndex=gCcargoIdx}.resno
var cname = {atomIndex=gCcargoIdx}.atomName
var ares = get_resno_max(gChain)
var aA = get_atom_rcn( ares, gChain, "C")
if (gCanchorIdx >= 0) {
aA = {atomIndex=gCanchorIdx}
}
var aname = aA.atomName
for (var r = cres; r <= ares; r++) {
var aCp = get_atom_rcn( r-1, gChain, "C")
var aN = get_atom_rcn( r, gChain, "N")
var aCa = get_atom_rcn( r, gChain, "CA")
var aC = get_atom_rcn( r, gChain, "C")
var aNn = get_atom_rcn( r+1, gChain, "N")
if (aNn.size < 1) {
aNn = aCp
}
# phi
if (aCa.group != "PRO") {
if (((r > cres) and (r < ares))
or ((r == cres) and (aname == "N"))
or ((r == ares) and (aname != "N"))) {
if (is_rotor_avail(aN.atomIndex, aCa.atomIndex)) {
gCrotors += aCp.atomIndex
gCrotors += aN.atomIndex
gCrotors += aCa.atomIndex
gCrotors += aC.atomIndex
}
}
}
# psi
if (((r >= cres) and (r < ares))
or ((r == cres) and (aname != "C"))
or ((r == ares) and (aname == "C"))) {
if (is_rotor_avail(aCa.atomIndex, aC.atomIndex)) {
gCrotors += aN.atomIndex
gCrotors += aCa.atomIndex
gCrotors += aC.atomIndex
gCrotors += aNn.atomIndex
}
}
} # endfor
}
}
function collect_rotors() {
collect_bb_rotors(false)
collect_bb_rotors(true)
}
function tug_sc(pt) {
# If destination atom defined
if (gDestAtomIdx >= 0) {
var v = {atomIndex=gDestAtomIdx}.xyz - {atomIndex=gSCidx}.xyz
if (abs(angle({atomIndex=gDestAtomIdx}.xyz, {0 0 0}, pt)) < 90) {
pt = -v/20.0
}
else {
pt = v/20.0
}
}
gSCpt += pt
draw arrow {atomIndex=gSCidx} @gSCpt
}
function set_colors() {
select (thisModel)
color {selected} @gScheme
color {atomIndex=g1pivotIdx} green
color {atomIndex=g2pivotIdx} green
color @gCargoSet @gAltScheme
color {gCargoSet and oxygen} pink
select {(atomIndex=gCcargoIdx) or (atomIndex=gNcargoIdx)
or (atomIndex=gCanchorIdx) or (atomIndex=gNanchorIdx)}
halo on
select {atomIndex=gDestAtomIdx}
star on
select none
}
function clear_atom_idxs() {
gCcargoIdx = -1
gNcargoIdx = -1
gCanchorIdx = -1
gNanchorIdx = -1
g1pivotIdx = -1
g2pivotIdx = -1
g1dynamicIdx = -1
g2dynamicIdx = -1
gDestAtomIdx = -1
gSCidx = -1
}
function timed_out (s) {
timeout ID"tug" OFF
refresh
if (prompt(format("%s - Undo?", s), "Yes|No", true) == "Yes") {
gBusy = false
restore state gState
connect
select gCargoSet
set bondPicking true
refresh
for (var i = 1; i <= gFreeze.size; i+=2) {
select {atomIndex=@{gFreeze[i]}} or {atomIndex=@{gFreeze[i+1]}}
color bonds lightblue
}
background ECHO yellow
echo @gEcho
select all
quit
}
}
function record_drag() {
var ls = format("select %s;", {selected})
ls += format("gCanchorIdx = %d;", gCanchorIdx)
ls += format("gCanchorNo = %d;", gCanchorNo)
ls += format("gNanchorIdx = %d;", gNanchorIdx)
ls += format("gNanchorNo = %d;", gNanchorNo)
ls += format("gCcargoIdx = %d;", gCcargoIdx)
ls += format("gNcargoIdx = %d;", gNcargoIdx)
ls += format("gCcargoNo = %d;", gCcargoNo)
ls += format("gNcargoNo = %d;", gNcargoNo)
ls += format("gDestAtomIdx = %d;", gDestAtomIdx)
ls += format("g1pivotIdx = %d;", g1pivotIdx)
ls += format("g2pivotIdx = %d;", g2pivotIdx)
ls += format("gOkCollide = %s;", gOkCollide)
ls += format("gChain = \"%s\";", gChain)
ls += format("gMinNo = %d;", gMinNo)
ls += format("gMaxNo = %d;", gMaxNo)
ls += format("gCargoSet = %s;", gCargoSet)
ls += format("gSCidx = %d;", gSCidx)
ls += format("gSCcircle = %d;", gSCcircle)
ls += format("gSCpt = %s;", gSCpt)
ls += "collect_rotors();"
ls += "tug_drag_done_mb();"
plico_record(ls)
}
# Pick call-back for freeze
function tug_pick_cb() {
if (_pickInfo[3][6] == "bond") {
var sel = {selected}
var i = _pickInfo.find(":")
var iChain = _pickInfo[i+1]
i = _pickInfo.find("#")
var a1no = 0 + _pickInfo[i+1][i+3]
var j = _pickInfo[i+1][9999].find("#")
var a2no = 0 + _pickInfo[i+j+1][i+j+3]
var i1idx = {(atomno=a1no) and (chain=iChain)
and thisModel}.atomIndex
var i2idx = {(atomno=a2no) and (chain=iChain)
and thisModel}.atomIndex
if (({atomIndex=i1idx}.atomName == "CA")
or ({atomIndex=i2idx}.atomName == "CA")) {
if (({atomIndex=i1idx}.atomName != "CB")
and ({atomIndex=i2idx}.atomName != "CB")) {
if (i1idx > i2idx) {
var idx = 0 + i1idx
i1idx = 0 + i2idx
i2idx = 0 + idx
}
select {atomIndex=i1idx} or {atomIndex=i2idx}
for (i = 1; i <= gFreeze.size; i += 2) {
if ((gFreeze[i] == i1idx) and (gFreeze[i+1] == i2idx)) {
if (i > 1) {
if (gFreeze.size = (i+1)) {
gFreeze = gFreeze[1][i-1]
}
else {
gFreeze = gFreeze[1][i-1] + gFreeze[i+2][0]
}
}
else {
gFreeze = gFreeze[i+2][0]
}
color bonds NONE
i = 0
break
}
}
if (i > gFreeze.size) {
gFreeze += i1idx
gFreeze += i2idx
color bonds lightblue
}
}
}
select {sel}
}
}
# Bound to LEFT-UP by tug_enable_drag
function tug_drag_done_mb() {
if (not gBusy) {
if (gPlicoRecord != "") {
record_drag()
}
# Move by rotation on rotor sets, smallest first
gBusy = true
background ECHO pink
refresh
# If side chain mode
if (gSCidx >= 0) {
drag_sc()
}
# Else
else if (not gTow) {
gOK = true
timeout ID"tug" 20.0 "timed_out(\"Tug timed out\")"
if ((gCrotors.size < gNrotors.size) or (gNanchorIdx < 0)) {
if (gCrotors.size > 4) {
tug_track_c()
}
if (gOK and (gNrotors.size > 4)) {
tug_track_n()
}
}
else {
if (gNrotors.size > 4) {
tug_track_n()
}
if (gOK and (gCrotors.size > 4)) {
tug_track_c()
}
}
timeout ID"tug" OFF
# If anchor angles acute, fail
if (gOK == true) {
if (gCanchorIdx >= 0) {
var ic = get_cward_bb_idx(gCanchorIdx, gChain)
var in = get_nward_bb_idx(gCanchorIdx, gChain)
if ((ic >= 0) and
angle({atomIndex=ic}, {atomIndex=gCanchorIdx}, {atomIndex=in})
< 100.0) {
gOK = false
}
}
if (gNanchorIdx >= 0) {
var ic = get_cward_bb_idx(gNanchorIdx, gChain)
var in = get_nward_bb_idx(gNanchorIdx, gChain)
if ((in >= 0) and
angle({atomIndex=ic}, {atomIndex=gNanchorIdx}, {atomIndex=in})
< 100.0) {
gOK = false
}
}
}
# If too far
if (not gOK) {
timed_out("TUG TOO FAR!")
}
# Else OK
else {
var idx = {
(atomno=@{{(chain=gChain) and thisModel}.atomno.min})
and (chain=gChain) and thisModel}.atomIndex
var ihc = 0
for (ihc = 0; ihc < 10; ihc++) {
select ((atomno >= gNanchorNo) and (atomno <= gCanchorNo)
and (chain = gChain) and thisModel)
handle_collisions( idx)
if (count_collisions(({})).size == 0) {
break
}
}
if (ihc == 10) {
timed_out("Unable to handle all collisions!")
}
}
}
select {gCargoSet}
gBusy = false
background ECHO yellow
set bondPicking true
refresh
}
}
# Bound to ALT-SHIFT-LEFT-DRAG by tug_enable_drag
function tug_drag_2_mb() {
tug_drag_mb(true)
}
# Bound to ALT-LEFT-DRAG by tug_enable_drag
function tug_drag_mb(alt) {
if (not gBusy) {
gBusy = true
var dx = (40.0 * (_mouseX - gMouseX))/_width
var dy = (40.0 * (_mouseY - gMouseY))/_height
var q = quaternion()
var ptd = {@dx @dy 0}
var pt = (!q)%ptd
var caxis = {0 0 0}
if (distance(pt, {0 0 0}) > 0.004) {
# If sidechain mode
if (gSCidx >= 0) {
if ({atomIndex=gSCidx}.atomName == "O") {
if ({atomIndex=gSCidx}.group != "PRO") {
var dir = ((abs(dx) > abs(dy))
? ((dx < 0) ? 10 : -10)
: ((dy < 0) ? 1 : -1))
counter_rotate(gSCidx, dir, not alt)
}
}
else {
gSCcheck = not alt
tug_sc(pt)
}
}
# Else
else {
# If new drag
if (gNewDrag) {
gNewDrag = false
save state gState
}
# If destination atom defined
if (gDestAtomIdx >= 0) {
var v = {atomIndex=gDestAtomIdx}.xyz - {selected}.xyz
if (abs(angle({atomIndex=gDestAtomIdx}.xyz, {0 0 0}, pt)) < 90) {
pt = -v/20.0
}
else {
pt = v/20.0
}
}
# Move the cargo
select {gCargoSet}
# If pivots defined, rotate it
if (g1pivotIdx >= 0) {
# If two pivots
if (g2pivotIdx >= 0) {
caxis = {atomIndex=g2pivotIdx}
}
# Else
else {
caxis = cross(pt, {0 0 0}) + {atomIndex=g1pivotIdx}.xyz
}
var dir = ((abs(dx) > abs(dy))
? ((dx < 0) ? 2 : -2)
: ((dy < 0) ? 2 : -2))
rotate_selected_record(g1pivotIdx, caxis, dir)
}
# Else translate it
else {
translate_selected_record(pt)
}
# If collisions
var cNotSels = (within(kCtolerance, false, {selected})
and not {gMovingSet})
if ((cNotSels) and (not alt)) {
gOk2 = true
for (var i = 1; i <= cNotSels.size; i++) {
# If net collision vector same as move vector
var cSels = (within(kCtolerance, false, cNotSels[i]) and {selected})
for (var j = 1; j <= cSels.size; j++) {
var v1 = cNotSels[i].xyz - cSels[j].xyz
if (abs(angle(v1, {0 0 0}, pt)) < 90) {
# If tow mode
if (gTow) {
# Make a dynamic pivot
if (g1pivotIdx < 0) {
g1pivotIdx = cSels[j].atomIndex
g1dynamicIdx = cNotSels[i].atomIndex
color {atomIndex=g1pivotIdx} lightgreen
set_distance_idx(cNotSels[i].atomIndex,
cSels[j].atomIndex,
kCtolerance + kDtolerance)
}
else if (g2pivotIdx < 0) {
g2pivotIdx = cSels[j].atomIndex
g2dynamicIdx = cNotSels[i].atomIndex
color {atomIndex=g2pivotIdx} lightgreen
set_distance_idx(cNotSels[i].atomIndex,
cSels[j].atomIndex,
kCtolerance + kDtolerance)
}
else {
gOk2 = false
}
}
else {
# Try to resolve
select @{cSels[j]}
var idx = {(atomno=@{{(chain=gChain)
and thisModel}.atomno.min})
and (chain=gChain) and thisModel}.atomIndex
handle_collisions( idx)
}
}
} # endfor
if (not gOk2) {
break
}
} # endfor
# If unable
if (not gOk2) {
# Back off
background ECHO pink
delay 1
if (g1pivotIdx >= 0) {
rotate_selected_record(g1pivotIdx, caxis, -a)
}
else {
translate_selected_record(-pt)
}
background ECHO yellow
set bondPicking true
}
}
}
# If dynamic pivots
if (g1dynamicIdx >= 0) {
var v1 = {atomIndex=g1dynamicIdx}.xyz - {atomIndex=g1pivotIdx}.xyz
if (abs(angle(v1, {0 0 0}, pt)) > 90) {
color {atomIndex=g1pivotIdx} @gAltScheme
g1pivotIdx = -1
g1dynamicIdx = -1
}
}
if (g2dynamicIdx >= 0) {
var v1 = {atomIndex=g2dynamicIdx}.xyz - {atomIndex=g2pivotIdx}.xyz
if (abs(angle(v1, {0 0 0}, pt)) > 90) {
color {atomIndex=g2pivotIdx} @gAltScheme
g2pivotIdx = -1
g2dynamicIdx = -1
}
}
gMouseX = _mouseX
gMouseY = _mouseY
}
select {gCargoSet}
gBusy = false
}
}
# Bound to ALT-LEFT-DOWN by tug_enable_drag
function tug_mark_mb() {
gMouseX = _mouseX
gMouseY = _mouseY
gNewDrag = true
}
# Called by tug_cargo_mb
function tug_enable_drag() {
gEcho = "__________TUG__________|ALT-CLICK=mark block|SHIFT-CLICK=anchors" +
"|ALT-CTRL-CLICK=pivots|ALT-SHIFT-CLICK=dest atom|ALT-DRAG=move" +
"|ALT-SHIFT-DRAG=alt move|CLICK bond=freeze|ALT-DOUBLE-CLICK=undo" +
"|SHIFT-DOUBLE-CLICK=exit"
echo @gEcho
# Allow atoms to be dragged
bind "ALT-LEFT-DOWN" "tug_mark_mb";
bind "ALT-LEFT-UP" "tug_drag_done_mb";
bind "ALT-SHIFT-LEFT-DOWN" "tug_mark_mb";
bind "ALT-LEFT-DRAG" "tug_drag_mb";
bind "ALT-SHIFT-LEFT-DRAG" "tug_drag_2_mb";
unbind "SHIFT-LEFT-CLICK"
bind "SHIFT-LEFT-CLICK" "_pickAtom";
bind "SHIFT-LEFT-CLICK" "+:tug_anchor_mb";
bind "ALT-CTRL-LEFT-CLICK" "_pickAtom";
bind "ALT-CTRL-LEFT-CLICK" "+:tug_pivot_mb";
bind "ALT-SHIFT-LEFT-CLICK" "_pickAtom";
bind "ALT-SHIFT-LEFT-CLICK" "+:tug_dest_atom_mb";
}
# Bound to SHIFT-LEFT-CLICK by tug_cargo_mb
function tug_anchor_mb() {
if ({atomIndex=_atomPicked}.chain == gChain) {
var aPidx = get_sc_bb_idx( _atomPicked, gChain)
var pno = {atomIndex=aPidx}.atomno
if (pno > {atomIndex=gCcargoIdx}.atomno) {
select {atomIndex=gCanchorIdx}
halo off
if (gCanchorIdx == aPidx) {
gCanchorIdx = -1
gCanchorNo = gMaxNo + 1
}
else {
gCanchorIdx = aPidx
gCanchorNo = {atomIndex=gCanchorIdx}.atomno
select {atomIndex=gCanchorIdx}
halo on
}
collect_bb_rotors(false)
}
else if (pno < {atomIndex=gNcargoIdx}.atomno) {
select {atomIndex=gNanchorIdx}
halo off
if (gNanchorIdx == aPidx) {
gNanchorIdx = -1
gNanchorNo = gMinNo - 1
}
else {
gNanchorIdx = aPidx
gNanchorNo = {atomIndex=gNanchorIdx}.atomno
select {atomIndex=gNanchorIdx}
halo on
}
collect_bb_rotors(true)
}
else {
tow_cargo_mb()
}
# Get moving atoms set
gMovingSet = {((atomno < gCanchorNo) and (atomno > gNanchorNo)
and (chain=gChain) and thisModel)}
}
select {gCargoSet}
}
# Bound to ALT-SHIFT-LEFT-CLICK by tug_cargo_mb
function tug_dest_atom_mb() {
var aOk = true
if ({atomIndex=_atomPicked}.chain == gChain) {
var pno = {atomIndex=_atomPicked}.atomno
if ((pno <= {atomIndex=gCcargoIdx}.atomno)
and (pno >= {atomIndex=gNcargoIdx}.atomno)) {
aOk = false
}
}
if (aOk) {
select {atomIndex=gDestAtomIdx}
star off
if (gDestAtomIdx == _atomPicked) {
gDestAtomIdx = -1
}
else {
gDestAtomIdx = _atomPicked
select {atomIndex=gDestAtomIdx}
star on
}
select {gCargoSet}
}
}
# Bound to CTRL-LEFT-CLICK by tug_cargo_mb
function tug_pivot_mb() {
if (g1pivotIdx == _atomPicked) {
color {atomIndex=g1pivotIdx} @gScheme
if (g2pivotIdx >= 0) {
g1pivotIdx = g2pivotIdx
g2pivotIdx = -1
g2dynamicIdx = -1
}
else {
g1pivotIdx = -1
g1dynamicIdx = -1
}
}
else if (g2pivotIdx == _atomPicked) {
color {atomIndex=g2pivotIdx} @gScheme
g2pivotIdx = -1
g2dynamicIdx = -1
}
else if (g1pivotIdx >= 0) {
if (g2pivotIdx >= 0) {
color {atomIndex=g2pivotIdx} @gScheme
}
g2pivotIdx = _atomPicked
g2dynamicIdx = -1
color {atomIndex=g2pivotIdx} green
}
else {
g1pivotIdx = _atomPicked
g1dynamicIdx = -1
color {atomIndex=g1pivotIdx} green
}
select {gCargoSet}
}
# Bound to SHIFT-LEFT-CLICK by plico_tug
function tow_cargo_mb() {
gTow = true
gChain = {atomIndex=_atomPicked}.chain
gMinNo = {(chain=gChain) and thisModel}.atomno.min
gMaxNo = {(chain=gChain) and thisModel}.atomno.max
gCcargoIdx = -1
gNcargoIdx = -1
gCanchorIdx = -1
gCanchorNo = gMaxNo + 1
gNanchorIdx = -1
gNanchorNo = gMinNo - 1
# Highlight cargo cluster
select {(chain=gChain) and thisModel}
gCargoSet = {selected}
gMovingSet = {selected}
set_colors()
# Enable dragging
tug_enable_drag()
select {gCargoSet}
halo off
var es = gEcho.replace("anchors","mark chain")
echo @es
unbind "SHIFT-LEFT-CLICK"
bind "SHIFT-LEFT-CLICK" "_pickAtom";
bind "SHIFT-LEFT-CLICK" "+:tow_cargo_mb";
}
# Bound to ALT-LEFT-CLICK by plico_tug or called by plicotoab.toabCargoMB
function tug_cargo_mb() {
# If O or movable side chain atom picked
if ((({atomIndex=_atomPicked}.atomName = "O")
and ({atomIndex=_atomPicked}.group != "PRO"))
or (is_moveable_sc( _atomPicked))) {
if (gSCidx >= 0) {
draw gSCcircle DELETE
}
if (gSCidx == _atomPicked) {
gSCidx = -1
}
else {
gSCidx = _atomPicked
gSCpt = {atomIndex=gSCidx}.xyz
draw gSCcircle CIRCLE {atomIndex=gSCidx} MESH NOFILL
}
}
else {
if ({atomIndex=_atomPicked}.chain != gChain) {
if (gTow) {
select {(chain=gChain) and thisModel}
color {selected} @gScheme
}
gChain = {atomIndex=_atomPicked}.chain
select ({atomIndex=gCcargoIdx} or {atomIndex=gNcargoIdx}
or {atomIndex=gCanchorIdx} or {atomIndex=gNanchorIdx})
halo off
gCcargoIdx = -1
gNcargoIdx = -1
gCanchorIdx = -1
gNanchorIdx = -1
}
gTow = false
gMinNo = {(chain=gChain) and thisModel}.atomno.min
gMaxNo = {(chain=gChain) and thisModel}.atomno.max
if (gNanchorIdx < 0) {
gNanchorNo = gMinNo - 1
}
if (gCanchorIdx < 0) {
gCanchorNo = gMaxNo + 1
}
var aPidx = get_sc_bb_idx( _atomPicked, gChain)
gSCidx = -1
draw gSCcircle DELETE
# If existing cWard cargo picked
if (gCcargoIdx == aPidx) {
# Clear the highlight
select {atomIndex=gCcargoIdx}
halo off
# If nWard cargo exists, mark it as the cWard cargo
if (gNcargoIdx != gCcargoIdx) {
gCcargoIdx = get_cp_idx(gNcargoIdx)
gCcargoNo = {atomIndex=gCcargoIdx}.atomno
}
else {
gCcargoIdx = -1
gNcargoIdx = -1
}
}
else if (gNcargoIdx == aPidx) {
select {atomIndex=gNcargoIdx}
halo off
gNcargoIdx = get_nm_idx(gCcargoIdx)
gNcargoNo = {atomIndex=gNcargoIdx}.atomno
}
else if (gCcargoIdx >= 0) {
var no = {atomIndex=aPidx}.atomno
# If pick is nWard of it
if (no < {atomIndex=gCcargoIdx}.atomno) {
# If exists, clear its highlight
if (gNcargoIdx != gCcargoIdx) {
select {atomIndex=gNcargoIdx}
halo off
}
# Set new nWard cargo and highlight it
gNcargoIdx = get_nm_idx(aPidx)
gNcargoNo = {atomIndex=gNcargoIdx}.atomno
}
# Else cWard
else {
# Clear its old highlight
select {atomIndex=gCcargoIdx}
if (gNcargoIdx != gCcargoIdx) {
halo off
}
# Set new cWard cargo and highlight
gCcargoIdx = get_cp_idx(aPidx)
gCcargoNo = {atomIndex=gCcargoIdx}.atomno
}
}
# Else no cWard cargo
else {
# Set new cWard cargo and highlight
gCcargoIdx = get_cp_idx(aPidx)
gCcargoNo = {atomIndex=gCcargoIdx}.atomno
gNcargoIdx = get_nm_idx(gCcargoIdx)
gNcargoNo = {atomIndex=gNcargoIdx}.atomno
}
# If any anchor now inside cargo cluster, kill it
if ({atomIndex=gCanchorIdx}.atomno <= {atomIndex=gCcargoIdx}.atomno) {
gCanchorIdx = -1
gCanchorNo = gMaxNo + 1
}
if ({atomIndex=gNanchorIdx}.atomno >= {atomIndex=gNcargoIdx}.atomno) {
gNanchorIdx = -1
gNanchorNo = gMinNo - 1
}
# Highlight cargo cluster
select_nward_idx(gCcargoIdx, gNcargoIdx)
gCargoSet = {selected}
set_colors()
# Collect the rotor sets
collect_rotors()
# Get moving atoms set
gMovingSet = {((atomno < gCanchorNo) and (atomno > gNanchorNo)
and (chain=gChain) and thisModel)}
}
# Enable dragging
if (gToab) {
to_ab_enable_drag()
}
else {
tug_enable_drag()
}
select {gCargoSet}
}
function tug_undo_mb() {
if (prompt("Undo", "Yes|No", true) == "Yes") {
restore state gState
}
}
# Top level of Tug
function plico_tug() {
# 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 = "TUG"
plico_prelim(true, true)
gBondPicking = bondPicking
set bondPicking true
set PickCallback "jmolscript:tug_pick_cb"
gEcho = ("_________TUG_________|ALT-CLICK=mark block|SHIFT-CLICK=mark chain" +
"|CLICK bond=freeze|ALT-DOUBLE-CLICK=undo|SHIFT-DOUBLE-CLICK=exit")
echo @gEcho
gCrotors = array()
gNrotors = array()
clear_atom_idxs()
gToab = false
bind "ALT-LEFT-CLICK" "_pickAtom";
bind "ALT-LEFT-CLICK" "+:tug_cargo_mb";
bind "SHIFT-LEFT-CLICK" "_pickAtom";
bind "SHIFT-LEFT-CLICK" "+:tow_cargo_mb";
bind "ALT-LEFT-DOUBLE" "tug_undo_mb";
bind "SHIFT-DOUBLE" "tug_exit(true)";
bind "LEFT-CLICK" "+:plico_menu_toggle";
}
# Bound to DOUBLE by plico_tug
function tug_exit() {
if (plico_exit()) {
set bondPicking gBondPicking
set PickCallback NONE
select all
color bonds none
reset kTug
reset gCanchorIdx
reset gCanchorNo
reset gPlico
reset gNanchorIdx
reset gNanchorNo
reset gCcargoIdx
reset gNcargoIdx
reset gCcargoNo
reset gNcargoNo
reset gDestAtomIdx
reset g1pivotIdx
reset g2pivotIdx
reset gSelSaves
reset gCrotors
reset gNrotors
reset gOkCollide
reset gChain
reset gMinNo
reset gMaxNo
reset gCargoSet
reset gMovingSet
reset gSCidx
reset gSCcircle
reset gSCpt
reset gTargetPt
reset gNewDrag
reset gTow
reset g1dynamicIdx
reset g2dynamicIdx
reset gSCcheck
reset gBondPicking
reset gFreeze
reset gToab
reset function "get_cp_idx"
reset function "get_cm_no"
reset function "get_nm_idx"
reset function "get_np_no"
reset function "get_cb_idx"
reset function "get_o_idx"
reset function "get_nward_bb_idx"
reset function "get_cward_bb_idx"
reset function "get_sc_set"
reset function "get_sc_bb_idx"
reset function "is_bb_idx"
reset function "is_sc_idx"
reset function "select_add_sc"
reset function "handle_collisions"
reset function "tug_track_idx"
reset function "do_counter_rotate"
reset function "counter_rotate"
reset function "counter_rotate_2"
reset function "repair_proline"
reset function "repair_sc"
reset function "tug_track_c"
reset function "tug_track_n"
reset function "translate_selected_record"
reset function "rotate_selected_record"
reset function "collect_sc_rotors"
reset function "drag_sc"
reset function "fix_sc_collision_2"
reset function "is_moveable_sc"
reset function "is_rotor_avail"
reset function "xcollect_bb_rotors"
reset function "collect_bb_rotors"
reset function "collect_rotors"
reset function "tug_sc"
reset function "set_colors"
reset function "clear_atom_idxs"
reset function "timed_out"
reset function "record_drag"
reset function "tug_pick_cb"
reset function "tug_drag_done_mb"
reset function "tug_drag_2_mb"
reset function "tug_drag_mb"
reset function "tug_mark_mb"
reset function "tug_anchor_mb"
reset function "tug_enable_drag"
reset function "tug_dest_atom_mb"
reset function "tug_pivot_mb"
reset function "tow_cargo_mb"
reset function "tug_cargo_mb"
reset function "tug_undo_mb"
reset function "plico_tug"
}
}
# End of TUG.SPT