Hot Ket to Cycle through Snap Positions

Case number:845813-988100
Topic:Game: Tools
Opened by:TheGUmmer
Status:Closed
Type:Suggestion
Opened on:Thursday, July 29, 2010 - 00:50
Last modified:Friday, October 15, 2010 - 10:22

In the selection interface would it possible to have a hot key to cycle through a segments sidechain snap positions. Sometimes I have a hard time trying to move the longer sidechains into the position I would like.

(Thu, 07/29/2010 - 00:50  |  30 comments)


Joined: 05/09/2008
Groups: Void Crushers
Status: Open » Closed

Never mind. It has benn point out to me that it is already there. Ctrl key and the left and right movement (arrow) keys.

Joined: 04/22/2009
Groups: None

Is this in the help screen? I didn't see it and tried to write a script to do it (but it turns out that's impossible).

Joined: 09/18/2009
Groups: SETI.Germany

@photoelectric:
If you want to do it by script, use the

do_sidechain_snap(segment index, snap index)

function. with

get_sidechain_snap_count(segment index)

you get the number of snaps (rotamers) for the selected segment index.

Joined: 09/18/2009
Groups: SETI.Germany

Mouse over the segment you want to change and press TAB, and you will see the segment index number.

Joined: 09/18/2009
Groups: SETI.Germany

For example,

l=get_sidechain_snap_count(1)
if l>0 then
for k=1,l do
do_sidechain_snap(1,k)
end -- k
end -- l

will cycle through all possible rotamers of the very first segment.

Tlaloc's picture
User offline. Last seen 1 day 10 hours ago. Offline
Joined: 08/04/2008
Groups: Mojo Risin'

A couple of notes, though:

1) The hot keys to cycle only works in the new interface

2) There is no need for the 'if' in the code above. You can just write it like this:

local segment = 1
for i=1, get_sidechain_snap_count(segment)
    do_sidechain_snap(segment, i)
end

A 'for' loop will be skipped if the number returned from get_sidechain_snap_count() is zero. Lua only executes the get_sidechain_snap_count() once, too.

3) Be warned, though, if you do anything that manipulates the backbone inside the loop (wiggle all, for example), it can change the number of possible snap positions. If this reduces the number of snap positions, your code will break. For example, this code will periodically cause runtime errors, in a non-deterministic way:

local segment = 1
for i=1, get_sidechain_snap_count(segment)
    do_sidechain_snap(segment, i)
    do_global_wiggle_all(1)
end
Joined: 09/18/2009
Groups: SETI.Germany

Glycine has 1 snap position, not 0, right?

Joined: 09/18/2009
Groups: SETI.Germany

To prevent this error, I would do it this way:

local segment = 1
for i=1, get_sidechain_snap_count(segment)
if i<=get_sidechain_snap_count(segment) then
do_sidechain_snap(segment, i)
do_global_wiggle_all(1)
end
end

Joined: 09/18/2009
Groups: SETI.Germany

Okay, it's a little bit clumsy to get the number of snap positions twice, but it prevents this error.

Joined: 09/18/2009
Groups: SETI.Germany

local segment = 1
i=1
repeat
do_sidechain_snap(segment, i)
do_global_wiggle_all(1)
i=i+1
until i>get_sidechain_snap_count(segment)

is safe.

Joined: 08/06/2010
Groups: Contenders

It turns out I got an error on:

for i=1, get_sidechain_snap_count(segment)
do_sidechain_snap(segment, i)
end

in puzzle 366. It looks like the test for zero is needed.
Unless Repeat... until tests at the top of the loop it would fail as well.

My final position on 366 will reveal this error using Gary MutateAll v0.2.
I wonder why the replace_aa didn't throw the error if there are no snap positions.

Joined: 09/18/2009
Groups: SETI.Germany

Then, do it this way:

local segment = 1 -- The segment index you want
i=1
while i<=get_sidechain_snap_count(segment) do
do_sidechain_snap(segment, i)
do_global_wiggle_all(1)
i=i+1
end

Joined: 09/18/2009
Groups: SETI.Germany

Replace only sets the sidchain shape at sets a snap position automatically, so the error can't occur then.

At which segment index # does it occur and which amino-acid shape does it have then?

