The problem of folding proteins is an inherently geometrically hard problem.
People have been found to have intuitive ideas on what the shape of the protein should look like. The game Fold.it was created to allow people to express this intuition.
The 3D shape of the protein is the most important property of a protein. The shape allows scientists to determine how the protein functions.
So how is all this something for a computer science blog?
Fold.It introduced a scripting language to allow repetitive folding tasks to be automated. There is a GUI scripting tool and a Lua scripting tool.
The Lua language allowed with Fold.it is a subset of the official langue. http://www.lua.org/ with an additional API for folding and client functions.
At Fold.it, a Lua script is called a 'recipe'.
Below is a user's guide for the Fold.it Lua Version 2.0. There was a version 1.0. It has been deprecated. Old version 1.0 scripts can still be run, but one cannot create new 1.0 scripts or modify 1.0 scripts without upgrading to version 2.0 API.
See the following two Lua recipes for the mapping of Lua 1.0 to Lua 2.0 functions. You will need to be running the Fold.it client in order to get a human readable version of the recipes.
http://fold.it/portal/recipe/43867
http://fold.it/portal/recipe/31012
Fold.it Lua 2.0 API
Lua V2.0 is the fold.it 'programming' language. It is a subset of the Lua 5.0 language. http://lua.org with an additional API.
The standard Lua 5.0 functions supported in Fold.it Lua V2.0 are found at http://foldit.wikia.com/wiki/Lua_Standard_Libraries.
The reader is expected to be familiar with how to run the Fold.it GUI client. Terminology here is the same as that found in the GUI.
The reader is also expected to have an understanding of programming and the syntax of Lua. If you are new to programming or Lua, please read here first, and elsewhere. http://foldit.wikia.com/wiki/Lua_Scripting
Programming Note: One does not have the ability to use libraries, other than those in the Lua standard libraries, or refer other files in a Fold.it Lua V2.0 script. A Fold.it Lua script is one large file. Thus it is a good habit to keep a file that contains all the custom functions you have written and will need from script to script and simply paste them into the top of each new script you write.
Short Example
When using the Fold.it client, one can hover over a segment and press <tab>.
This brings up a note.
Showing segment information for segment #15, Glycine The segment had been mutated as its original amino acide was Iosleucine |
This note has information about the protein at the segment hovered. It has the segment number and the amino acid of the segment. It has the segment score. It also has a list of additional values: clashing,
pairwise (sometimes), packing, hiding, bonding, sidechain, and reference. This information can be obtained using Lua V2.0 objects and functions.
segmentindex = 15
current.GetSegmentEnergySubscore(segmentindex, "packing")
will return the packing value of segmentindex. The image above shows a packing score of 34.2.
Segments are referred to by the term segmentindex. This number runs from 1 to the number of segments in the protein.
structure.GetCount()returns the number of segments in the protein.
structure.GetAminoAcid(segmentindex)returns a single lowercase letter representing the amino acid for a particular segment index. The letter follows the standard as shown at this link http://en.wikipedia.org/wiki/Amino_acid and http://foldit.wikia.com/wiki/Lua_Script_Library
If there are ligands in the puzzle, then the ligand is given a secondary structure with the capital letter 'M, and it located at the last segment of the protein. One needs to decrease the segment count by one if a ligand exists.
function filib.GetProteinSegCount()
segCount = structure.GetCount()
-- ligand is 'M' at the last segment of the protein
isLigand =(structure.GetSecondaryStructure(game.segCount))
if isLigand == 'M' then
segCount = segCount - 1
end
return segCount
end
Fold.it Lua V2 Objects
Fold.it Lua V2 uses objects to group functions. The list of objects are:
- absolutebest
- band
- behavior
- contactmap
- creditbest
- current
- dialog
- freeze
- puzzle
- recentbest
- recipe
- rotamer
- save
- scoreboard
- selection
- structure
- user
- ui
The objects and their functions fall into three broad categories,
- those functions that get information ("getters)
- those functions that set information ("setters)
- those functions that physically change the puzzle ("doers").
The objects that strictly retrieve information ("getters" only) are:
Note: The 'puzzle' object has one function that does change the puzzle ("doer"), StartOver().
The objects that get and set information ("getters and setters") and are "doers" are:
- behavior
- dialog
- recipe
- save
- structure
- freeze
- band
The structure and rotamer objects retrieve information of the protein and
provide the functions to manipulate the protein directly.
The contactmap object is used during exploration puzzles.
[Don't know if the script can determine if the puzzle is an explorations puzzle?]
The recipe and save objects provide storage of information to measure progress and restore previous poses.
The behavior object is the same as the Behavior/Clash Importance GUI feature.
The freeze and band objects add additional items to the puzzle to help manipulate the protein, similar to the GUI freeze and band features.
The dialog object helps the Lua V2.0 script writer communicate with the user. This is a new feature with version 2.0
GUI Features and Lua functions
The Fold.it functions provide access to most, but not all of the same GUI features found in the client.
The GUI controls that are not available in Lua V2.0 are:
- The 'Undo' GUI feature is not available in the Lua V2.0. One cannot go back through the 'undo' list using Lua V2.0 scripts.
- Tweak features are not available with Lua V2.0
As of 9Jul2013, a band cannot connect to an adjacent segment.
It will be noted when a Lua function is the same as a GUI control.
A comparison table of GUI and Lua features would be handy. I should add such a table later.
For the most current, but not detailed documentation of functions,
open the recipe editor, click on New (ScriptV2.0), then click on the
Help icon.
Also the following recipe lists Fold.it Lua functions, with a brief description. http://fold.it/portal/recipe/46122
Print and Help()
There are two miscellaneous functions, print() and help().
print() outputs to the recipe window.
print() uses the following syntax. Each argument is separated by a comma. The '+' (append) operator is not available as is found in standard Lua.
print(segmentscore," ",creditbest.GetScore())
Anytime print() is called, the string is shown on the recipe output window. It is also written to file. On Windows 7 the file is in C:\foldit\scriptlog.default.xml.
When using tracks, the name of the track will be used for the file. If the name of the track was Wigglefast, then the log file would be C:\foldit\scriptlog.Wigglefast.xml.
When using tracks, the name of the track will be used for the file. If the name of the track was Wigglefast, then the log file would be C:\foldit\scriptlog.Wigglefast.xml.
help() outputs a list of the API functions. No descriptions.
Shows number output generated by print(). Shows start of function output generated by help() |
Puzzle Score
There are four objects that refer to the puzzle's score. They are 'getters' only.
- absolutebest
- creditbest
- current
- recentbest
Each of these four objects have slightly different list of functions.
The functions below are marked with AB, CR, CU, RE, or ALL. This shows
which object supports that function.
The absolutebest, creditbest, and current objects more or less stay in sync if one is on-line. They will be different if one is working on a puzzle off-line.
[Need to document what happens with these objects when one is off-line]
AreConditionsMet() [ALL] - This is the same as at the top of the client window. Will always return true when 'No bonuses or conditions' are show in the scoring window at the top of the client screen.
This text 'No bonuses or conditions' always returns true. |
GetEnergyScore() [ALL] - This is the score shown in the score window at the top of the client.
GetExplorationMultiplier() [ALL] - Some puzzles have an exploration multiplier. This function returns that multiplier. If not an exploration puzzle, it returns 0.
GetScore() [ALL] - This is the same as GetEnergyScore(). Not sure why there are two functions. Technically the energy score gets smaller as the protein is folded more towards its natural shape.
GetSegmentEnergyScore(segmentindex) [ALL] - Get the Rosetta energy score for segmentindex. The sum of all segment scores will be 8000 points lower than the GetScore().
segscore = 0
for i=1,structure.GetCount(),1 do
segscore = segscore + creditbest.GetSegmentEnergyScore()
-- 8000 difference between scores.
print(segscore," ", creditbest.GetScore())
GetSegmentEnergySubscore(segmentindex,part) [ALL] - Get the energy score of a part of the segment. The part argument may be one of the following strings.
- "clashing"
- "packing"
- "hiding"
- "bonding"
- "backbone"
- "sidechain"
- "reference"
- "disulfides"
- "density"
This is the same list as seen in the Note when the GUI feature <tab> key is pressed when hovering over a segment. See above.
function filib.reportsegmentparts(segmentindex)
local parts =
{"clashing","pairwise","packing","bonding","hiding",
"sidechain","reference","disulfides","density"}
report = "segment#: "..segmentindex.." \n"
segment_total = 0
for i=1,#parts,1 do
partvalue =
recentbest.GetSegmentEnergySubscore(segmentindex,parts[i])
report = report .. " "..parts[i]..": "..partvalue.." \n"
segment_total = segment_total + partvalue
end
print(report)
end
Restore() [AB,CR,RE] - Load the best score of the appropriate object. Just like the GUI control.
Save() [RE] - Save the current pose as the best for recentbest only. Just like the GUI control.
All of the scoring functions are 'read-only'. The values can only be read, not changed. That would be cheating. :)
puzzle.GetDescription() - Returns the text description of the puzzle as seen in the comment section of the Select Puzzle window. The text is one long string.
puzzle.GetExpirationTime() - Can compare to current time to find out how much time is left. This time is GMT. Below is the code to display the time left, as is shown at the top of the client in the score window.
expire = puzzle.GetExpirationTime()
now = os.time()
timeleft = expire-now
print("Time left in seconds ",timeleft)
days = math.floor(timeleft/(60*60*24))
timeleft = timeleft - days*60*60*24
hours = math.floor(timeleft/(60*60))
timeleft = timeleft - hours*60*60
minutes = math.floor(timeleft/60)
timeleft = timeleft - minutes*60
seconds = timeleft
daystring = string.format("%2d",days)
hourstring = string.format("%2d",hours)
minutestring = string.format("%2d",minutes)
secondsstring = string.format("%2d",seconds)
timestring = "Time left on puzzle: "..daystring..
" days "..hourstring..":"..minutestring..":"..secondsstring
print(timestring)
puzzle.GetName() - A string is return holding the name of the puzzle.
puzzle.GetPuzzleID() - The ID of the puzzle is returned. Not certain how to use this.
puzzle.StartOver() - This is an action, not a read. It changes the puzzle. It resets the puzzle to the start pose.
scoreboard.GetGroupRank() - Can determine if recent recipe action has raised the ranking, or the ranking has fallen during the time the script was running. One's ranking can fall even if the score increased.
scoreboard.GetGroupScore() - Get group score. This is the best group score for this puzzle. Not necessarily the absolutebest.GetScore() of the puzzle.
scoreboard.GetRank(scoretype) - Get rank of this puzzle.
scoretype is a number from 0 to 3.
- 0 - SCORE_SOLOIST
- 1 -SCORE_EVOLVER
- 2 - SCORE_ALL_HANDS
- 3 - SCORE_NO_SCORE
scoreboard.GetRank(scoreboard.GetType())
Solo rank if puzzle is being run solo. Group rank if puzzle is being evolved.
scoreboard.GetScore(scoretype) - Get the score based on type.
scoreboard.GetScoreType() - Return the scoreboard type.
Thus scoreboard.GetScore(scoreboard.GetScoreType()) returns
the current score for active puzzle.
The user object holds information about the user.
GetGroupID(), GetGroupName(), GetPlayerID(), GetPlayerName().
Again read only functions. These values are changed at the http://fold.it website, under the user's profile.
The recipe object is helpful to output information to the user as the script runs.
CompareNumbers() - Return true if two real numbers are the same to the precision Lua prints. This is a useful function to determine if there has been any change in the score.
GetRandomSeed() - The value returned from this function can be input into the
standard lua function math.randomseed().
WARNING- Please read the following two links before generating random numbers.
To make sure random numbers are generated, add this code to the start of each script that requires random numbers. Seed the random number generator and ignore the first random number.
math.randomseed( os.time() )
math.random()
The three functions SectionStart(), SectionEnd(), and ReportStatus() create three XML elements:
<Section name="startname">, </SectionName>, and <SectionStatus ...>, respectively.
ReportStatus() - Reports status to recipe output window and the recipe log file.
Returns a lot of information.
SectionStart(sectionname) - Marks a section with a string name.
SectionEnd() - Returns the scoring difference between now and SectionStart(). This does not disturb recentbest, absolutebest, creditbest values.
The output of SectionStart(), SectionEnd(), and ReportStatus() are written to the file script.default.xml. This file is same file that the output of the print() function is recorded in. See print() function above.
save
The save object is helpful to create snapshots of the protein. There are 100 slots allowed.
Quickload(n) - Load snapshot in slot n.
Quicksave(n) - Save snapshot into slot n.
LoadSecondaryStructure() - Restore secondary structure stored by SaveSecondaryStructure().
SaveSecondaryStructure() - This saves the secondary structure. structure.SetSecondaryStructure(...)changes the secondary structure. Only one save slot for secondary structure.
structure
The structure object, the rotamer, and the contactmap objects tells you about the protein.
Now we're getting somewhere. :)
The functions of the structure object that retrieve information about the protein ("getters") are:
CanMutate(segmentindex,aminoacid) - Returns if a specific segment can be mutated to a specific amino acid. The aminoacid value is one of the standard one letter representations for amino acids.See http://en.wikipedia.org/wiki/Amino_acid
As of 14Mar2013,
Virtual residues will now return 'vrt'
Sugars will now return 'unk'
DNA will now return 'da' for "ADE", 'dc' for "CYT", 'dg' for "GUA", and 'dt' for "THY"
RNA will now return 'ra' for "RAD", 'rc' for "RCY", 'rg' for "RGU", and 'ru' for "URA"
GetAminoAcid(segmentindex) - Returns the aminoacid letter or letters.
GetAtomCount(segmentindex) - Returns the number of side chain atoms in a segment. For instance, glycine has no side chain atoms, so the count is zero.
GetCount() - Get the number of segments in the protein. Almost all scripts use this function. This count is for the current count. The count can change in design puzzles.
[don't know if the script can determine if the puzzle is a design puzzle]
GetDistance(segmentindex1,segmentindex2)- Get the distance between two segments.
GetNote(segmentindex) - Gets the text notes of the segment.
GetSecondaryStructure(segmentindex) - Returns E=sheet, H=helix, L=loop, M=molecule.
Note: UPPER case letters for secondary structure, lowercase for amino acids.
IsHydrophobic(segmentindex) - Is the segment index hydrophobic or hydrophilic? True- the segment is hydrophobic.
IsLocked(segmentindex) - Is the segment index locked? In some puzzles, part of the segments are locked. This can allow the script to skip segments that can't be changed.
IsMutable(segmentindex)- Returns whether a segment is mutable.
Now for the structure object functions that set information about the protein ("setters")
SetAminoAcid(segmentindex, aminoacid) - Change the segment index to the new aminoacid.
SetAminoAcidSelected(aminoacid) - Change all selected segments to the new aminoacid.
SetNote(segmentindex,string) - Place string into note section of segment.
SetSecondaryStructure(segmentindex,secondarystructure) - Change the segment index to the secondary structure, e=sheet, h=helix, l=loop, m=molecule. Letter can be uppercase or lowercase.
SetSecondaryStructureSelected(secondarystructure) - Change all selected segments to the secondary structure.
Lastly, the structure object functions that change the protein ("doers").
IdealizeSelected() - Idealize the selected segments. The selection object is used to select the segments idealized.
LocalWiggleAll(iterations,[backbone, sidechains]) - Does a local wiggle of all segments for iterations. Can be set to wiggle on the backbone or the side chains for both. Note LocalWiggleAll() is not the same as WiggleAll().
LocalWiggleSelected(iterations,[backbone,sidechains]) - Does a local wiggle of the selected segments. Can be set to wiggle the backbone or the side chains for both.
MutateSidechainsAll(iterations) - The same as the GUI 'Mutate'.
MutateSidechainsSelected(iterations)- Mutate selected segments' side chains for iterations. The selection object is used to select the segments mutated.
RebuildSelected(iterations) - Rebuild selected segments for iterations. The selection object is used to select the segments rebuilt. The GUI Rebuild automatically selects all the segments of the selected secondary structure.
ShakeSidechainsAll(iterations) - Same as GUI Shake.
ShakeSidechainsSelected(iterations)- Shakes the selected side chains.
WiggleAll()- Same as GUI Wiggle All.
WiggleAllSelected()- Wiggle All selected segments. The selection object is used select segments to wiggle.
rotamer
The rotamer object has two functions, one "getter", one "setter".
GetCount(index) - This is the number of rotamers the sidechain at index can snap to.
SetRotamer(index, position)- This sets the rotamer position for the given index. Position can be from 1 to rotamer.GetCount().
behavior
The behavior object modifies how shake and wiggle operate, "getters", and "setters".
GetClashImportance() - This gets the clash importance, or CI, a value from 0 to 1.0.
SetClashImportance(ci) - Set the CI to a value from 0 to 1.0.
GetBandStrengthMultiplier() - Get the band strength multiplier.
SetBandStrengthMultiplier(factor) - Sets the band strength multiplier, 0.5 to 1.5, +/- 50%
GetSlowFiltersDisabled() - Get true if slow filters are disabled. See SetSlowFilterDisabled()
SetSlowFiltersDisabled() - Same a GUI Behavior/Disable Slow Filters. If on, skips CPU intensive filters. Must be enabled to credit score. Disabling slow filters will make AreConditionsMet() return false.
contactmap
The contactmap object is only used for exploration puzzles, ("getter").
IsContact(index1,index2) - Are two segments in contact (within a specified minimum)?
GetHeat(index1,index2) - Get the heat of two segments. This returns a value from 0 to 1.
1 indicates all users have this pair of segments in contact.
0 indicates no users have this pair of segments in contact.
Between 0 and 1 is the percentage of users that have this pair of segments in contact.
One would expect GetHeat(n,n+1) to always return 1 for all segments of the protein.
On a non-exploration puzzle IsContact(n,n+1) returns false.
selection
One of the features of a Lua V2.0 script is to be able to manipulate the protein one segment or more
at a time. In the GUI client, one makes selections with the shift key down for freezing
one segment and right-click to select an entirestructure. Lua V2.0 can be more detailed
than the GUI.
The selection object provides the functions to select, and deselect segments for manipulation
by the structure.xxxSelected() functions.
The segments are selected using these functions.
Select(index) - Select a segment index, just one.
SelectAll() - Select all the segments, 1 to structure.GetCount()
SelectRange(index1,index2) - Select from segment index1 to segment index2, inclusive.
Deselect(index) - Deselect segment index.
DeselectAll() - Deselect all segments.
No. There is no DeselectRange(index1,index2).
The selected segments do not affect the structure.xxxAll() functions.
Only the structure.xxxSelected() functions act on the selected segments.
There is only one set of selected segments.
One has to create storage in your Lua V2.0 script to hold more than one list
of segments to be selected and call DeselectAll() each time you want to use it.
freeze
The freeze object modifies the properties of the protein. It is just like the GUI feature.
A Lua V2.0 program must select a sub-structure to freeze the whole sub-structure.
The GUI just requires a right-click followed by a freeze.
The freeze functions are:
Freeze(index,backbone,sidechain) - The segment index is frozen. The backbone may be frozen. The sidechain may be frozen, or both. If neither are selected, nothing happens.
FreezeAll() - Freezes all segments, both backbone and sidechains.
integer, integer GetCount() - Get the count of the number of segments frozen. This is an unusual function, as it returns two values instead of one. The first value is the backbone frozen count. The second value is the sidechain frozen count.
boolean, boolean IsFrozen(segment index) - Is the backbone or sidechain of the segment index frozen?
UnfreezeAll() - Unfreeze all backbones and sidechains.
band
The band manipulates the bands. In the GUI, if one right-clicks on a band,
one sees the list of options, enable/disable, set length, set strength, delete.
These options are also available in the band object, and with more range
to strength and length.
Bands are numbered starting at 1. Each time a band is created a number is assigned.
The function that created the band returns the band number of the new band.
The default length of a band is 3.5. The default strength of a band 1.0.
Call SetGoalLength() and SetStrength() to change these values after creating a band.
When a band is created it is automatically enabled. Call Disable() to disable band.
Add(segmentOrigin, segmentXaxis, segmentYaxis, rho, phi, [atomindexorigin],[atomXaxis],[atomYaxis])
This produces a band that ends in empty space. This is the only 3-D function in Lua V2.
See http://foldit.wikia.com/wiki/Foldit_Lua_Function_band.Add for details.
AddBetweenSegments(index1,index2,[atomindex1],[atomindex2])
A band is drawn between the two segments or between the two atom indices
of the two segments. The band length is structure.GetDistance(index1,index2) or close there to.
AddBetweenSegments(4,10,1,2) will create a band between segments 4 atom index 1 and segment 10 atom index 2. The maximum value of atom index for segment 4 is structure.GetAtomCount(4) and for segment 10 is structure.GetAtomCount(10).
AddToBandEndpoint(segmentindex, bandindex,[atomindex])
A band from segment index or atom index of segment index to the endpoint of bandindex band. This only applies to bands created that end in empty space.
Delete(bandindex) - Delete band index band.
DeleteAll() - Delete all bands. Same as GUI Remove All Bands.
Disable(bandindex) - Disables band index band. Same as right-click on band, disable.
DisableAll() - Disable all bands.
Enable(bandindex) - Enable band index band. Same as right-click on band, enable.
EnableAll() - Enable all the bands.
GetCount() - Get the count of the number of bands.
GetGoalLength() - This is the 'true' length of the band, at which length the band
neither pushes or pulls. See SetGoalLength().
GetLength(bandindex) - Get the current length of the band.
GetStrength(bandindex) - Get the strength of the band. See SetStrength()
IsEnabled(bandindex) - Is the band enabled?
SetGoalLength(index,length) - Set the 'true' length of the band. A value from 0 to 1000.
If the band is less than this length, GetLength(index) < GetGoalLength(index), then the band pushes the endpoints apart. If GetLength(index) > GetGoalLength(index), then the band pulls the endpoints inward.
SetStrength(bandindex,strength) - Set the band strength.
ui
The ui dialog allows the Lua V2.0 scripts to move the puzzle around on screen in a limited way.
AlignGuide(segmentindex) - This is the same as the GUI feature. Align the protein with
the guide at the segment index.
CenterViewport() - This is the same as the GUI feature, HOME. Useful to make
sure the user can see the protein after many iterations.
GetPlatform() - Gets the 'OS' the client (script) is running on.
win_x86 is one response.
GetTrackName() - Gets the track name. This gets the name of the current track.
GUI allows user to create independent tracks. Since each track must be unique from puzzle to puzzle, some naming convention must be agreed to with the user so that the script doesn't have to change with each puzzle if the script is to use a particular track.
puzzle.GetPuzzleName() or puzzle.GetPuzzleID() could provide a 'root' and then append standard suffixes for all puzzles. Without a GetTrackNameList() or a SetTrackName(), this function seems limited without a convention in track names.
dialog
Finally, the dialog object. This is the most complicated Fold.it Lua V2.0 object.
The functions are required to be called in a specific order.
CreateDialog() - Call this function first. It returns a lua table that is used
with the rest of the 'dialog' functions.
One can add to the dialog window sliders, checkboxes, labels, and buttons.
AddLabel(string)
AddCheckbox(string,[true,false]) - If 'true', box is checked by default
AddSlider(string,default,low,high,precision) - A slider is presented that allows the user to select a number from 'low' to 'high' with a decimal precision of 'precision'. Use 0 for precision when working with integers. 'default' is the value shown at the start.
AddButton(string,value) - Each button needs to have its own unique value.
dialog.AddButton("OK",1) dialog.AddButton("Cancel",0)
CreateDialog(string) - A dialog object is created that has labels, checkboxes, sliders and buttons added to it. dialog.show(dialog) is used to display the dialog object created by dialog.CreateDialog(string)
Show(dialog) - Here dialog.Show(dialog) receives the variable of dialog.CreateDialog(string). The return code of dialog.Show(dialog) will be the button selected.
The dialog window is a finite width and maximum height. It maybe necessary to program a 'Next' button to provide the user with another window of selections.
A Glimpse into the Future
With a little investigating, one is able to find that there are several functions that are available to be called, but do not do anything.
One can only speculate what the functions will do. Get and Set give some hint. structure.Tweakxxx() is obvious. behavior.xxxAccuracy() would seem to be a feature to make wiggle and shake run until the change in points is within a range and simply wait however many iterations it takes to get there.
The following code will expose the functions of each of the major objects.
for key,value in pairs(object) do
print("found member " .. key);
end
where object is one of the Fold.it Lua 2.0 objects, such as structure, band, or current.
These functions are:
structure.TweakRotate(segmentindex,angle) - Rotate segment by angle, angle in radians, -pi to +pi. Segment must be a sheet or helix.
structure.TweakShift(segmentindex,shiftDirection) - Shift segment index one way or other. Segment must be a sheet.
structure.TweakStraighten(segmentindex) - Straighten segment index. Segment must be a sheet.
behavior.GetBuriedSideChainAccuracy() - ??
behavior.SetBuriedSideChainAccuracy() - range 0 to 1
behavior.GetExposedSideChainAccuracy() - ??
behavior.SetExposedSideChainAccuracy() - range 0 to 1
behavior.GetShakeAccuracy() - Returns the shake accuracy
behavior.GetWiggleAccuracy() - Returns the wiggle accuracy
behavior.SetShakeAccuracy() - Sets the shake accuracy. range ?
behavior.SetWiggleAccuracy() - Sets the wiggle accuracy. range ?