Code
--QuakeR - a randomized Quake
recipeTitle='QuakeR & BWF v1.5 '
--v1.0 combined two recpies QuakeR v5.0 with mutate
-- updated and changed some functions!
-- future plans more settings in the gui
-- created 2025-05-22 ZeroLeak7
-- QuakeR & BWF v1.5
-- updated 28 May 2025 ZeroLeak7
-- No Shake! or Shake! two Buttons option in the gui and some optimizations
--[[
Based on "Quake" by Grom
v2.51 -- update 2011-01-15 rav3n_pl
v3.0 -- update 2011-04-18 rav3n_pl
v4.0 -- updated 27 Dec 2014 GaryForbis
v4.5 -- updated 2019-12-30 ZeroLeak7
v5.0 -- updated 2019-12-31
-converted to script v2
-band hydrophobes to beta carbon
-clean up on early exit
-better shake and wiggle ci in Fuze and with mutate now
-updated with a gui
]]
-- original -- behavior wiggle fuze v1 by Bruno Kestemont
--Bravo BWF
--v1 i did a brute force of all single variable behaivor wiggle variations that were reasonable, this script includes all gains that were >0.1
-- it's just a potential script that might see some gains. totally experimental.
-- just a small script that uses recipe scoring mods. works well on ligand / small molecule placement
--v1.1 fixed glitch on Behavior importance
--Wiggle all
Best_Score_slot_num = 3
save.Quicksave(Best_Score_slot_num) --save starting score as best score saved in quick save 3
BestScore = current.GetScore()
StartScore = BestScore
BestBonus = filter.GetBonusTotal()
StartBonus = BestBonus
Importance = 3
global_clashing_importance = 1
behavior_string = "starting"
Behavior_value = 1
print("Make sure RECIPE SCORE MODDING is checked before running")
function SaveBest()
local ss= current.GetScore()
local g = ss - BestScore
local tb = filter.GetBonusTotal()
local bg = tb - BestBonus --dont let the bonus score decrease
if g > 0 then --and bg >= 0 then -- removed bonus requirements
--if g > 0.1 then
print(behavior_string .. Importance)
print("Iteration length: " , iteration_variable , " CI: " , global_clashing_importance)
print("Gained another " .. g.. " Score: "..ss.. " Bonus: "..tb)
print("Total Gain: ".. (ss-StartScore))
--end
BestScore= ss
BestBonus = tb
save.Quicksave(Best_Score_slot_num) --best score saved in quick save 3
else
--print(":( no gain")
end
return getScore()-BestScore
end
function SidechainsHbondFuze()
--print("SidechainHbond")
behavior_string= "SidechainHbond: "
recentbest.Save()
behavior.SetClashImportance(global_clashing_importance)
behavior.SetSidechainHBondImportance(Importance)
structure.WiggleAll(iteration_variable,true,true) -- wa
Behavior_reset()
structure.WiggleAll(25,true,true)
is_recent_best_better()
SaveBest()
--behavior.SetSidechainHBondImportance(1)
end
function BackboneHbondFuze()
--print("BackboneHbond")
behavior_string= "BackboneHbond: "
recentbest.Save()
behavior.SetClashImportance(global_clashing_importance)
behavior.SetBackboneHBondImportance(Importance)
structure.WiggleAll(iteration_variable,true,true) -- wa
Behavior_reset()
structure.WiggleAll(25,true,true)
is_recent_best_better()
SaveBest()
--behavior.SetBackboneHBondImportance(1)
end
function PairWiseFuze()
--print("PairWise")
behavior_string= "PairWise: "
recentbest.Save()
behavior.SetClashImportance(global_clashing_importance)
behavior.SetPairwiseImportance(Importance)
structure.WiggleAll(iteration_variable,true,true) -- wa
Behavior_reset()
structure.WiggleAll(25,true,true)
is_recent_best_better()
SaveBest()
--behavior.SetPairwiseImportance(1)
end
function PackingFuze()
--print("Packing")
behavior_string= "Packing: "
recentbest.Save()
behavior.SetClashImportance(global_clashing_importance)
behavior.SetPackingImportance(Importance)
structure.WiggleAll(iteration_variable,true,true) -- wa
Behavior_reset()
structure.WiggleAll(25,true,true)
is_recent_best_better()
SaveBest()
--behavior.SetPackingImportance(1)
end
function HidingFuze()
--print("Hiding")
behavior_string= "Hiding: "
recentbest.Save()
behavior.SetClashImportance(global_clashing_importance)
behavior.SetHidingImportance(Importance)
structure.WiggleAll(iteration_variable,true,true) -- wa
Behavior_reset()
structure.WiggleAll(25,true,true)
is_recent_best_better()
SaveBest()
--behavior.SetHidingImportance(1)
end
function ClashingFuze()
--print("Clashing importance 0.9")
behavior_string= "Clash: "
recentbest.Save()
--behavior.SetClashImportance(0.9)
behavior.SetClashImportance(global_clashing_importance)
structure.WiggleAll(iteration_variable,true,true) -- wa
Behavior_reset()
structure.WiggleAll(25,true,true)
is_recent_best_better()
SaveBest()
--behavior.SetClashImportance(1)
end
function DensityFuze()
--print("Density")
behavior_string = "Density: "
recentbest.Save()
behavior.SetClashImportance(global_clashing_importance)
behavior.SetDensityImportance(Importance)
structure.WiggleAll(iteration_variable,true,true) -- wa
Behavior_reset()
structure.WiggleAll(25,true,true)
is_recent_best_better()
SaveBest()
--behavior.SetDensityImportance(1)
end
recent_best_count=0
function is_recent_best_better() --sometime recent best is better than settled score
local score = current.GetScore()
recentbest.Restore()
recent_best_score = current.GetScore()
if (recent_best_score>score and recent_best_score > BestScore) then
print("Recent best restored")
structure.WiggleAll(10,true,true)
if (recent_best_count<4) then --infinite recursion != infinite gain. breaks on 4 failed attemps. might get triggered many times
recent_best_count = recent_best_count + 1
print ("recent_best_count: " .. recent_best_count .. " of 5")
is_recent_best_better() --fixes a bug where the score goes down with these settings
end
score = current.GetScore()
if (score < recent_best_score ) then
recentbest.Restore()
end
end
recent_best_count=0
end
function Behavior_reset()
behavior.SetClashImportance(1)
behavior.SetHidingImportance(1)
behavior.SetPackingImportance(1)
behavior.SetPairwiseImportance(1)
behavior.SetBackboneHBondImportance(1)
behavior.SetSidechainHBondImportance(1)
behavior.SetDensityImportance(1)
end
function Bravo_BWF(BWF_string,Behavior_value,Iterationlength,CI)
Importance = Behavior_value
iteration_variable = Iterationlength
global_clashing_importance = CI
if (BWF_string== "SidechainHbond:") then
SidechainsHbondFuze()
elseif (BWF_string== "BackboneHbond:") then
BackboneHbondFuze()
elseif (BWF_string== "PairWise:") then
PairWiseFuze()
elseif (BWF_string== "Packing:") then
PackingFuze()
elseif (BWF_string== "Hiding:") then
HidingFuze()
elseif (BWF_string== "Density:") then
DensityFuze()
elseif (BWF_string== "Clash:") then
ClashingFuze()
else
print("error Bravo_BWF: BWF_string: ".. BWF_string)
end
end
-- variables users probably don't want to play with
USENORMALSCORE = true
InitialScore = 0.0 -- not important: will be reinitialized in InitializePuzzleState( )
StartTime = 0 -- not important: will be reinitialized in InitializePuzzleState( )
CurrentBestScore = 0 -- not important: will be reinitialized in InitializePuzzleState( )
-- Globals
loop_starts = {}
loop_ends = {}
n_loops = 0
n_residues = 0
function residues_range ()
selection.SelectAll()
structure.SetSecondaryStructureSelected("L")
end
function GetLoops ()
within_loop = false
for i = 1, n_residues do
if ( structure.GetSecondaryStructure ( i ) == "L" and structure.IsLocked(i) == false ) then
if ( within_loop == false ) then
-- start of a new loop
within_loop = true
n_loops = n_loops + 1
loop_starts [ n_loops ] = i
end
elseif ( within_loop == true ) then
-- end of a loop
within_loop = false
loop_ends [ n_loops ] = i -1
end
end -- for i
if ( within_loop == true ) then
loop_ends [ n_loops ] = n_residues
end
end
function floor3(x)--cut at 3rd decimal place
return tostring(x-x%0.001)
end
function internalGetScore( wantRB )
if wantRB == nil then wantRB = false end
local s=0.0
if not USENORMALSCORE then
if wantRB then s = recentbest.GetEnergyScore( )
else s=current.GetEnergyScore( )
end
else
if wantRB then s = recentbest.GetScore( )
else s=current.GetScore( )
end
end
return s
end
function getScore( )
behavior.SetFiltersDisabled(false)
behavior.SetFiltersDisabled(true)
return internalGetScore( false )
end
function getRBScore( )
behavior.SetFiltersDisabled(false)
behavior.SetFiltersDisabled(true)
return internalGetScore( true )
end
function SaveBest2()
local score = getScore()
if score > current.GetScore() then
print("Gained another "..floor3(score-current.GetScore()).." points. new Score: "..floor3(score))
score=current.GetScore()
save.Quicksave(4)
recentbest.Restore()
save.Quicksave(3)
save.Quickload(4)
end
return getScore()-current.GetScore()
end
function InitializePuzzleState( )
InitialScore = getRBScore( )
CurrentBestScore = InitialScore
StartTime = os.time()
end
function Wiggle(how, iters, minppi, shakeiters) --score conditioned recursive wiggle/shake
if how==nil then how="wa" end
if iters==nil then iters=6 end
if minppi==nil then minppi=0.1 end
if shakeiters==nil then shakeiters=2 end
if iters>0 then
iters=iters-1
local sp=getScore()
if how == "s" then structure.ShakeSidechainsAll(shakeiters)
elseif how == "wb" then structure.WiggleAll(iters,true,false)
elseif how == "ws" then structure.WiggleAll(iters,false,true)
elseif how == "wa" then structure.WiggleAll(iters,true,true)
end
if getScore()-sp > minppi then return Wiggle(how, iters, minppi, shakeiters) end
end
end
function qStab()
behavior.SetClashImportance(0.21)
Wiggle("wa",13)
if fastQstab==false then
behavior.SetClashImportance(0.02)
Wiggle("wa",25)
behavior.SetClashImportance(1)
if (local_shake == true) then
print("Shake!")
Wiggle("s",shakeiters)
else
Wiggle("wa",25)
end
end
behavior.SetClashImportance(1)
Wiggle("wa",7)
return SaveBest2()
end
function reFuze(scr)
local s=getRBScore()
if s<scr then
recentbest.Restore()
else
scr=s
end
return scr
end
function Fuze1(ci1, ci2, iters, shakeiters)
behavior.SetSidechainHBondImportance(3)
behavior.SetBackboneHBondImportance(3)
behavior.SetPackingImportance(3)
behavior.SetHidingImportance(3)
behavior.SetPairwiseImportance(3)
behavior.SetDensityImportance(3)
behavior.SetClashImportance(ci1)
behavior.SetClashImportance(ci2)
Wiggle("wa",iters)
Behavior_reset()
if (local_shake == true) then
print("Shake!")
Wiggle("s",shakeiters)
end
behavior.SetClashImportance(ci1)
Wiggle("wa",iters)
end
function Fuze2(ci1, ci2, iters)
behavior.SetClashImportance(ci1)
Wiggle("wa",iters)
behavior.SetClashImportance(0.21)
Wiggle("wa",iters)
behavior.SetClashImportance(ci2)
Wiggle("wa",iters)
end
function FuzeEnd(iters, shakeiters)
print("FuzeEnd")
behavior.SetClashImportance(1)
Wiggle("wa",iters)
if (local_shake == true) then
print("Shake!")
Wiggle("s",shakeiters)
end
behavior.SetClashImportance(0.21)
Wiggle("wa",iters)
behavior.SetClashImportance(1)
Wiggle("wa",iters)
SaveBest()
end
function Fuze()
local scr=getScore()
print("Fuze1")
Fuze1(1, 0.21, 7, 2) FuzeEnd(7, 4)
print("reFuze")
qStab()
scr=reFuze(scr)
print("Fuze2")
Fuze2(1,1,7) SaveBest()
print("reFuze")
scr=reFuze(scr)
print("Fuze1")
Fuze1(1, 0.21, 7, 2) SaveBest()
print("reFuze")
qStab()
scr=reFuze(scr)
print("Fuze2")
Fuze2(1, 1, 7) FuzeEnd(7, 4)
print("reFuze")
scr=reFuze(scr)
print("Fuze1")
Fuze1(1,0.21,7,2) SaveBest()
print("reFuze")
qStab()
scr=reFuze(scr)
end
function bandstr(str) --set all band strength
for i=1, band.GetCount() do
band.SetStrength(i, str)
end
end
function calcBandAtom()
bandAtom={}
for x = 1,segCnt do
if (structure.GetAminoAcid(x) == 'g') or not structure.IsHydrophobic(x) then
bandAtom[x] = 2 -- center for Glycine and Hydophiles
elseif x == segCnt then
bandAtom[x] = 6 -- beta carbon for terminal segment
else
bandAtom[x] = 5 -- beta carbon
end
end
end
function QuakeR(ix,iy,ql,rev)
math.randomseed(os.time()) math.random() math.random() math.random()
calcBandAtom()
-- Disable filters
behavior.SetFiltersDisabled(true)
selection.SelectAll()
StartingScore=getScore()
bestScore=StartingScore
recentbest.Save()
save.Quicksave(3)
print("----------------------------------------------------------------------------")
print("Starting "..recipeTitle..tostring(ql).." passes.")
print("----------------------------------------------------------------------------")
print("Start score: "..floor3(StartingScore))
for x=1, ql do
print("Pass "..tostring(x).." of "..tostring(ql))
local step=math.floor(math.random((iy-ix)/10,((iy-ix)/10)+10))
local step2=math.floor(math.random(((iy-ix)/10)-10,(iy-ix)/10))
band.DeleteAll()
if(rev==true) then
print("----------------------------------------------------------------------------")
print("Bands from segment "..tostring(ix))
print(" of length "..tostring(step2).." every "..tostring(step2).." segments.")
print("----------------------------------------------------------------------------")
print("Pulling..")
for x=ix,iy, step2 do
for y=ix, iy, step2 do
band.AddBetweenSegments(x,y)
end
end
else
print("----------------------------------------------------------------------------")
print("Bands from segment "..tostring(ix))
print(" of length "..tostring(step).." every "..tostring(step).." segments.")
print("----------------------------------------------------------------------------")
print("Pulling..")
for x=ix,iy, step do
for y=ix+step, iy, step do
band.AddBetweenSegments(x,y)
end
end
end
behavior.SetClashImportance(pullingCI)
recentbest.Save()
local gain
for str=minBS,maxBS,0.07 do--search enough band strength to move
bandstr(str)
repeat
structure.WiggleAll(2,true,false)
gain=SaveBest2( )
if gain > 0 then
recentbest.Restore()
end
until gain<=0
break
end
band.DeleteAll()
behavior.SetClashImportance(1)
recentbest.Save() --after pulling
print("Stabilizing...")
if qStab() > doFuze then
print("Fuzing....")
Fuze()
print("end of Fuzing!...")
is_recent_best_better()
SaveBest()
save.Quicksave(3)
gain=SaveBest()
if gain > 0 then
recentbest.Restore()
end
loop_starting_score = current.GetScore()
loop_gain = 1.1
loop_count = 0
current_Score = current.GetScore()
while (loop_gain > 0.1) do -- recent best tends to make .01 gains forever. want to avoid that slowness.
print("Starting Score: ".. StartScore)
print("Current Score: ".. current_Score)
loop_starting_score = current.GetScore()
loop_count = loop_count+1
-- these were experimentally determined to make gains. doesn't always work but it's better then brute force.
-- Bravo_BWF(Behavior type,B_v , Iteration length , Clashing Importance)
print ("Starting behavior wiggle fuze (BWF)...")
print (" ")
print ("Density: Fuze...")
print (" ")
Bravo_BWF("Density:",3,8,0.07)
print ("BackboneHbond: Fuze...")
print (" ")
Bravo_BWF("BackboneHbond:",3,8,0.02)
print ("PairWise: Fuze...")
print (" ")
Bravo_BWF("PairWise:",3,8,1)
print ("Hiding: Fuze...")
print (" ")
Bravo_BWF("Hiding:",3,8,1)
print ("Packing: Fuze...")
print (" ")
Bravo_BWF("Packing:",3,8,0.1)
print ("Clashing: Fuze...")
print (" ")
Bravo_BWF("Clash:",0.5,8,0.07)
print ("Hiding: Fuze...")
print (" ")
Bravo_BWF("Hiding:",3,8,0.07)
print ("BackboneHbond: Fuze...")
print (" ")
Bravo_BWF("BackboneHbond:",3,8,0.07)
print ("Hiding: Fuze...")
print (" ")
Bravo_BWF("Hiding:",0.5,8,0.07)
print ("Density: Fuze...")
print (" ")
Bravo_BWF("Density:",0.5,8,0.07)
print ("Hiding: Fuze...")
print (" ")
Bravo_BWF("Hiding:",1.1,8,0.05)
print ("Hiding: Fuze...")
print (" ")
Bravo_BWF("Hiding:",3,8,0.05)
loop_gain = current.GetScore() - loop_starting_score
current_Score = current_Score + loop_gain
print("Loop " .. loop_count .. " Gain: " .. loop_gain)
end
is_recent_best_better()
SaveBest()
save.Quicksave(3)
if qStab() > doFuze then
print("Starting End Round: Fuzing....")
Fuze()
end
is_recent_best_better()
SaveBest()
save.Quickload(3) --load best state
print("Current score: "..floor3(getScore()).." Total gain: "..floor3(getScore()-StartingScore))
end
print("Total QuakeR & BWF gain: "..floor3(getScore()-StartingScore))
end
end
function GetParameters ()
local dlog = dialog.CreateDialog ( "QuakeR & BWF v1.5" )
dlog.iterations = dialog.AddSlider ( "normal iter: " , qLoops , 1 , 1000 , 0 )
dlog.iterationsr = dialog.AddSlider ( "reverse iter: " , qLoops2 , 1 , 1000 , 0 )
dlog.local_shake = dialog.AddButton ( "Shake!" , 1)
dlog.local_no_shake = dialog.AddButton ( "No Shake!" , 2 )
dlog.cancel = dialog.AddButton ( "Cancel" , 0 )
local choice = dialog.Show ( dlog )
if (choice > 1) then
qLoops = dlog.iterations.value
qLoops2 = dlog.iterationsr.value
local_shake = false
elseif (choice > 0) then
qLoops = dlog.iterations.value
qLoops2 = dlog.iterationsr.value
else
print("Dialog cancelled")
end
return choice
end
function main ()
if ( GetParameters () == false ) then
return -- graceful exit
end
n_residues = structure.GetCount ()
behavior.SetClashImportance ( 1 )
InitializePuzzleState( )
print("wait! initializing...")
residues_range ()
GetLoops ()
n_loops = #loop_starts
print ( n_loops .. " loops" )
n_loops = #loop_starts
for i = 1 , n_loops do
print ( "Loop " .. i .. " : (" .. loop_starts [ i ] .. "-" .. loop_ends [ i ] .. ")" )
end
local idx_starts = loop_starts[ 1 ]
local idx_ends = loop_ends[ 1 ]
QuakeR(idx_starts, idx_ends, qLoops,false)
print("reverse QuakeR & BWF starts:")
QuakeR(idx_ends, idx_starts, qLoops2,true)
CleanUp()
end
function CleanUp(err)
undo.SetUndo(true)
if EndCalled then return end -- no infinite recursion please
EndCalled = true
if err:find("Cancelled") ~= nil then
print "QuakeR & BWF Cancelled"
behavior.SetClashImportance(1)
Behavior_reset()
band.DeleteAll()
else
print(err)
end
behavior.SetClashImportance(1)
Behavior_reset()
band.DeleteAll()
SaveBest()
recentbest.Restore()
-- Re-enable filters
behavior.SetFiltersDisabled(false)
print("Total QuakeR & BWF gain: " .. floor3(current.BestScore() - StartingScore))
end
segCnt=structure.GetCount()
while structure.GetSecondaryStructure(segCnt)=="M" do segCnt=segCnt-1 end
--- VVVVVVVVVV OPTIONS
normal=(current.GetExplorationMultiplier()==0)
qLoops=5 --number of passes
qLoops2=5 -- <<<OVER THERE! do more! much more!
minBS=0.3 --starting minimum bands strength
maxBS=1.0 --maximum band strength
pullingCI=1.0 --clash importance while pulling
fastQstab=false --true for 1s1w as stabilize (faster)
local_shake=true --true for local shake in fuze1
doFuze=-500 --run fuze when score after qstabilize is close to best.
xpcall(main,CleanUp)