Icon representing a recipe

Recipe: bandfun 1.0

created by LociOiling

Profile


Name
bandfun 1.0
ID
102587
Shared with
Public
Parent
None
Children
None
Created on
December 21, 2017 at 00:56 AM UTC
Updated on
December 21, 2017 at 00:56 AM UTC
Description

Demonstrates the use of band.Add, which allows drawing spacebands with precise geometry.

Best for


Code


--[[ bandfun Example of adding spacebands (lots of spacebands) with precise geometry using band.Add. Also demonstrates using pcall to trap errors returned by one of the Foldit Lua functions. Without pcall, invalid parameters to a function like band.Add cause the recipe to terminate. ]]-- Recipe = "bandfun" Version = "1.0" ReVersion = Recipe .. " v." .. Version -- -- safe functions v 1.0 -- -- safe functions use pcall to invoke functions which -- may unexpectedly terminate the script -- -- safe functions are added to the exist foldit psuedo-classes -- -- -- ParseError -- common routine used by safe functions -- function ParseError ( errmsg ) local reason local start, stop, line, msg start, stop, line, msg = errmsg:find ( ":(%d+):%s()" ) if msg ~= nil then errmsg = errmsg:sub ( msg, #errmsg ) end return errmsg end -- -- band.SafeAdd uses pcall -- to call band.Add, returning -- a numeric return code. -- -- If the return code is zero, the band index -- is the second returned value. -- -- The return codes are: -- -- 0 - successful, second returned -- value is band index -- -1 - bad segment number -- -2 - reserved -- -3 - reserved -- -4 - bad rho -- -5 - bad theta -- -6 - bad phi -- -999 - other error -- band.SafeAdd = function ( ... ) -- -- error messages -- local BADSEG = "segment index out of bounds" local BADRHO = "rho must be" local BADTHETA = "theta must be" local BADPHI = "phi must be" -- local good, errmsg = pcall ( band.Add, unpack ( arg ) ) if good then return 0, errmsg else local err2 = ParseError ( errmsg ) local errp = err2:find ( BADSEG ) if errp ~= nil then return -1, err2 end local errp = err2:find ( BADRHO ) if errp ~= nil then return -4, err2 end local errp = err2:find ( BADTHETA ) if errp ~= nil then return -5, err2 end local errp = err2:find ( BADPHI ) if errp ~= nil then return -6, err2 end return -999, err2 end end -- -- band.SafeAddBetweenSegments uses pcall -- to call band.AddBetweenSegments, returning -- a numeric return code. -- -- If the return code is zero, the band index -- is the second returned value. -- -- The return codes are: -- -- 0 - successful, second returned -- value is band index -- -1 - bad segment number -- -2 - bad atom number -- -999 - other error -- band.SafeAddBetweenSegments = function ( ... ) -- -- error messages -- local BADSEG = "segment index out of bounds" local BADATOM = "atom number out of bounds" -- local good, errmsg = pcall ( band.AddBetweenSegments, unpack ( arg ) ) if good then return 0, errmsg else local err2 = ParseError ( errmsg ) local errp = err2:find ( BADSEG ) if errp ~= nil then return -1, err2 end local errp = err2:find ( BADATOM ) if errp ~= nil then return -2, err2 end return -999, err2 end end -- -- band.SafeAddToBandEndpoint uses pcall -- to call band.ToBandEndpoint, returning -- a numeric return code. -- -- If the return code is zero, the band index -- is the second returned value. -- -- The return codes are: -- -- 0 - successful, second returned -- value is band index -- -1 - bad segment number -- -2 - bad atom number -- -3 - bad band number -- -999 - other error -- band.SafeAddToBandEndpoint = function ( ... ) -- -- error messages -- local BADSEG = "segment index out of bounds" local BADATOM = "atom number out of bounds" local BADBAND = "band index out of bounds" -- local good, errmsg = pcall ( band.AddToBandEndpoint, unpack ( arg ) ) if good then return 0, errmsg else local err2 = ParseError ( errmsg ) local errp = err2:find ( BADSEG ) if errp ~= nil then return -1, err2 end local errp = err2:find ( BADATOM ) if errp ~= nil then return -2, err2 end local errp = err2:find ( BADBAND ) if errp ~= nil then return -3, err2 end return -999, err2 end end -- -- behavior.SafeSetClashImportance uses pcall -- to call behavior.SetClashImportance, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad CI -- -999 - other error -- behavior.SafeSetClashImportance = function ( ... ) -- -- error message -- local BADCLASH = "clashing importance value outside valid range" -- local good, errmsg = pcall ( behavior.SetClashImportance, unpack ( arg ) ) if good then return 0, nil else local err2 = ParseError ( errmsg ) local errp = err2:find ( BADCLASH ) if errp ~= nil then return -1, err2 end return -999, err2 end end -- -- selection.SafeSelect uses pcall -- to call selection.Select, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -999 - other error -- selection.SafeSelect = function ( ... ) -- -- error message -- local BADSEG = "segment index out of bounds" -- local good, errmsg = pcall ( selection.Select, unpack ( arg ) ) if good then return 0, nil else local err2 = ParseError ( errmsg ) local errp = err2:find ( BADSEG ) if errp ~= nil then return -1, err2 end return -999, err2 end end -- -- selection.SafeSelectRange uses pcall -- to call selection.SelectRange, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -999 - other error -- selection.SafeSelectRange = function ( ... ) -- -- error message -- local BADSEG = "segment index out of bounds" -- local good, errmsg = pcall ( selection.SelectRange, unpack ( arg ) ) if good then return 0, nil else local err2 = ParseError ( errmsg ) local errp = err2:find ( BADSEG ) if errp ~= nil then return -1, err2 end return -999, err2 end end -- -- rotamer.SafeSetRotamer uses pcall -- to call rotamer.SetRotamer, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -2 - bad rotamer index -- -999 - other error -- rotamer.SafeSetRotamer = function ( ... ) -- -- error messages -- local BADSEG = "segment index out of bounds" local BADSNAP = "snap index out of bounds" -- local good, errmsg = pcall ( rotamer.SetRotamer, unpack ( arg ) ) if good then return 0, nil else local err2 = ParseError ( errmsg ) local errp = err2:find ( BADSEG ) if errp ~= nil then return -1, err2 end local errp = err2:find ( BADSNAP ) if errp ~= nil then return -2, err2 end return -999, err2 end end -- -- structure.SafeSetAminoAcid uses pcall -- to call structure.SetAminoAcid, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -2 - bad amino acid code -- -999 - other error -- structure.SafeSetAminoAcid = function ( ... ) -- -- error messages -- local BADSEG = "(segment index out of bounds)" local BADACID = "invalid argument, unknown aa code" -- local good, errmsg = pcall ( structure.SetAminoAcid, unpack ( arg ) ) if good then return 0, nil else local err2 = ParseError ( errmsg ) local errp = err2:find ( BADSEG ) if errp ~= nil then return -1, err2 end local errp = err2:find ( BADACID ) if errp ~= nil then return -2, err2 end return -999, err2 end end -- -- structure.SafeSetAminoAcidSelected uses pcall -- to call structure.SetAminoAcidSelected, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -2 - bad amino acid code -- -999 - other error -- structure.SafeSetAminoAcidSelected = function ( ... ) -- -- error message -- local BADACID = "invalid argument, unknown aa code" -- local good, errmsg = pcall ( structure.SetAminoAcidSelected, unpack ( arg ) ) if good then return 0, nil else local err2 = ParseError ( errmsg ) local errp = err2:find ( BADACID ) if errp ~= nil then return -2, err2 end return -999, err2 end end -- -- structure.SafeSetSecondaryStructure uses pcall -- to call structure.SetSecondaryStructure, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -2 - bad secondary structure code -- -999 - other error -- structure.SafeSetSecondaryStructure = function ( ... ) -- -- error messages -- local BADSEG = "segment index out of bounds" local BADCODE = "invalid argument" local good, errmsg = pcall ( structure.SetSecondaryStructure, unpack ( arg ) ) if good then return 0, nil else local err2 = ParseError ( errmsg ) local errp = err2:find ( BADSEG ) if errp ~= nil then return -1, err2 end local errp = err2:find ( BADCODE ) if errp ~= nil then return -2, err2 end return -999, err2 end end -- -- structure.SafeSetSecondaryStructureSelected uses pcall -- to call structure.SetSecondaryStructureSelected, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -2 - bad secondary structure code -- -999 - other error -- structure.SafeSetSecondaryStructureSelected = function ( ... ) -- -- error message for an invalid secondary structure code -- local BADCODE = "invalid argument" local good, errmsg = pcall ( structure.SetSecondaryStructureSelected, unpack ( arg ) ) if good then return 0, nil else local err2 = ParseError ( errmsg ) local errp = err2:find ( BADCODE ) if errp ~= nil then return -2, err2 end return -999, err2 end end -- -- end of safe functions v 1.0 -- function main () print ( ReVersion ) print ( "Puzzle: " .. puzzle.GetName () ) print ( "Track: " .. ui.GetTrackName () ) save.Quicksave ( 3 ) save.SaveSecondaryStructure () local segCnt = structure.GetCount () print ( "Segment count = " .. segCnt ) -- -- many functions use segment indexes, -- define some useful ones -- local SEGOUT = segCnt + 1 local SEGFOO1 = -1 local SEGFOO2 = -999 local SEGFOO3 = 999 local SEGMID = math.floor ( segCnt / 2 ) print ( "Middle segment = " .. SEGMID ) -- -- assorted other bad values -- local HIATOM = 99 -- atom number local HIROTA = 999 -- rotamer number local HIRHO = 11000 -- you take the high rho local LORHO = -39 -- and I'll take the low rho local OKRHO = 20 -- and this one is just right local HITHETA = 4.0 local LOTHETA = -1.0 local OKTHETA = 3.14 / 2 local HIPHI = 3.14 * 3 local LOPHI = -1.0 local OKPHI = 3.14 local rc, errmsg for theta = 0, 3.14, 3.14 / 4 do for phi = 0, 2 * 3.14, 3.14 / 4 do rc, errmsg = band.SafeAdd ( SEGMID, 1, segCnt , OKRHO * 2, theta, phi ) if rc == 0 then band.SetStrength ( errmsg, 10 ) else print ( "rc = " .. rc ) if errmsg ~= nil then print ( "errmsg = " .. errmsg ) end end end end for theta = 0, 3.14, 3.14 / 16 do for phi = 0, 2 * 3.14, 3.14 / 16 do rc, errmsg = band.SafeAdd ( SEGMID, 1, segCnt, OKRHO, theta, phi ) if rc ~= 0 then print ( "rc = " .. rc ) if errmsg ~= nil then print ( "errmsg = " .. errmsg ) end end end end -- cleanup () end function cleanup ( error ) print ( "---" ) -- -- model 100 - print recipe name, puzzle, track, time, score, and gain -- local reason local start, stop, line, msg if error == nil then reason = "complete" else -- -- model 120 - civilized error reporting, -- thanks to Bruno K. and Jean-Bob -- start, stop, line, msg = error:find ( ":(%d+):%s()" ) if msg ~= nil then error = error:sub ( msg, #error ) end if error:find ( "Cancelled" ) ~= nil then reason = "cancelled" else reason = "error" end end print ( ReVersion .. " " .. reason ) print ( "Puzzle: " .. puzzle.GetName () ) print ( "Track: " .. ui.GetTrackName () ) if reason == "error" then print ( "Unexpected error detected" ) if line ~= nil then print ( "Error line: " .. line ) end print ( "Error: \"" .. error .. "\"" ) end -- -- model 130 - reset clash importance, clear selections, restore structures, etc. -- end -- main call xpcall ( main, cleanup ) --end of script

Comments


LociOiling Lv 1

This recipe demonstrates the use of band.Add, which allows drawing spacebands with precise geometry.

The recipe also show how to use the Lua pcall function to trap errors. Without pcall, one wrong parameter to band.Add terminates the recipe. Pcall allows the recipe to trap the error and keep going. This especially important for band.Add, which is kind of persnickety.

As a bonus, wiggle the protein after running the recipe. You'll be amazed. Your protein will most likely be severely damaged.