Profile
- Name
- Loop Remix/Rebuild 12.5
- ID
- 109090
- Shared with
- Public
- Parent
- Loop Remix/Rebuild 12.0
- Children
- Created on
- July 02, 2025 at 20:45 PM UTC
- Updated on
- July 03, 2025 at 21:43 PM UTC
- Description
See first comment + added rebuild worst segments + for Density Puzzles with many residues
Best for
Code
-- Copyright notice.
-- You may copy and paste at will. Plagiarize shamelessly!
-- End copyright notice
-- =========================================================================================
-- Adapted by jeff101 11/13/17 from spvincent's public 11/04/16 "Loop rebuild 8.0" recipe:
-- 8.0a.txt = Original "Loop rebuild 8.0" code
-- copy/pasted by 848am 10/05/17 from Foldit client 10b.
-- Should be <Foldit:MacroID>102235</Foldit:MacroID>
-- and <Foldit:MacroRevisionID>203034</Foldit:MacroRevisionID>
-- code as used for scriptlog1445h14.txt.
-- 8.0b.txt = Remove blank lines, replace some tabs w/spaces,
-- make indenting & comments more uniform.
-- Ideally all changes are superficial not functional.
-- 9.0a.txt = Let user specify residues to rebuild & mutate.
-- Last updated 11/17/17 303pm
-- 12.0.txt = + added rebuild worst segments + settings in the gui and how many worst segments to rebuild
-- Last updated 06/23/25 530am
-- 12.5.txt = changed max_residue = structure.GetCount() -- max segments/residues like the current puzzle has!
-- "for the next very large Puzzles"
-- =========================================================================================
-- Below sets the globals
prog_name='Loop Remix/Rebuild 12.5'
-- Mostly user-configurable globals
number_of_rebuilds = 8 -- It'll look for the best score from this number of rebuilds.
ss_criterion = 4 -- Controls whether to rebuild a section based on secondary structure
convert_to_loop = false -- If true, any non-loop residues will be temporarily converted to loops
test_for_credit = true -- If true, test that all conditions are satisfied before registering an improvement
keep_bands = true
min_residue = 1
max_residue = structure.GetCount() -- max segments/residues like the current puzzle has!
kInvalidScore = -99999
rebuild_worst = true -- Rebuild Worst Segments = true
-- How many Worst segments to remix/rebuild (default value 30% from the number of residues of the entire Protein)
howmany = (structure.GetCount() / 100) * 30
run_remix = true
fidealize = false -- Final Idealize = false (default)
inner_sphere = {}
outer_sphere = {}
kInnerSphereRadius = 10
kOuterSphereRadius = 18
kDefaultWiggleDuration = 12
kLowCiWiggle = 0.2
pw_threshold_value = 80
score_type = 1
rebuild_str=""
rebuild_list={} -- will be a list of 1's & 0's for each residue. 1 means can rebuild. 0 means don't rebuild.
mutate_str=""
mutate_list={} -- will be a list of 1's & 0's for each residue. 1 means can mutate. 0 means don't mutate.
-- Use of quicksave slots
kOriginalStructureOrNewBest = 1
kBestPostRebuild_a = 2
kBestPostRebuild_b = 3
kBestPostRebuild_a_post_wiggle = 4
kTemp = 5
kRemixQuicksaveStart = 30
-- Globals
original_secondary_structure = {}
fixed_residues = {}
original_slow_filters_setting = 0
n_bands = 0
orig_enabled_bands = {}
n_residues = 0
best_score = 0
start_score = 0
score_after_bc_wiggle = 0
rb = 0
rb1 = 0
rx1 = 0
rb_last_gain = 0
rx_last_gain = 0
-- Controls whether we should do a mini-fuze
-- (Shake at Low CI, Wiggle at CI of 1) after
-- completion of the Rebuild sequence.
-- A value of 0 means do it iff there's an overall improvement:
-- a high negative value would mean do it always:
-- a high positive value would mean do it always.
post_rebuild_threshold = 2
-- For design
mutate_not_shake = 0
-- 0 = shake only. default if not design
-- 1 = mutate then shake
-- 2 = mutate only. default for design
-- For monitoring
loss_from_low_ci_wiggle = {}
original_residues = {}
new_residues = {}
start_time = os.time()
-- Amino acids. Hydrophobics first.
single_letter_codes={ "g", "a", "v", "l", "i",
"m", "f", "w", "p", "s",
"t", "c", "y", "n", "q",
"d", "e", "k", "r", "h"}
three_letter_codes={"Gly","Ala","Val","Leu","Ile",
"Met","Phe","Trp","Pro","Ser",
"Thr","Cys","Tyr","Asn","Gln",
"Asp","Glu","Lys","Arg","His"}
-- Above sets the globals
-- =========================================================================================
-- Below defines the functions
function r0 ( x )
-- Round to 0 decimal places
return math.floor ( x + 0.5 )
-- x = -2.5 to -1.5001 becomes -2.0
-- x = -1.5 to -0.5001 becomes -1.0
-- x = -0.5 to 0.4999 becomes 0.0
-- x = 0.5 to 1.4999 becomes 1.0
-- x = 1.5 to 2.4999 becomes 2.0
-- x = 2.5 to 3.4999 becomes 3.0
end
function r3 ( x )
-- Round to 3 decimal places
t = 10 ^ 3
return math.floor ( x*t + 0.5 ) / t
end
function trunc3 (x)
-- truncates to 3 decimal places
-- as for the scores listed in Foldit GUI
return math.floor(x*1000)/1000
end
function GetScore ()
if ( score_type == 1 ) then
score = current.GetScore ()
elseif ( score_type == 2 ) then
score = current.GetEnergyScore ()
elseif ( score_type == 3 ) then
score = current.GetScore ()
score = score * current.GetExplorationMultiplier ()
elseif ( score_type == 4 ) then
score = 0
for i = 1 , n_residues do
score = score + current.GetSegmentEnergySubscore ( i , "hiding" )
end
elseif ( score_type == 5 ) then
score = 0
for i = 1 , n_residues do
score = score + current.GetSegmentEnergySubscore ( i , "bonding" )
end
elseif ( score_type == 6 ) then
behavior.SetSlowFiltersDisabled ( false )
score_with_filters = current.GetScore ()
behavior.SetSlowFiltersDisabled ( true )
score_without_filters = current.GetScore ()
score = score_with_filters - score_without_filters
elseif ( score_type == 7 ) then
behavior.SetSlowFiltersDisabled ( false )
score = current.GetScore ()
behavior.SetSlowFiltersDisabled ( true )
end
return score
end
function IsPuzzleMutable ()
for i = 1 , n_residues do
if ( structure.IsMutable ( i ) ) then
return true
end
end
return false
end
function aa1_to_aa3 ( k )
for j = 1, 20 do
if ( k == single_letter_codes [ j ] ) then
return three_letter_codes [ j ]
end
end
return "Unk"
end
function DoesPuzzleHaveSlowFilters ()
init_setting = behavior.GetSlowFiltersDisabled ()
if ( init_setting == false ) then
score_without_sf = current.GetScore ()
behavior.SetSlowFiltersDisabled ( true )
score_with_sf = current.GetScore ()
else
score_with_sf = current.GetScore ()
behavior.SetSlowFiltersDisabled ( false )
score_without_sf = current.GetScore ()
end
behavior.SetSlowFiltersDisabled ( init_setting )
if ( math.abs ( score_without_sf - score_with_sf ) >1e-3 ) then
return true
else
return false
end
end
function Coprime ( n )
-- 11/15/17 http://primes.utm.edu/lists/small/1000.txt
-- lists the following plus many more prime numbers:
local primes = {2,3,5,7,11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
947, 953, 967, 971, 977, 983, 991, 997,1009,1013}
i = #primes
-- find the highest prime < 70% of the residue count
-- and which is coprime with the number of residues
while ( i >= 1 ) do
if ( primes [ i ] < n*0.7 and n % primes [ i ] ~= 0 ) then
return primes [ i ]
end
i = i - 1
end
return 1
end
function SegmentComposition ( first, last )
-- Returns number of residues of each secondary structure type
n_loop_residues = 0
n_helix_residues = 0
n_sheet_residues = 0
for i = first, last do
ss = structure.GetSecondaryStructure ( i )
if ( ss == "L" ) then
n_loop_residues = n_loop_residues + 1
elseif ( ss == "H" ) then
n_helix_residues = n_helix_residues + 1
elseif ( ss == "E" ) then
n_sheet_residues = n_sheet_residues + 1
end
end
return n_loop_residues, n_helix_residues, n_sheet_residues
end
function IsSegmentRebuildable ( first, last )
local i,tot
tot = 0
for i = first, last do
tot = tot + rebuild_list[i]
end
if tot < rebuild_length then
return false
end
-- Above checks if enough residues in the segment are in the rebuild_list.
-- Below checks if the segment is rebuildable in the sense that its
-- secondary structure satisfies the specified criteria.
n_loop_residues,n_helix_residues,n_sheet_residues=SegmentComposition(first,last)
if ( ss_criterion == 1 ) then
-- Loops only
if ( n_helix_residues > 0 or n_sheet_residues > 0 ) then
return false
else
return true
end
elseif ( ss_criterion == 2 ) then
-- Loops with one non-loop residue
if ( n_helix_residues + n_sheet_residues > 1 ) then
return false
else
return true
end
elseif ( ss_criterion == 3 ) then
-- Loops or sheets
if ( n_helix_residues > 0 ) then
return false
else
return true
end
elseif ( ss_criterion == 4 ) then
return true
end
end
function ConvertToLoop ( first , last )
-- Slightly inefficient to call SegmentComposition twice
n_loop_residues,n_helix_residues,n_sheet_residues=SegmentComposition(first,last)
if ( n_helix_residues + n_sheet_residues > 0 ) then
selection.DeselectAll ( )
selection.SelectRange ( first , last )
structure.SetSecondaryStructureSelected ( "L" )
end
end
function pseudorandom ( score )
-- Returns a pseudorandom number >= 0 and < 1.
-- Based on the fractional part of the score
if ( score >= 0 ) then
return score % 1
else
return (-score ) % 1
end
end
function GetListOfFixedResidues ()
for i = 1 , n_residues do
fixed_residues [ i ] = false
end
for i = 1 , n_residues do
seg_backbone_frozen, seg_sidechain_frozen = freeze.IsFrozen ( i )
-- what to do if just the sidechains are frozen?
if ( seg_backbone_frozen == true ) then
fixed_residues [ i ] = true
end
s = structure.IsLocked ( i )
if ( s == true ) then
fixed_residues [ i ] = true
end
end
end
function DoesSectionContainFixedResidues ( start_idx , end_idx )
for i = start_idx , end_idx do
if ( fixed_residues [ i ] == true ) then
return true
end
end
return false
end
function ShakeLowCIWiggle ( c_score )
save.Quicksave ( kTemp )
behavior.SetClashImportance ( 0.10 )
structure.ShakeSidechainsSelected ( 1 )
behavior.SetClashImportance ( 1 )
structure.WiggleSelected ( kDefaultWiggleDuration )
score = GetScore ()
if ( score < c_score ) then
save.Quickload ( kTemp )
score = c_score
end
end
function FinalIdealize ( c_score , start_idx , end_idx )
kFallApartThreshold = 1000
save.Quicksave ( kTemp )
selection.DeselectAll ()
selection.SelectRange ( start_idx , end_idx )
structure.IdealizeSelected ()
score_after_idealize = GetScore ()
selection.SelectAll ()
if ( ( c_score - score_after_idealize ) > kFallApartThreshold ) then
structure.WiggleAll ( 1, false , true ) -- wiggle sidechains
end
if ( math.abs ( score - c_score ) > 1e-3 ) then
structure.WiggleSelected ( 12 )
score = GetScore ()
if ( score < c_score ) then
save.Quickload ( kTemp )
score = c_score
end
end
end
function WiggleNudge ( c_score )
save.Quicksave ( kTemp )
structure.WiggleSelected ( kDefaultWiggleDuration )
aa_score = GetScore ()
if ( aa_score < c_score ) then
save.Quickload ( kTemp )
aa_score = c_score -- Cater to filter-induced score decrease
end
save.Quicksave ( kTemp )
behavior.SetClashImportance ( kLowCiWiggle )
structure.WiggleSelected ( 1 )
table.insert ( loss_from_low_ci_wiggle , aa_score - GetScore () )
behavior.SetClashImportance ( 1 )
structure.WiggleSelected ( kDefaultWiggleDuration )
score = GetScore ()
if ( score < aa_score ) then
save.Quickload ( kTemp )
end
end
function WiggleTwoBestCandidatesAndSelectBest ()
save.Quickload ( kBestPostRebuild_a )
structure.WiggleSelected ( kDefaultWiggleDuration )
score_a = GetScore ()
save.Quicksave ( kBestPostRebuild_a_post_wiggle )
if ( best_score_after_rebuild_and_shake_b > kInvalidScore ) then
-- To cater for single rebuild
save.Quickload ( kBestPostRebuild_b )
structure.WiggleSelected ( kDefaultWiggleDuration )
score_b = GetScore ()
if ( score_a > score_b ) then
save.Quickload ( kBestPostRebuild_a_post_wiggle )
end
end
end
function PostWiggle ()
local i
local mutstr=''
local selstr=''
local swapsel = {}
init_score = GetScore ()
save.Quicksave ( kTemp )
if ( score_type == 4 or score_type == 5 or score_type == 6 ) then
return 1 -- Hiding or bonding
elseif ( best_score - init_score < pw_threshold_value ) then
if ( mutate_not_shake >= 1) then
-- 1 or 2 do mutate
for i = 1, n_residues do
swapsel[i]=0
if selection.IsSelected(i) == true then
selstr=(selstr..i..' ')
if mutate_list[i]==0 then
selection.Deselect(i)
swapsel[i]=1
else
mutstr=(mutstr..i..' ')
end
end
end
print('Trying to mutate residues '..mutstr)
structure.MutateSidechainsSelected ( 1 )
for i = 1, n_residues do
if swapsel[i]==1 then
selection.Select(i)
end
end
end
if (mutate_not_shake <= 1) then
-- 0 or 1 do shake
print('Shaking residues '..selstr)
structure.ShakeSidechainsSelected ( 1 )
end
score = GetScore ()
if ( score < init_score ) then
save.Quickload ( kTemp ) -- Cater for filters causing a decrease
score = init_score
end
WiggleNudge ( score )
return 1
else
return 0
end
end
function FinalFuse ( start_x , end_x )
-- After rebuilding, if we've got a new best score
-- (tweakable by adjusting post_rebuild_threshold),
-- do a shake at low CI followed by a wiggle
init_score = GetScore ()
score_below_best = best_score - init_score
if ( score_type == 4 or score_type == 5 or score_type == 6 ) then
return -- Hiding or bonding
elseif ( score_below_best < post_rebuild_threshold ) then
if (fidealize == true) then
FinalIdealize ( init_score , start_x , end_x )
else
ShakeLowCIWiggle ( init_score )
end
return
else
return
end
end
function RecordImprovement ()
curr_score = GetScore ()
if ( ( test_for_credit == false ) or ( creditbest.AreConditionsMet () == true ) ) then
rb_last_gain = rb
rx_last_gain = rx
new_gain = curr_score - best_score
all_gain = curr_score - start_score
best_score = curr_score
save.LoadSecondaryStructure ()
save.Quicksave ( kOriginalStructureOrNewBest )
print(string.format("Improvement to %.3f (%.3f/%.3f)\n=%d%% of gain so far.",
trunc3(best_score),r3(new_gain),r3(all_gain),r0(100*new_gain/all_gain) ))
return 1
else
return 0
end
end
function ConstructListOfResiduesWithinInnerSphere ( start_idx , end_idx )
for i = 1 , n_residues do
inner_sphere [ i ] = false
end
for i = 1 , n_residues do
for j = start_idx , end_idx do
if ( structure.GetDistance ( i , j ) < kInnerSphereRadius ) then
inner_sphere [ i ] = true
end
end
end
end
function SelectInnerSphere ()
selection.DeselectAll ()
for i = 1 , n_residues do
if ( inner_sphere [ i ] == true ) then
selection.Select ( i )
end
end
end
function ConstructListOfResiduesWithinOuterSphere ( start_idx , end_idx )
for i = 1 , n_residues do
outer_sphere [ i ] = false
end
for i = 1 , n_residues do
for j = start_idx , end_idx do
if ( structure.GetDistance ( i , j ) < kOuterSphereRadius ) then
outer_sphere [ i ] = true
end
end
end
end
function SelectOuterSphere ()
selection.DeselectAll ()
for i = 1 , n_residues do
if ( outer_sphere [ i ] == true ) then
selection.Select ( i )
end
end
end
function RebuildPreamble ( start_idx , end_idx )
save.Quickload ( kOriginalStructureOrNewBest )
if ( convert_to_loop == true ) then
ConvertToLoop ( start_idx , end_idx )
end
selection.DeselectAll ()
selection.SelectRange ( start_idx , end_idx )
end
function RebuildSeg ( start_idx , end_idx)
local i
local n_rebuilds
local n_good_rebuilds = 0
best_score_after_rebuild_and_shake_a = kInvalidScore
best_score_after_rebuild_and_shake_b = kInvalidScore
ConstructListOfResiduesWithinInnerSphere ( start_idx , end_idx )
ConstructListOfResiduesWithinOuterSphere ( start_idx , end_idx )
use_remix = run_remix
if ( use_remix == true ) then
RebuildPreamble ( start_idx , end_idx )
n_remix = structure.RemixSelected ( kRemixQuicksaveStart , number_of_rebuilds )
if (n_remix == 0) then
n_rebuilds = number_of_rebuilds
use_remix = false
rx = 0
else
use_remix = true
rx = 1
end
else
n_rebuilds = number_of_rebuilds
end
if (rx >= 1) then rx=n_remix else rx=n_rebuilds end
for i = 1 , rx do
if ( use_remix == true ) then
save.Quickload ( kRemixQuicksaveStart -1 + i )
rx = n_remix
else
RebuildPreamble ( start_idx , end_idx )
structure.RebuildSelected ( 1 )
rb = n_rebuilds
end
score_after_rebuild = GetScore ()
if ( math.abs ( score_after_rebuild - best_score ) >= 1e-5 ) then
n_good_rebuilds = n_good_rebuilds + 1
SelectInnerSphere ()
structure.ShakeSidechainsSelected ( 1 )
score_after_shake_wiggle = GetScore ()
if (score_after_shake_wiggle > math.min(best_score_after_rebuild_and_shake_a,best_score_after_rebuild_and_shake_b)) then
if (best_score_after_rebuild_and_shake_b < best_score_after_rebuild_and_shake_a) then
best_score_after_rebuild_and_shake_b = score_after_shake_wiggle
save.Quicksave ( kBestPostRebuild_b )
else
best_score_after_rebuild_and_shake_a = score_after_shake_wiggle
save.Quicksave ( kBestPostRebuild_a )
end
end
end
end -- for i
if (rb == n_rebuilds) then
rb1 = rb1 + 1
print("rb "..rb1.." rb_number: "..rb.." "..start_idx.."-"..end_idx.." ("..start_idx.."/"..max_residue..")")
else
rx1 = rx1 + 1
print("rx "..rx1.." rx_found: "..rx.." "..start_idx.."-"..end_idx.." ("..start_idx.."/"..max_residue..")")
end
return n_good_rebuilds
end
-- below is main part of main loop
function RebuildAllAtSpecifiedLength ( rebuild_length )
local inc
max_possible_residue = max_residue - rebuild_length + 1
n_possible_segs = max_possible_residue - min_residue + 1
r = pseudorandom ( best_score )
start_idx = min_residue + n_possible_segs * r
start_idx = start_idx - start_idx % 1
inc = Coprime ( n_possible_segs ) -- increment used for start_idx
-- The point of this Coprime, start_idx business is so we go through the protein in a
-- nonuniform way. Rather than rebuilding 1-4, 2-5 , 3-6 for example, we might do 21-24, 53-57, 3-6
-- or something like that
candidate_section_found = false
print("Starting a new cycle thru the protein at:\n"..os.date()..".")
print("==============="..prog_name.. "===============")
for i = 1 , n_possible_segs do
end_idx = start_idx + rebuild_length - 1
assert ( start_idx >= min_residue and end_idx <= max_residue , "Range error" )
save.LoadSecondaryStructure ()
if ( ( DoesSectionContainFixedResidues ( start_idx , end_idx ) == false ) and
( IsSegmentRebuildable ( start_idx , end_idx ) == true ) ) then
candidate_section_found = true
print("("..i.."/"..n_possible_segs..")")
print(n_possible_segs+1-i, " segments left to do.")
if ( RebuildSeg ( start_idx , end_idx ) > 0 ) then
print('1')
SelectOuterSphere ()
print('2')
WiggleTwoBestCandidatesAndSelectBest ()
print('3')
score_after_bc_wiggle = GetScore ()
if ( PostWiggle () == 1 ) then
score_after_post_wiggle = GetScore ()
print('4')
FinalFuse ( start_idx , end_idx )
print('5')
score_after_final_fuse = GetScore ()
if ( score_after_final_fuse > best_score ) then
print ( " " .. r3 ( score_after_bc_wiggle - best_score ) ..
" " .. r3 ( score_after_post_wiggle - score_after_bc_wiggle ) ..
" " .. r3 ( score_after_final_fuse - score_after_post_wiggle ) )
RecordImprovement () -- prints new score
else
print ( " " .. r3 ( score_after_bc_wiggle - best_score ) ..
" " .. r3 ( score_after_post_wiggle - score_after_bc_wiggle ) )
end -- if(score
else
print ( " " .. r3 ( score_after_bc_wiggle - best_score ) )
end -- if(PostWiggle
else
print ( "Skipped" )
end -- if(RebuildSeg
end -- if((DoesSectionContainFixedResidues
print('6')
start_idx = start_idx + inc
if ( start_idx > max_possible_residue ) then
start_idx = start_idx - n_possible_segs
end
end -- for i
print('7')
if ( candidate_section_found == false ) then
print ( "No rebuildable sections found" )
exit (0)
end
end
-- above is main part of main loop
--
-- the function Sort is taken from http://fold.it/portal/recipe/49233
-- "Tvdl enhanced DRW 3.0.1" by Timo van der Laan
--
function Sort ( tab, items ) --BACKWARD bubble sorting - lowest on top, only needed items
for xx = 1, items do --items do
for yy = xx + 1, #tab do
if tab [ xx ] [ 1 ] > tab [ yy ] [ 1 ] then
tab [ xx ], tab [ yy ] = tab [ yy ], tab [ xx ]
end
end
end
return tab
end
function Rebuild_Worst(howmany, rebuild_length)
segCnt = structure.GetCount()
--
-- get the score of each segment, store it in a table
--
scoreTab = {} -- a new, empty table
for ii = 1, segCnt do
scoreTab [ #scoreTab + 1 ] = current.GetSegmentEnergyScore ( ii )
end
--
-- now get the worst sections of the specified length
--
worstTab = {} -- another new empty table
for ii = 1, segCnt - rebuild_length + 1 do
local partScore = 0
for jj = ii, ii + rebuild_length - 1 do
partScore = partScore + scoreTab [ jj ]
end
worstTab [ #worstTab + 1 ] = { partScore, ii, ii + rebuild_length - 1 }
end
buildWorst = howmany
worstTab = Sort ( worstTab, buildWorst )
max_possible_residue = max_residue
n_possible_segs = max_possible_residue - min_residue + 1
candidate_section_found = false
print("Starting a new cycle of Remix/Rebuild Worst Segments:\n"..os.date()..".")
print("============= Remix/Rebuild Worst =============")
for i = 1 , howmany do
print(howmany+1-i, " segments left to do.")
seg = worstTab [ i ] [ 2 ]
end_idx = worstTab [ i ] [ 3 ]
save.LoadSecondaryStructure ()
if ( ( DoesSectionContainFixedResidues ( seg , end_idx ) == false ) and
( IsSegmentRebuildable ( seg , end_idx ) == true ) ) then
candidate_section_found = true
if ( RebuildSeg ( seg , end_idx ) > 0 ) then
print('1')
SelectOuterSphere ()
print('2')
WiggleTwoBestCandidatesAndSelectBest ()
print('3')
score_after_bc_wiggle = GetScore ()
if ( PostWiggle () == 1 ) then
score_after_post_wiggle = GetScore ()
print('4')
FinalFuse ( seg , end_idx )
print('5')
score_after_final_fuse = GetScore ()
if ( score_after_final_fuse > best_score ) then
print ( " " .. r3 ( score_after_bc_wiggle - best_score ) ..
" " .. r3 ( score_after_post_wiggle - score_after_bc_wiggle ) ..
" " .. r3 ( score_after_final_fuse - score_after_post_wiggle ) )
RecordImprovement () -- prints new score
else
print ( " " .. r3 ( score_after_bc_wiggle - best_score ) ..
" " .. r3 ( score_after_post_wiggle - score_after_bc_wiggle ) )
end -- if(score
else
print ( " " .. r3 ( score_after_bc_wiggle - best_score ) )
end -- if(PostWiggle
else
print ( "Skipped" )
end -- if(RebuildSeg
end -- if((DoesSectionContainFixedResidues
end -- for i
print('7')
if ( candidate_section_found == false ) then
print ( "No rebuildable sections found" )
exit (0)
end
end
function PrintParameters ()
if ( score_type == 1 ) then
print ( "Score type : Normal" )
elseif ( score_type == 2 ) then
print ( "Score type : Energy" )
elseif ( score_type == 3 ) then
print ( "Score type : Exploration" )
elseif ( score_type == 4 ) then
print ( "Score type : Hiding" )
elseif ( score_type == 5 ) then
print ( "Score type : Bonding" )
elseif ( score_type == 6 ) then
print ( "Score type : Filters" )
elseif ( score_type == 7 ) then
print ( "Score type : Normal/Slow Filters" )
end -- if score_type
print(string.format("Start score: %.3f",trunc3(best_score)))
print ( "Rebuild length: " .. rebuild_length )
if ( ss_criterion == 1 ) then
print ( "Loops only" )
elseif ( ss_criterion == 2 ) then
print ( "Loops + 1" )
elseif ( ss_criterion == 3 ) then
print ( "Loops + sheets" )
elseif ( ss_criterion == 4 ) then
print ( "Any" )
end -- ss_criterion
if ( convert_to_loop == true ) then
print ( "Converting to loops" )
end
if ( run_remix == true ) then
print ( "Using remix" )
end
if ( rebuild_worst == true ) then
print ( "Run Rebuild Worst Segments" )
end
if ( fidealize == true) then
print ( "Run Final Idealize in Final Fuze" )
else
print ( "Run ShakeLowCIWiggle in Final Fuze" )
end
if ( design_puzzle == true ) then
print('Mutate_list = \"'..mutate_str..'\" = \"'..printlist(mutate_list)..'\"')
if (mutate_not_shake==0) then
print("Shake not mutate")
elseif(mutate_not_shake==1) then
print("Mutate then shake")
elseif(mutate_not_shake==2) then
print("Mutate not shake")
else
print('MSflag='..mutate_not_shake..' is not in range (0-2)')
end
end -- if design_puzzle
print('Rebuild_list = \"'..rebuild_str..'\" = \"'..printlist(rebuild_list)..'\"')
print ( "Rebuild range " .. min_residue .. " to " .. max_residue )
print ( "N rebuilds " .. number_of_rebuilds )
if ( keep_bands == true) then
print('Won\'t disable bands')
end
end
-- http://www.lua.org/manual/5.2/manual.html#6.4
-- helped make this function 11/16/17
function getlist(liststr)
local newlist={}
local i,ilo,ihi,idir,substr
for i=1,n_residues do
newlist[i]=0
end -- for i
-- below reads from liststr a series of substr's
-- where each substr contains an integer
-- followed by one or more '-' signs
-- followed by an integer
for substr in string.gmatch(liststr,"(%d+%-+%d+)") do
-- substr includes one or more '-' characters in a row
-- below gets ilo & ihi from substr
ilo=string.gsub(substr,"(%d+)%-+(%d+)","%1")+0
ihi=string.gsub(substr,"(%d+)%-+(%d+)","%2")+0
-- above gets ilo & ihi from substr
idir=1 -- the increment to use from ilo to ihi
if ilo>ihi then
idir= -1
end -- if ilo
for i=ilo,ihi,idir do -- for i=ilo to ihi step idir
if i>=1 and i<=n_residues then
newlist[i]=1
end -- if i
end -- for i
end -- for substr
-- below reads from liststr a series of substr's
-- where each substr contains an integer
for substr in string.gmatch(liststr,"(%d+)") do
i=substr+0 -- converts substr into the number i
if i>=1 and i<=n_residues then
newlist[i]=1
end -- if i
end -- for substr
return newlist
end
function checklist()
local i,resinrow,maxresinrow
min_residue=0
max_residue=0
resinrow=0
maxresinrow=0
for i=1,n_residues do
if rebuild_list[i]==1 then
resinrow=resinrow+1
max_residue=i
if min_residue==0 then
min_residue=i
end
else
if resinrow>maxresinrow then
maxresinrow=resinrow
end
resinrow=0
end -- if rebuild_list
end -- for i
if resinrow>maxresinrow then
maxresinrow=resinrow
end
if maxresinrow<rebuild_length then
print("Rebuild range error.")
print("The list of residues to rebuild (\""..rebuild_str.."\" input above)")
print("has at most "..maxresinrow.." of the desired "..rebuild_length.." residues in a row.")
return 0
else
return 1
end -- if maxresinrow
end
-- http://www.lua.org/manual/5.2/manual.html#6.4
-- helped make this function 11/16/17
function printlist(templist)
local outstr=''
local i,gotone,strlen
gotone=0
for i=1,n_residues do
if templist[i]==1 then
gotone=gotone+1
if gotone==1 then
outstr=(outstr..i)
end -- if gotone
else -- templist[i]==0
if gotone>1 then
outstr=(outstr..'-'..(i-1)..' ')
elseif gotone==1 then
outstr=(outstr..' ')
end -- if gotone
gotone=0
end -- if templist
end -- for i
if gotone>1 then
outstr=(outstr..'-'..n_residues)
end -- if gotone
strlen=string.len(outstr)
if string.sub(outstr,strlen,strlen)==' ' then
-- if outstr ends with a blank space,
-- then remove that blank space
outstr=string.sub(outstr,1,strlen-1)
end
return outstr
end
function GetOptionalParameters ()
local dlog = dialog.CreateDialog("Options")
dlog.pw_threshold = dialog.AddSlider("Post sw threshold", pw_threshold_value, 0, 200, 0)
dlog.cnvt_loops = dialog.AddCheckbox("Convert to loops", convert_to_loop)
dlog.keep_bands = dialog.AddCheckbox("Keep bands", keep_bands)
dlog.ok = dialog.AddButton ( "OK" , 1 )
dlog.cancel = dialog.AddButton ( "Cancel" , 0 )
if ( dialog.Show ( dlog ) > 0 ) then
pw_threshold_value = dlog.pw_threshold.value
convert_to_loop = dlog.cnvt_loops.value
keep_bands = dlog.keep_bands.value
return true
else
return false
end
end
function GetParameters ()
local dlog = dialog.CreateDialog (prog_name)
dlog.f_idealize = dialog.AddCheckbox ("Final Idealize" , fidealize)
dlog.rb_worst_howmany = dialog.AddSlider ( "How many worst" , howmany , 3 , structure.GetCount() , 0 )
dlog.rb_worst = dialog.AddCheckbox ( "Rebuild worst segments" , rebuild_worst )
dlog.rb_length = dialog.AddSlider ( "Rebuild length" , 6 , 3 , 9 , 0 )
dlog.rlabel_list = dialog.AddLabel("Rebuild Segments:")
dlog.rebuild_list = dialog.AddTextbox ( "Rebuild Segs" , rebuild_str )
dlog.rlabela = dialog.AddLabel('List segs to rebuild like 1-3,6,19-30,45-62')
if design_puzzle == true then
dlog.mutate_list = dialog.AddTextbox ( "Mutate segments" , mutate_str )
dlog.mlabela = dialog.AddLabel('List segs to mutate like 1-3,6,19-30,45-62')
end -- if design_puzzle
dlog.rebuild_criterion = dialog.AddSlider ( "Rebuild criterion" , ss_criterion , 1 , 4 , 0 )
dlog.rc = dialog.AddLabel ( "1 = L only : 2 = L only + 1 : 3 = L + E : 4 = Any" )
dlog.n_rebuilds = dialog.AddSlider ( "N rebuilds" , number_of_rebuilds , 1 , 40 , 0 )
dlog.run_remix = dialog.AddCheckbox ( "Use remix" , run_remix )
dlog.div_1 = dialog.AddLabel ( "__________________________________________" )
if ( design_puzzle == true ) then
dlog.mutate = dialog.AddSlider ( "MSflag" , mutate_not_shake, 0, 2, 0 )
dlog.mlabelb = dialog.AddLabel ( "0=Shake only, 1=Mutate then Shake, 2=Mutate only" )
end
if ( DoesPuzzleHaveSlowFilters () == true ) then
score_type = 7
end
dlog.score_type = dialog.AddSlider ( "Score type" , score_type , 1 , 7 , 0 )
dlog.tp = dialog.AddLabel ( "1 = Normal : 2 = Energy : 3 = Explore : 4 = Hiding" )
dlog.tp_2 = dialog.AddLabel ( "5 = Bonding : 6 = Filters : 7 = Normal for Slow Filters" )
dlog.credit_check = dialog.AddCheckbox ( "Check conditions met " , test_for_credit )
dlog.ok = dialog.AddButton ( "OK" , 1 )
dlog.cancel = dialog.AddButton ( "Cancel" , 0 )
dlog.other_options = dialog.AddButton ( "Other options" , 2 )
return_code = dialog.Show ( dlog )
if ( return_code > 0 ) then
fidealize = dlog.f_idealize.value
howmany = dlog.rb_worst_howmany.value
rebuild_worst = dlog.rb_worst.value
rebuild_length = dlog.rb_length.value
rebuild_list = getlist(dlog.rebuild_list.value)
rebuild_str = printlist(rebuild_list)
ss_criterion = dlog.rebuild_criterion.value
number_of_rebuilds = dlog.n_rebuilds.value
run_remix = dlog.run_remix.value
if ( design_puzzle == true ) then
mutate_list = getlist(dlog.mutate_list.value)
mutate_str = printlist(mutate_list)
mutate_not_shake = dlog.mutate.value
end
score_type = dlog.score_type.value
test_for_credit = dlog.credit_check.value
end
return return_code
end
function main()
local n_enabled, n_disabled, templist
n_bands = band.GetCount ()
n_enabled = 0
n_disabled = 0
for i = 1, n_bands do
orig_enabled_bands [i] = 0
if band.IsEnabled(i) == true then
orig_enabled_bands [i] = 1
n_enabled = n_enabled + 1
else
n_disabled = n_disabled + 1
end
end
n_residues = structure.GetCount ()
for i = 1, n_residues do
original_secondary_structure [ i ] = structure.GetSecondaryStructure ( i )
end
save.SaveSecondaryStructure ()
templist = string.format('1-%d',n_residues)
rebuild_str=templist
rebuild_list=getlist(templist)
design_puzzle = IsPuzzleMutable ()
if design_puzzle == true then
mutate_not_shake = 2
mutate_str=templist
mutate_list=getlist(templist)
else
mutate_not_shake = 0
end
rb = 0
rb_last_gain = 0
save.Quicksave ( kOriginalStructureOrNewBest )
behavior.SetClashImportance ( 1 )
if ( current.GetExplorationMultiplier () > 0 ) then
score_type = 3
end
original_slow_filters_setting = behavior.GetSlowFiltersDisabled ()
-- below gets player input
repeat
dialog_code = GetParameters ()
if ( dialog_code == 2 ) then
GetOptionalParameters ()
end
until ( dialog_code < 2 )
if ( dialog_code == 0 ) then
return
end
best_score = GetScore ()
start_score = best_score
print(string.format('Running %s on %s for\nPuzzle %s \n (%s) with',
prog_name, ui.GetPlatform(), puzzle.GetPuzzleID(), puzzle.GetName() ))
print(string.format('%d residues, %d bands (%d enabled, %d disabled),\nand Score %.3f.',
n_residues, n_bands, n_enabled, n_disabled, start_score))
if checklist() == 0 then
return
end
-- above gets player input
PrintParameters ()
start_time = os.time ()
if ( keep_bands == false ) then
band.DisableAll () -- turns all bands gray
end
GetListOfFixedResidues ()
if ( mutate_not_shake >= 1 ) then
for i = 1 , n_residues do
original_residues [ i ] = structure.GetAminoAcid ( i )
end
end
-- main loop is below & endless
while true do
if (rebuild_worst == true) then
Rebuild_Worst(howmany,rebuild_length)
end
RebuildAllAtSpecifiedLength ( rebuild_length )
end
-- main loop is above & endless
print('This line should never be reached')
cleanup()
end
function cleanup (errmsg)
if CLEANUPENTRY ~= nil then
return
end
CLEANUPENTRY = true
print ( "---" )
local reason
local start, stop, line, msg
if errmsg == nil then
reason = "complete"
else
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 ( prog_name .. " " .. reason .. " " .. os.date ( "%x %X" ))
if reason == "error" then
print ( "Unexpected error detected" )
print ( "Error line: " .. line )
print ( "Error: \"" .. errmsg .. "\"" )
end
local tot
print ( "Cleaning up" )
behavior.SetClashImportance ( 1.0 )
save.Quickload ( kOriginalStructureOrNewBest )
best_score = GetScore()
if ( convert_to_loop == true ) then
save.LoadSecondaryStructure ()
end
selection.SelectAll ()
if ( keep_bands == false ) then
for i=1,n_bands do -- turn certain bands purple again
if orig_enabled_bands[i]==1 then
band.Enable(i)
end
end -- for i
end -- if keep_bands
behavior.SetSlowFiltersDisabled ( original_slow_filters_setting )
end_time = os.time ()
print(os.date())
print("Elapsed time : "..os.difftime(end_time,start_time).." secs")
print("Final Score "..trunc3(best_score))
if ( #loss_from_low_ci_wiggle > 1 ) then
table.sort ( loss_from_low_ci_wiggle )
mid_pt = math.ceil ( #loss_from_low_ci_wiggle / 2 )
print("Median loss from low ci ("..kLowCiWiggle..") wiggle "..r3(loss_from_low_ci_wiggle[mid_pt]))
end
if ( mutate_not_shake >= 1 ) then
tot=0
for i = 1 , n_residues do
new_residues [ i ] = structure.GetAminoAcid ( i )
if ( new_residues [ i ] ~= original_residues [ i ] ) then
tot=tot+1
end
end -- for i
if tot>0 then
print('Did '..tot..' mutations as below:')
for i = 1 , n_residues do
if ( new_residues [ i ] ~= original_residues [ i ] ) then
print (i.." : "..aa1_to_aa3(original_residues[i]).." to "..aa1_to_aa3(new_residues[i]))
end
end -- for i
end -- if tot
end -- if mutate_not_shake
end
-- Above defines the functions
-- =========================================================================================
-- Below runs the program
-- main ()
xpcall ( main , cleanup )