Profile
- Name
- FSPtest4.04Filter
- ID
- 103149
- Shared with
- Public
- Parent
- FSPtest4.03Filter
- Children
- None
- Created on
- September 06, 2019 at 05:43 AM UTC
- Updated on
- September 06, 2019 at 05:43 AM UTC
- Description
*3.txt 9/6/19 1224am midnight code
Best for
Code
function main()
-- FSP 4.04 Filter
-- last updated 9/6/19 1224am midnight by jeff101
-- FSP 4.03 Filter
-- last updated 10/22/16 145pm by jeff101
-- FSP 4.02
-- last updated 10/17/14 218pm by jeff101
-- updated for foldit v2
-- multiple use rebuild script with lots of options v1.06
-- Version 1.01 added printing of ranked score and multiplier
-- version 1.02 updated get_score2 function with latest try at scoring exploration puzzles
-- version 1.03 fixed increment for do_sections loop
-- version 1.04 fixed output, fixed problems ith do_loop_sections and do_sections scoring
-- version 1.05 add shake and wiggle_sidechains after rebuild in rebuild_worst_segment function
-- version 1.06 added do_worst_sections option
-- version 2.01 added banding and local wiggle algorithms
-- version 2.02 moved banding algorithm into function
-- version 2.03 cleaned up do_all_with_repeat processing
-- version 2.04 added mutating for mutable puzzles
-- version 2.05 added recording information in Note
-- version 2.06 fixed problem in mutate code
-- version 3.00 added multiple rebuild tries before continuing and added =ui
-- version 3.01 conditionally call gui (meant to do this in 3.00),
-- fixed bug in new rebuild code
-- version 3.02 added first and last seg on gui
-- version 3.03 added another mutate step after stabilization
-- version 3.04 added save.Quickload(fsp.slot2) at very end to restore best score
-- version 3.05 added function select_rebuildable() to select unfrozen, unlocked,
-- non-ligand segments before rebuilding
-- version 3.06 updated band_and_wiggle to allow initial bands and banding algorithm
-- don't unfreeze protein
-- version 3.07 modified banding for frozen and ligand puzzles,
-- added fsp.disable_existing_bands variable
-- version 3.08 added segment list to the menu
-- (use #,#,#,# to run FSP on multiple segment sections)
-- version 3.09 added segment list information to Note
-- version 4.01 added segment list information to Note
-- fixed(?) disable_existing_bands option
-- added fsp.disable_existing_bands_only_during_rebuild_worst
-- version 4.02 jeff101 added checkbox option to not mutate
-- version 4.02F BK added filter management by porky for slow filter puzzles
-- version 4.03F jeff101 listed band info periodically, changed defaults,
-- let it restore enabled/disabled user bands as needed,
-- made filter management optional, listed input parameters,
-- and let rebuilds not change all to loop
-- version 4.04F jeff101 added more band info & truncate scores to match GUI better
print("find_starting_point version 4.04 filter foldit v2")
fsp={} -- 9/6/19 code seems to treat fsp as a global variable
fsp.title='FSPtest4.04Filter'
fsp.use_gui=true -- use gui
fsp.clashes={0.01,0.05,0.1,0.2,0.4,0.6,0.8,1.0} -- values for the run_clash_algorith function
fsp.iters={1,1,5,5,5,5,10,15} -- values for the run_clash_algorith function
fsp.use_user_bands=true -- use the bands that exist in puzzle
fsp.do_double_rebuild=false -- rebuild without bands first then rebuild with bands
fsp.minimum_rebuild=1 -- minimum iterations value for do_local_rebuild command
fsp.maximum_rebuild=10 -- maximum iterations value for do_local_rebuild command
-- new options for v3.00+_
fsp.maximum_rebuild_loss_before_continuing=2 -- %loss acceptable on rebuild before continuing
fsp.maximum_rebuilds_before_continuing=5 -- maximum # of rebuilds before continuing (picks highest rebuild)
fsp.slot3=9 --
--
fsp.quick=false -- skip many steps, gives poorer results
fsp.slot1=1 -- save slot for intermediate best results
fsp.slot2=3 -- save slot for overall best
fsp.shake_limit=2 -- iterations value on do_shake command
fsp.wiggle_limit1=1 -- iterations value on structure.WiggleAll command
fsp.wiggle_limit2=0.5 -- iterations value on structure.WiggleAll command
fsp.rca_count=3 -- number of iterations for the run_clash_algorithm function
fsp.stw_count=3 -- number of iterations for the shake_then_wiggle function
fsp.rebuild_worst_tries=3 -- number of times to rebuild worst segment
fsp.loop_count=99 -- total loop count
fsp.enable_band_algorithm=true -- do some banding
fsp.banding_tries=5 -- number of banding tries
fsp.disable_existing_bands=false -- disable existing bands before adding bands in band_and_wiggle function
fsp.disable_existing_bands_only_during_rebuild_worst=true -- disable existing bands only during rebuild worst function
fsp.enable_local_wiggle=false -- gives minimum improvement
fsp.enable_mutate=true -- mutates after every loop for mutable puzzles
fsp.make_all_loop=false -- if true, converts all 2nd str to loop before rebuilds
fsp.keep_filters_on=false -- if true, keeps Slow Filters Enabled
getbands() -- gets fsp.nbands & fsp.ison
print('Starting with '..fsp.nbands..' bands.')
-- do options -- set one or more to true
fsp.do_all=true -- rebuild all segments at once
fsp.do_loop_sections=false -- loop through segment snippets (see options below)
fsp.do_sections=false -- loop through user specified segment snippets
fsp.do_worst_sections=false -- rebuild worst sections
fsp.do_all_with_repeat=false -- rebuild all segments at once but restart every fsp.tries_per_repeat iterations, turns off other options
-- do_loop_sections options
fsp.section_size=5 -- segment snippet size
fsp.section_increment=3 -- segment snippet increment
fsp.tries_per_section=3 -- tries per segment snippet
-- do_sections options
fsp.sections={1,10,5,15} -- user specified segment snippets in pairs {seg1a,seg1b,seg2a,seg2b,...,...}
fsp.tries=3 -- number of tries per user specifed segment snippet
-- do_all_with_repeat options (turns off other options)
fsp.repeat_start_slot=4 -- saves starting protein to use for starting point on successive iterations
fsp.best_repeat_score_slot=6 -- save best score for all repeated iterations
fsp.tries_per_repeat=5 -- tries per repeat
fsp.total_tries=10 -- total tries
-- example fsp.total tries=10, fsp.tries_per_repeat is 10 FSP tries starting at
-- starting score using 5 loops of FSP, best score stored in slot 6
if band.GetCount()==0 then fsp.do_double_rebuild=false end
-- if fsp.use_user_bands and (band.GetCount()>0) then fsp.enable_band_algorithm=false end
if fsp.do_all_with_repeat then
fsp.do_all=false
fsp.do_loop_sections=false
fsp.do_sections=false
fsp.do_worst_sections=false
end
count=0
for seg=1,structure.GetCount() do
if structure.IsMutable(seg) then count=count+1 end
end
if count==0 then fsp.enable_mutate=false end
fsp.note_number=structure.GetCount()
for seg=structure.GetCount(),1,-1 do
if structure.GetNote(seg)~="" then break end
fsp.note_number=seg
end
print(string.format("Recording %s results in Note for segment %i",fsp.title,fsp.note_number))
fsp.starting_score=current.GetScore()
--structure.SetNote(fsp.note_number,string.format("(%s) %.3f + FSP",user.GetPlayerName(),trunc3to0(fsp.starting_score)))
if fsp.use_gui then find_starting_point_gui() end
-- below manages Slow Filters
classes_copied = 0
myclcp = {}
if fsp.keep_filters_on then
MutClass(structure, true) -- Enable Slow Filters
MutClass(band, true) -- Enable Slow Filters
else
MutClass(structure, false) -- Disable Slow Filters
MutClass(band, false) -- Disable Slow Filters
end -- if fsp
MutClass(current, true) -- Enable Slow Filters
-- add fsp.sections to Note
fsp.label=fsp.title
if fsp.do_sections then
if #fsp.sections>2 or fsp.sections[1]~=1 or fsp.sections[2]~=structure.GetCount() then
fsp.label=fsp.label.."("
for i=1,#fsp.sections,2 do
if (i+1)==#fsp.sections then
fsp.label=fsp.label..fsp.sections[i].."-"..fsp.sections[i+1]..")"
else
fsp.label=fsp.label..fsp.sections[i].."-"..fsp.sections[i+1]..","
end
end
end
end
start_clock=os.clock()
start_time=os.time()
math.randomseed(os.clock())
n=fsp.loop_count
loop_count=1
fsp.last_starting_score=current.GetScore()
fsp.worst_segment_processed_list={}
while(loop_count<=fsp.loop_count) do
if not fsp.do_all_with_repeat then
print(string.format("Loop %i/%i",loop_count,fsp.loop_count))
end -- if not
-- below does band report
listbands()
-- above does band report
print(string.format("Best solution is stored in slot %i",fsp.slot2))
print(string.format("Intermediate solutions are stored in slot %i",fsp.slot1))
if fsp.do_all_with_repeat then
print(string.format("Best repeat solutions are stored in slot %i",fsp.best_repeat_score_slot))
end -- if fsp
if fsp.do_all then
find_starting_point_all(1)
end -- if fsp
if fsp.do_all_with_repeat then
find_starting_point_all_with_repeat(fsp.tries_per_repeat,fsp.total_tries)
end
if fsp.do_loop_sections then
find_starting_point_loop_sections(fsp.section_size,fsp.section_increment,fsp.tries_per_section)
end
if fsp.do_sections then
for ix=1,#fsp.sections,2 do
seg1=fsp.sections[ix]
seg2=fsp.sections[ix+1]
find_starting_point_section({seg1,seg2},fsp.tries)
end
end
if fsp.do_worst_sections then
sections=get_worst_sections(1,structure.GetCount())
for i=#sections,1,-1 do
seg1=sections[i][1]
seg2=sections[i][2]
find_starting_point_section({seg1,seg2},1)
end
end
structure.SetNote(fsp.note_number,string.format("(%s) %.3f + %s(%i) %.3f",
user.GetPlayerName(),trunc3to0(fsp.starting_score),fsp.label,loop_count,trunc3to0(current.GetScore())))
save.Quicksave(fsp.slot1)
save.Quickload(fsp.slot2)
structure.SetNote(fsp.note_number,string.format("(%s) %.3f + %s(%i) %.3f",
user.GetPlayerName(),trunc3to0(fsp.starting_score),fsp.label,loop_count,trunc3to0(current.GetScore())))
save.Quicksave(fsp.slot2)
save.Quickload(fsp.slot1)
loop_count=loop_count+1
end
save.Quickload(fsp.slot2)
-- below does band report
listbands()
-- above does band report
end -- function main()
-- below are filter managment functions
-- function to copy class/table
function CopyTable(orig)
local copy = {}
for orig_key, orig_value in pairs(orig) do
copy[orig_key] = orig_value
end
return copy
end -- function CopyTable()
-- functions for filters
function FiltersOn() -- Enable Slow Filters
if behavior.GetSlowFiltersDisabled() then
behavior.SetSlowFiltersDisabled(false)
end
end -- function FiltersOn()
function FiltersOff() -- Disable Slow Filters
if behavior.GetSlowFiltersDisabled()==false then
behavior.SetSlowFiltersDisabled(true)
end
end -- function FiltersOff()
-- function to overload a funtion
function mutFunction(func)
local currentfunc = func
local function mutate(func, newfunc)
local lastfunc = currentfunc
currentfunc = function(...) return newfunc(lastfunc, ...) end
end -- local function
local wrapper = function(...) return currentfunc(...) end
return wrapper, mutate
end -- function mutFunction()
-- function to overload a class
-- to do: set the name of function
function MutClass(cl, filters)
classes_copied = classes_copied+1
myclcp[classes_copied] = CopyTable(cl)
local mycl =myclcp[classes_copied]
for orig_key, orig_value in pairs(cl) do
myfunc, mutate = mutFunction(mycl[orig_key])
if filters==true then
mutate(myfunc, function(...)
FiltersOn() -- Enable Slow Filters
if table.getn(arg)>1 then
-- first arg is self (function pointer), we pack from second argument
local arguments = {}
for i=2,table.getn(arg) do
arguments[i-1]=arg[i]
end -- for i
return mycl[orig_key](unpack(arguments))
else -- if table
--print("No arguments")
return mycl[orig_key]()
end -- if table
end) -- mutate(
cl[orig_key] = myfunc
else -- if filters is false
mutate(myfunc, function(...)
FiltersOff() -- Disable Slow Filters
if table.getn(arg)>1 then
local arguments = {}
for i=2, table.getn(arg) do
arguments[i-1]=arg[i]
end -- for i
return mycl[orig_key](unpack(arguments))
else -- if table
return mycl[orig_key]()
end -- if table
end) -- mutate(
cl[orig_key] = myfunc
end -- if filters
end -- for orig_key
end -- function MutClass()
-- above are filter management functions
function find_starting_point_gui()
menu=dialog.CreateDialog(fsp.title.." gui")
menu.loop_count=dialog.AddTextbox("Total loops",fsp.loop_count)
menu.rca_count=dialog.AddTextbox("# loops 1",fsp.rca_count)
menu.stw_count=dialog.AddTextbox("# loops 2",fsp.stw_count)
menu.rebuild_worst_tries=dialog.AddTextbox("Rebuild worst tries",fsp.rebuild_worst_tries)
menu.banding_tries=dialog.AddTextbox("Banding tries",fsp.banding_tries)
if band.GetCount()>0 then
menu.disable_existing_bands_only_during_rebuild_worst=dialog.AddCheckbox("Disable existing bands only during rebuild worst",fsp.disable_existing_bands_only_during_rebuild_worst)
menu.disable_existing_bands=dialog.AddCheckbox("Disable existing bands before adding new bands",fsp.disable_existing_bands)
end -- if band
if fsp.enable_mutate then
menu.enable_mutate=dialog.AddCheckbox("Try mutating protein",fsp.enable_mutate)
end -- if fsp
menu.make_all_loop=dialog.AddCheckbox("Change all to loop",fsp.make_all_loop)
menu.keep_filters_on=dialog.AddCheckbox("Keep Slow Filters on",fsp.keep_filters_on)
menu.maximum_rebuild_loss_before_continuing=dialog.AddTextbox("Max rebuild loss %",fsp.maximum_rebuild_loss_before_continuing)
menu.maximum_rebuilds_before_continuing=dialog.AddTextbox("Max rebuilds",fsp.maximum_rebuilds_before_continuing)
menu.seglist=dialog.AddTextbox("Segment list","1-"..structure.GetCount())
menu.run=dialog.AddButton("Run",1)
rc=dialog.Show(menu)
if rc==1 then
fsp.loop_count=tonumber(menu.loop_count.value)
fsp.rca_count=tonumber(menu.rca_count.value)
fsp.stw_count=tonumber(menu.stw_count.value)
fsp.rebuild_worst_tries=tonumber(menu.rebuild_worst_tries.value)
fsp.banding_tries=tonumber(menu.banding_tries.value)
if band.GetCount()>0 then
fsp.disable_existing_bands_only_during_rebuild_worst=menu.disable_existing_bands_only_during_rebuild_worst.value
fsp.disable_existing_bands=menu.disable_existing_bands.value
end -- if band
if fsp.enable_mutate then
fsp.enable_mutate=menu.enable_mutate.value
end -- if fsp
fsp.make_all_loop=menu.make_all_loop.value
fsp.keep_filters_on=menu.keep_filters_on.value
fsp.maximum_rebuild_loss_before_continuing=tonumber(menu.maximum_rebuild_loss_before_continuing.value)
fsp.maximum_rebuilds_before_continuing=tonumber(menu.maximum_rebuilds_before_continuing.value)
fsp.sections={}
for w in string.gmatch(menu.seglist.value,"%d+") do
fsp.sections[#fsp.sections+1]=tonumber(w)
end -- for w
firstseg=fsp.sections[1]
lastseg=fsp.sections[#fsp.sections]
if #fsp.sections>2 or firstseg~=1 or lastseg~=structure.GetCount() then
fsp.do_all=false
fsp.do_sections=true
fsp.tries=1
end -- if #fsp
-- below lists inputs got above
print(' \nJust got the following inputs:')
print(string.format(' Total loops=%d, # loops 1=%d, # loops 2=%d,',fsp.loop_count,fsp.rca_count,fsp.stw_count))
print(string.format(' Rebuild worst tries=%d, Banding tries=%d,',fsp.rebuild_worst_tries,fsp.banding_tries))
-- in below use tostring to print booleans as strings
if band.GetCount()>0 then
print(' Disable existing bands only during rebuild worst='..tostring(fsp.disable_existing_bands_only_during_rebuild_worst)..',')
print(' Disable existing bands before adding new bands='..tostring(fsp.disable_existing_bands)..',')
end -- if band
print(' Try mutating protein='..tostring(fsp.enable_mutate)..',')
print(' Change all to loop='..tostring(fsp.make_all_loop)..',')
print(' Keep slow filters on='..tostring(fsp.keep_filters_on)..',')
print(' Max rebuild loss='..fsp.maximum_rebuild_loss_before_continuing..'%,')
print(' Max rebuilds='..fsp.maximum_rebuilds_before_continuing..',')
print(' Segment list='..menu.seglist.value..'.\n ')
end -- if rc
end -- function
function select_rebuildable(seg1,seg2)
local seg
if seg1==nil then seg1=1 end
if seg2==nil then seg2=structure.GetCount() end
selection.SelectRange(seg1,seg2)
for seg=seg1,seg2 do
if selection.IsSelected(seg) then
if structure.IsLocked(seg) or
freeze.IsFrozen(seg) or
structure.GetSecondaryStructure(seg)=="M" then
selection.Deselect(seg)
end -- if structure
end -- if selection
end -- for seg
end -- function
function all_scores()
if current.GetEnergyScore()~=current.GetScore() then
return string.format("Score: %.3f: Energy score: %.3f Multiplier: %.3f",
trunc3to0(current.GetScore()),trunc3to0(current.GetEnergyScore()),
round3(current.GetExplorationMultiplier()))
else
return string.format("Score: %.3f",trunc3to0(current.GetScore()))
end
end -- function
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="Elapsed 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
function get_worst_sections(first,last)
local len,worst_score,score,seg1,seg2
local scores={}
local sections={}
for seg1=first,last do
scores[seg1]=current.GetSegmentEnergyScore(seg1)
end -- for seg1
for len=1,10 do
sections[len]={}
if last-len+1>=first then
worst_score=99999999
for seg1=first,last-len+1 do
score=0
for seg2=seg1,seg1+len-1 do
score=score+scores[seg2]
end -- for seg2
if score<worst_score then
worst_score=score
sections[len][1]=seg1
sections[len][2]=seg1+len-1
sections[len][3]=score
sections[len][4]=score/len
end -- if score
end -- for seg1
end -- if last
end -- for len
return sections
end -- function
function rebuild(seg_pair_list,minn,maxn)
local score
local n
local ix
selection.DeselectAll()
for ix=1,#seg_pair_list,2 do
-- selection.SelectRange(seg_pair_list[ix],seg_pair_list[ix+1])
select_rebuildable(seg_pair_list[ix],seg_pair_list[ix+1])
end -- for ix
score=current.GetEnergyScore()
n=minn
repeat
structure.RebuildSelected(n)
n=n+1
until (score~=current.GetEnergyScore() or n>=maxn)
selection.SelectAll()
end -- function
function add_band(seg1,seg2,length,strength)
band.AddBetweenSegments(seg1,seg2)
band=band.GetCount()
band.SetGoalLength(band,length)
band.SetStrength(band,strength)
end -- function
function wiggle(limit)
local score1,score2
repeat
score1=current.GetScore()
structure.WiggleSelected(2,true,true)
score2=current.GetScore()
until score2<score1+limit
end -- function
function shake(limit)
local score1,score2
repeat
score1=current.GetScore()
structure.ShakeSidechainsSelected(1)
score2=current.GetScore()
until score2<score1+limit
end -- function
function run_clash_algorithm(n)
local clashes=fsp.clashes
local iters=fsp.iters
local i,score,best_score,count
if n==nil then n=1 end
if n<=0 then return end
best_score=current.GetScore()
save.Quicksave(fsp.slot1)
recentbest.Save()
selection.SelectAll()
count=1
repeat
for i=1,#clashes do
behavior.SetClashImportance(clashes[i])
if clashes[i] < 0.5 then
structure.WiggleSelected(iters[i],true,false)
structure.ShakeSidechainsSelected(1)
elseif clashes[i]<1 then
structure.WiggleSelected(iters[i],true,true)
else
wiggle(1)
end
score=current.GetScore()
end -- for i
print(string.format(" (%i/%i) %s",count,n,all_scores()))
if score>best_score then
best_score=score
save.Quicksave(fsp.slot1)
end -- if score
count=count+1
until count>n
recentbest.Restore()
end -- function
function sort2a(a,b)
if a[2]<b[2] then return true else return false end
end -- function
function rebuild_worst_segment(wiggle_deltasize,tries,wiggle_limit)
local worst_score,worst_segment,first,last,best_score,new_score,all_loops,segment_scores,flag
worst_score=99999
worst_segment=1
segment_scores={}
all_loops=true
if fsp.disable_existing_bands_only_during_rebuild_worst then
band.DisableAll()
end -- if fsp
for seg=1,structure.GetCount() do
if structure.GetSecondaryStructure(seg)=="E" or structure.GetSecondaryStructure=="H" then
all_loops=false
break
end
end -- for seg
for seg=1,structure.GetCount() do
if selection.IsSelected(seg) and structure.GetSecondaryStructure(seg)~="M" then
if (not freeze.IsFrozen(seg)) then
score=current.GetSegmentEnergyScore(seg)
segment_scores[#segment_scores+1]={seg,score}
end -- if (not
end -- if sel
end -- for seg
table.sort(segment_scores,sort2a)
-- find first segment in segment_scores not in fsp.worst_segment_processed_list
flag={}
for seg=1,structure.GetCount() do
flag[seg]=true
end -- for seg
for i=1,#fsp.worst_segment_processed_list do
flag[fsp.worst_segment_processed_list[i]]=false
end -- for i
for i=1,#segment_scores do
worst_segment=segment_scores[i][1]
worst_score=segment_scores[i][2]
if flag[worst_segment] then break end
end -- for i
print(string.format(" Worst segment: %i Worst segment score: %.3f (%i)",
worst_segment,trunc3to0(worst_score),#fsp.worst_segment_processed_list+1))
fsp.worst_segment_processed_list[#fsp.worst_segment_processed_list+1]=worst_segment
first=worst_segment-wiggle_deltasize
last=first+wiggle_deltasize+wiggle_deltasize
if first<=0 then
first=1
last=first+wiggle_deltasize+wiggle_deltasize
end -- if first
if last>structure.GetCount() then
last=structure.GetCount()
first=last-wiggle_deltasize-wiggle_deltasize
end -- if last
save.Quicksave(fsp.slot1)
recentbest.Save()
best_score=current.GetScore()
if not all_loops then save.SaveSecondaryStructure() end
for try=1,tries do
if not all_loops then
if fsp.make_all_loop then
selection.SelectAll()
structure.SetSecondaryStructureSelected("L")
end -- if fsp
end -- if not
selection.DeselectAll()
selection.SelectRange(first,last)
structure.RebuildSelected(3)
selection.SelectAll()
if fsp.disable_existing_bands_only_during_rebuild_worst then EnableAllBands() end
structure.ShakeSidechainsSelected(1)
shake(5)
wiggle(wiggle_limit)
new_score=current.GetScore()
if new_score>best_score then
best_score=new_score
if not all_loops then save.LoadSecondaryStructure() end
save.Quicksave(fsp.slot1)
else
recentbest.Restore()
if not all_loops then save.LoadSecondaryStructure() end
end -- if new
end -- for try
if not all_loops then save.LoadSecondaryStructure() end
if fsp.disable_existing_bands_only_during_rebuild_worst then EnableAllBands() end
end -- function
function shake_then_wiggle(n)
local best_score,score,count
if n==nil then n=1 end
if n==0 then return end
save.Quicksave(fsp.slot1)
recentbest.Save()
best_score=current.GetScore()
print(string.format(" Pre-shake and wiggle %s",all_scores()))
count=1
repeat
behavior.SetClashImportance(0.01)
structure.ShakeSidechainsSelected(1)
behavior.SetClashImportance(1.0)
delta=99999
best_score=current.GetScore()
wiggle(1)
score=current.GetScore()
if score>best_score then
save.Quicksave(fsp.slot1)
best_score=score
end
print(string.format(" (%i/%i) %s",count,n,all_scores()))
count=count+1
until count>n
recentbest.Restore()
end -- function
function band_and_wiggle(banding_tries,disable_existing_bands,shake_limit,wiggle_limit)
local try,i,lastseg,seg1,seg2,b,m,lastband,bandcount
local allsegs,unlockedsegs,ligands
if banding_tries==nil then banding_tries=5 end
if disable_existing_bands==nil then band_existing_bands=true end
if shake_limit==nil then shake_limit=2 end
if wiggle_limit==nil then wiggle_limit=1 end
if bnading_tries==0 then return end
lastseg=structure.GetCount()
allsegs={}
unlockedsegs={}
ligandsegs={}
for seg=1,lastseg do
allsegs[#allsegs+1]=seg
if not structure.IsLocked(seg) then unlockedsegs[#unlockedsegs+1]=seg end
if structure.GetSecondaryStructure(seg)=="M" then ligandsegs[#ligandsegs+1]=seg end
end -- for seg
bandcount=band.GetCount()
EnableAllBands()
if disable_existing_bands then band.DisableAll() end
for banding_try=1,banding_tries do
lastband=band.GetCount()
for i=1,math.random(math.ceil(lastseg*0.1)) do
if #ligandsegs==0 or math.random()>0.5 then
seg1=allsegs[math.random(#allsegs)]
seg2=unlockedsegs[math.random(#unlockedsegs)]
else
seg1=unlockedsegs[math.random(#unlockedsegs)]
seg2=ligandsegs[math.random(#ligandsegs)]
end -- if #ligandsegs
band.AddBetweenSegments(seg1,seg2)
b=band.GetCount()
if b>lastband then
band.SetStrength(b,0.1+0.9*math.random())
band.SetGoalLength(b,math.max(0,structure.GetDistance(seg1,seg2)-(5+5*math.random())))
lastband=b
end -- if b
end -- for i
score1=current.GetScore()
m=1
repeat
structure.WiggleAll(1)
score2=current.GetScore()
m=m+1
until score2<score1-100 or m>5
for b=band.GetCount(),bandcount+1,-1 do
band.Delete(b)
end -- for b
shake(shake_limit)
wiggle(wiggle_limit)
recentbest.Restore()
if band.GetCount()>bandcount then
for b=band.GetCount(),bandcount+1,-1 do
band.Delete(b)
end -- for b
end -- if band
end -- for banding_try
EnableAllBands()
end -- function
function find_starting_point(seg_pair_list,n)
local best_score,score,count,seg1,seg2,lastseg,dist,b,i,score1,score2,m,score3,score4,gain
local rebuild_count,rebuild_acceptable_score,rebuild_highest_score,rebuild_starting_score
lastseg=structure.GetCount()
selection.SelectAll()
-- freeze.UnfreezeAll()
behavior.SetClashImportance(1.0)
count=1
best_score=current.GetScore()
save.Quicksave(fsp.slot2)
-- below starts outer loop
repeat
if fsp.do_all_with_repeat then
print(string.format("Best repeat solution is stored in slot %i",fsp.best_repeat_score_slot))
print(string.format(" (%i/%i) Processing segments %i through %i",
count,n,seg_pair_list[1],seg_pair_list[2]))
else
print(string.format(" Processing segments %i through %i",seg_pair_list[1],seg_pair_list[2]))
end -- if fsp.do
print(string.format(" Starting %s (%s)",all_scores(),os.date()))
if math.abs(current.GetScore()-fsp.last_starting_score)>0.5 then
fsp.last_starting_score=current.GetScore()
fsp.worst_segment_processed_list={}
end -- if math.abs
rebuild_starting_score=current.GetScore()
rebuild_acceptable_score=(1-0.01*fsp.maximum_rebuild_loss_before_continuing)*rebuild_starting_score
print(string.format(" Rebuild target score: %.3f Maximum rebuild tries: %i",
trunc3to0(rebuild_acceptable_score),fsp.maximum_rebuilds_before_continuing))
rebuild_count=0
rebuild_highest_score=-1e10
if fsp.maximum_rebuilds_before_continuing> 0 then
-- below starts inner loop
repeat
save.Quickload(fsp.slot2)
if fsp.do_double_rebuild then
band.DisableAll()
rebuild(seg_pair_list,fsp.minimum_rebuild,fsp.maximum_rebuild)
end -- if fsp.do
-- add_or_enable_bands()
EnableAllBands()
rebuild(seg_pair_list,fsp.minimum_rebuild,fsp.maximum_rebuild)
rebuild_count=rebuild_count+1
shake(fsp.shake_limit)
wiggle(fsp.wiggle_limit1)
if not fsp.disable_existing_bands_only_during_rebuild_worst then band.DisableAll() end
wiggle(fsp.wiggle_limit1)
if fsp.enable_mutate then
score1=current.GetScore()
repeat
score2=current.GetScore()
structure.MutateSidechainsAll(1)
score3=current.GetScore()
until score3<score2+0.01
score4=current.GetScore()
gain=score4-score1
print(string.format(" Mutated from %.3f to %.3f (gain=%.3f)",
trunc3to0(score1),trunc3to0(score4),round3(gain)))
end -- if fsp.enable
if current.GetScore()>rebuild_acceptable_score then
-- print(string.format(" (%i/%i) Rebuild score %.3f greater than the acceptable score of %.3f, continuing on",
-- rebuild_count,fsp.maximum_rebuilds_before_continuing,trunc3to0(current.GetScore()),trunc3to0(rebuild_acceptable_score)))
else
-- print(string.format(" (%i/%i) Rebuild score %.3f less than the acceptable score of %.3f, retrying rebuild",
-- rebuild_count,fsp.maximum_rebuilds_before_continuing,trunc3to0(current.GetScore()),trunc3to0(rebuild_acceptable_score)))
end -- if current
print(string.format(" (%i/%i) Rebuild score %.3f",
rebuild_count,fsp.maximum_rebuilds_before_continuing,trunc3to0(current.GetScore())))
if current.GetScore()>rebuild_highest_score then
rebuild_highest_score=current.GetScore()
save.Quicksave(fsp.slot3)
end -- if current
until current.GetScore()>rebuild_acceptable_score or rebuild_count>=fsp.maximum_rebuilds_before_continuing
-- above ends inner loop
end -- if fsp.max
save.Quickload(fsp.slot3)
print(string.format(" Continuing on using score %.3f",trunc3to0(current.GetScore())))
if not fsp.quick then
run_clash_algorithm(fsp.rca_count)
print(string.format(" Post clash and wiggle %s",all_scores()))
rebuild_worst_segment(2,fsp.rebuild_worst_tries,1)
recentbest.Save()
wiggle(fsp.wiggle_limit2)
recentbest.Restore()
shake_then_wiggle(fsp.stw_count)
if fsp.enable_band_algorithm then
band_and_wiggle(fsp.banding_tries,fsp.disable_existing_bands,fsp.shake_limit,fsp.wiggle_limit1)
print(string.format(" Post banding score %s",all_scores()))
end -- if fsp.enable_band
if fsp.enable_local_wiggle then
recentbest.Save()
for seg=1,lastseg,3 do
selection.DeselectAll()
selection.SelectRange(seg,math.min(seg+3,lastseg))
structure.LocalWiggleSelected(2)
end -- for seg
recentbest.Restore()
print(string.format(" Post local wiggle score %s",all_scores()))
selection.SelectAll()
end -- if fsp.enable_local
if fsp.enable_mutate then
score1=current.GetScore()
repeat
score2=current.GetScore()
structure.MutateSidechainsAll(1)
score3=current.GetScore()
until score3<score2+0.01
score4=current.GetScore()
gain=score4-score1
print(string.format(" Mutated from %.3f to %.3f (gain=%.3f)",
trunc3to0(score1),trunc3to0(score4),round3(gain)))
end -- if fsp.enable_mutate
end -- if not fsp.quick
score=current.GetScore()
if score>best_score then
best_score=score
save.Quicksave(fsp.slot2)
end -- if score
print(string.format(" This Best %s Best score: %.3f",
all_scores(),trunc3to0(best_score)))
report_time(start_clock,start_time)
count=count+1
save.Quickload(fsp.slot2)
until count>n
-- above ends outer loop
end -- function
function find_starting_point_all(tries)
local first,last
first=1
last=structure.GetCount()
find_starting_point({first,last},tries)
end -- function
function find_starting_point_all_with_repeat(tries_per_repeat,total_tries)
local first,last,ix,best_repeat_score
first=1
last=structure.GetCount()
save.Quicksave(fsp.repeat_start_slot)
best_repeat_score=-99999
for ix=1,total_tries do
save.Quickload(fsp.repeat_start_slot)
print(string.format("Starting try %i Score: %.3f",
ix,trunc3to0(current.GetScore())))
find_starting_point({first,last},tries_per_repeat)
score=current.GetScore()
if score>best_repeat_score then
best_repeat_score=score
save.Quicksave(fsp.best_repeat_score_slot)
end -- if score
print(string.format("Try: %i Best repeat score: %.3f %s",
ix,trunc3to0(best_repeat_score),all_scores()))
save.Quickload(fsp.best_repeat_score_slot)
end -- for ix
save.Quickload(fsp.best_repeat_score_slot)
end -- function
function find_starting_point_loop_sections(section_size,section_increment,tries_per_section)
local first,last,seg1,seg2
first=1
last=structure.GetCount()
for seg1=first,last,section_increment do
seg2=seg1+section_size-1
if seg2>last then seg2=last end
find_starting_point({seg1,seg2},tries_per_section)
end -- for seg1
end -- function
function find_starting_point_section(seg_pair_list,tries)
find_starting_point({seg1,seg2},tries)
end -- function
-- below truncates val to nearest 0.001 towards 0
-- so 500.0029 becomes 500.002
-- and -5.0029 becomes -5.002
function trunc3to0(val)
if val>=0 then
return math.floor(val*1000)/1000
else
return math.ceil(val*1000)/1000
end -- if val
end -- trunc3to0()
-- below were adapted from multibander v3.13 last updated 1235am midnight 11/11/12 in file v3.13dx.txt
-- below truncates val down to nearest 0.001
-- so 500.0029 becomes 500.002
-- and -5.0029 becomes -5.003
function trunc3(val)
return val-(val % 0.001)
end -- trunc3()
-- below rounds val to 3 decimal places
function round3(val)
return round(val*1000)/1000
end -- round3()
-- below rounds val to 2 decimal places
function round2(val)
return round(val*100)/100
end -- round2()
-- below rounds val to the nearest integer to get res
function round(val)
local res=math.floor(val)
if val-res>=0.5 then
res=res+1
end -- if val
return res
end -- round()
function getbands()
local num, nbands
nbands=band.GetCount()
fsp.nbands=nbands
fsp.ison={}
for num=1,nbands do
fsp.ison[num]=band.IsEnabled(num)
end -- for num
end -- getbands()
function EnableAllBands()
local num
band.EnableAll()
for num=1,fsp.nbands do
if not fsp.ison[num] then
band.Disable(num)
end -- if not
end -- for num
end -- EnableAllBands()
function listbands()
-- new to v3.13. adapted from adjustbands2d3.txt
-- lists how well present conformation obeys user-supplied bands
-- changed more 8/28/2019 for FSPtest4.04Filter
local nbands, len, glen, str, ison, tots, avgdiff, rmsdiff, btype, mindiff, maxdiff
local maxstr, minstr, num, diff, diff2, indx, btype, typenams
local len2, minlen, maxlen, minglen, maxglen, avglen, avglen2, rmsdev
nbands=fsp.nbands
ison=fsp.ison
tots={}
avglen={} -- <x>
avglen2={} -- <x^2>
rmsdev={} -- sqrt(<(x-<x>)^2>) = sqrt(<(x^2 - 2 x <x> + <x>^2)>) = sqrt(<x^2> - 2<x>^2 + <x>^2)
-- = sqrt(<x^2> - <x>^2)
avgdiff={} -- <|x-xo|>
rmsdiff={} -- sqrt(<|x-xo|^2>) = sqrt(<(x-xo)^2>)
-- = sqrt(<(x^2 - 2 x xo + xo^2)>) = sqrt(<x^2> - 2 <x> xo + xo^2)
for btype=0,2 do
avglen[btype]=0
avglen2[btype]=0
rmsdev[btype]=0
avgdiff[btype]=0
rmsdiff[btype]=0
tots[btype]=0
end -- for btype
minlen={} -- min band length x
maxlen={} -- max band length x
minglen={} -- min goal length xo
maxglen={} -- max goal length xo
minstr={} -- min band strength
maxstr={} -- max band strength
mindiff={} -- min |x-xo| value
maxdiff={} -- max |x-xo| value
for num=1,nbands do
len=band.GetLength(num) -- x
len2=len*len -- x^2
glen=band.GetGoalLength(num) -- xo
str=band.GetStrength(num) -- band strength
diff=math.abs(len-glen) -- |x-xo|
diff2=diff*diff -- |x-xo|^2 = (x-xo)^2
if ison[num]==true then
btypes={1,2} -- for enabled bands
else
btypes={0,2} -- for disabled bands
end -- if ison
for indx=1,2 do
btype=btypes[indx]
avglen[btype]=avglen[btype]+len -- finding sum of x
avglen2[btype]=avglen2[btype]+len2 -- finding sum of x^2
avgdiff[btype]=avgdiff[btype]+diff -- finding sum of |x-xo|
rmsdiff[btype]=rmsdiff[btype]+diff2 -- finding sum of |x-xo|^2
tots[btype]=tots[btype]+1
if tots[btype]==1 then
minlen[btype]=len
maxlen[btype]=len
minglen[btype]=glen
maxglen[btype]=glen
minstr[btype]=str
maxstr[btype]=str
mindiff[btype]=diff
maxdiff[btype]=diff
else
if len>maxlen[btype] then
maxlen[btype]=len
elseif len<minlen[btype] then
minlen[btype]=len
end
if glen>maxglen[btype] then
maxglen[btype]=glen
elseif glen<minglen[btype] then
minglen[btype]=glen
end
if str>maxstr[btype] then
maxstr[btype]=str
elseif str<minstr[btype] then
minstr[btype]=str
end
if diff>maxdiff[btype] then
maxdiff[btype]=diff
elseif diff<mindiff[btype] then
mindiff[btype]=diff
end
end -- if tots
end -- for indx
end -- for num
for btype=0,2 do
avglen[btype]=avglen[btype]/tots[btype] -- finds <x>
avglen2[btype]=avglen2[btype]/tots[btype] -- finds <x^2>
rmsdev[btype]=math.sqrt((avglen2[btype]-((avglen[btype])^2))) -- finds sqrt(<x^2>-<x>^2)
avgdiff[btype]=avgdiff[btype]/tots[btype] -- finds <|x-xo|>
rmsdiff[btype]=math.sqrt((rmsdiff[btype]/tots[btype])) -- finds sqrt(<|x-xo|^2>)
end
print('For '..nbands..' user-supplied bands and score '..trunc3to0(current.GetScore())..' we have:')
typenams={}
typenams[0]='disabled'
typenams[1]=' enabled'
typenams[2]='any-type'
for btype=0,2 do
if tots[btype]>0 then
print(' '..tots[btype]..' '..typenams[btype]..
' bands with lens='..round2(minlen[btype])..'-'..round2(maxlen[btype])..
', avglen='..round2(avglen[btype])..', rmsdev='..round2(rmsdev[btype])..
', goal-lengths='..round2(minglen[btype])..'-'..round2(maxglen[btype])..',')
print(' avglen2='..round2(avglen2[btype])..
', diffs='..round2(mindiff[btype])..'-'..round2(maxdiff[btype])..
', avgdiff='..round2(avgdiff[btype])..', rmsdiff='..round2(rmsdiff[btype])..
', and strengths='..round2(minstr[btype])..'-'..round2(maxstr[btype])..'.')
end -- if tots
end -- for btype
end -- listbands()
-- above were adapted from multibander v3.13 last updated 1235am midnight 11/11/12 in file v3.13dx.txt
main()