It can also be that a try to snap locked (grey) segments can cause an error.
Possible, that with get_sidechain_snap_count() you get a value above 0, but if you try to execute snapping, you get an error because the segment is locked in this puzzle.

We need a function that tells lua if a backbone or sidechain is locked, similar to the do_freeze() command, but working not to set but to fetch values.

Joined: 08/06/2010
Groups: Contenders

Good replacement code. Thanks.

I tried using snapcount on sidechains to identify locked sidechains but it returns a number > 1 even though locked. I don't yet know what happens if one attempts to snap a frozen or locked sidechain.

Joined: 09/18/2009
Groups: SETI.Germany

Under which conditions does snapcount 0 occurr?
Can somebody show how to reproduce it?
I only know that it CAN happen (had it also long time ago, but didn't investigate further then), so this is why I added zero check before I had the idea for this simpler way.

Tlaloc is right.
Lua doesn't execute a "for" loop if running range and stepsize don't fit together.
I didn't know this detail and just wanted to make sure, because there are programming languages, which do this check at the loop end (similar like a repeat-until-block), and not at the beginning.

So, I learned something more, thanks.

Joined: 08/06/2010
Groups: Contenders

OK, we're looking at a changing background.

I did this test on 367:

x=get_segment_count()
print (x)
deselect_all()
select_index(x)
do_local_wiggle(1)
print(get_sidechain_snap_count(x))
do_sidechain_snap(x,1)
for y=1,0 do
print (y)
end
for y=1,0,-1 do
print(y)
end

It went into a long pause but didn't throw an error.
When I tried it again it didn't even go into the long puase but just
returned:
490
1
1
0

So this doesn't explain the error when attempting to do the snap.

I've tried reproducing the case with snapcount=0 on 366 but haven't found it yet
and am at 8 of 17 mutable segments. I thought it failed on the 4th.

It's a mystery.

Joined: 09/18/2009
Groups: SETI.Germany

Well, as there is 1 snap position and you do this one snap, this can't produce the error.

Let's see:
You get the number of segments and store it in x, printing it results 490.
You get the snap count of segment x=490 (last segment), it's 1 printed.
you do snapping of segment x=490 and use snap position 1, which is in an aceptable range.

for y=1,0 is skipped completely.
for y=1,0,-1 works and prints out 1 and 0.

The long pause at first run and the missing of the pause on second run is normal.
Before (a new) script starts, the code is checked for errors and translated (compiled).
Once it has been compiled successfully, this step is not done again if the script is run another time.

You can even change some values and the script will start earlier than on the first run.

Joined: 08/06/2010
Groups: Contenders

The puzzle is a ligand puzzle. The last segement is supposed to be a ligand. I thought something was suppsed to fail on the ligand. It appears to have a snap count and can be snapped. Since I cannot reproduce the error running the same script on the same puzzle with the same starting score (use by tlaloc and my derivatve scripts as seed for random) I suspect something has changed elsewhere. Though it doesn't mean much my restore to best on 367 is down one point from my creditted best and my own recollection of it. There's too many moving parts to know what's going on so I'll just write it off for now. Since the for loop tests at beginning of loop I don't know why snap would fail. I've used the same script on many puzzles. That it would fail several times at the same place but doesn't fail now is just a mystery. Not all mysteries need to be solved. At least I can rule out snap count of 0. Why snap would fail when index is in the range indicated by snap count is beyond me and doesn't really matter any more. Next time I'll document better. Maybe there won't be a next time. An error saying the index is out of range without giving the index or range isn't too helpful. As far as I know there's no debugger I can enter so as to recover the values once the program abends.

Joined: 09/18/2009
Groups: SETI.Germany

Yes, but you could print segment index and snap position before you execute snapping.
I'll take the example above again:

local segment = 1 -- The segment index you want
i=1
while i<=get_sidechain_snap_count(segment) do
print("segment:",segment," snap:",i)
do_sidechain_snap(segment, i)
do_global_wiggle_all(1)
i=i+1
end

So, if snapping fails, you will have printed out what was tried before.

As you say ligand puzzle, keep in mind that you can't change the "amino-acid" of a ligand.
On all ligand puzzles, replace_aa() of the last segment produces an error.

Joined: 09/18/2009
Groups: SETI.Germany

But some words for comfort:
I created a script which does snapping and wiggling, but it turned out that it didn't make big points:
http://fold.it/portal/recipe/6235

So, sticked on using shake again (which is some kind of auto-snapping).

Joined: 08/06/2010
Groups: Contenders

If I had been able to reproduce the error I would have created special code since I'm already identifying segment#, old amino and new before I try the snaps. I didn't want to modify the code until I could reprodcue segment and amino since it could cause different behavior. The fewer changes the better.

I'll try using pcall to see if foldit's lua implementation can trap the ligand when mutating last sement. My energy doesn't let me do as much as I'd like. If I can trap the error I can set a global indicating the puzzle is a ligand puzzle. If I could detect snap position I could detect locked sidechains in a similar way to identifying mutable segments. I'm pretty sure I could just go though the snap positions and see if score changed. If score doesn't change the segment's sidechain is locked. Since a recient puzzle has some unlocked sidechains on immutable segments this would be helpful knowledge in improving score.

Joined: 09/18/2009
Groups: SETI.Germany

What is pcall?

At the moment, I do it this way to identify a ligand puzzle:
http://fold.it/portal/recipe/13246

Right, by changing snap positions and watching score, you can check if the current sidechain you are working on is locked or not.

But the best would be if there were any functions which can tell us this.
See, the game already "knows" what is allowed and what not, so testing it again to transfer this information to Lua's guts is always some kind of double-doing to me.

regards,
Alex

Joined: 08/06/2010
Groups: Contenders

It seems like one could call x=pcall(replace_aa, 'a') and find out if it threw an error. I haven't tried this yet. Too much to do when I get home to try everything at once.

from: http://www.lua.org/manual/5.1/manual.html#pdf-pcall

pcall (f, arg1, ยทยทยท)
Calls function f with the given arguments in protected mode. This means that any error inside f is not propagated; instead, pcall catches the error and returns a status code. Its first result is the status code (a boolean), which is true if the call succeeds without errors. In such case, pcall also returns all results from the call, after this first result. In case of any error, pcall returns false plus the error message.

xpcall (f, err)
This function is similar to pcall, except that you can set a new error handler.

xpcall calls function f in protected mode, using err as the error handler. Any error inside f is not propagated; instead, xpcall catches the error, calls the err function with the original error object, and returns a status code. Its first result is the status code (a boolean), which is true if the call succeeds without errors. In this case, xpcall also returns all results from the call, after this first result. In case of any error, xpcall returns false plus the result from err.

Joined: 09/18/2009
Groups: SETI.Germany

Sounds helpful, but as far I've read this function is part of the Lua basic library, which is not included in Foldit at the moment.

So, again a vote for the standard Lua library.

Joined: 08/06/2010
Groups: Contenders

I'll verify this evening if it works or not. Lunch is over so I've got to go back to work.
I can understand limitations that prevent me from writing to disk even though that would be very helpful but basic error trapping seems of little risk to security. I guess I could try the roundabout

x=assert(replace_aa('g') == nil, 'who knows it might work')

assert is implented. I've seen it used in tlaloc's scripts.

Joined: 08/06/2010
Groups: Contenders

I don't know if it's generally true but on 367:

print(get_ss(get_segment_count()))

returns M. Wouldn't that be simple?

pcall isn't implemented.
assert didn't trap the error.

Joined: 09/18/2009
Groups: SETI.Germany

Not E for sheet, H for helix or L for loop, it's M (mixed?), really :)

You had a good intuition!

Yes, it would be good, if this would be the case for all ligand puzzles.
Makes it very simple to fetch if there is a ligand.

Joined: 09/18/2009
Groups: SETI.Germany

Maybe we should ask the developers if it is always the case.

Joined: 08/06/2010
Groups: Contenders

OK, Here's the problem. I'll show three pictures. Look at the recipe output.

OK, I'll switch to the repeat loop but why would the snap count change when snapping
through the possibilities?

Joined: 08/06/2010
Groups: Contenders

Now that I think about it, I understand why Tlaloc restarts snapping at 1 after finding a new best. The snaps may be to different positions after a new best is found unless one starts from the saved position rather than the new best.

Sitemap

Developed by: UW Center for Game Science, UW Institute for Protein Design, Northeastern University, Vanderbilt University Meiler Lab, UC Davis
Supported by: DARPA, NSF, NIH, HHMI, Amazon, Microsoft, Adobe, RosettaCommons