Code
--QuakeR - a randomized Quake
recipeTitle='QuakeR v5.0wm'
--[[
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
]]
function floor3(x)--cut at 3rd decimal place
return tostring(x-x%0.001)
end
function Score()
local s=0
if normal==true then
s=current.GetEnergyScore()
else
for i=1,segCnt do
s=s+current.GetSegmentEnergyScore(i)
end
end
return s
end
function ScoreRB()
local s=0
if normal==true then
s=recentbest.GetEnergyScore()
else
for i=1,segCnt do
s=s+recentbest.GetSegmentEnergyScore(i)
end
end
return s
end
function SaveBest()
local g=Score()-bestScore
if g>0 then
print("Gained another "..floor3(g).." points.")
bestScore=Score()
save.Quicksave(4) -- under normal conditions retain pose even as recording improvement
recentbest.Restore()
save.Quicksave(3)
save.Quickload(4)
end
return Score()-bestScore
end
function Wiggle(how, iters, minppi) --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 iters>0 then
iters=iters-1
local sp=Score()
if how == "s" then structure.ShakeSidechainsAll(1)
elseif how == "wb" then structure.WiggleAll(2,true,false)
elseif how == "ws" then structure.WiggleAll(2,false,true)
elseif how == "wa" then structure.WiggleAll(2,true,true)
end
if Score()-sp > minppi then return Wiggle(how, iters, minppi) end
end
end
function qStab()
behavior.SetClashImportance(0.21)
structure.MutateSidechainsSelected(1)
Wiggle("s",1)
if fastQstab==false then
behavior.SetClashImportance(0.4)
Wiggle("wa",1)
behavior.SetClashImportance(1)
Wiggle("s",1)
end
behavior.SetClashImportance(1)
Wiggle()
return SaveBest()
end
function Fuze1(ci1,ci2)
behavior.SetClashImportance(ci1)
Wiggle("s",1)
behavior.SetClashImportance(ci2)
Wiggle("wa",1)
end
function Fuze2(ci1,ci2)
behavior.SetClashImportance(ci1)
Wiggle("wa",1)
behavior.SetClashImportance(1)
Wiggle("wa",1)
behavior.SetClashImportance(ci2)
Wiggle("wa",1)
end
function FuzeEnd()
behavior.SetClashImportance(1)
Wiggle("wa",1)
Wiggle("s",1)
behavior.SetClashImportance(0.9)
Wiggle()
behavior.SetClashImportance(1)
Wiggle("wa",1)
SaveBest()
end
function reFuze(scr)
local s=ScoreRB()
if s<scr then
recentbest.Restore()
else
scr=s
end
return scr
end
function Fuze()
local scr=Score()
Fuze1(1,0.6) FuzeEnd()
scr=reFuze(scr)
Fuze2(1,1) SaveBest()
scr=reFuze(scr)
Fuze1(1,0.9) SaveBest()
scr=reFuze(scr)
Fuze2(1,1) FuzeEnd()
scr=reFuze(scr)
Fuze1(1,1) SaveBest()
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()
math.randomseed(os.time()) math.random() math.random() math.random()
calcBandAtom()
--freeze.UnfreezeAll()
selection.SelectAll()
StartingScore=Score()
bestScore=StartingScore
recentbest.Save()
save.Quicksave(3)
print("Starting "..recipeTitle..tostring(qLoops).." passes. Start score: "..floor3(StartingScore))
for x=1, qLoops do
print("Pass "..tostring(x).." of "..tostring(qLoops))
local start=math.floor(math.random(segCnt/10)) --first band somewhere in first 10% of protein
local len=math.floor(math.random(segCnt/2-5))+10
local step=math.floor(math.random(segCnt/2-5))+10
local loss=math.abs(math.floor(Score()*maxLoss/100))
band.DeleteAll()
print("Bands from segment "..tostring(start).." of length "..tostring(len)
.." every "..tostring(step).." segments.")
print("Pulling until loss of "..tostring(loss).." points.")
for x=start,segCnt, step do
for y=start+len, segCnt, step do
band.AddBetweenSegments(x,y,bandAtom[x],bandAtom[y])
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(1,true,false)
gain=SaveBest()
if gain > 0 then
recentbest.Restore()
end
until gain<=0
if gain<-loss then
break
end
end
band.DeleteAll()
behavior.SetClashImportance(1)
recentbest.Save() --after pulling
print("Stabilizing...")
if qStab() > doFuze then
print("Fuzing....")
Fuze()
end
SaveBest()
save.Quickload(3) --load best state
print("Current score: "..floor3(Score()).." Total gain: "..floor3(Score()-StartingScore))
end
print("Total QuakeR gain: "..floor3(Score()-StartingScore))
return true
end
function GetParameters ()
local dlog = dialog.CreateDialog ( "QuakeR v5 with mutate" )
dlog.iterations = dialog.AddSlider ( "iterations: " , qLoops , 1 , 1000 , 0 )
dlog.ok = dialog.AddButton ( "OK" , 1 )
dlog.cancel = dialog.AddButton ( "Cancel" , 0 )
if ( dialog.Show ( dlog ) > 0 ) then
qLoops = dlog.iterations.value
return true
else
return false
end
end
function main ()
if ( GetParameters () == false ) then
return -- graceful exit
end
QuakeR()
cleanUp()
end
function CleanUp(err)
if err:find('Cancelled')~=nil then
print "QuakeR Cancelled"
else
print(err)
end
behavior.SetClashImportance(1)
-- band.DeleteAll()
SaveBest()
save.Quickload(3)
print("Total QuakeR gain: "..floor3(bestScore-StartingScore))
end
segCnt=structure.GetCount()
while structure.GetSecondaryStructure(segCnt)=="M" do segCnt=segCnt-1 end
--- VVVVVVVVVV OPTIONS
normal=(current.GetExplorationMultiplier()==0)
qLoops=50 -- <<<OVER THERE! do more! much more!
minBS=0.3 --starting minimum bands strength
maxBS=1.0 --maximum band strength
maxLoss=1 --minimum percentage loss when pulling. ie 5% of 10000 is 500pts
pullingCI=1.0 --clash importance while pulling
fastQstab=false --true for 1s1w as stabilize (faster)
doFuze=-10 --run fuze when score after qstabilize is close to best.
xpcall(main,CleanUp)