Difference between revisions of "User:Remig/plico/tug"
< User:Remig | plico
Jump to navigation
Jump to search
(Fix side-chain mode problems with multiple chains) |
(Avoid "axis," a newly reserved word) |
||
(14 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 | + | 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 by mouse actions | + | # 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++ | |
− | |||
− | |||
− | |||
− | function | ||
− | var | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | 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)}.atomName != " | + | while ((iNo > 0) and ({(atomno=iNo) and (chain=gChain) |
+ | and thisModel}.atomName != "C")) { | ||
iNo-- | iNo-- | ||
} | } | ||
Line 101: | Line 67: | ||
} | } | ||
− | function | + | function get_nm_idx (idx) { |
− | var no = {atomIndex=idx | + | var no = {atomIndex=idx}.atomno |
− | + | while ((no > 0) and ({(atomno=no) and (chain=gChain) | |
− | + | and thisModel}.atomName != "N")) { | |
− | + | no-- | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | while ( | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | + | return ({(atomno=no) and (chain=gChain) and thisModel}.atomIndex) | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | return ({(atomno=no) and (chain=gChain)}.atomIndex) | ||
} | } | ||
− | function | + | function get_np_no (iNo) { |
− | while ((iNo < gMaxNo) and ({(atomno=iNo) and (chain=gChain)}.atomName != "N")) { | + | while ((iNo < gMaxNo) and ({(atomno=iNo) and (chain=gChain) |
+ | and thisModel}.atomName != "N")) { | ||
iNo++ | iNo++ | ||
} | } | ||
Line 166: | Line 84: | ||
} | } | ||
− | function | + | function get_cb_idx (BBidx) { |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
var no = {atomIndex=BBidx}.atomno | var no = {atomIndex=BBidx}.atomno | ||
var i = 1 | var i = 1 | ||
for (; i < 5; i++) { | for (; i < 5; i++) { | ||
− | if ({(atomno=@{no+i}) and (chain=gChain)}.atomName == "CB") { | + | if ({(atomno=@{no+i}) and (chain=gChain) |
+ | and thisModel}.atomName == "CB") { | ||
break | break | ||
} | } | ||
} | } | ||
− | return {(atomno=@{no+i}) and (chain=gChain)}.atomIndex | + | return {(atomno=@{no+i}) and (chain=gChain) and thisModel}.atomIndex |
} | } | ||
− | function | + | function get_o_idx (BBidx) { |
var no = {atomIndex=BBidx}.atomno | var no = {atomIndex=BBidx}.atomno | ||
var i = 1 | var i = 1 | ||
for (; i < 4; i++) { | for (; i < 4; i++) { | ||
− | if ({(atomno=@{no+i}) and (chain=gChain)}.atomName == "O") { | + | if ({(atomno=@{no+i}) and (chain=gChain) |
+ | and thisModel}.atomName == "O") { | ||
break | break | ||
} | } | ||
} | } | ||
− | return {(atomno=@{no+i}) and (chain=gChain)}.atomIndex | + | return {(atomno=@{no+i}) and (chain=gChain) and thisModel}.atomIndex |
} | } | ||
− | function | + | function get_nward_bb_idx (idx, iChain) { |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
var no = {atomIndex=idx}.atomno - 1 | 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 | + | 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 | var no = {atomIndex=idx}.atomno + 1 | ||
− | no = | + | for (; no < gMaxNo; no++) { |
− | return ((no >= 0) ? ({(atomno=no) and (chain=iChain)}.atomIndex) : -1) | + | 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_sc_set (scIdx, iChain) { |
var scSet = ({}) | var scSet = ({}) | ||
− | var idx = | + | var idx = get_sc_bb_idx(scIdx, iChain) |
var iNo = {atomIndex=idx}.atomno + 3 | var iNo = {atomIndex=idx}.atomno + 3 | ||
− | + | ||
for (var i = 1; i < 20; i++) { | for (var i = 1; i < 20; i++) { | ||
− | idx = {(atomno=@{iNo+i}) and (chain=iChain)}.atomIndex | + | idx = {(atomno=@{iNo+i}) and (chain=iChain) |
− | if ( | + | and thisModel}.atomIndex |
+ | if (is_bb_idx(idx)) { | ||
break | break | ||
} | } | ||
Line 241: | Line 150: | ||
} | } | ||
− | function | + | function get_sc_bb_idx (idx, iChain) { |
var no = {atomIndex=idx}.atomno | var no = {atomIndex=idx}.atomno | ||
for (; no > 0; no--) { | for (; no > 0; no--) { | ||
− | if ({(atomno=no) and (chain=iChain)}.atomName == "CA") { | + | if ({(atomno=no) and (chain=iChain) |
+ | and thisModel}.atomName == "CA") { | ||
break | break | ||
} | } | ||
− | else if ({(atomno=no) and (chain=iChain)}.atomName == "C") { | + | else if ({(atomno=no) and (chain=iChain) |
+ | and thisModel}.atomName == "C") { | ||
break | break | ||
} | } | ||
− | else if ({(atomno=no) and (chain=iChain)}.atomName == "N") { | + | else if ({(atomno=no) and (chain=iChain) |
+ | and thisModel}.atomName == "N") { | ||
break | break | ||
} | } | ||
− | else if ({(atomno=no) and (chain=iChain)}.atomName == "CB") { | + | else if ({(atomno=no) and (chain=iChain) |
+ | and thisModel}.atomName == "CB") { | ||
no -= 3 | no -= 3 | ||
break | break | ||
} | } | ||
} | } | ||
− | return {(atomno=no) and (chain=iChain)}.atomIndex | + | return {(atomno=no) and (chain=iChain) and thisModel}.atomIndex |
} | } | ||
− | function | + | function is_bb_idx(aIdx) { |
− | var ret = | + | var ret = false |
switch({atomIndex=aIdx}.atomName) { | switch({atomIndex=aIdx}.atomName) { | ||
case "N": | case "N": | ||
case "CA": | case "CA": | ||
case "C": | case "C": | ||
− | ret = | + | ret = true |
break | break | ||
} | } | ||
Line 273: | Line 186: | ||
} | } | ||
− | function | + | function is_sc_idx(aIdx) { |
− | var ret = | + | var ret = false |
− | if ( | + | if (not is_bb_idx(aIDx)) { |
− | ret = | + | ret = true |
switch({atomIndex=aIdx}.atomName) { | switch({atomIndex=aIdx}.atomName) { | ||
case "O": | case "O": | ||
case "CB": | case "CB": | ||
− | ret = | + | ret = false |
break | break | ||
} | } | ||
Line 289: | Line 202: | ||
} | } | ||
− | function | + | function select_add_sc(fromIdx) { |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
var iNo = {atomIndex=fromIdx}.atomno | var iNo = {atomIndex=fromIdx}.atomno | ||
var iChain = {atomIndex=fromIdx}.chain | var iChain = {atomIndex=fromIdx}.chain | ||
select none | select none | ||
− | while ({(atomno=iNo) and (chain=iChain)} | + | while ({(atomno=iNo) and (chain=iChain) |
− | {(atomno=iNo) and (chain=iChain)}.selected = | + | and thisModel and sidechain}) { |
+ | var a = {(atomno=iNo) and (chain=iChain)and thisModel} | ||
+ | a.selected = true | ||
iNo++ | iNo++ | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
} | } | ||
− | + | # Resolve collisions on selection | |
− | + | function handle_collisions( targetIdx) { | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | # Resolve collisions | ||
− | function | ||
# For all selected atoms | # For all selected atoms | ||
for (var iNo = {selected}.min.atomno; iNo <= {selected}.max.atomno; iNo++) { | for (var iNo = {selected}.min.atomno; iNo <= {selected}.max.atomno; iNo++) { | ||
− | var idx = {(atomno=iNo) and (chain=gchain)}.atomIndex | + | var idx = {(atomno=iNo) and (chain=gchain) |
+ | and thisModel}.atomIndex | ||
if ({atomindex=idx}.selected) { | if ({atomindex=idx}.selected) { | ||
# Collect local colliders | # Collect local colliders | ||
− | var lcAtoms = (within(kCtolerance, | + | var lcAtoms = (within(kCtolerance, false, {atomIndex=idx}) |
and not {atomIndex=idx} | and not {atomIndex=idx} | ||
and not {gOkCollide} | and not {gOkCollide} | ||
and not connected({atomIndex=idx})) | and not connected({atomIndex=idx})) | ||
− | if (lcAtoms | + | if (lcAtoms) { |
− | |||
# Ignore kinked BB | # Ignore kinked BB | ||
− | if ( | + | 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 { | ||
} | } | ||
Line 460: | Line 250: | ||
# else if it is with side chain not proline, fix it | # else if it is with side chain not proline, fix it | ||
− | else if ( | + | else if (is_sc_idx(cidx) and ({atomIndex=cidx}.group != "PRO")) { |
− | + | fix_sc_collision_2(cidx) | |
− | + | ||
− | |||
# If not fixed, exit fail | # If not fixed, exit fail | ||
− | if (gOk2 | + | if (not gOk2) { |
return # early exit (break n jmol bug) | return # early exit (break n jmol bug) | ||
} | } | ||
Line 471: | Line 260: | ||
# else if it is itself a side chain not proline, fix it | # else if it is itself a side chain not proline, fix it | ||
− | else if ( | + | else if (is_sc_idx(idx) and ({atomIndex=idx}.group != "PRO")) { |
− | + | fix_sc_collision_2(idx) | |
− | |||
# If not fixed, exit fail | # If not fixed, exit fail | ||
− | if (gOk2 | + | if (not gOk2) { |
return # early exit (break n jmol bug) | return # early exit (break n jmol bug) | ||
} | } | ||
Line 483: | Line 271: | ||
# Else if it is with O, counter-rotate | # Else if it is with O, counter-rotate | ||
else if (lcAtoms[c].atomName = "O") { | else if (lcAtoms[c].atomName = "O") { | ||
− | + | counter_rotate_2(lcAtoms[c].atomIndex, | |
− | {atomIndex=idx}.xyz, targetIdx, | + | {atomIndex=idx}.xyz, targetIdx, false) |
# If not fixed, exit fail | # If not fixed, exit fail | ||
− | if (gOk2 | + | if (not gOk2) { |
return # early exit (break n jmol bug) | return # early exit (break n jmol bug) | ||
} | } | ||
Line 494: | Line 282: | ||
# Else if it is itself O, counter-rotate | # Else if it is itself O, counter-rotate | ||
else if ({atomIndex=idx}.atomName = "O") { | else if ({atomIndex=idx}.atomName = "O") { | ||
− | + | counter_rotate_2(idx, lcAtoms[c].xyz, targetIdx, false) | |
# If not fixed, exit fail | # If not fixed, exit fail | ||
− | if (gOk2 | + | if (not gOk2) { |
return # early exit (break n jmol bug) | return # early exit (break n jmol bug) | ||
} | } | ||
Line 503: | Line 291: | ||
else { # Else not fixed, exit fail | else { # Else not fixed, exit fail | ||
− | gOk2 = | + | gOk2 = false |
return # early exit (break n jmol bug) | return # early exit (break n jmol bug) | ||
} | } | ||
Line 513: | Line 301: | ||
# Rotate rotor set to move target atom to its proper place | # Rotate rotor set to move target atom to its proper place | ||
− | function | + | function tug_track_idx(targetIdx, targetPt, nWard, cDetect) { |
− | gOK = | + | gOK = false |
var pt = targetPt | var pt = targetPt | ||
var dist = distance(pt, {atomIndex=targetIdx}.xyz) | var dist = distance(pt, {atomIndex=targetIdx}.xyz) | ||
Line 559: | Line 347: | ||
var dt = angle({atomIndex=targetIdx}, {atomIndex=i2}, {atomIndex=i3}, pt) | var dt = angle({atomIndex=targetIdx}, {atomIndex=i2}, {atomIndex=i3}, pt) | ||
var dh = angle({atomIndex=i1}, {atomIndex=i2}, {atomIndex=i3}, {atomIndex=i4}) | var dh = angle({atomIndex=i1}, {atomIndex=i2}, {atomIndex=i3}, {atomIndex=i4}) | ||
− | if (dh == " | + | if (abs(dh).type == "string") { |
dh = -50 | dh = -50 | ||
} | } | ||
Line 567: | Line 355: | ||
# Compute resultant psi and phi | # Compute resultant psi and phi | ||
# and select from target atom to first half of rotor | # and select from target atom to first half of rotor | ||
− | var movePt = | + | var movePt = false |
if (nWard) { | if (nWard) { | ||
if ({atomIndex=i2}.atomName="CA") { | if ({atomIndex=i2}.atomName="CA") { | ||
− | psi = angle({atomIndex=@{ | + | psi = angle({atomIndex=@{get_cward_bb_idx(i1, gChain)}}, {atomIndex=i1}, |
{atomIndex=i2}, {atomIndex=i3}) + dt | {atomIndex=i2}, {atomIndex=i3}) + dt | ||
} | } | ||
else { | else { | ||
phi = angle({atomIndex=i1}, {atomIndex=i2}, | phi = angle({atomIndex=i1}, {atomIndex=i2}, | ||
− | {atomIndex=i3}, {atomIndex=@{ | + | {atomIndex=i3}, {atomIndex=@{get_nward_bb_idx(i3, gChain)}}) + dt |
} | } | ||
if ({atomIndex=i2}.atomno > {atomIndex=targetIdx}.atomno) { | if ({atomIndex=i2}.atomno > {atomIndex=targetIdx}.atomno) { | ||
− | movePt = | + | movePt = true |
− | + | select_nward_idx(i3, get_cward_bb_idx(targetIdx, gChain)) | |
− | {atomIndex=targetIdx}.selected = | + | {atomIndex=targetIdx}.selected = true |
} | } | ||
else { | else { | ||
− | + | select_cward_idx(i2, targetIdx) | |
} | } | ||
} | } | ||
else { | else { | ||
if (({atomIndex=i2}.atomName="CA")) { | if (({atomIndex=i2}.atomName="CA")) { | ||
− | phi = angle({atomIndex=@{ | + | phi = angle({atomIndex=@{get_nward_bb_idx(i1, gChain)}}, {atomIndex=i1}, |
{atomIndex=i2}, {atomIndex=i3}) + dt | {atomIndex=i2}, {atomIndex=i3}) + dt | ||
} | } | ||
else { | else { | ||
psi = angle({atomIndex=i2}, {atomIndex=i3}, | psi = angle({atomIndex=i2}, {atomIndex=i3}, | ||
− | {atomIndex=i4}, {atomIndex=@{ | + | {atomIndex=i4}, {atomIndex=@{get_cward_bb_idx(i4, gChain)}}) + dt |
} | } | ||
if ({atomIndex=i2}.atomno < {atomIndex=targetIdx}.atomno) { | if ({atomIndex=i2}.atomno < {atomIndex=targetIdx}.atomno) { | ||
− | movePt = | + | movePt = true |
− | + | select_cward_idx(i3, get_nward_bb_idx(targetIdx, gChain)) | |
− | {atomIndex=targetIdx}.selected = | + | {atomIndex=targetIdx}.selected = true |
} | } | ||
else { | else { | ||
− | + | select_nward_idx(i2, targetIdx) | |
} | } | ||
} | } | ||
Line 630: | Line 418: | ||
# If collision, back off by eighths | # If collision, back off by eighths | ||
− | var wasCollision = | + | var wasCollision = false |
for (var ci = 0; ci < 4; ci++) { | for (var ci = 0; ci < 4; ci++) { | ||
if (ci < 3) { | if (ci < 3) { | ||
dt /= 2 | dt /= 2 | ||
} | } | ||
− | + | handle_collisions( targetIdx) | |
− | if (gOk2 | + | if (not gOk2) { |
− | wasCollision = | + | wasCollision = true |
rotateSelected {atomIndex=i2} {atomIndex=i3} @{-dt} | rotateSelected {atomIndex=i2} {atomIndex=i3} @{-dt} | ||
} | } | ||
Line 665: | Line 453: | ||
# If close enough, stop | # If close enough, stop | ||
if (distance(pt, {atomIndex=targetIdx}) < kDtolerance) { | if (distance(pt, {atomIndex=targetIdx}) < kDtolerance) { | ||
− | gOK = | + | gOK = true |
gTargetPt = pt | gTargetPt = pt | ||
break | break | ||
Line 678: | Line 466: | ||
break | break | ||
} | } | ||
− | } # endfor | + | } # endfor 20 passes |
} | } | ||
# Counter rotate bonds on either side of a BB O | # Counter rotate bonds on either side of a BB O | ||
− | function | + | function do_counter_rotate(caPhiIdx, nIdx, cIdx, oIdx, caPsiIdx, dir, nWard) { |
# Rotate psi | # Rotate psi | ||
Line 697: | Line 485: | ||
} | } | ||
− | function | + | function counter_rotate(oIdx, dir, nWard) { |
var iChain = {atomIndex=oIdx}.chain | var iChain = {atomIndex=oIdx}.chain | ||
var selsave = {selected} | var selsave = {selected} | ||
− | var cIdx = | + | var cIdx = get_sc_bb_idx(oIdx, iChain) |
− | var nIdx = | + | var nIdx = get_cward_bb_idx(cIdx, iChain) |
− | var caPhiIdx = | + | var caPhiIdx = get_cward_bb_idx(nIdx, iChain) |
− | var caPsiIdx = | + | var caPsiIdx = get_nward_bb_idx(cIdx, iChain) |
if (nWard) { | if (nWard) { | ||
− | nNo = {chain=iChain}.atomno.min | + | var nNo = {(chain=iChain) and thisModel}.atomno.min |
− | + | select_nward_idx(caPsiIdx, {(atomno=nNo) and (chain=iChain) | |
+ | and thisModel}.atomIndex) | ||
} | } | ||
else { | else { | ||
− | cNo = {chain=iChain}.atomno.max | + | var cNo = {(chain=iChain) and thisModel}.atomno.max |
− | + | select_cward_idx(caPhiIdx, {(atomno=cNo) and (chain=iChain) | |
+ | and thisModel}.atomIndex) | ||
} | } | ||
# Counter-rotate | # Counter-rotate | ||
− | + | do_counter_rotate(caPhiIdx, nIdx, cIdx, oIdx, caPsiIdx, dir, not nWard) | |
select selsave | select selsave | ||
} | } | ||
− | function | + | function counter_rotate_2(oIdx, toPt, terminalIdx, oDrag) { |
var iChain = {atomIndex=oIdx}.chain | var iChain = {atomIndex=oIdx}.chain | ||
var selsave = {selected} | var selsave = {selected} | ||
− | var gOk2 = | + | var gOk2 = true |
− | var cIdx = | + | var cIdx = get_sc_bb_idx(oIdx, iChain) |
− | var nIdx = | + | var nIdx = get_cward_bb_idx(cIdx, iChain) |
− | var caPhiIdx = | + | var caPhiIdx = get_cward_bb_idx(nIdx, iChain) |
− | var caPsiIdx = | + | var caPsiIdx = get_nward_bb_idx(cIdx, iChain) |
var nTward = ({atomIndex=oIdx}.atomno < {atomIndex=terminalIdx}.atomno) | var nTward = ({atomIndex=oIdx}.atomno < {atomIndex=terminalIdx}.atomno) | ||
if (nTward) { | if (nTward) { | ||
− | + | select_cward_idx(cIdx, terminalIdx) | |
} | } | ||
else { | else { | ||
− | + | select_nward_idx(nIdx, terminalIdx) | |
} | } | ||
Line 742: | Line 532: | ||
var ang = angle(toPt, {atomIndex=oIdx}, {atomIndex=cIdx}) | var ang = angle(toPt, {atomIndex=oIdx}, {atomIndex=cIdx}) | ||
var tcount = 0 | var tcount = 0 | ||
− | while (oDrag or (within(kCtolerance, | + | while (oDrag or (within(kCtolerance, false, {atomIndex=oIdx}) |
and not {atomIndex=oIdx} and not connected({atomIndex=oIdx}) | and not {atomIndex=oIdx} and not connected({atomIndex=oIdx}) | ||
and not {gOkCollide} > 0)) { | and not {gOkCollide} > 0)) { | ||
# Counter-rotate | # Counter-rotate | ||
− | + | do_counter_rotate(caPhiIdx, nIdx, cIdx, oIdx, caPsiIdx, dir, nTward) | |
var newang = angle(toPt, {atomIndex=oIdx}, {atomIndex=cIdx}) | var newang = angle(toPt, {atomIndex=oIdx}, {atomIndex=cIdx}) | ||
# If wrong direction once, undo and reverse | # If wrong direction once, undo and reverse | ||
if (newang > ang) { | if (newang > ang) { | ||
− | + | do_counter_rotate(caPhiIDx, nIdx, cIdx, oIdx, caPsiIdx, -dir, nTward) | |
# If first time, continue in opposite direction | # If first time, continue in opposite direction | ||
Line 768: | Line 558: | ||
tcount++ | tcount++ | ||
if (tcount > (360/abs(dir))) { | if (tcount > (360/abs(dir))) { | ||
− | gOk2 = | + | gOk2 = false |
break | break | ||
} | } | ||
Line 777: | Line 567: | ||
# Repair proline | # Repair proline | ||
− | function | + | function repair_proline(BBidx) { |
− | var cbidx = | + | var cbidx = get_cb_idx(BBidx) |
var cbno = {atomIndex=cbidx}.atomno | var cbno = {atomIndex=cbidx}.atomno | ||
− | var cgidx = {(atomno=@{cbno+1}) and (chain=gChain)}.atomIndex | + | var cgidx = {(atomno=@{cbno+1}) and (chain=gChain) |
− | var cdidx = {(atomno=@{cbno+2}) and (chain=gChain)}.atomIndex | + | and thisModel}.atomIndex |
− | var caidx = {(atomno=@{cbno-3}) and (chain=gChain)}.atomIndex | + | var cdidx = {(atomno=@{cbno+2}) and (chain=gChain) |
− | var nidx = {(atomno=@{cbno-4}) and (chain=gChain)}.atomIndex | + | 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} | select {atomIndex=cbidx} | ||
− | + | set_angle_idx(nidx, caidx, cbidx, 109.5) | |
select {atomIndex=cdidx} | 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} | 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 | # Repair side chain | ||
− | function | + | function repair_sc(targetIdx, nWard) { |
− | var idx = (nWard ? | + | var idx = (nWard ? get_cward_bb_idx(targetIdx, gChain) : get_nward_bb_idx(targetIdx, gChain)) |
if (({atomIndex=targetIdx}.atomName == "CA") | if (({atomIndex=targetIdx}.atomName == "CA") | ||
and ({atomIndex=targetIdx}.group != "GLY")) { | and ({atomIndex=targetIdx}.group != "GLY")) { | ||
− | var cbidx = | + | var cbidx = get_cb_idx(targetIdx) |
select none | 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") { | if ({atomIndex=targetIdx}.group != "PRO") { | ||
− | var colliders = (within(kCtolerance, | + | var colliders = (within(kCtolerance, false, {selected}) |
and not {atomIndex=targetIdx} and not {selected}) | and not {atomIndex=targetIdx} and not {selected}) | ||
− | if (colliders | + | if (colliders) { |
if ({atomIndex=targetIdx}.group != "ALA") { | if ({atomIndex=targetIdx}.group != "ALA") { | ||
− | + | fix_sc_collision_2(cbidx) | |
} | } | ||
} | } | ||
Line 824: | Line 618: | ||
} | } | ||
else { | else { | ||
− | + | set_dihedral_idx(get_nward_bb_idx(idx, gChain), idx, targetIdx, cbidx, 174.2) | |
} | } | ||
} | } | ||
Line 830: | Line 624: | ||
else if ({atomIndex=targetIdx}.atomName == "C") { | else if ({atomIndex=targetIdx}.atomName == "C") { | ||
− | var oidx = | + | var oidx = get_o_idx(targetIdx) |
select {atomIndex=oidx} | select {atomIndex=oidx} | ||
− | + | set_angle_idx(idx, targetIdx, oidx, 120.0) | |
− | + | set_distance_idx(targetIdx, oidx, 1.21) | |
if (nWard) { | if (nWard) { | ||
− | + | set_dihedral_idx(get_cward_bb_idx(idx, gChain), idx, targetIdx, oidx, 0.0) | |
} | } | ||
if ({atomIndex=idx}.group == "PRO") { | if ({atomIndex=idx}.group == "PRO") { | ||
− | + | repair_proline(idx) | |
var dNo = {atomIndex=targetIdx}.atomno + 4 | var dNo = {atomIndex=targetIdx}.atomno + 4 | ||
− | var dIdx = {(atomno=dNO) and (chain=gChain)}.atomIndex | + | var dIdx = {(atomno=dNO) and (chain=gChain) |
− | var colliders = (within(kCtolerance, | + | and thisModel}.atomIndex |
+ | var colliders = (within(kCtolerance, false, {atomIndex=dIdx}) | ||
and not connected({atomIndex=dIdx}) | and not connected({atomIndex=dIdx}) | ||
and not {atomIndex=dIdx}) | and not {atomIndex=dIdx}) | ||
for (var i = 1; i <= colliders.size; i++) { | for (var i = 1; i <= colliders.size; i++) { | ||
if (colliders[i].atomName == "O") { | if (colliders[i].atomName == "O") { | ||
− | + | counter_rotate_2(colliders[i].atomIndex, | |
− | {atomIndex=dIdx}.xyz, targetIdx, | + | {atomIndex=dIdx}.xyz, targetIdx, false) |
} | } | ||
} | } | ||
Line 855: | Line 650: | ||
# Rebuild Cward rotors set | # Rebuild Cward rotors set | ||
− | function | + | function tug_track_c() { |
# For all bb atoms cWard of cargo | # For all bb atoms cWard of cargo | ||
Line 864: | Line 659: | ||
gOkCollide = gCargoSet | gOkCollide = gCargoSet | ||
var tcount = 0 | var tcount = 0 | ||
− | while (targetIdx != | + | while (targetIdx != gNanchorIdx) { |
# Step to next atom | # Step to next atom | ||
− | targetIdx = | + | targetIdx = get_cward_bb_idx(targetIdx, gChain) |
+ | if (targetIdx < 0) { | ||
+ | break | ||
+ | } | ||
# No collision with cargo allowed after two atoms placed | # No collision with cargo allowed after two atoms placed | ||
Line 876: | Line 674: | ||
# Compute targets desired coords | # Compute targets desired coords | ||
− | var c1idx = | + | 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 successful | ||
− | if (gOK == | + | if (gOK == true) { |
# Adust any side atoms | # Adust any side atoms | ||
− | + | repair_sc(targetIdx, false) | |
} | } | ||
Line 954: | Line 755: | ||
# Rebuild Nward rotors set | # Rebuild Nward rotors set | ||
− | function | + | function tug_track_n() { |
− | gOK = | + | gOK = true |
# For all bb atoms nWard of cargo | # For all bb atoms nWard of cargo | ||
Line 968: | Line 769: | ||
# Step to next atom | # Step to next atom | ||
− | targetIdx = | + | targetIdx = get_nward_bb_idx(targetIdx, gChain) |
− | + | if (targetIdx < 0) { | |
+ | break | ||
+ | } | ||
+ | |||
# No collision with cargo allowed after two atoms placed | # No collision with cargo allowed after two atoms placed | ||
if (tcount == 2) { | if (tcount == 2) { | ||
Line 977: | Line 781: | ||
# Compute targets desired coords | # Compute targets desired coords | ||
− | var n1idx = | + | var n1idx = get_nward_bb_idx(targetIdx, gChain) |
− | var c1idx = | + | var c1idx = get_cward_bb_idx(targetIdx, gChain) |
− | var c2idx = | + | var c2idx = get_cward_bb_idx(c1idx, gChain) |
− | var c3idx = | + | var c3idx = get_cward_bb_idx(c2idx, gChain) |
var pt = {0 0 0} | var pt = {0 0 0} | ||
if ({atomIndex=targetIdx}.atomName == "CA") { | if ({atomIndex=targetIdx}.atomName == "CA") { | ||
# Desired target location is trigonal O | # Desired target location is trigonal O | ||
− | var oidx = | + | var oidx = get_o_idx(c1idx) |
select {atomIndex=oidx} | select {atomIndex=oidx} | ||
− | + | set_distance_idx(c1idx, oidx, 1.39) | |
− | pt = | + | pt = get_trigonal_idx(c2idx, c1idx, oidx, 1.41) |
− | + | set_distance_idx(c1idx, oidx, 1.21) | |
} | } | ||
else if (({atomIndex=targetIdx}.atomName == "N") | else if (({atomIndex=targetIdx}.atomName == "N") | ||
Line 995: | Line 799: | ||
# Desired target location is r-tetragonal CB | # Desired target location is r-tetragonal CB | ||
− | var cbidx = | + | var cbidx = get_cb_idx(c1idx) |
− | pt = | + | pt = get_tet_idx(cbidx, c1idx, c2idx, 1.5) |
} | } | ||
else { # C | else { # C | ||
Line 1,005: | Line 809: | ||
# Set target atom at desired distance and angle | # Set target atom at desired distance and angle | ||
select {atomIndex=targetIdx} | select {atomIndex=targetIdx} | ||
− | + | set_distance_idx(c1idx, targetIdx, 1.37) | |
− | + | set_angle_idx(c2idx, c1idx, targetIdx, 110.0) | |
if ({atomIndex=targetIdx}.group == "PRO") { | if ({atomIndex=targetIdx}.group == "PRO") { | ||
− | + | set_dihedral_idx(c3idx, c2idx, c1idx, targetIdx, -57.0) | |
} | } | ||
Line 1,022: | Line 826: | ||
gTargetPt = pt | gTargetPt = pt | ||
var xcount = 0 | var xcount = 0 | ||
− | gOK = | + | gOK = false |
− | while ((xcount < 20) and (gOK | + | while ((xcount < 20) and (not gOK)) { |
− | # Rotate on | + | # Rotate on nWard rotor set to move it there |
− | + | tug_track_idx(targetIdx, pt, true, false) | |
− | |||
xcount++ | xcount++ | ||
} | } | ||
} | } | ||
else { | else { | ||
− | gOK = | + | gOK = true |
okCount++ | okCount++ | ||
} | } | ||
# If sucessful | # If sucessful | ||
− | if (gOK == | + | if (gOK == true) { |
# Adust any side atoms | # Adust any side atoms | ||
− | + | repair_sc(targetIdx, true) | |
} | } | ||
Line 1,054: | Line 857: | ||
} # endwhile (targetIdx != gNanchorIdx) { | } # endwhile (targetIdx != gNanchorIdx) { | ||
− | |||
} | } | ||
# gPlicoRecord is maintained by the macro pilcoRecord | # gPlicoRecord is maintained by the macro pilcoRecord | ||
− | function | + | function translate_selected_record(pt) { |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
if (gPlicoRecord != "") { | if (gPlicoRecord != "") { | ||
− | + | plico_record(format("select %s;translateSelected %s;", {selected}, pt)) | |
} | } | ||
translateSelected @pt | translateSelected @pt | ||
Line 1,077: | Line 868: | ||
# gPlicoRecord is maintained by the macro pilcoRecord | # gPlicoRecord is maintained by the macro pilcoRecord | ||
− | function | + | function rotate_selected_record(pivotIdx, caxis, a) { |
if (gPlicoRecord != "") { | if (gPlicoRecord != "") { | ||
− | + | plico_record(format("select %s;", {selected})) | |
− | + | plico_record(format("rotateSelected {atomIndex=%d} @%s @%s;", | |
− | + | pivotIdx, caxis, a)) | |
} | } | ||
− | rotateSelected {atomIndex= | + | rotateSelected {atomIndex=pivotIdx} @caxis @a |
} | } | ||
− | function | + | function collect_sc_rotors(no, iChain) { |
var scBondIdxs = array() | var scBondIdxs = array() | ||
for (var iNo = no; iNo >= 0; iNo--) { | for (var iNo = no; iNo >= 0; iNo--) { | ||
var ile = 0 | var ile = 0 | ||
− | switch ({(atomno=iNo) and (chain=iChain)}.atomName) { | + | switch ({(atomno=iNo) and (chain=iChain) |
+ | and thisModel}.atomName) { | ||
case "CA" : | case "CA" : | ||
return scBondIdxs # Early exit since break 1 appears broken | return scBondIdxs # Early exit since break 1 appears broken | ||
case "CZ" : | case "CZ" : | ||
− | if ({(atomno=iNo) and (chain=iChain)}.group == "TYR") { | + | if ({(atomno=iNo) and (chain=iChain) |
+ | and thisModel}.group == "TYR") { | ||
break | break | ||
} | } | ||
case "CE" : | case "CE" : | ||
− | if ({(atomno=iNo) and (chain=iChain)}.group == "MET") { | + | if ({(atomno=iNo) and (chain=iChain) |
+ | and thisModel}.group == "MET") { | ||
break | break | ||
} | } | ||
case "CG1" : | case "CG1" : | ||
− | if ({(atomno=iNo) and (chain=iChain)}.group == "VAL") { | + | if ({(atomno=iNo) and (chain=iChain) |
+ | and thisModel}.group == "VAL") { | ||
break | break | ||
} | } | ||
− | if ({(atomno=iNo) and (chain=iChain)}.group == "ILE") { | + | if ({(atomno=iNo) and (chain=iChain) |
+ | and thisModel}.group == "ILE") { | ||
ile = 1 | ile = 1 | ||
} | } | ||
Line 1,113: | Line 909: | ||
case "CG" : | case "CG" : | ||
case "CB" : | case "CB" : | ||
− | scBondIdxs += {(atomno=@{iNo+1+ile}) and (chain=iChain)}.atomIndex | + | scBondIdxs += {(atomno=@{iNo+1+ile}) and (chain=iChain) |
− | scBondIdxs += {(atomno=@{iNo+0}) and (chain=iChain)}.atomIndex | + | and thisModel}.atomIndex |
− | if ({(atomno=iNo) and (chain=iChain)}.atomName%2 == "CG") { | + | scBondIdxs += {(atomno=@{iNo+0}) and (chain=iChain) |
− | scBondIdxs += {(atomno=@{iNo-1}) and (chain=iChain)}.atomIndex | + | and thisModel}.atomIndex |
− | scBondIdxs += {(atomno=@{iNo-4}) and (chain=iChain)}.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)}.atomName == "CB") { | + | else if ({(atomno=iNo) and (chain=iChain) |
− | scBondIdxs += {(atomno=@{iNo-3}) and (chain=iChain)}.atomIndex | + | and thisModel}.atomName == "CB") { |
− | scBondIdxs += {(atomno=@{iNo-4}) and (chain=iChain)}.atomIndex | + | scBondIdxs += {(atomno=@{iNo-3}) and (chain=iChain) |
+ | and thisModel}.atomIndex | ||
+ | scBondIdxs += {(atomno=@{iNo-4}) and (chain=iChain) | ||
+ | and thisModel}.atomIndex | ||
} | } | ||
else { | else { | ||
− | scBondIdxs += {(atomno=@{iNo-1}) and (chain=iChain)}.atomIndex | + | scBondIdxs += {(atomno=@{iNo-1}) and (chain=iChain) |
− | scBondIdxs += {(atomno=@{iNo-2}) and (chain=iChain)}.atomIndex | + | and thisModel}.atomIndex |
+ | scBondIdxs += {(atomno=@{iNo-2}) and (chain=iChain) | ||
+ | and thisModel}.atomIndex | ||
} | } | ||
break | break | ||
Line 1,136: | Line 942: | ||
# Drag Side Chain | # Drag Side Chain | ||
− | function | + | function drag_sc() { |
− | |||
var iNo = {atomIndex=gSCidx}.atomno | var iNo = {atomIndex=gSCidx}.atomno | ||
var iChain = {atomIndex=gSCidx}.chain | var iChain = {atomIndex=gSCidx}.chain | ||
− | |||
if ({atomIndex=gSCidx}.group != "PRO") { | if ({atomIndex=gSCidx}.group != "PRO") { | ||
− | var scBondIdxs = | + | var scBondIdxs = collect_sc_rotors( iNo, iChain) |
var numChi = scBondIdxs.size / 4 | var numChi = scBondIdxs.size / 4 | ||
var dist = distance({atomIndex=gSCidx}.xyz, gSCpt) | var dist = distance({atomIndex=gSCidx}.xyz, gSCpt) | ||
+ | var scSet = get_sc_set(gSCidx, iChain) | ||
− | |||
− | |||
− | |||
− | |||
− | |||
# For all rotor combinations | # For all rotor combinations | ||
var dh = array() | var dh = array() | ||
Line 1,164: | Line 964: | ||
for (var j = 0; j < 6; j++) { | for (var j = 0; j < 6; j++) { | ||
rot += 60*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) | scBondIdxs[2+(4*i)], scBondIdxs[1+(4*i)], rot) | ||
var newDist = distance({atomIndex=gSCidx}.xyz, gSCpt) | var newDist = distance({atomIndex=gSCidx}.xyz, gSCpt) | ||
if (gSCcheck) { | if (gSCcheck) { | ||
− | var colliders = (within(kCtolerance, | + | var colliders = (within(kCtolerance, false, scSet) |
and not connected(scSet) and not {scSet}) | and not connected(scSet) and not {scSet}) | ||
− | if (colliders | + | if (colliders) { |
continue | continue | ||
} | } | ||
} | } | ||
− | + | ||
# Find the best | # Find the best | ||
if (newDist < dist) { | if (newDist < dist) { | ||
Line 1,191: | Line 991: | ||
# Now set the best | # Now set the best | ||
for (var i = 0; i < numChi; i++) { | 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]) | 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 | else { # PRO - toggle between puckers up and down | ||
− | var icd = {(atomno=@{iNo+1}) and (chain=iChain)}.atomIndex | + | var icd = {(atomno=@{iNo+1}) and (chain=iChain) |
− | var icb = {(atomno=@{iNo-1}) and (chain=iChain)}.atomIndex | + | and thisModel}.atomIndex |
− | var ica = {(atomno=@{iNo-4}) and (chain=iChain)}.atomIndex | + | var icb = {(atomno=@{iNo-1}) and (chain=iChain) |
− | var in = {(atomno=@{iNo-5}) and (chain=iChain)}.atomIndex | + | 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} | select {atomIndex=gSCidx} | ||
if (angle({atomIndex=ica}, {atomIndex=in}, | if (angle({atomIndex=ica}, {atomIndex=in}, | ||
{atomIndex=icd}, {atomIndex=gSCidx}) < -10.0) { | {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) | |
} | } | ||
} | } | ||
Line 1,221: | Line 1,029: | ||
# Fix side chain collisions | # Fix side chain collisions | ||
− | function | + | function fix_sc_collision_2(idx) { |
− | gOk2 = | + | gOk2 = false |
var iNo = {atomIndex=idx}.atomno | var iNo = {atomIndex=idx}.atomno | ||
var iChain = {atomIndex=idx}.chain | var iChain = {atomIndex=idx}.chain | ||
− | var resno = {(atomno=iNo) and (chain=iChain)}.resno | + | var resno = {(atomno=iNo) and (chain=iChain) |
+ | and thisModel}.resno | ||
# Get SC terminus | # Get SC terminus | ||
− | while (resno == {(atomno=iNo) and (chain=iChain)}.resno) { | + | while (resno == {(atomno=iNo) and (chain=iChain) |
+ | and thisModel}.resno) { | ||
iNo++ | iNo++ | ||
} | } | ||
Line 1,235: | Line 1,045: | ||
var sc = array() | var sc = array() | ||
var iBno = iNo | var iBno = iNo | ||
− | while ({(atomno=iBno) and (chain=iChain)}.atomName != "CB") { | + | while ({(atomno=iBno) and (chain=iChain) |
− | sc += {(atomno=iBno) and (chain=iChain)} | + | and thisModel}.atomName != "CB") { |
+ | sc += {(atomno=iBno) and (chain=iChain) | ||
+ | and thisModel} | ||
iBno-- | iBno-- | ||
} | } | ||
− | var cbidx = {(atomno=iBno) and (chain=iChain)}.atomIndex | + | var cbidx = {(atomno=iBno) and (chain=iChain) |
+ | and thisModel}.atomIndex | ||
− | var scBondIdxs = | + | var scBondIdxs = collect_sc_rotors( iNo, iChain) |
var numChi = scBondIdxs.size / 4 | var numChi = scBondIdxs.size / 4 | ||
Line 1,249: | Line 1,062: | ||
for (var j = 0; j < 6; j++) { | for (var j = 0; j < 6; j++) { | ||
rot += 60 | 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) | scBondIdxs[3+(4*i)], scBondIdxs[4+(4*i)], rot) | ||
− | + | ||
# If no collision, exit | # If no collision, exit | ||
− | colliders = (within(kCtolerance, | + | var colliders = (within(kCtolerance, false, {sc}) |
and not {atomIndex=cbidx} and not {sc}) | and not {atomIndex=cbidx} and not {sc}) | ||
Line 1,266: | Line 1,079: | ||
if (colliders.size == 0) { | if (colliders.size == 0) { | ||
− | gOk2 = | + | gOk2 = true |
return # Early exit since break 1 appears broken | return # Early exit since break 1 appears broken | ||
} | } | ||
Line 1,274: | Line 1,087: | ||
} | } | ||
− | function | + | function is_moveable_sc(aIdx) { |
var ret = (({atomIndex=aIdx}.group != "PRO") | var ret = (({atomIndex=aIdx}.group != "PRO") | ||
Line 1,285: | Line 1,098: | ||
case "O": | case "O": | ||
case "O4\'": | case "O4\'": | ||
− | ret = | + | ret = false |
break | break | ||
} | } | ||
Line 1,291: | Line 1,104: | ||
} | } | ||
− | + | 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 | + | function xcollect_bb_rotors(nWard) { |
var anchorNo = (nWard | var anchorNo = (nWard | ||
? ((gNanchorIdx >= 0) ? {atomIndex=gNanchorIdx}.atomno : gMinNo) | ? ((gNanchorIdx >= 0) ? {atomIndex=gNanchorIdx}.atomno : gMinNo) | ||
Line 1,309: | Line 1,134: | ||
for (var iNo = cargoNo; iNo <= anchorNo; iNo++) { | for (var iNo = cargoNo; iNo <= anchorNo; iNo++) { | ||
− | if ({(atomno=iNo) and (chain=gChain)}.atomName == "CA") { | + | if ({(atomno=iNo) and (chain=gChain) |
− | if ( | + | and thisModel}.atomName == "CA") { |
− | if (({(atomno=iNo) and (chain=gChain)}.group != "PRO") and (iNo > cargoNo)) { # phi | + | if (is_rotor_avail(iNo)) {# xxx |
− | rotors += [{(atomno=@{ | + | if (({(atomno=iNo) and (chain=gChain) |
− | {(atomno=@{iNo-1}) and (chain=gChain)}.atomIndex] | + | and thisModel}.group != "PRO") and (iNo > cargoNo)) { # phi |
− | rotors += [{(atomno=@{iNo}) and (chain=gChain)}.atomIndex, | + | rotors += [{(atomno=@{get_cm_no(iNo-1)}) and (chain=gChain) |
− | {(atomno=@{iNo+1}) and (chain=gChain)}.atomIndex] | + | 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 | if (iNo != (anchorNo-1)) { # psi | ||
− | rotors += [{(atomno=@{iNo-1}) and (chain=gChain)}.atomIndex, | + | rotors += [{(atomno=@{iNo-1}) and (chain=gChain) |
− | {(atomno=@{iNo}) and (chain=gChain)}.atomIndex] | + | and thisModel}.atomIndex, |
− | rotors += [{(atomno=@{iNo+1}) and (chain=gChain)}.atomIndex, | + | {(atomno=@{iNo}) and (chain=gChain) |
− | {(atomno=@{ | + | 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] | ||
} | } | ||
} | } | ||
Line 1,330: | Line 1,165: | ||
for (var iNo = cargoNo; iNo >= anchorNo; iNo--) { | for (var iNo = cargoNo; iNo >= anchorNo; iNo--) { | ||
− | if ({(atomno=iNo) and (chain=gChain)}.atomName == "CA") { | + | if ({(atomno=iNo) and (chain=gChain) |
− | if ( | + | and thisModel}.atomName == "CA") { |
+ | if (is_rotor_avail(iNo)) { | ||
if ((iNo != (anchorNo-1)) and (iNo < cargoNo)) { # psi | if ((iNo != (anchorNo-1)) and (iNo < cargoNo)) { # psi | ||
− | rotors += [{(atomno=@{ | + | rotors += [{(atomno=@{get_np_no(iNo+2)}) and (chain=gChain) |
− | {(atomno=@{iNo+1}) and (chain=gChain)}.atomIndex] | + | and thisModel}.atomIndex, |
− | rotors += [{(atomno=@{iNo}) and (chain=gChain)}.atomIndex, | + | {(atomno=@{iNo+1}) and (chain=gChain) |
− | {(atomno=@{iNo-1}) and (chain=gChain)}.atomIndex] | + | 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)}.group != "PRO") { # phi | + | if ({(atomno=iNo) and (chain=gChain) |
− | rotors += [{(atomno=@{iNo+1}) and (chain=gChain)}.atomIndex, | + | and thisModel}.group != "PRO") { # phi |
− | {(atomno=@{iNo}) and (chain=gChain)}.atomIndex] | + | rotors += [{(atomno=@{iNo+1}) and (chain=gChain) |
− | rotors += [{(atomno=@{iNo-1}) and (chain=gChain)}.atomIndex, | + | and thisModel}.atomIndex, |
− | {(atomno=@{ | + | {(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] | ||
} | } | ||
} | } | ||
Line 1,354: | Line 1,199: | ||
else { | else { | ||
gCrotors = rotors | 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 | + | function collect_rotors() { |
− | + | collect_bb_rotors(false) | |
− | + | collect_bb_rotors(true) | |
} | } | ||
− | function | + | function tug_sc(pt) { |
# If destination atom defined | # If destination atom defined | ||
Line 1,378: | Line 1,317: | ||
} | } | ||
− | function | + | function set_colors() { |
− | select | + | select (thisModel) |
color {selected} @gScheme | color {selected} @gScheme | ||
color {atomIndex=g1pivotIdx} green | color {atomIndex=g1pivotIdx} green | ||
color {atomIndex=g2pivotIdx} green | color {atomIndex=g2pivotIdx} green | ||
color @gCargoSet @gAltScheme | color @gCargoSet @gAltScheme | ||
+ | color {gCargoSet and oxygen} pink | ||
select {(atomIndex=gCcargoIdx) or (atomIndex=gNcargoIdx) | select {(atomIndex=gCcargoIdx) or (atomIndex=gNcargoIdx) | ||
or (atomIndex=gCanchorIdx) or (atomIndex=gNanchorIdx)} | or (atomIndex=gCanchorIdx) or (atomIndex=gNanchorIdx)} | ||
Line 1,392: | Line 1,332: | ||
} | } | ||
− | function | + | function clear_atom_idxs() { |
gCcargoIdx = -1 | gCcargoIdx = -1 | ||
gNcargoIdx = -1 | gNcargoIdx = -1 | ||
Line 1,399: | Line 1,339: | ||
g1pivotIdx = -1 | g1pivotIdx = -1 | ||
g2pivotIdx = -1 | g2pivotIdx = -1 | ||
+ | g1dynamicIdx = -1 | ||
+ | g2dynamicIdx = -1 | ||
gDestAtomIdx = -1 | gDestAtomIdx = -1 | ||
gSCidx = -1 | gSCidx = -1 | ||
} | } | ||
− | function | + | function timed_out (s) { |
timeout ID"tug" OFF | timeout ID"tug" OFF | ||
− | |||
− | |||
− | |||
− | |||
− | |||
refresh | refresh | ||
− | quit | + | 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("select %s;", {selected}) | ||
ls += format("gCanchorIdx = %d;", gCanchorIdx) | ls += format("gCanchorIdx = %d;", gCanchorIdx) | ||
Line 1,435: | Line 1,387: | ||
ls += format("gSCcircle = %d;", gSCcircle) | ls += format("gSCcircle = %d;", gSCcircle) | ||
ls += format("gSCpt = %s;", gSCpt) | ls += format("gSCpt = %s;", gSCpt) | ||
− | ls += " | + | ls += "collect_rotors();" |
− | ls += " | + | ls += "tug_drag_done_mb();" |
− | + | plico_record(ls) | |
} | } | ||
− | # Bound to LEFT-UP by | + | # Pick call-back for freeze |
− | function | + | function tug_pick_cb() { |
− | if (gBusy | + | 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 != "") { | if (gPlicoRecord != "") { | ||
− | + | record_drag() | |
} | } | ||
# Move by rotation on rotor sets, smallest first | # Move by rotation on rotor sets, smallest first | ||
− | gBusy = | + | gBusy = true |
background ECHO pink | background ECHO pink | ||
refresh | refresh | ||
Line 1,454: | Line 1,460: | ||
# If side chain mode | # If side chain mode | ||
if (gSCidx >= 0) { | if (gSCidx >= 0) { | ||
− | + | drag_sc() | |
} | } | ||
# Else | # Else | ||
else if (not gTow) { | else if (not gTow) { | ||
− | gOK = | + | gOK = true |
− | timeout ID"tug" 20.0 " | + | timeout ID"tug" 20.0 "timed_out(\"Tug timed out\")" |
if ((gCrotors.size < gNrotors.size) or (gNanchorIdx < 0)) { | if ((gCrotors.size < gNrotors.size) or (gNanchorIdx < 0)) { | ||
if (gCrotors.size > 4) { | if (gCrotors.size > 4) { | ||
− | + | tug_track_c() | |
} | } | ||
if (gOK and (gNrotors.size > 4)) { | if (gOK and (gNrotors.size > 4)) { | ||
− | + | tug_track_n() | |
} | } | ||
} | } | ||
else { | else { | ||
if (gNrotors.size > 4) { | if (gNrotors.size > 4) { | ||
− | + | tug_track_n() | |
} | } | ||
if (gOK and (gCrotors.size > 4)) { | if (gOK and (gCrotors.size > 4)) { | ||
− | + | tug_track_c() | |
} | } | ||
} | } | ||
Line 1,480: | Line 1,486: | ||
# If anchor angles acute, fail | # If anchor angles acute, fail | ||
− | if (gOK == | + | if (gOK == true) { |
if (gCanchorIdx >= 0) { | if (gCanchorIdx >= 0) { | ||
− | var ic = | + | var ic = get_cward_bb_idx(gCanchorIdx, gChain) |
− | var in = | + | var in = get_nward_bb_idx(gCanchorIdx, gChain) |
if ((ic >= 0) and | if ((ic >= 0) and | ||
angle({atomIndex=ic}, {atomIndex=gCanchorIdx}, {atomIndex=in}) | angle({atomIndex=ic}, {atomIndex=gCanchorIdx}, {atomIndex=in}) | ||
< 100.0) { | < 100.0) { | ||
− | gOK = | + | gOK = false |
} | } | ||
} | } | ||
if (gNanchorIdx >= 0) { | if (gNanchorIdx >= 0) { | ||
− | var ic = | + | var ic = get_cward_bb_idx(gNanchorIdx, gChain) |
− | var in = | + | var in = get_nward_bb_idx(gNanchorIdx, gChain) |
if ((in >= 0) and | if ((in >= 0) and | ||
angle({atomIndex=ic}, {atomIndex=gNanchorIdx}, {atomIndex=in}) | angle({atomIndex=ic}, {atomIndex=gNanchorIdx}, {atomIndex=in}) | ||
< 100.0) { | < 100.0) { | ||
− | gOK = | + | gOK = false |
} | } | ||
} | } | ||
Line 1,502: | Line 1,508: | ||
# If too far | # If too far | ||
− | if (gOK | + | if (not gOK) { |
− | + | timed_out("TUG TOO FAR!") | |
} | } | ||
Line 1,509: | Line 1,515: | ||
else { | else { | ||
− | + | var idx = { | |
− | + | (atomno=@{{(chain=gChain) and thisModel}.atomno.min}) | |
− | var idx = {(atomno=@{{chain=gChain}.atomno.min}) | + | and (chain=gChain) and thisModel}.atomIndex |
− | and (chain=gChain)}.atomIndex | ||
var ihc = 0 | var ihc = 0 | ||
for (ihc = 0; ihc < 10; ihc++) { | for (ihc = 0; ihc < 10; ihc++) { | ||
− | + | select ((atomno >= gNanchorNo) and (atomno <= gCanchorNo) | |
− | if ( | + | and (chain = gChain) and thisModel) |
+ | handle_collisions( idx) | ||
+ | if (count_collisions(({})).size == 0) { | ||
break | break | ||
} | } | ||
} | } | ||
if (ihc == 10) { | if (ihc == 10) { | ||
− | + | timed_out("Unable to handle all collisions!") | |
− | |||
} | } | ||
} | } | ||
} | } | ||
select {gCargoSet} | select {gCargoSet} | ||
− | gBusy = | + | gBusy = false |
background ECHO yellow | background ECHO yellow | ||
+ | set bondPicking true | ||
refresh | refresh | ||
} | } | ||
} | } | ||
− | # Bound to ALT-SHIFT-LEFT-DRAG by | + | # Bound to ALT-SHIFT-LEFT-DRAG by tug_enable_drag |
− | function | + | function tug_drag_2_mb() { |
− | + | tug_drag_mb(true) | |
} | } | ||
− | # Bound to ALT-LEFT-DRAG by | + | # Bound to ALT-LEFT-DRAG by tug_enable_drag |
− | function | + | function tug_drag_mb(alt) { |
− | if (gBusy | + | if (not gBusy) { |
− | gBusy = | + | gBusy = true |
var dx = (40.0 * (_mouseX - gMouseX))/_width | var dx = (40.0 * (_mouseX - gMouseX))/_width | ||
var dy = (40.0 * (_mouseY - gMouseY))/_height | var dy = (40.0 * (_mouseY - gMouseY))/_height | ||
Line 1,549: | Line 1,556: | ||
var ptd = {@dx @dy 0} | var ptd = {@dx @dy 0} | ||
var pt = (!q)%ptd | var pt = (!q)%ptd | ||
− | var | + | var caxis = {0 0 0} |
if (distance(pt, {0 0 0}) > 0.004) { | if (distance(pt, {0 0 0}) > 0.004) { | ||
# If sidechain mode | # If sidechain mode | ||
if (gSCidx >= 0) { | if (gSCidx >= 0) { | ||
if ({atomIndex=gSCidx}.atomName == "O") { | if ({atomIndex=gSCidx}.atomName == "O") { | ||
− | dir = ((abs(dx) > abs(dy)) | + | 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 { | else { | ||
gSCcheck = not alt | gSCcheck = not alt | ||
− | + | tug_sc(pt) | |
} | } | ||
} | } | ||
Line 1,570: | Line 1,579: | ||
# If new drag | # If new drag | ||
if (gNewDrag) { | if (gNewDrag) { | ||
− | gNewDrag = | + | gNewDrag = false |
save state gState | save state gState | ||
} | } | ||
Line 1,593: | Line 1,602: | ||
# If two pivots | # If two pivots | ||
if (g2pivotIdx >= 0) { | if (g2pivotIdx >= 0) { | ||
− | + | caxis = {atomIndex=g2pivotIdx} | |
} | } | ||
# Else | # Else | ||
else { | else { | ||
− | + | caxis = cross(pt, {0 0 0}) + {atomIndex=g1pivotIdx}.xyz | |
} | } | ||
− | dir = ((abs(dx) > abs(dy)) | + | var dir = ((abs(dx) > abs(dy)) |
? ((dx < 0) ? 2 : -2) | ? ((dx < 0) ? 2 : -2) | ||
: ((dy < 0) ? 2 : -2)) | : ((dy < 0) ? 2 : -2)) | ||
− | + | rotate_selected_record(g1pivotIdx, caxis, dir) | |
} | } | ||
Line 1,610: | Line 1,619: | ||
# Else translate it | # Else translate it | ||
else { | else { | ||
− | + | translate_selected_record(pt) | |
} | } | ||
# If collisions | # If collisions | ||
− | var cNotSels = (within(kCtolerance, | + | var cNotSels = (within(kCtolerance, false, {selected}) |
and not {gMovingSet}) | and not {gMovingSet}) | ||
− | if (cNotSels | + | if ((cNotSels) and (not alt)) { |
− | gOk2 = | + | gOk2 = true |
for (var i = 1; i <= cNotSels.size; i++) { | for (var i = 1; i <= cNotSels.size; i++) { | ||
# If net collision vector same as move vector | # If net collision vector same as move vector | ||
− | cSels = (within(kCtolerance, | + | var cSels = (within(kCtolerance, false, cNotSels[i]) and {selected}) |
for (var j = 1; j <= cSels.size; j++) { | for (var j = 1; j <= cSels.size; j++) { | ||
var v1 = cNotSels[i].xyz - cSels[j].xyz | var v1 = cNotSels[i].xyz - cSels[j].xyz | ||
Line 1,634: | Line 1,643: | ||
g1dynamicIdx = cNotSels[i].atomIndex | g1dynamicIdx = cNotSels[i].atomIndex | ||
color {atomIndex=g1pivotIdx} lightgreen | color {atomIndex=g1pivotIdx} lightgreen | ||
− | + | set_distance_idx(cNotSels[i].atomIndex, | |
cSels[j].atomIndex, | cSels[j].atomIndex, | ||
kCtolerance + kDtolerance) | kCtolerance + kDtolerance) | ||
Line 1,642: | Line 1,651: | ||
g2dynamicIdx = cNotSels[i].atomIndex | g2dynamicIdx = cNotSels[i].atomIndex | ||
color {atomIndex=g2pivotIdx} lightgreen | color {atomIndex=g2pivotIdx} lightgreen | ||
− | + | set_distance_idx(cNotSels[i].atomIndex, | |
cSels[j].atomIndex, | cSels[j].atomIndex, | ||
kCtolerance + kDtolerance) | kCtolerance + kDtolerance) | ||
} | } | ||
else { | else { | ||
− | gOk2 = | + | gOk2 = false |
} | } | ||
} | } | ||
Line 1,653: | Line 1,662: | ||
# Try to resolve | # Try to resolve | ||
− | select cSels[j] | + | select @{cSels[j]} |
− | var idx = {(atomno=@{{chain=gChain}.atomno.min}) | + | var idx = {(atomno=@{{(chain=gChain) |
− | and (chain=gChain)}.atomIndex | + | and thisModel}.atomno.min}) |
− | + | and (chain=gChain) and thisModel}.atomIndex | |
+ | handle_collisions( idx) | ||
} | } | ||
} | } | ||
} # endfor | } # endfor | ||
− | if (gOk2 | + | if (not gOk2) { |
break | break | ||
} | } | ||
} # endfor | } # endfor | ||
− | # If unable | + | # If unable |
− | if ( | + | if (not gOk2) { |
# Back off | # Back off | ||
Line 1,672: | Line 1,682: | ||
delay 1 | delay 1 | ||
if (g1pivotIdx >= 0) { | if (g1pivotIdx >= 0) { | ||
− | + | rotate_selected_record(g1pivotIdx, caxis, -a) | |
} | } | ||
else { | else { | ||
− | + | translate_selected_record(-pt) | |
} | } | ||
background ECHO yellow | background ECHO yellow | ||
+ | set bondPicking true | ||
} | } | ||
} | } | ||
} | } | ||
− | # If dynamic | + | # If dynamic pivots |
if (g1dynamicIdx >= 0) { | if (g1dynamicIdx >= 0) { | ||
var v1 = {atomIndex=g1dynamicIdx}.xyz - {atomIndex=g1pivotIdx}.xyz | var v1 = {atomIndex=g1dynamicIdx}.xyz - {atomIndex=g1pivotIdx}.xyz | ||
Line 1,705: | Line 1,716: | ||
} | } | ||
select {gCargoSet} | select {gCargoSet} | ||
− | gBusy = | + | gBusy = false |
} | } | ||
} | } | ||
− | # Bound to ALT-LEFT-DOWN by | + | # Bound to ALT-LEFT-DOWN by tug_enable_drag |
− | function | + | function tug_mark_mb() { |
gMouseX = _mouseX | gMouseX = _mouseX | ||
gMouseY = _mouseY | gMouseY = _mouseY | ||
− | gNewDrag = | + | gNewDrag = true |
} | } | ||
− | # Called by | + | # Called by tug_cargo_mb |
− | function | + | function tug_enable_drag() { |
gEcho = "__________TUG__________|ALT-CLICK=mark block|SHIFT-CLICK=anchors" + | gEcho = "__________TUG__________|ALT-CLICK=mark block|SHIFT-CLICK=anchors" + | ||
"|ALT-CTRL-CLICK=pivots|ALT-SHIFT-CLICK=dest atom|ALT-DRAG=move" + | "|ALT-CTRL-CLICK=pivots|ALT-SHIFT-CLICK=dest atom|ALT-DRAG=move" + | ||
− | "|SHIFT | + | "|ALT-SHIFT-DRAG=alt move|CLICK bond=freeze|ALT-DOUBLE-CLICK=undo" + |
+ | "|SHIFT-DOUBLE-CLICK=exit" | ||
echo @gEcho | echo @gEcho | ||
# Allow atoms to be dragged | # Allow atoms to be dragged | ||
− | bind "ALT-LEFT-DOWN" " | + | bind "ALT-LEFT-DOWN" "tug_mark_mb"; |
− | bind "ALT-LEFT-UP" " | + | bind "ALT-LEFT-UP" "tug_drag_done_mb"; |
− | bind "ALT-SHIFT-LEFT-DOWN" " | + | bind "ALT-SHIFT-LEFT-DOWN" "tug_mark_mb"; |
− | + | bind "ALT-LEFT-DRAG" "tug_drag_mb"; | |
− | bind "ALT-LEFT-DRAG" " | + | bind "ALT-SHIFT-LEFT-DRAG" "tug_drag_2_mb"; |
− | bind "ALT-SHIFT-LEFT-DRAG" " | ||
unbind "SHIFT-LEFT-CLICK" | unbind "SHIFT-LEFT-CLICK" | ||
bind "SHIFT-LEFT-CLICK" "_pickAtom"; | bind "SHIFT-LEFT-CLICK" "_pickAtom"; | ||
− | bind "SHIFT-LEFT-CLICK" "+: | + | bind "SHIFT-LEFT-CLICK" "+:tug_anchor_mb"; |
bind "ALT-CTRL-LEFT-CLICK" "_pickAtom"; | bind "ALT-CTRL-LEFT-CLICK" "_pickAtom"; | ||
− | bind "ALT-CTRL-LEFT-CLICK" "+: | + | bind "ALT-CTRL-LEFT-CLICK" "+:tug_pivot_mb"; |
bind "ALT-SHIFT-LEFT-CLICK" "_pickAtom"; | bind "ALT-SHIFT-LEFT-CLICK" "_pickAtom"; | ||
− | bind "ALT-SHIFT-LEFT-CLICK" "+: | + | bind "ALT-SHIFT-LEFT-CLICK" "+:tug_dest_atom_mb"; |
} | } | ||
− | # Bound to SHIFT-LEFT-CLICK by | + | # Bound to SHIFT-LEFT-CLICK by tug_cargo_mb |
− | function | + | function tug_anchor_mb() { |
if ({atomIndex=_atomPicked}.chain == gChain) { | if ({atomIndex=_atomPicked}.chain == gChain) { | ||
− | var aPidx = | + | var aPidx = get_sc_bb_idx( _atomPicked, gChain) |
var pno = {atomIndex=aPidx}.atomno | var pno = {atomIndex=aPidx}.atomno | ||
Line 1,761: | Line 1,772: | ||
halo on | halo on | ||
} | } | ||
− | + | collect_bb_rotors(false) | |
} | } | ||
else if (pno < {atomIndex=gNcargoIdx}.atomno) { | else if (pno < {atomIndex=gNcargoIdx}.atomno) { | ||
Line 1,776: | Line 1,787: | ||
halo on | halo on | ||
} | } | ||
− | + | collect_bb_rotors(true) | |
} | } | ||
else { | else { | ||
− | + | tow_cargo_mb() | |
} | } | ||
# Get moving atoms set | # Get moving atoms set | ||
gMovingSet = {((atomno < gCanchorNo) and (atomno > gNanchorNo) | gMovingSet = {((atomno < gCanchorNo) and (atomno > gNanchorNo) | ||
− | and (chain=gChain))} | + | and (chain=gChain) and thisModel)} |
} | } | ||
select {gCargoSet} | select {gCargoSet} | ||
} | } | ||
− | # Bound to ALT-SHIFT-LEFT-CLICK by | + | # Bound to ALT-SHIFT-LEFT-CLICK by tug_cargo_mb |
− | function | + | function tug_dest_atom_mb() { |
− | var aOk = | + | var aOk = true |
if ({atomIndex=_atomPicked}.chain == gChain) { | if ({atomIndex=_atomPicked}.chain == gChain) { | ||
var pno = {atomIndex=_atomPicked}.atomno | var pno = {atomIndex=_atomPicked}.atomno | ||
− | if ((pno <= {atomIndex=gCcargoIdx}.atomno) and (pno >= {atomIndex=gNcargoIdx}.atomno)) { | + | if ((pno <= {atomIndex=gCcargoIdx}.atomno) |
− | aOk = | + | and (pno >= {atomIndex=gNcargoIdx}.atomno)) { |
+ | aOk = false | ||
} | } | ||
} | } | ||
Line 1,814: | Line 1,826: | ||
} | } | ||
− | # Bound to CTRL-LEFT-CLICK by | + | # Bound to CTRL-LEFT-CLICK by tug_cargo_mb |
− | function | + | function tug_pivot_mb() { |
if (g1pivotIdx == _atomPicked) { | if (g1pivotIdx == _atomPicked) { | ||
color {atomIndex=g1pivotIdx} @gScheme | color {atomIndex=g1pivotIdx} @gScheme | ||
Line 1,821: | Line 1,833: | ||
g1pivotIdx = g2pivotIdx | g1pivotIdx = g2pivotIdx | ||
g2pivotIdx = -1 | g2pivotIdx = -1 | ||
+ | g2dynamicIdx = -1 | ||
} | } | ||
else { | else { | ||
g1pivotIdx = -1 | g1pivotIdx = -1 | ||
+ | g1dynamicIdx = -1 | ||
} | } | ||
} | } | ||
Line 1,829: | Line 1,843: | ||
color {atomIndex=g2pivotIdx} @gScheme | color {atomIndex=g2pivotIdx} @gScheme | ||
g2pivotIdx = -1 | g2pivotIdx = -1 | ||
+ | g2dynamicIdx = -1 | ||
} | } | ||
else if (g1pivotIdx >= 0) { | else if (g1pivotIdx >= 0) { | ||
Line 1,836: | Line 1,851: | ||
g2pivotIdx = _atomPicked | g2pivotIdx = _atomPicked | ||
+ | g2dynamicIdx = -1 | ||
color {atomIndex=g2pivotIdx} green | color {atomIndex=g2pivotIdx} green | ||
} | } | ||
else { | else { | ||
g1pivotIdx = _atomPicked | g1pivotIdx = _atomPicked | ||
+ | g1dynamicIdx = -1 | ||
color {atomIndex=g1pivotIdx} green | color {atomIndex=g1pivotIdx} green | ||
} | } | ||
Line 1,845: | Line 1,862: | ||
} | } | ||
− | # Bound to SHIFT-LEFT-CLICK by | + | # Bound to SHIFT-LEFT-CLICK by plico_tug |
− | function | + | function tow_cargo_mb() { |
− | gTow = | + | gTow = true |
gChain = {atomIndex=_atomPicked}.chain | gChain = {atomIndex=_atomPicked}.chain | ||
− | gMinNo = {chain=gChain}.atomno.min | + | gMinNo = {(chain=gChain) and thisModel}.atomno.min |
− | gMaxNo = {chain=gChain}.atomno.max | + | gMaxNo = {(chain=gChain) and thisModel}.atomno.max |
gCcargoIdx = -1 | gCcargoIdx = -1 | ||
gNcargoIdx = -1 | gNcargoIdx = -1 | ||
Line 1,859: | Line 1,876: | ||
# Highlight cargo cluster | # Highlight cargo cluster | ||
− | select {chain=gChain} | + | select {(chain=gChain) and thisModel} |
gCargoSet = {selected} | gCargoSet = {selected} | ||
gMovingSet = {selected} | gMovingSet = {selected} | ||
− | + | set_colors() | |
# Enable dragging | # Enable dragging | ||
− | + | tug_enable_drag() | |
select {gCargoSet} | select {gCargoSet} | ||
halo off | halo off | ||
Line 1,872: | Line 1,889: | ||
unbind "SHIFT-LEFT-CLICK" | unbind "SHIFT-LEFT-CLICK" | ||
bind "SHIFT-LEFT-CLICK" "_pickAtom"; | bind "SHIFT-LEFT-CLICK" "_pickAtom"; | ||
− | bind "SHIFT-LEFT-CLICK" "+: | + | bind "SHIFT-LEFT-CLICK" "+:tow_cargo_mb"; |
} | } | ||
− | # Bound to ALT-LEFT-CLICK by | + | # Bound to ALT-LEFT-CLICK by plico_tug or called by plicotoab.toabCargoMB |
− | function | + | function tug_cargo_mb() { |
# If O or movable side chain atom picked | # If O or movable side chain atom picked | ||
− | if (({atomIndex=_atomPicked}.atomName = "O") | + | if ((({atomIndex=_atomPicked}.atomName = "O") |
− | or ( | + | and ({atomIndex=_atomPicked}.group != "PRO")) |
+ | or (is_moveable_sc( _atomPicked))) { | ||
if (gSCidx >= 0) { | if (gSCidx >= 0) { | ||
draw gSCcircle DELETE | draw gSCcircle DELETE | ||
Line 1,896: | Line 1,914: | ||
if ({atomIndex=_atomPicked}.chain != gChain) { | if ({atomIndex=_atomPicked}.chain != gChain) { | ||
if (gTow) { | if (gTow) { | ||
− | select {chain=gChain} | + | select {(chain=gChain) and thisModel} |
color {selected} @gScheme | color {selected} @gScheme | ||
} | } | ||
Line 1,908: | Line 1,926: | ||
gNanchorIdx = -1 | gNanchorIdx = -1 | ||
} | } | ||
− | gTow = | + | gTow = false |
− | gMinNo = {chain=gChain}.atomno.min | + | gMinNo = {(chain=gChain) and thisModel}.atomno.min |
− | gMaxNo = {chain=gChain}.atomno.max | + | gMaxNo = {(chain=gChain) and thisModel}.atomno.max |
if (gNanchorIdx < 0) { | if (gNanchorIdx < 0) { | ||
gNanchorNo = gMinNo - 1 | gNanchorNo = gMinNo - 1 | ||
Line 1,917: | Line 1,935: | ||
gCanchorNo = gMaxNo + 1 | gCanchorNo = gMaxNo + 1 | ||
} | } | ||
− | var aPidx = | + | var aPidx = get_sc_bb_idx( _atomPicked, gChain) |
gSCidx = -1 | gSCidx = -1 | ||
Line 1,931: | Line 1,949: | ||
# If nWard cargo exists, mark it as the cWard cargo | # If nWard cargo exists, mark it as the cWard cargo | ||
if (gNcargoIdx != gCcargoIdx) { | if (gNcargoIdx != gCcargoIdx) { | ||
− | gCcargoIdx = | + | gCcargoIdx = get_cp_idx(gNcargoIdx) |
gCcargoNo = {atomIndex=gCcargoIdx}.atomno | gCcargoNo = {atomIndex=gCcargoIdx}.atomno | ||
} | } | ||
Line 1,942: | Line 1,960: | ||
select {atomIndex=gNcargoIdx} | select {atomIndex=gNcargoIdx} | ||
halo off | halo off | ||
− | gNcargoIdx = | + | gNcargoIdx = get_nm_idx(gCcargoIdx) |
gNcargoNo = {atomIndex=gNcargoIdx}.atomno | gNcargoNo = {atomIndex=gNcargoIdx}.atomno | ||
} | } | ||
Line 1,959: | Line 1,977: | ||
# Set new nWard cargo and highlight it | # Set new nWard cargo and highlight it | ||
− | gNcargoIdx = | + | gNcargoIdx = get_nm_idx(aPidx) |
gNcargoNo = {atomIndex=gNcargoIdx}.atomno | gNcargoNo = {atomIndex=gNcargoIdx}.atomno | ||
} | } | ||
Line 1,973: | Line 1,991: | ||
# Set new cWard cargo and highlight | # Set new cWard cargo and highlight | ||
− | gCcargoIdx = | + | gCcargoIdx = get_cp_idx(aPidx) |
gCcargoNo = {atomIndex=gCcargoIdx}.atomno | gCcargoNo = {atomIndex=gCcargoIdx}.atomno | ||
} | } | ||
Line 1,982: | Line 2,000: | ||
# Set new cWard cargo and highlight | # Set new cWard cargo and highlight | ||
− | gCcargoIdx = | + | gCcargoIdx = get_cp_idx(aPidx) |
gCcargoNo = {atomIndex=gCcargoIdx}.atomno | gCcargoNo = {atomIndex=gCcargoIdx}.atomno | ||
− | gNcargoIdx = | + | gNcargoIdx = get_nm_idx(gCcargoIdx) |
gNcargoNo = {atomIndex=gNcargoIdx}.atomno | gNcargoNo = {atomIndex=gNcargoIdx}.atomno | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
Line 2,009: | Line 2,017: | ||
# Highlight cargo cluster | # Highlight cargo cluster | ||
− | + | select_nward_idx(gCcargoIdx, gNcargoIdx) | |
gCargoSet = {selected} | gCargoSet = {selected} | ||
− | + | set_colors() | |
# Collect the rotor sets | # Collect the rotor sets | ||
− | + | collect_rotors() | |
# Get moving atoms set | # Get moving atoms set | ||
gMovingSet = {((atomno < gCanchorNo) and (atomno > gNanchorNo) | gMovingSet = {((atomno < gCanchorNo) and (atomno > gNanchorNo) | ||
− | and (chain=gChain))} | + | and (chain=gChain) and thisModel)} |
} | } | ||
# Enable dragging | # Enable dragging | ||
− | + | if (gToab) { | |
+ | to_ab_enable_drag() | ||
+ | } | ||
+ | else { | ||
+ | tug_enable_drag() | ||
+ | } | ||
select {gCargoSet} | select {gCargoSet} | ||
+ | } | ||
+ | |||
+ | function tug_undo_mb() { | ||
+ | if (prompt("Undo", "Yes|No", true) == "Yes") { | ||
+ | restore state gState | ||
+ | } | ||
} | } | ||
# Top level of Tug | # Top level of Tug | ||
− | function | + | function plico_tug() { |
− | # | + | # Load common functions if not already |
− | + | if (kCommon < 7) { | |
− | if ( | + | script $SCRIPT_PATH$plicoCommon.spt |
− | + | if (kCommon < 7) { | |
− | + | prompt ("A newer version of plicoCommon.SPT is required") | |
− | |||
quit | 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" + | gEcho = ("_________TUG_________|ALT-CLICK=mark block|SHIFT-CLICK=mark chain" + | ||
− | "|DOUBLE-CLICK=exit") | + | "|CLICK bond=freeze|ALT-DOUBLE-CLICK=undo|SHIFT-DOUBLE-CLICK=exit") |
echo @gEcho | echo @gEcho | ||
gCrotors = array() | gCrotors = array() | ||
gNrotors = array() | gNrotors = array() | ||
− | + | clear_atom_idxs() | |
− | + | gToab = false | |
− | |||
bind "ALT-LEFT-CLICK" "_pickAtom"; | bind "ALT-LEFT-CLICK" "_pickAtom"; | ||
− | bind "ALT-LEFT-CLICK" "+: | + | 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 "DOUBLE" " | + | bind "ALT-LEFT-DOUBLE" "tug_undo_mb"; |
+ | bind "SHIFT-DOUBLE" "tug_exit(true)"; | ||
+ | bind "LEFT-CLICK" "+:plico_menu_toggle"; | ||
} | } | ||
− | # Bound to DOUBLE by | + | # Bound to DOUBLE by plico_tug |
− | function | + | function tug_exit() { |
− | + | if (plico_exit()) { | |
− | + | set bondPicking gBondPicking | |
− | + | set PickCallback NONE | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | set | ||
− | |||
select all | 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</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