Code
--[[
SS Edit
Get and set secondary structure
SS Edit displays the current secondary structure.
The displayed value can be selected and cut or copied.
A new value can be pasted in. When the "Change" button
is clicked, the currently displayed secondary structure
will be applied to the protein.
SS Edit doesn't validate or edit the secondary structure
codes. Only the foldit codes "H" for helix, "E" for sheet,
and "L" for loop should be used. Other values may produce
unpredictable results.
If the structure list is longer than the protein, SS Edit
discards the extra entries at the end of the list.
If the structure list is shorter than the protein, SS Edit
applies the list to the first *n* segments of the protein,
where *n* is the length of the list. Any remaining segments
are unchanged.
All changes are written to the scriptlog.
See "AA Copy Paste Compare v 1.1.1 -- Brow42" for
a full-function recipe that works with primary and
secondary structures.
version 1.1 -- 2015/07/06 -- LociOiling
* speed things up a bit by disabling filters
* add standard cleanup
* don't crash trying to set type "M", skip invalid codes
version 1.2 -- 2016/12/23 -- LociOiling
* a string is not a table
* enable 1-step undo with undo.SetUndo ( false )
]]--
--
-- Globals
--
Recipe = "SS Edit"
Version = "1.2"
ReVersion = Recipe .. " v." .. Version
STYPES = {
E = { "sheet" },
H = { "helix" },
L = { "loop" },
}
--
-- end of globals section
--
function report_time(start_clock,start_time,clock_msg,time_msg)
local seconds,minutes,hours,days
if clock_msg==nil then clock_msg="CPU time" end
if time_msg==nil then time_msg="Elasped time" end
print(string.format("%s",os.date()))
days,remainder=math.modf((os.clock()-start_clock)/(24*60*60))
hours,remainder=math.modf(remainder*24)
minutes,remainder=math.modf(remainder*60)
seconds,remainder=math.modf(remainder*60)
print(string.format("%s(%02id:%02ih:%02im:%02is)",clock_msg,days,hours,minutes,seconds))
days,remainder=math.modf(os.difftime(os.time(),start_time)/(24*60*60))
hours,remainder=math.modf(remainder*24)
minutes,remainder=math.modf(remainder*60)
seconds,remainder=math.modf(remainder*60)
print(string.format("%s(%02id:%02ih:%02im:%02is)",time_msg,days,hours,minutes,seconds))
end
function getSS ( )
ssList = ""
for ii = 1, structure.GetCount () do
ssList = ssList .. structure.GetSecondaryStructure ( ii )
end
return ssList
end
function setSS ( oldtab, tab )
local changes = 0
for ii = 1, math.min ( tab:len (), structure.GetCount () ) do
local sType = tab:sub ( ii, ii )
local oType = oldtab:sub ( ii, ii )
if sType ~= oType then
local sName = STYPES [ sType ]
if sName ~= nil then
structure.SetSecondaryStructure ( ii, sType )
changes = changes + 1
else
print ( "segment " .. ii .. ", skipping invalid type \"" .. sType .. "\"" )
end
end
end
return changes
end
function GetParameters ( tab )
local dlog = dialog.CreateDialog ( ReVersion )
dlog.tab0 = dialog.AddLabel ( "Secondary structure" )
dlog.tab = dialog.AddTextbox ( "SStruct", tab )
dlog.u0 = dialog.AddLabel ( "" )
dlog.u1 = dialog.AddLabel ( "Usage: use select all and copy, cut, or paste" )
dlog.u2 = dialog.AddLabel ( "to save or change secondary structure" )
dlog.w0 = dialog.AddLabel ( "" )
dlog.w1 = dialog.AddLabel ( "Windows: ctrl + a = select all" )
dlog.w2 = dialog.AddLabel ( "Windows: ctrl + x = cut" )
dlog.w3 = dialog.AddLabel ( "Windows: ctrl + c = copy" )
dlog.w4 = dialog.AddLabel ( "Windows: ctrl + v = paste" )
dlog.z0 = dialog.AddLabel ( "" )
dlog.ok = dialog.AddButton ( "Change" , 1 )
dlog.exit = dialog.AddButton ( "Exit" , 0 )
if ( dialog.Show ( dlog ) > 0 ) then
tab = dlog.tab.value
return tab:upper ()
else
return ""
end
end
function main ()
print ( ReVersion )
print ( "Puzzle: " .. puzzle.GetName () )
print ( "Track: " .. ui.GetTrackName () )
undo.SetUndo ( false )
local changeNum = 0
local ssList = ""
repeat
ssList = getSS ()
print ( "secondary structure, change # " .. changeNum )
print ( ssList )
local ssList2 = GetParameters ( ssList )
if ssList2:len () > 0 then
changeNum = changeNum + 1
local start_clock = os.clock ()
local start_time = os.time ()
local filter = behavior.GetFiltersDisabled ()
behavior.SetFiltersDisabled ( true )
print ( "-------- " .. "start of change " .. changeNum .. " --------" )
local sChg = setSS ( ssList, ssList2 )
behavior.SetFiltersDisabled ( filter )
report_time ( start_clock, start_time )
print ( sChg .. " segments changed" )
print ( "-------- " .. "end of change " .. changeNum .. " --------" )
end
until ssList2:len () == 0
cleanup ()
end
function cleanup ( errmsg )
--
-- optionally, do not loop if cleanup causes an error
-- (any loop here is automatically terminated after a few iterations, however)
--
if CLEANUPENTRY ~= nil then
return
end
CLEANUPENTRY = true
print ( "---" )
--
-- model 100 - print recipe name, puzzle, track, time, score, and gain
--
local reason
local start, stop, line, msg
if errmsg == nil then
reason = "complete"
else
--
-- model 120 - civilized errmsg reporting,
-- thanks to Bruno K. and Jean-Bob
--
start, stop, line, msg = errmsg:find ( ":(%d+):%s()" )
if msg ~= nil then
errmsg = errmsg:sub ( msg, #errmsg )
end
if errmsg: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" )
print ( "Error line: " .. line )
print ( "Error: \"" .. errmsg .. "\"" )
end
end
xpcall ( main, cleanup )