Icon representing a recipe

Recipe: Utility_belt 1.0

created by robgee

Profile


Name
Utility_belt 1.0
ID
104128
Shared with
Public
Parent
None
Children
None
Created on
November 21, 2020 at 23:02 PM UTC
Updated on
November 21, 2020 at 23:02 PM UTC
Description

Collection of simple functions

Best for


Code


-- Utility_belt 1.0 -- Collection of various code snippets to perform some basic functions -- Thanks to Timo van der Laan, LociOiling and others -- from whose code some snippets were taken -- Quicksave9 is odd, seems to store both structs and a pose -- This recipe will not overwrite Quicksave 9 -- ------------------------------------ -- ---------- GLOBAL VARS ------------- -- ------------------------------------ Recipe = "Utility belt" Version = "1.0" ReVersion = Recipe .. " " .. Version -- --------- OPTIONS -------------- LoadFromQS = 1 SaveToQS = 1 numSegs = structure.GetCount() OG_FILTER_SETTING = 0 DBG = false ------------------------------------------------------ -- HELPER FUNCTIONS ------------------------------------------------------ function DoesPuzzleHaveFilters() local names = filter.GetNames() if names ~= nil and #names > 0 then return true else return false end --Thnx LociOiling end function round ( drie ) return drie - drie % 0.001 end function nodupes(duptbl) local hash = {} local uniques = {} for _, v in ipairs( duptbl ) do if not hash[v] then uniques[#uniques+1] = v hash[v] = true end end return uniques end--Thnx vogomatix @ SO function GetRanges(rTable) local txt = '' local rStart = nil local rangestable={} for key, value in pairs(rTable) do if rTable[key + 1] == value + 1 then --are sequential if not rStart then rStart = value end else if rStart then txt = txt .. rStart .. "-" .. value .. ", " rangestable[#rangestable+1]={rStart,value} rStart = nil else txt = txt .. value .. ", " rangestable[#rangestable + 1] = { value } end end end print( txt:sub(1, -3) ) --how to fomat over 2 lines for big table ? return rangestable end -- rosettacode.org function Cleanup( err ) if CLEANUPENTRY ~= nil then return end CLEANUPENTRY = true --Tx LociOiling print( 'Cleaning up' ) print( '========================' ) print( ReVersion..' Cleaning up' ) behavior.SetFiltersDisabled ( OG_FILTER_SETTING ) print( err ) end ------------------------------------------------------ -- BIG FUNCTIONS ------------------------------------------------------ function load_from_slot() local function SetDialog() local dlg = dialog.CreateDialog ( "Load from Quicksave position" ) dlg.loadquicksave = dialog.AddSlider ( "Load quicksave:", 1, 1, 99, 0 ) dlg.ok = dialog.AddButton ( "OK", 1) dlg.cancel2 = dialog.AddButton ( "Cancel", 0 ) if dialog.Show( dlg ) > 0 then LoadFromQS = dlg.loadquicksave.value return true else return ('exit') end end local go = SetDialog() if go == 'exit' then print('Load Quicksave cancelled') return end if save.QuicksaveEmpty ( LoadFromQS ) then print('Quicksave '.. LoadFromQS..' is empty, nothing to load') else save.Quickload( LoadFromQS ) print('Loaded pose from Quicksave number: '..LoadFromQS) end end -- ---------------------------------------------------------------------------------- function save_to_slot()--copypasta code is so wrong, merging these 2 functions should be simple --but then we break clean code rules, "function should do 1 thing and do it well." local function SetDialog() local dlg = dialog.CreateDialog ( "Save to Quicksave position" ) dlg.savequicksave = dialog.AddSlider ( "Save in Qsave", 1, 1, 99, 0 ) dlg.ok = dialog.AddButton ( "OK", 1 ) dlg.cancel2 = dialog.AddButton ( "Cancel", 0 ) if dialog.Show( dlg ) > 0 then SaveToQS = dlg.savequicksave.value return true else return ('exit') end end local function proceedwithqs( SaveToQS ) local stdlg = dialog.CreateDialog ( "Alert Quicksave occupied" ) stdlg.label1 = dialog.AddLabel ('Quicksave '.. SaveToQS .. ' is occupied' ) stdlg.label2 = dialog.AddLabel ('Overwrite with current pose ?') stdlg.ok = dialog.AddButton ( "Yes", 1 ) stdlg.cancel2 = dialog.AddButton ( "No", 0 ) if dialog.Show( stdlg ) > 0 then return true else return false end end local go = SetDialog() if go == 'exit' then print('Save to Quicksave cancelled') return end if save.QuicksaveEmpty ( SaveToQS ) == false then print('Quicksave '.. SaveToQS .. ' is occupied' ) if proceedwithqs( SaveToQS ) == false then print('Save to Quicksave '..SaveToQS..' cancelled') return end end save.Quicksave( SaveToQS ) print('Saved pose in Quicksave number: '..SaveToQS) print('') end -- --------------------------------------- function Quicksave_purge() --overwrites quicksaves 1-99 with current pose local ljust = string.rep(" ",12) local function Warning() local dlg = dialog.CreateDialog ( "!! WARNING !!" ) dlg.warninglabel = dialog.AddLabel ( ljust.. " Every non-empty Quicksave") dlg.warninglabel2 = dialog.AddLabel (ljust.. "will be overwritten with current pose" ) dlg.warninglabel3 = dialog.AddLabel ( " ") dlg.ok = dialog.AddButton ( "OK", 1 ) dlg.cancel2 = dialog.AddButton ( "Cancel", 0 ) if dialog.Show( dlg ) > 0 then return true else return ('exit') end end local go = Warning() if go == 'exit' then print('Overwrite cancelled') return end --QS(9) Is for structs --if 9 contains a struct this api still calls it empty print('Overwriting all non-empty Quicksave') print(' slots with current pose') for i = 1, 99 do if not save.QuicksaveEmpty( i ) then --Is the quicksave empty. if i ~=9 then save.Quicksave( i ) print('saving current pose to Quicksave:', i) end if i==9 then print('Quicksave 9 is non-empty but it is reserved for Structures?') print('This recipe will not overwrite Quicksave 9') end end end print('') end -- -------------------------------------- -- QS_status -- Thanks to TimovdL -- ListToSet and SetToString adapted from TvdL -- 02-05-2012 TvdL Free to use for non commercial purposes -- function ListToSet ( list ) -- remove dupes local result = {} local ff = 0 local ll = -1 table.sort ( list ) for ii = 1, #list do if list [ ii ] ~= ll + 1 and list [ ii ] ~= ll then -- note: duplicates are removed if ll > 0 then result [ #result + 1 ] = { ff, ll } end ff = list [ ii ] end ll = list [ ii ] end if ll > 0 then result [ #result + 1 ] = { ff, ll } end return result end function SetToString ( set ) -- to print local line = "" for ii = 1, #set do if ii ~= 1 then line = line .. ", " end line = line .. set [ ii ] [ 1 ] .. "-" .. set [ ii ] [ 2 ] end return line end -- This code completely ripped from -- Slot Grabber 1.0 by LociOiling -- Thanks to LociOiling function QS_status() local firstempty = 0 local quickz = {} for ii = 1, 99 do if not save.QuicksaveEmpty ( ii ) then --if quicksave has something quickz [ #quickz + 1 ] = ii --add its number to list elseif firstempty == 0 then firstempty = ii --record the 1st empty one end end set_of_used_quickz = ListToSet ( quickz ) print( "Quicksave slots are from 1 to 99") print( "Amount of occupied Quicksave slots:", #quickz) print( "Ranges of occupied Quicksave slots:", SetToString ( set_of_used_quickz ) ) if firstempty ~= 0 then print ( "First empty Quicksave is:", firstempty ) else print ( "All Quicksave slots are occupied !" ) end print('') end -- --------------------------------------- function convert_to_loop() --autostructures will return it to normal. print('Converting to all loops') local MakeLoop = false for i = 1, numSegs do if structure.GetSecondaryStructure( i ) ~= "L" then MakeLoop = true break end end if MakeLoop then save.SaveSecondaryStructure( ) --Use Ctrl+Shift+9 or save.LoadSecondaryStructure() to recover saved struct print('Secondary structure assignment saved to QS(9).') print('Use Ctrl+9 to reload Structures') selection.SelectAll( ) structure.SetSecondaryStructureSelected( "L" ) else print('Structure is already all Loops.') end print('') selection.DeselectAll( ) end --thnx to TvdL -- --------------------------------------- function SecondaryStructureData() print(' Secondary structure Data') print('Protein has this many residues:', numSegs) print() local StructDict = { ["L"] = "loop", ["H"] = "helix", ["E"] = "sheet", ["M"] = "molecule" } --SecStructTable = {"L", "E", "H","M"} --how often is there a molecule ?? not often local SecStructTable = { "L", "E", "H" } local init = -1 for _, whatstruct in ipairs( SecStructTable ) do local sstruct = StructDict[whatstruct] print('Searching for', whatstruct, sstruct,'data.') print('Secondary structure Data for '..sstruct..':') local count = 0 local maxcount = 0 local realcount = 0 local seqq = {} local seggys={} for i = 1, numSegs do local foo = structure.GetSecondaryStructure( i ) if foo == whatstruct then seggys[#seggys+1] = i count = count + 1 realcount = realcount + 1 if count > maxcount then maxcount = count end else if count ~= 0 then seqq[#seqq+1] = tostring(count) end count = 0 end if i==numSegs and count ~=0 then seqq[#seqq+1]=tostring(count) end --fix for misses last sequence end local percent= ( realcount / numSegs ) * 100 print('How many segs are '..sstruct..': '..realcount) print('Percent of protein is '..sstruct..': '..round(percent)..' %') print('Longest sequence:', maxcount) print(sstruct..' sequences:', #seqq) print('Sequence lengths:', table.concat( seqq, "," )) print('Segment range of sequences:') GetRanges(seggys) print('') end end -- ----------------------------------------------------- function delete_cuts( ) print('Deleting any cuts...') for i = 1, numSegs - 1 do if not structure.IsLocked( i ) then structure.DeleteCut( i ) end end print('deleting cuts..done') print('') end -- ----------------------------------------------------- --Thnx to Frutchy --for idea of selected outside the loop function freezySideChains() print("Freezing sidechains (unlocked segments only)") for idx = 1, numSegs do if not structure.IsLocked( idx ) then selection.Select( idx ) end end freeze.FreezeSelected( false, true ) selection.DeselectAll() end -- ----------------------------------------------------- function freezyBackBone() print("Freezing backbone (unlocked segments only)") for idx = 1, numSegs do if not structure.IsLocked( idx ) then selection.Select( idx ) end end freeze.FreezeSelected( true, false ) selection.DeselectAll() end -- --------------------------------------------------- function unfreezy() print('Unfreezing all segments, backbone and sidechains') freeze.UnfreezeAll() end -- -------------------------------------------------- function part_totals_in_worst_order() print('Scoreparts totals') --here attempt to get the used partscores for this puzzle local SubScores = {} local scoreparts = {} scoreparts = puzzle.GetPuzzleSubscoreNames( ) --foldit API returns a table for us to use for i = 1, structure.GetCount( ) do for j = 1, #scoreparts do local subscore = current.GetSegmentEnergySubscore ( i, scoreparts [ j ] ) if subscore ~= 0 then --if its exactly zero we assume its an invalid partscore ( It may actually be zero ! ) SubScores[#SubScores+1] = scoreparts [j] end end end--foldit wiki --calculate partscore totals local ActiveSubScores = nodupes( SubScores ) local worst_table = {} local currentPartscore --forward declaration needed here local worst = 99999999 local wpart = '' for i in ipairs( ActiveSubScores ) do local subtot = 0 --this is locally scoped for j = 1, numSegs do currentPartscore = ActiveSubScores[i] local subb = round ( current.GetSegmentEnergySubscore ( j, currentPartscore ) ) subtot = subtot + subb end if subtot < worst then worst = subtot wpart = currentPartscore end worst_table[#worst_table+1] = { currentPartscore, subtot} end table.sort( worst_table, function( a, b ) return a[2] < b[2] end ) if next( worst_table ) == nil then print('Error : Table is empty') return false --perhaps should call cleanup since this should never happen end for k,v in ipairs( worst_table ) do print('Total ', v[1], ' ', v[2]) end print('Worst score part:', wpart, 'Score:', worst) print('') end -- ------------------------------------------------------------------ function SetDialog() local dlg = dialog.CreateDialog ( ReVersion ) dlg.loadqs= dialog.AddCheckbox ( "Load from Quicksave" , false ) dlg.saveqs = dialog.AddCheckbox ( "Save to Quicksave" , false ) dlg.qsempty = dialog.AddCheckbox ( "List non-empty Quicksaves" , false ) if DBG then -- Overwrite all non-empty Quicksave slots with current pose, for debugging purposes mostly dlg.purgeqs= dialog.AddCheckbox ( "Overwrite all non-empty Quicksaves" , false ) end dlg.changetoloop = dialog.AddCheckbox ( "Convert to loop" , false ) dlg.sidchainfreeze = dialog.AddCheckbox ( "Freeze sidechains", false ) dlg.bkbonefreeze = dialog.AddCheckbox ( "Freeze backbone", false ) dlg.unfrzall = dialog.AddCheckbox( "Unfreeze All", false) dlg.secstrdat = dialog.AddCheckbox ( "Secondary Structure Data" , false ) dlg.remcuts = dialog.AddCheckbox ( "Delete cuts" , false ) dlg.ptsubtot = dialog.AddCheckbox ( "Show partscore totals" , false ) dlg.ok = dialog.AddButton ( "OK", 1) dlg.cancel2 = dialog.AddButton ( "Cancel", 0 ) if (dialog.Show(dlg) > 0) then LoadFromQS = dlg.loadqs.value SaveToQS = dlg.saveqs.value QStak = dlg.qsempty.value if DBG then prgqs = dlg.purgeqs.value end chtlp = dlg.changetoloop.value sesda = dlg.secstrdat.value rcuts = dlg.remcuts.value ptsub = dlg.ptsubtot.value frzdc = dlg.sidchainfreeze.value frzbb = dlg.bkbonefreeze.value unfrz = dlg.unfrzall.value return true else print("Dialog cancelled") return false end end function Main() print( ReVersion ) print( puzzle.GetName () ) print( "Track:", ui.GetTrackName() ) OG_FILTER_SETTING = behavior.GetFiltersDisabled() while SetDialog() do if LoadFromQS then load_from_slot() end if SaveToQS then save_to_slot() end if QStak then QS_status() end if prgqs then Quicksave_purge() end if chtlp then convert_to_loop() end if frzdc then freezySideChains() selection.DeselectAll() end if frzbb then freezyBackBone() selection.DeselectAll() end if unfrz then unfreezy() end if sesda then SecondaryStructureData() end if rcuts then if DoesPuzzleHaveFilters() then behavior.SetFiltersDisabled ( true ) delete_cuts() behavior.SetFiltersDisabled ( false ) else delete_cuts() end end if ptsub then part_totals_in_worst_order() end end behavior.SetFiltersDisabled ( OG_FILTER_SETTING ) end xpcall( Main, Cleanup ) --utility belt 1.0

Comments


robgee Lv 1

Collection of code snippets to perform some basic functions.

freeze backbone
freeze sidechains
unfreeze all
convert all to loop
delete cuts
save, load, from quicksave
occupied quicksaves *
partscore totals
structure data

Thanks to Timo van der Laan and LociOiling.

*Code taken from Slot Grabber 1.0 by LociOiling
use that recipe for better QS handling.

Try FreezeSelectSome1 by jeff101 for detailed freeze work.