Code
--[[
V2 Interactive void killer 1.0 Tvdl
A lot of code used from: Voids Killer by rav3n_pl
An interactive program where you can specify segments
opposit a void.
Makes all bands from those segments that have a smaller
angle to the connecting band. These bands pull.
Adjust the length the bands that pull in an angle in such a way that
it is a parallel pull.
Also can make bands backwards. These bands try to preserve.
]]--
-- "lua v1 in v2" library by rav3n_pl
--just add it in front of your v1 code and use v2 and v1 code in v2 scripts :)
-- print(arg1[,...,argN]) no change :)
function are_conditions_met()
return current.AreConditionsMet()
end
function band_add_segment_segment(sgi1, sgi2)
band.AddBetweenSegments(sgi1, sgi2)
end
function band_delete(bndIdx)
if bndIdx~= nil then
band.Delete(bndIdx)
else
band.DeleteAll()
end
end
function band_disable(bndIdx)
if bndIdx~=nil then
band.Disable(bndIdx)
else
band.DisableAll()
end
end
function band_enable(bndIdx)
if bndIdx~=nil then
band.Enable(bndIdx)
else
band.EnableAll()
end
end
function band_set_length(bndIdx, len)
band.SetGoalLength(bndIdx, len)
end
function band_set_strength(bndIdx, str)
band.SetStrength(bndIdx, str)
end
function get_band_count()
return band.GetCount()
end
function deselect_all()
selection.DeselectAll()
end
function deselect_index(sgn)
selection.Deselect(sgn)
end
function select_all()
selection.SelectAll()
end
function select_index(sgn)
selection.Select(sgn)
end
function select_index_range(sg1,sg2)
selection.SelectRange(sg1,sg2)
end
function do_freeze(bbone,schain)
freeze.FreezeSelected(bbone,schain)
end
function do_unfreeze_all()
freeze.UnfreezeAll()
end
function do_global_wiggle_all(iters)
structure.WiggleAll(iters,true,true)
end
function do_global_wiggle_backbone(iters)
structure.WiggleAll(iters, true,false)
end
function do_global_wiggle_sidechains(iters)
structure.WiggleAll(iters,false,true)
end
function do_local_rebuild(iters)
structure.RebuildSelected(iters)
end
function do_local_wiggle(iters)
structure.LocalWiggleSelected(iters,true,true)
end
function do_mutate(iters)
structure.MutateSidechainsSelected(iters)
end
function do_shake(iters)
structure.ShakeSidechainsSelected(iters)
end
function do_sidechain_snap(sgn, snap)
rotamer.SetRotamer(sgn, snap)
end
function get_sidechain_snap_count(sgn)
return rotamer.GetCount(sgn)
end
function load_structure()
save.LoadSecondaryStructure()
end
function save_structure()
save.SaveSecondaryStructure()
end
function quickload(slot)
save.Quickload(slot)
end
function quicksave(slot)
save.Quicksave(slot)
end
function get_exploration_score()
return current.GetExplorationMultiplier()
end
function get_ranked_score()
return current.GetScore()
end
function get_score()
return current.GetEnergyScore()
end
function get_segment_distance(sg1,sg2)
return structure.GetDistance(sg1,sg2)
end
function get_aa(sn)
return structure.GetAminoAcid(sn)
end
function get_segment_count()
return structure.GetCount()
end
function get_ss(sn)
return structure.GetSecondaryStructure(sn)
end
function is_hydrophobic(sn)
return structure.IsHydrophobic(sn)
end
function replace_aa(aa)
for i=1,structure.GetCount() do
if selection.IsSelected(i) then
structure.SetAminoAcid(i, aa)
end
end
end
function replace_ss(ss)
for i=1,structure.GetCount() do
if selection.IsSelected(i) then
structure.SetSecondaryStructure(i,ss)
end
end
end
function get_segment_score(sg)
return current.GetSegmentEnergyScore(sg)
end
function get_segment_score_part(score_part,sg)
return current.GetSegmentEnergySubscore(sg,score_part)
end
function reset_puzzle()
puzzle.StartOver()
end
function restore_abs_best()
absolutebest.Restore()
end
function restore_credit_best()
creditbest.Restore()
end
function reset_recent_best()
recentbest.Save()
end
function restore_recent_best()
recentbest.Restore()
end
function set_behavior_clash_importance(ci)
behavior.SetClashImportance(ci)
end
-- end of library
normal=true --set false if want use exploration score not energy score
--rest of options at end
p=print
CI=set_behavior_clash_importance
segCnt=get_segment_count()
while get_ss(segCnt)=="M" do segCnt=segCnt-1 end
function Score()
local s=0
if normal==true then
s=get_score(true)
else
s=get_ranked_score(true)
end
return s
end
function round(x)--cut all afer 3-rd place
return x-x%0.001
end
function down(x)
return x-x%1
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 do_shake(1)
elseif how == "wb" then do_global_wiggle_backbone(2)
elseif how == "ws" then do_global_wiggle_sidechains(2)
elseif how == "wa" then do_global_wiggle_all(2)
end
if Score()-sp > minppi then return Wiggle(how, iters, minppi) end
end
end
function qStab()
CI(0.1)
Wiggle("s",1)
select_all()
if fastQstab==false then
CI(0.4)
Wiggle("wa",1)
CI(1)
Wiggle("s",1)
end
CI(1)
Wiggle()
end
function FuzeEnd()
CI(1)
Wiggle("wa",1)
Wiggle("s",1)
Wiggle()
SaveBest()
end
function Fuze1(ci1,ci2)
CI(ci1)
Wiggle("s",1)
CI(ci2)
Wiggle("wa",1)
end
function Fuze2(ci1,ci2)
CI(ci1)
Wiggle("wa",1)
CI(1)
Wiggle("wa",1)
CI(ci2)
Wiggle("wa",1)
end
function reFuze(scr,slot)
local s=Score()
if s<scr then
quickload(slot)
else
scr=s
quicksave(slot)
end
return scr
end
function Fuze(slot)
local scr=Score()
quicksave(slot)
select_all()
Fuze1(0.3,0.6) FuzeEnd()
scr=reFuze(scr,slot)
Fuze2(0.3,1) SaveBest()
scr=reFuze(scr,slot)
Fuze1(0.05,1) SaveBest()
scr=reFuze(scr,slot)
Fuze2(0.7,0.5) FuzeEnd()
scr=reFuze(scr,slot)
Fuze1(0.07,1) SaveBest()
reFuze(scr,slot)
end
math.randomseed(Score())
bestScore=Score()
function SaveBest()
local g=Score()-bestScore
if g>0 then
p("Gained another ",round(g)," pts.")
bestScore=Score()
quicksave(3)
end
end
distances={}
distScore=Score()
function getDist()
if #distances<1 or distScore~=Score() then --run only if needed
p("Calculating distances...")
for i=1,segCnt do --filling table
distances[i]={} --need to delclare second dimension
for j=i+1,segCnt do --not counting from beginning - not need :)
distances[i][j]=get_segment_distance(i,j)
end
end
p("Done")
distScore=Score()
end
end
function dist(a,b)
if a==b then return 0 end
if a>b then a,b=b,a end
return distances[a][b]
end
function Sort(tab,items)
for x=1,items do
for y=x+1,#tab do
if tab[x][2]>tab[y][2] then
tab[x],tab[y]=tab[y],tab[x]
end
end
end
return tab
end
function findSegAngle(a,b,angle)
-- search all segments within a cone
-- with center a and centerline ab
-- max angle from centerline forward and backward
local maxanglef=(angle/180)*math.pi
local minangleb=math.pi-maxanglef
local Forward={}
local Backward={}
local ab=dist(a,b)
for c=1,segCnt do
if c~=a then
local ac=dist(a,c)
local bc=dist(b,c)
local cab=math.acos((ac*ac+ab*ab-bc*bc)/(2*ac*ab))
if cab < maxanglef then Forward[#Forward+1]={c,math.cos(cab)*ac}
else if cab > minangleb then Backward[#Backward+1]=c end
end
end
end
local Result={}
Result[1]=Forward
Result[2]=Backward
return Result
end
function bandList(a,list,diff)
for i=1,#list do
local d
if diff==0 then --This is backward, no computing
band_add_segment_segment(a,list[i])
d=dist(a,list[i])
else -- forward, distance depends on angle
band_add_segment_segment(a,list[i][1])
d=dist(a,list[i][1])
local x=list[i][2]
local y=(d*d-x*x)^0.5
d=(y*y+(x-diff)*(x-diff))^0.5
end
if d<3 then d=3 end
local bnr=get_band_count()
--print( "bandnr ",bnr)
band_set_length(bnr,d)
end
end
function mkangleBand(pair,angle)
local a=pair[1]
local b=pair[2]
local backalso=pair[3]
p("Banding segment ", a," and ",b)
getDist()
if dist(a,b)-compFrac < 3 then
compFrac=dist(a,b)-3
print("Adjusting pull distance to ",round(compFrac))
end
local t1=findSegAngle(a,b,angle)
local t2=findSegAngle(b,a,angle)
bandList(a,t1[1],compFrac)
if backalso then bandList(a,t1[2],0) end
bandList(b,t2[1],compFrac)
if backalso then bandList(b,t2[2],0) end
end
function bandstr(str) --set all band strength
for i=1, get_band_count() do
band_set_strength(i, str)
end
end
function SaveRB()
quicksave(4)
restore_recent_best()
SaveBest()
quickload(4)
end
function PullAngle(pairlist,angle)
local bscore=Score()
quicksave(5)
band_delete()
for i=1,#pairlist do
mkangleBand(pairlist[i],angle)
end
if get_band_count()>0 then
select_all()
CI(pullingCI)
reset_recent_best()
local loss=math.abs(down(Score()*maxLoss/100))
for str=minBS,maxBS,0.11 do--search enough band strenght to move
restore_recent_best() --because sometimes it makes points during pull :D
ss=Score()
bandstr(str)
do_global_wiggle_backbone(1)
if ss-Score()>loss then
lastBS=str-0.1
if lastBS<minBS then lastBS=minBS end
break
end
end
band_delete()
SaveRB() --because sometimes it missing fractions
p("Stabilizing...")
CI(1)
reset_recent_best() --after pulling
qStab()
if bestScore-Score()<doFuze then
SaveBest()
p("Fuzing....")
Fuze(4)
end
SaveBest()
p("Run gained: ",round(Score()-bscore))
if bscore > Score() then
if not askAccept("Will restore loop start if loss is not accepted",round(bscore-Score())) then
quickload(5)
end
end
p("Current score: ",round(Score())," Total gain: ",round(Score()-qsc))
end
end
function askAccept(title,loss)
local ask = dialog.CreateDialog(title)
local accept=false
ask.lab1=dialog.AddLabel("Run lost "..round(loss).." points")
ask.accept=dialog.AddCheckbox("Accept loss",false)
ask.OK = dialog.AddButton("OK",1) ask.Cancel = dialog.AddButton("Cancel",0)
if dialog.Show(ask) > 0 then
accept=ask.accept.value
end
return accept
end
function askSegPairs(title,struc,subtitle)
local Pairs={}
local Err={}
local Input=""
if struc==nil then struc="Pairs" end
repeat
local ask = dialog.CreateDialog(title)
-- Build resultstring from pairs found
local listP=""
for i=1,#Pairs do
if i>1 then listP=listP.."," end
listP=listP..Pairs[i][1].." "..Pairs[i][2]
end
if subtitle~=nil then ask.sub= dialog.AddLabel(subtitle) end
-- Present max 4 errors found
if #Err > 0 then ask.error1=dialog.AddLabel(Err[1]) end
if #Err > 1 then ask.error1=dialog.AddLabel(Err[2]) end
if #Err > 2 then ask.error1=dialog.AddLabel(Err[3]) end
if #Err > 3 then ask.error1=dialog.AddLabel(Err[4]) end
Err={}
if listP=="" then
ask.sub1=dialog.AddLabel("Input "..struc.. " of segmentnumbers between 1 and "..segCnt)
ask.nums=dialog.AddTextbox(struc,Input)
ask.OK = dialog.AddButton("OK",1)
ask.Cancel = dialog.AddButton("Cancel",0)
else
ask.conf=dialog.AddLabel(struc.." found: "..listP)
ask.OK = dialog.AddButton("Confirm",1)
ask.Cancel = dialog.AddButton("Again",0)
end
if dialog.Show(ask) > 0 then
if listP=="" then --Asking mode
local NoNegatives='%d+' -- - is not part of a number
local nums = {}
for v in string.gfind(ask.nums.value,NoNegatives) do
table.insert(nums, tonumber(v))
end
Input=ask.nums.value
-- Now checking
if #nums%2 ~= 0 then
Err[#Err+1]="Not an even number of segments found"
else
for i=1,#nums do
if nums[i]==0 or nums[i]>segCnt then
Err[#Err+1]="Number "..nums[i].." is not a segment"
end
end
if #Err==0 then
for i=1,#nums/2 do
Pairs[i]={nums[2*i-1],nums[2*i]}
end
end
end
else
return Pairs
end
else if listP=="" then return nil else Pairs={} end
end
until false
end
function runInter()
repeat
local ask = dialog.CreateDialog("Settings for Interactive")
ask.l0=dialog.AddLabel("Script make bands within cones")
ask.l01=dialog.AddLabel("Based on pairs of segments")
ask.l1=dialog.AddLabel("Minimum strength for pull")
ask.BandsMin = dialog.AddSlider("Band Strength",minBS,0.1,1.0,1)
ask.l2=dialog.AddLabel("Maximum strength for pull")
ask.BandsMax = dialog.AddSlider("Band Strength",maxBS,0.1,1.0,1)
ask.l3=dialog.AddLabel("Pull harder if loss is less")
ask.maxLoss=dialog.AddSlider("Percentage",maxLoss,0,2,1)
ask.l4=dialog.AddLabel("Maximum angle relative to cone middle")
ask.MaxAngle = dialog.AddSlider("Angle (degrees)",30,1,60,0)
ask.l6 = dialog.AddLabel("Class importance while pulling")
ask.CI = dialog.AddSlider("Class importance",pullingCI,0.3,1,2)
ask.l7 = dialog.AddLabel("If unchecked only fuse after gain")
ask.fuze = dialog.AddCheckbox("Always Fuze",true)
ask.OK = dialog.AddButton("OK",1) ask.Cancel = dialog.AddButton("Cancel",0)
if dialog.Show(ask) > 0 then
local PairList=askSegPairs("Input pairs to be pulled")
minBS=ask.BandsMin.value
maxBS=ask.BandsMax.value
maxLoss=ask.maxLoss.value
maxAngle=ask.MaxAngle.value
if ask.fuze.value then doFuze=1000 end
pullingCI=ask.CI.value
if #PairList==0 then break end
PullAngle(PairList,maxAngle)
else break end
until false
end
qsc=Score()
--- Defaults HERE! vvv
doFuze=0 --run fuzes when close to saved best (negative - run if gain after qstab)
pullingCI=0.90 --clash importance during pull
minBS=0.3 --starting band strength
maxBS=1 --maximum bands strength
compFrac=3 --how much shorter band should be
maxLoss=1 --pull till perc loss (ie 1 on 10`000 ptsy = pull till 100 pt loss after pull)
-- Real Options here vvv
fastQstab = true --1s1w then true, double if false
runInter()