Icon representing a recipe

Recipe: Tvdl VoidCrushers 4.2.2

created by Bruno Kestemont

Profile


Name
Tvdl VoidCrushers 4.2.2
ID
103171
Shared with
Public
Parent
Tvdl VoidCrushers 4.1.5
Children
None
Created on
May 10, 2021 at 18:12 PM UTC
Updated on
January 06, 2023 at 19:15 PM UTC
Description

Wiggle Factor added, NC adapted, hiding hydrophobes, voids to user end bands (band to symmetrics)

Best for


Code


--[[ Voids Killer by rav3n_pl script is searching for possible banding across voids. Because we not have any voids detection in Lua, I do some math to find them Not always perfect, but mostly works :) Tvdl: 09-01-2012 Added extra option to pull all the bands in one go, pulls harder, if wanted, on hydro's Works also as a stabilizer (like Hydrophobic script) Compacts the protein Warning: when used all at once will accept a loss If so the previous score is in slot 3 Tvdl: 12-07-2012 - Made totally V2 MDC: 2-19-2014 Added Wiggle Factor BK: 2-22-*-2014 restore recursive wiggle BK: 3.03 infinite run BK: 3.04 change options on each loop BK: 3.05 added set notes BK: 3.1.0 atoms on hydrophobic pull & more hydrophobics BK: 3.1.1 fixed main loop BK: 3.1.2 fixed delete bands BK: 4.0.0 added bands to existing bands (for symmetric): if the user previously add bands to symmetrics, the recipe will be able to add bands to symmetrics and detect voids between the 2 monomers BK: 4.1.0 optional band to existing bands (TO DO: recognizes sym puzzles) WARNING: end point is only in one direction. If you want the 2 end points, you have to add a reverse band (this is only possible for bands to main monomer) BK: 4.1.1 added a log to recall scores on each steps (jeff101's display) BK: 4.1.2 SemiRandomStr added (slightly randomizes band strength on pull all) BK: 4.1.3 added CI function, deleted abs in wiggle, for debugging BK: 4.1.4 smaller band length when banded to end of sidechains BK: 4.1.5 fixed a bug on end band line 550 BK: 4.2 New commands for symmetrics 22/10/2019 BK: 4.2.1 bands to only one sym is enough (3 times faster than previous version) BK: 4.2.2 disabling filters during wiggle and during distances ]]-- Version="4.2.2" recipename="Void Crusher "..Version -- Handy shorts module normal= (current.GetExplorationMultiplier() == 0) --CI=behavior.SetClashImportance segCnt=structure.GetCount() segCnt2=segCnt while structure.GetSecondaryStructure(segCnt2)=="M" do segCnt2=segCnt2-1 end DIST2USERBANDS= false SYMMETRIC= false ExistingBands=band.GetCount() if ExistingBands >0 then DIST2USERBANDS = true end print("Starting "..recipename.. " on\n puzzle "..(puzzle.GetName())) print(' with puzzle ID '..(puzzle.GetPuzzleID())..' and '..ExistingBands..' user-supplied bands.\n ') SymCount=structure.GetSymCount() -- new 22/10/2019 if SymCount>0 then SYMMETRIC = true end CIfactor=1 filters= false -- disabling filters during wiggle function CI(CInr) behavior.SetClashImportance(CInr*CIfactor) end -- Score functions function Score() if normal==nil or normal==true then -- FIX for big negatives local total= current.GetEnergyScore() if total < -999999 and total > -1000001 then total=SegScore() end return total else return current.GetScore() end end function SegScore() local total=8000 for i=1,segCnt2 do total=total+current.GetSegmentEnergyScore(i) end return total end function RBScore() if normal then return recentbest.GetEnergyScore() else return recentbest.GetScore() end end function round3(x)--cut all afer 3-rd place return x-x%0.001 end --START SET NOTES BY PD --[[ Set note with author, recipe and big steps -- By Pauldunn module to paste it in existing recipe, by BK ]]-- --HOW TO include in a recipe? --1a) COPY from here ================ function InitNotes(recipename) local recipename=recipename or "" note_number=structure.GetCount() for seg=structure.GetCount(),1,-1 do if structure.GetNote(seg)~="" then break end note_number=seg end print(string.format("Recording "..recipename.." results in Note for segment %i",note_number)) starting_score=current.GetScore() --structure.SetNote(note_number,string.format("(%s) %.3f + %s(%i) %.3f",user.GetPlayerName(),starting_score,recipename,loop_count,current.GetScore())) end function SetNote(note_number, starting_score, recipename, loop_count) local recipename=recipename or "" local starting_score=starting_score or 0 local loop_count=loop_count or 1 --print(string.format("Recording "..recipename.." results in Note for segment %i",note_number)) structure.SetNote(note_number,string.format("(%s) %.3f + %s(%i) %.3f",user.GetPlayerName(),starting_score,recipename,loop_count,current.GetScore())) end InitNotes(recipename) -- WARNING: and mach "recipename" with the recipename of the recipe --1b) COPY to here. ================ --2) PASTE somewhere to the beginning of your recipe. --3a) COPY from here --------------- --SetNote(note_number, starting_score, recipename, loop_count) -- WARNING: and mach "recipename" and "loop_count" with the names of the recipe --3b) COPY to here -------------- --4) PASTE at the end of the main loop function of your recipe, at the end of the cleanup function, at the end of the recipe --better loop_count a global variable --END SET NOTES BY PD bestScore=Score() function SaveBest() local g=Score()-bestScore if g>0 then if g>0.01 then print("Gained another "..round3(g).." pts.") end bestScore=Score() SetNote(note_number, starting_score, recipename, loop_count) save.Quicksave(3) end end -- New WiggleFactor WF=1 -- Wiggle function -- Optimized due to Susumes ideas -- Note the extra parameter to be used if only selected parts must be done function Wiggle(how, iters, minppi,onlyselected) -- 22/02/2014 reset recursive wiggle --score conditioned recursive wiggle/shake --fixed a bug, absolute difference is the threshold now if filters then filter.DisableAll() end--Disables all filters if how==nil then how="wa" end if iters==nil then iters=3 end if minppi==nil then minppi=0.1 end if onlyselected==nil then onlyselected=false end local wf=1 if maxCI then wf=WF end --print("Wiggle FactorA= ",WF) if iters>0 then --iters=iters-1 local sp=Score() if onlyselected then if how == "s" then -- Shake is not considered to do much in second or more rounds structure.ShakeSidechainsSelected(1) return elseif how == "wb" then structure.WiggleSelected(2*wf*iters,true,false) elseif how == "ws" then structure.WiggleSelected(2*wf*iters,false,true) elseif how == "wa" then structure.WiggleSelected(2*wf*iters,true,true) end else if how == "s" then -- Shake is not considered to do much in second or more rounds structure.ShakeSidechainsAll(1) return elseif how == "wb" then structure.WiggleAll(2*wf*iters,true,false) elseif how == "ws" then structure.WiggleAll(2*wf*iters,false,true) elseif how == "wa" then structure.WiggleAll(2*wf*iters,true,true) end end if Score()-sp > minppi then return Wiggle(how, iters, minppi,onlyselected) end iters=iters-1 -- 22/02/2014 end if filters then filter.EnableAll() end--Enables all filters end -- end of handy shorts module -- Standard Fuze module -- Picks up all gains by using recentbest function FuzeEnd() CI(1) Wiggle("wa",1) Wiggle("s",1) Wiggle() if RBScore()> Score() then recentbest.Restore() end 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 save.Quickload(slot) else scr=s save.Quicksave(slot) end return scr end function Fuze(slot) local scr=Score() recentbest.Save() Fuze1(0.3,0.6) FuzeEnd() scr=reFuze(scr,slot) Fuze2(0.3,1) if RBScore()>Score() then recentbest.Restore() end SaveBest() scr=reFuze(scr,slot) Fuze1(0.05,1) if RBScore()>Score() then recentbest.Restore() end SaveBest() scr=reFuze(scr,slot) Fuze2(0.7,0.5) FuzeEnd() scr=reFuze(scr,slot) Fuze1(0.07,1) if RBScore()>Score() then recentbest.Restore() end SaveBest() reFuze(scr,slot) if RBScore()>Score() then recentbest.Restore() end SaveBest() end -- end standard Fuze module -- Distance lib -- distances={} -- a list of distances between segments only distancesb={} -- a list of distances between segments and end bands distancessym={} -- a list of distances to symmetric chains distScore=Score() function getDist() -- 1 dim for speed if #distances<1 or distScore ~= Score() then distScore=Score() distances[1]=0 print("Calculating distances...") for i=1,segCnt do --filling table for j=i+1,segCnt do --not counting from beginning - no need :) distances[i*segCnt+j]=structure.GetDistance(i,j) end end print("Done") end end function getDistSym() -- 1 dim for speed if not SYMMETRIC then return end local iBand= 0 local s = 1 -- distance to first sym is enough for all if #distancessym<1 or distScore ~= Score() then distScore=Score() print("Calculating distances to symmetrics... be patient it's very SLOW !") distancessym[1]=0 for i=1,segCnt do --filling table for syms for j=i+1,segCnt do --not counting from beginning - no need :) iBand=band.AddBetweenSegments(i,j,0,0, s) -- adding a band to symmetrics for measuring distance -- (integer segmentIndex1, integer segmentIndex2, [integer atomIndex1], [integer atomIndex2], [integer symnr2]) distancessym[s*i*segCnt+j]=band.GetLength(iBand) band.Delete(iBand) end end print("Done") end end function distsym(a,b, s) -- reverse becaus we didnt calculate all backward distances for economy if a==b then return 0 end if a>b then a,b=b,a end return distancessym[s*a*segCnt+b] end function dist(a,b) if a==b then return 0 end if a>b then a,b=b,a end return distances[a*segCnt+b] end function getDist2Band() -- 1 dim for speed if not DIST2USERBANDS then return end if #distancesb<1 or distScore ~= Score() then distScore=Score() distancesb[1]=0 print("Calculating distances to end bands...") for i=1,segCnt do --filling table for j=1,ExistingBands do distancesb[i*segCnt+j]=dist2band(i,j) end end print("Done") end end function distSeg2band(a,b) if b==0 then return 0 end return distancesb[a*segCnt+b] end function dist2band(s,b) -- distance between a segment and a band end point VERY SLOW !! local iBand= 0 iBand = band.AddToBandEndpoint(s, b) local distance=band.GetLength(iBand) band.Delete(iBand) return distance end -- Safe band module --ExistingBands=band.GetCount() --if ExistingBands >0 then DIST2USERBANDS = true end function disableExistingBands() for i=1,ExistingBands do band.Disable(i) end end function enableExistingBands() for i=1,ExistingBands do band.Enable(i) end end function bandDisableAll() for i=ExistingBands+1,band.GetCount() do band.Disable(i) end end function bandEnableAll() for i=ExistingBands+1,band.GetCount() do band.Enable(i) end end function bandDeleteAll() for i=ExistingBands+1,band.GetCount() do band.Delete(ExistingBands+1) end end function bandSetStrengthAll(str) -- randomized if SemiRandomStr then local minBS2, maxBS2=minBS, maxBS if str-minBS > maxBS-str then minBS2= 2*str - maxBS else maxBS2= 2* str - minBS end local strbase=str for i=ExistingBands+1,band.GetCount() do strbase= random2numbers(minBS2,maxBS2) band.SetStrength(i,strbase) end else for i=ExistingBands+1,band.GetCount() do band.SetStrength(i,str) end end end function bandGetCount() return band.GetCount()-ExistingBands end -- end safe band module function down(x) return x-x%1 end function round(x)--cut all afer 3-rd place return x-x%0.001 end function qStab() CI(0.1) Wiggle("s",1) if fastQstab==false then CI(0.4) Wiggle("wa",1) CI(1) Wiggle("s",1) end CI(1) Wiggle() end math.randomseed(Score()) math.random(100) -- Because first random is not random function random2numbers(n1,n2) --random function returns int or float depends on input vars if n2==nil and n1==nil then return math.random() --float 0-1 else if n2==nil then if n1%1==0 then return math.random(n1) --integer 1-n1 else return math.random()*n1 --float 0-n1 end else if n1%1==0 and n2%1==0 then return math.random(n1,n2) --integer between else return math.random()*(n2-n1)+n1 --float between, including 0 --return math.random(n1,n2) --float between BK 17/02/2015, this is also correct end end end 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 BuildTargetList(first) -- to segments or end points of user bands if not DIST2USERBANDS then return end targetList={} -- reset list of segments and endpoints for first = 1,segCnt do targetList[#targetList + 1] = {"s",i} end for i = 1,ExistingBands do targetList[#targetList + 1] = {"b",i} end end function mkBand(a) --make band if found void in area of that segment print("Banding segment "..a) if filters then filter.DisableAll() end--Disables all filters getDist() -- distances between all segments getDist2Band() -- distances between all end band and all segs getDistSym() -- distances with symmetrics local t={}--there we store possible voids between segments of the monomer local ts={}--there we store possible voids between symmetrics (end of band) local tssym={}--there we store possible voids between symmetrics local first=1 local voidsym= false if allatonce then first=a+2 end if first > segCnt then return false end --BuildTargetList(first)-- to segments or end points of user bands for b=first,segCnt do --test all segments of monomer if useRegionBool[a] or useRegionBool[b] then -- case of segments to segments local ab=dist(a,b) --distance between segments voids=false -- voids between segments if ab>minLength and ab < maxLength and math.abs(a-b) >= minDist then --no void if less --print(a," ",b," ",ab) local void=true for c=1,segCnt do --searching that is any segment between them local ac=dist(a,c) local bc=dist(b,c) if ac~=0 and bc~=0 and ac<ab and bc<ab and ac>4 and bc>4 then if ac+bc<ab+1.5 then void=false break --no void there for sure end end end if void==true and (not allatonce or a<b) then t[#t+1]={a,b} voids=true end end end end if SYMMETRIC then -- case with symmetrics, only banding from monomer to a segment from symmetrics local s=1 -- no need to band all symetrics, the effetc is the same with only one for b=first,segCnt do --test all segments if useRegionBool[a] or useRegionBool[b] then -- case of segments to segments local ab=distsym(a,b, s) --distance between segment a and symmetric b voidsym=false -- voids between symmetrics if ab>minLength and ab < maxLength and math.abs(a-b) >= minDist then --no void if less --print(a," ",b," ",ab) local void=true -- temp for c=1,segCnt do --searching that is any segment between them local ac=distsym(a,c, s) local bc=distsym(b,c, s) if ac~=0 and bc~=0 and ac<ab and bc<ab and ac>4 and bc>4 then if ac+bc<ab+1.5 then void=false break --no void there for sure end end end if void==true and (not allatonce or a<b) then tssym[#tssym+1]={a,b, s} voidsym=true print("DEBUG "..tssym[b][1]) print("DEBUG "..tssym[b][2]) print("DEBUG "..tssym[b][3]) end end end end end if DIST2USERBANDS then -- New 15/12/2015 for b= 1, ExistingBands do if useRegionBool[a] and b>0 then -- case of symmetric, bands to end user bands local ab=distSeg2band(a,b) voidss=false -- voids between segs and bands (monomers in symmetric) if ab>minLength and ab < maxLength then local voidb=true for c=1,segCnt do --searching that is any segment between them local ac=dist(a,c) local bc=distSeg2band(c,b) if ac~=0 and bc~=0 and ac<ab and bc<ab and ac>4 and bc>4 then if ac+bc<ab+1.5 then voidb=false break --no void there for sure end end end if voidb then ts[#ts+1]={a,b} voidss=true end end end end end if voids or voidss then local tt= #t + #ts + #tssym print("Found "..tt.." possible bands across voids") else print("No voids found") end if voids then print("Testing "..#t.." possible bands across voids (seg to seg)") for i=1,#t do local s=t[i][1] local e=t[i][2] local atoms=0 local atome=0 if OrangeInside or OrangeSidechain then if structure.IsHydrophobic(s) and structure.GetAtomCount(s)>0 then atoms=1 if OrangeSidechain then atoms=structure.GetAtomCount(s) end end if structure.IsHydrophobic(e) and structure.GetAtomCount(e)>0 then atome=1 if OrangeSidechain then atome=structure.GetAtomCount(e) end end end band.AddBetweenSegments(s,e,atoms,atome) -- (integer segmentIndex1, integer segmentIndex2, [integer atomIndex1], [integer atomIndex2], [integer symnr2]) local d=dist(s,e) d=d-compFrac - (atome+ atoms -2)-- compFrac= 3, distance between atoms of sidechains is more or less 1 if d<2 then d=2 end -- was 3 but for sidechains, bonds are <3 if d>20 then d=20 end local bnr=band.GetCount() band.SetGoalLength(bnr,d) if allatonce then if structure.IsHydrophobic(s) or structure.IsHydrophobic(e) then band.SetStrength(bnr,pullextrahydro*allBS) else band.SetStrength(bnr,allBS) end end end end if voidss then -- voids between segs and bands (monomers in symmetric) print("Testing "..#ts.." possible bands across voidsb(seg to end of user bands)") for i=1,#ts do local s=ts[i][1] local b=ts[i][2] local atoms=0 if OrangeInside or OrangeSidechain then -- WARNING: here I favour hydrophillic to end points -- because end points (on symmetric) are supposed to be outside of the protein !!! Good for H-Bonds if not structure.IsHydrophobic(s) and structure.GetAtomCount(s)>0 then -- not hydrophobic ! atoms=1 if OrangeSidechain then atoms=structure.GetAtomCount(s) end end end band.AddToBandEndpoint(s, b, atoms) local d=distSeg2band(s,b) d=d-compFrac - (atoms -2)-- compFrac= 3, distance between atoms of sidechains is more or less 1, here only one sidechain (end band is on atom 0) if d<2 then d=2 end -- was 3 but for sidechains, bonds are <3 if d>20 then d=20 end local bnr=band.GetCount() band.SetGoalLength(bnr,d) if allatonce then if structure.IsHydrophobic(s) then band.SetStrength(bnr,pullextrahydro*allBS) else band.SetStrength(bnr,allBS) end end end end if voidsym then print("Testing "..#tssym.." possible bands across symmetrics (seg to first symmetric chain)") -- print("Some fake voids are possible if") local k=1 -- always 1, we only can band to monomer for i=1,#tssym do local s=tssym[i][1] local e=tssym[i][2] local atoms=0 local atome=0 if OrangeInside or OrangeSidechain then if structure.IsHydrophobic(s) and structure.GetAtomCount(s)>0 then atoms=1 if OrangeSidechain then atoms=structure.GetAtomCount(s) end end if structure.IsHydrophobic(e) and structure.GetAtomCount(e)>0 then atome=1 if OrangeSidechain then atome=structure.GetAtomCount(e) end end end band.AddBetweenSegments(s,e,atoms,atome, k) -- (integer segmentIndex1, integer segmentIndex2, [integer atomIndex1], [integer atomIndex2], [integer symnr2]) local d=distsym(s,e, k) d=d-compFrac - (atome+ atoms -2)-- compFrac= 3, distance between atoms of sidechains is more or less 1 if d<2 then d=2 end -- was 3 but for sidechains, bonds are <3 if d>20 then d=20 end local bnr=band.GetCount() band.SetGoalLength(bnr,d) if allatonce then if structure.IsHydrophobic(s) or structure.IsHydrophobic(e) then band.SetStrength(bnr,pullextrahydro*allBS) else band.SetStrength(bnr,allBS) end end end end if filters then filter.EnableAll() end--Enables all filters end function SaveRB() if RBScore() > Score() then save.Quicksave(9) recentbest.Restore() SaveBest() save.Quickload(9) end end function Pull(List) -- List is a list of segments disableExistingBands() if List==nil then for i=1,segCnt do mkBand(i) end else for i=1,#List do mkBand(List[i]) end end if bandGetCount() >0 then -- it counts new bands only CI(pullingCI) -- Make an estimation of the required strength if lastAllBS > 0 then lastBS=lastAllBS/bandGetCount() end if lastBS < minBS then lastBS=minBS end if lastBS > maxBS then lastBS=maxBS end recentbest.Save() local loss=math.abs(down(Score()*maxLoss/100)) for str=lastBS,maxBS,0.11 do --search enough band strenght to move recentbest.Restore() ss=Score() if not allatonce then bandSetStrengthAll(str) end Wiggle("wb",1) if ss-Score()>loss then lastAllBS=(str-0.1)*bandGetCount() break end end bandDeleteAll() SaveRB() --because sometimes it missing fractions print("Stabilizing...") CI(1) recentbest.Save() --after pulling qStab() if bestScore-Score()<doFuze or allatonce then SaveBest() print("Fuzing....") Fuze(4) SaveBest() end if not allatonce then save.Quickload(3) --load best state end print("Current score: "..round3(Score()).." VC gain: "..round3(Score()-StartScore)) end end loop_count=0 function KillVoids() -- main loops are here loop_count=loop_count+1 -- for setnotes if allatonce then lastBS=allBS minBS=allBS maxBS=allBS end lastBS=minBS local s={} if filters then filter.DisableAll() end--Disables all filters getDist() --calculate distances now getDist2Band() -- calculate distances of all segs with ends of all existing bands getDistSym() -- distances with symmetrics if filters then filter.EnableAll() end--Disables all filters if #Speclist > 0 then for i=1,#Speclist do s[#s+1]={Speclist[i], current.GetSegmentEnergyScore(Speclist[i])} end else for i=1,segCnt do s[#s+1]={i, current.GetSegmentEnergyScore(i)} end end if Vworst==true then Sort(s,#s) end if Vrandom==true then -- not really random, it's always the same !! for i=1,#s do local r=math.random(#s) s[i],s[r]=s[r],s[i] end end if allatonce then Pull() else local Speclist2={} --Clear list for i=1,#s/Combinum do print("Loop "..loop..". Kill "..i.." of "..(#s-#s%Combinum)/Combinum.." started.") for j=1,Combinum do Speclist2[j]=s[Combinum*i-Combinum+j][1] end Pull(Speclist2) end end end -- Segment set and list module -- Notice that most functions assume that the sets are well formed -- (=ordered and no overlaps) -- 02-05-2012 TvdL Free to use for non commercial purposes function SegmentListToSet(list) local result={} local f=0 local l=-1 table.sort(list) for i=1,#list do if list[i] ~= l+1 and list[i] ~= l then -- note: duplicates are removed if l>0 then result[#result+1]={f,l} end f=list[i] end l=list[i] end if l>0 then result[#result+1]={f,l} end --print("list to set") --SegmentPrintSet(result) return result end function SegmentSetToList(set) local result={} for i=1,#set do --print(set[i][1],set[i][2]) for k=set[i][1],set[i][2] do result[#result+1]=k end end return result end function SegmentCleanSet(set) -- Makes it well formed return SegmentListToSet(SegmentSetToList(set)) end function SegmentInvertSet(set,maxseg) -- Gives back all segments not in the set -- maxseg is added for ligand local result={} if maxseg==nil then maxseg=structure.GetCount() end if #set==0 then return {{1,maxseg}} end if set[1][1] ~= 1 then result[1]={1,set[1][1]-1} end for i=2,#set do result[#result+1]={set[i-1][2]+1,set[i][1]-1} end if set[#set][2] ~= maxseg then result[#result+1]={set[#set][2]+1,maxseg} end return result end function SegmentInList(s,list) table.sort(list) for i=1,#list do if list[i]==s then return true elseif list[i]>s then return false end end return false end function SegmentInSet(set,s) for i=1,#set do if s>=set[i][1] and s<=set[i][2] then return true elseif s<set[i][1] then return false end end return false end function SegmentJoinList(list1,list2) local result=list1 if result == nil then return list2 end for i=1,#list2 do result[#result+1]=list2[i] end table.sort(result) return result end function SegmentJoinSet(set1,set2) return SegmentListToSet(SegmentJoinList(SegmentSetToList(set1),SegmentSetToList(set2))) end function SegmentCommList(list1,list2) local result={} table.sort(list1) table.sort(list2) if #list2==0 then return result end local j=1 for i=1,#list1 do while list2[j]<list1[i] do j=j+1 if j>#list2 then return result end end if list1[i]==list2[j] then result[#result+1]=list1[i] end end return result end function SegmentCommSet(set1,set2) return SegmentListToSet(SegmentCommList(SegmentSetToList(set1),SegmentSetToList(set2))) end function SegmentSetMinus(set1,set2) return SegmentCommSet(set1,SegmentInvertSet(set2)) end function SegmentPrintSet(set) print(SegmentSetToString(set)) end function SegmentSetToString(set) local line = "" for i=1,#set do if i~=1 then line=line..", " end line=line..set[i][1].."-"..set[i][2] end return line end function SegmentSetInSet(set,sub) if sub==nil then return true end -- Checks if sub is a proper subset of set for i=1,#sub do if not SegmentRangeInSet(set,sub[i]) then return false end end return true end function SegmentRangeInSet(set,range) if range==nil or #range==0 then return true end local b=range[1] local e=range[2] for i=1,#set do if b>=set[i][1] and b<=set[i][2] then return (e<=set[i][2]) elseif e<=set[i][1] then return false end end return false end function SegmentSetToBool(set) local result={} for i=1,structure.GetCount() do result[i]=SegmentInSet(set,i) end return result end --- End of Segment Set module -- Module Find Segment Types function FindMutables() local result={} for i=1,structure.GetCount() do if structure.IsMutable(i) then result[#result+1]=i end end return SegmentListToSet(result) end function FindFrozen() local result={} for i=1,structure.GetCount() do if freeze.IsFrozen(i) then result[#result+1]=i end end return SegmentListToSet(result) end function FindLocked() local result={} for i=1,structure.GetCount() do if structure.IsLocked(i) then result[#result+1]=i end end return SegmentListToSet(result) end function FindSelected() local result={} for i=1,structure.GetCount() do if selection.IsSelected(i) then result[#result+1]=i end end return SegmentListToSet(result) end function FindAAtype(aa) local result={} for i=1,structure.GetCount() do if structure.GetSecondaryStructure(i)== aa then result[#result+1]=i end end return SegmentListToSet(result) end function FindAminotype(at) -- This one returns a list not a set local result={} for i=1,structure.GetCount() do if structure.GetAminoAcid(i) == at then result[#result+1]=i end end return result end -- end Module Find Segment Types -- Module AskSelections -- 02-05-2012 Timo van der Laan, Free to use for non commercial purposes function AskForSelections(title,mode) local result={{1,structure.GetCount()}} -- All segments if mode == nil then mode={} end if mode.askloops==nil then mode.askloops=true end if mode.asksheets==nil then mode.asksheets=true end if mode.askhelixes==nil then mode.askhelixes=true end if mode.askligands==nil then mode.askligands=false end if mode.askselected==nil then mode.askselected=true end if mode.asknonselected==nil then mode.asknonselected=true end if mode.askmutateonly==nil then mode.askmutateonly=true end if mode.askignorelocks==nil then mode.askignorelocks=true end if mode.askignorefrozen==nil then mode.askignorefrozen=true end if mode.askranges==nil then mode.askranges=true end if mode.defloops==nil then mode.defloops=true end if mode.defsheets==nil then mode.defsheets=true end if mode.defhelixes==nil then mode.defhelixes=true end if mode.defligands==nil then mode.defligands=false end if mode.defselected==nil then mode.defselected=false end if mode.defnonselected==nil then mode.defnonselected=false end if mode.defmutateonly==nil then mode.defmutateonly=false end if mode.defignorelocks==nil then mode.defignorelocks=false end if mode.defignorefrozen==nil then mode.defignorefrozen=false end local Errfound=false repeat local ask = dialog.CreateDialog(title) if Errfound then ask.E1=dialog.AddLabel("Try again, ERRORS found, check output box") result={{1,structure.GetCount()}} --reset start Errfound=false end if mode.askloops then ask.loops = dialog.AddCheckbox("Work on loops",mode.defloops) elseif not mode.defloops then ask.noloops= dialog.AddLabel("Loops will be auto excluded") end if mode.askhelixes then ask.helixes = dialog.AddCheckbox("Work on helixes",mode.defhelixes) elseif not mode.defhelixes then ask.nohelixes= dialog.AddLabel("Helixes will be auto excluded") end if mode.asksheets then ask.sheets = dialog.AddCheckbox("Work on sheets",mode.defsheets) elseif not mode.defsheets then ask.nosheets= dialog.AddLabel("Sheets will be auto excluded") end if mode.askligands then ask.ligands = dialog.AddCheckbox("Work on ligands",mode.defligands) elseif not mode.defligands then ask.noligands= dialog.AddLabel("Ligands will be auto excluded") end if mode.askselected then ask.selected = dialog.AddCheckbox("Work only on selected",mode.defselected) end if mode.asknonselected then ask.nonselected = dialog.AddCheckbox("Work only on nonselected",mode.defnonselected) end if mode.askmutateonly then ask.mutateonly = dialog.AddCheckbox("Work only on mutateonly",mode.defmutateonly) end if mode.askignorelocks then ask.ignorelocks =dialog.AddCheckbox("Dont work on locked ones",true) elseif mode.defignorelocks then ask.nolocks=dialog.AddLabel("Locked ones will be auto excluded") end if mode.askignorefrozen then ask.ignorefrozen = dialog.AddCheckbox("Dont work on frozen",true) elseif mode.defignorefrozen then ask.nofrozen=dialog.AddLabel("Frozen ones will be auto excluded") end if mode.askranges then ask.R1=dialog.AddLabel("Or put in segmentranges. Above selections also count") ask.ranges=dialog.AddTextbox("Ranges","") end ask.OK = dialog.AddButton("OK",1) ask.Cancel = dialog.AddButton("Cancel",0) if dialog.Show(ask) > 0 then -- We start with all the segments including ligands if mode.askloops then mode.defloops=ask.loops.value end if not mode.defloops then result=SegmentSetMinus(result,FindAAtype("L")) end if mode.asksheets then mode.defsheets=ask.sheets.value end if not mode.defsheets then result=SegmentSetMinus(result,FindAAtype("E")) end if mode.askhelixes then mode.defhelixes=ask.helixes.value end if not mode.defhelixes then result=SegmentSetMinus(result,FindAAtype("H")) end if mode.askligands then mode.defligands=ask.ligands.value end if not mode.defligands then result=SegmentSetMinus(result,FindAAtype("M")) end if mode.askignorelocks then mode.defignorelocks=ask.ignorelocks.value end if mode.defignorelocks then result=SegmentSetMinus(result,FindLocked()) end if mode.askignorefrozen then mode.defignorefrozen=ask.ignorefrozen.value end if mode.defignorefrozen then result=SegmentSetMinus(result,FindFrozen()) end if mode.askselected then mode.defselected=ask.selected.value end if mode.defselected then result=SegmentCommSet(result,FindSelected()) end if mode.asknonselected then mode.defnonselected=ask.nonselected.value end if mode.defnonselected then result=SegmentCommSet(result,SegmentInvertSet(FindSelected())) end if mode.askranges and ask.ranges.value ~= "" then local rangetext=ask.ranges.value local function Checknums(nums) -- Now checking if #nums%2 ~= 0 then print("Not an even number of segments found") return false end for i=1,#nums do if nums[i]==0 or nums[i]>structure.GetCount() then print("Number "..nums[i].." is not a segment") return false end end return true end local function ReadSegmentSet(data) local nums = {} local NoNegatives='%d+' -- - is not part of a number local result={} for v in string.gfind(data,NoNegatives) do table.insert(nums, tonumber(v)) end if Checknums(nums) then for i=1,#nums/2 do result[i]={nums[2*i-1],nums[2*i]} end result=SegmentCleanSet(result) else Errfound=true result={} end return result end local rangelist=ReadSegmentSet(rangetext) if not Errfound then result=SegmentCommSet(result,rangelist) end end end until not Errfound return result end -- end of module AskSelections --MAIN is in askMode here function askMode() local ask = dialog.CreateDialog("Voidcrusher "..Version.." Runmode") ask.l1=dialog.AddLabel("Run specified number of kills at a time") ask.Combi = dialog.AddSlider("Nr of segments: ",Combinum,1,10,0) ask.allatonce=dialog.AddCheckbox("Or pull all in one go",allatonce) ask.l3=dialog.AddLabel("Or do multiple runs on 1 to 6 segments") ask.multi=dialog.AddSlider("Repeat multi",multi,0,20,0) ask.l2 = dialog.AddLabel("The choices above also apply if selections are made") ask.selected=dialog.AddCheckbox("Set selection where to pull from",false) ask.selection=dialog.AddCheckbox("Select segments where 1 bandend must be",false) ask.OrangeInside=dialog.AddCheckbox("Hide hydrophobic chains",OrangeInside) ask.OrangeSidechain=dialog.AddCheckbox("Band end of sidechains",OrangeSidechain) if SYMMETRIC then ask.SYMMETRIC=dialog.AddCheckbox("Band to symmetric (SLOW !)",SYMMETRIC) end if DIST2USERBANDS then ask.DIST2USERBANDS=dialog.AddCheckbox("Band to end of user bands",DIST2USERBANDS) end ask.mutateOnce = dialog.AddCheckbox("Mutate once",false) ask.filters = dialog.AddCheckbox("No filter during wiggle",false) ask.l4 = dialog.AddLabel("Modify fine tuning options, depended on mode") ask.WF = dialog.AddSlider("WiggleFactor:",WF,1,5,0) --print("Wiggle FactorB= ",ask.WF.value) ask.modOptions=dialog.AddCheckbox("Modify options",false) ask.OK = dialog.AddButton("OK",1) ask.Cancel = dialog.AddButton("Cancel",0) if dialog.Show(ask) > 0 then Combinum=ask.Combi.value allatonce=ask.allatonce.value multi=ask.multi.value OrangeInside=ask.OrangeInside.value OrangeSidechain=ask.OrangeSidechain.value if SYMMETRIC then SYMMETRIC=ask.SYMMETRIC.value end if DIST2USERBANDS then -- possibility to disable in case of non symmetric but wanted keeping bands DIST2USERBANDS=ask.DIST2USERBANDS.value end WF=ask.WF.value -- print("Wiggle FactorC= ",ask.WF.value) if ask.selected.value then local SelMode={} SelMode.askligands=true --override the defaults SelMode.defligands=true SelMode.defignorelocks=false SelMode.defignorefrozen=false local PullFrom=AskForSelections("Set where to pull from",SelMode) for i=1,segCnt do if SegmentInSet(PullFrom,i) then Speclist[#Speclist+1]=i end end end if ask.selection.value then local SelMode={} SelMode.askligands=true --override the defaults SelMode.defligands=true SelMode.askignorelocks=false SelMode.defignorelocks=true SelMode.defignorefrozen=false useRegion=AskForSelections("At least one bandend must be",SelMode) else useRegion={{1,segCnt}} useRegion=SegmentSetMinus(useRegion,FindLocked()) end useRegionBool=SegmentSetToBool(useRegion) if ask.modOptions.value then AskOptions() end filters=ask.filters.value mutateOnce=ask.mutateOnce.value MAIN() end end function ChangeOptions() print("Changing all options:") if minDist==1 then minDist=15 else minDist= minDist-1 end--minimum segment distance if minLength==2 then minLength= 10 else minLength=minLength-1 end --minimum spatial distance maxLength=50 --maximum spatial distance fastQstab = not fastQstab --1s1w then true, double if false if compFrac==1 then compFrac= 3 else compFrac=compFrac-1 end --how much shorter band should be -- Defaults here VVV Vworst=not Vworst --start form worst scoring one Vrandom=not Vrandom --true --go it in random order -- if both are false then it will band form 1st to last if multi==0 then multi=1 else multi=0 end-- Multirun overrides all other options if Combinum==10 then Combinum=1 else Combinum=1+1 end-- Nr of segments to be treated in 1 go if doFuze==-5 then doFuze=5 else doFuze= doFuze-1 end --run fuzes when close to saved best (negative - run if gain after qstab) if pullingCI<=0.1 then pullingCI=0.90 else pullingCI=pullingCI-0.1 end--clash importance during pull Speclist={} minBS=0.12 --absolute minimum band strength if maxBS==5 then maxBS=1 else maxBS=maxBS+1 end--absolute maximum band strength if maxLoss==5 then maxLoss=1 else maxLoss=maxLoss+1 end --pull till perc loss (ie 1 on 10`000 ptsy = pull till 100 pt loss after pull) -- New options allatonce=not allatonce --false -- set to true if all at once pullextrahydro=1.1 --multiplier for extra pull on hydro segments allBS=0.12 -- strength if all lastAllBS=0 lastBS=minBS OrangeInside= not OrangeInside OrangeSidechain= not OrangeSidechain SemiRandomStr = not SemiRandomStr PrintOptions() end function AskOptions() -- fine tuning local ask = dialog.CreateDialog("Finetune options Voidcrusher "..Version) if not allatonce or #Speclist > 0 then ask.l1=dialog.AddLabel("Band strength during pull") ask.BandsAbsMin=dialog.AddSlider("Minimum",minBS,0.1,1,2) ask.BandsAbsMax=dialog.AddSlider("Maximum",maxBS,0.1,2,2) ask.SemiRandomStr=dialog.AddCheckbox("and semi-random",SemiRandomStr) end if not allatonce then ask.l2=dialog.AddLabel("Order of treatement") ask.random=dialog.AddCheckbox("Random",Vrandom) ask.worst=dialog.AddCheckbox("Worst first",Vworst) ask.l3=dialog.AddLabel("Pull harder if loss is less") ask.maxLoss=dialog.AddSlider("Percentage",maxLoss,0,2,1) ask.l4 = dialog.AddLabel("Run fuze if qstab is close to recent best") ask.doFuze = dialog.AddSlider("Neg, only after gain",doFuze,-10,20,1) else ask.l11=dialog.AddLabel("Band strength to pull with") ask.allBS = dialog.AddSlider("Band strength",allBS,0.1,1,2) ask.l21 = dialog.AddLabel("Multiplier to pull hydrophobics more") ask.hydro = dialog.AddSlider("Phobic factor: ",pullextrahydro,0.5,3,1) end ask.lx1= dialog.AddLabel("Maximum band length") ask.maxLength=dialog.AddSlider("maxLength",maxLength,15,100,1) ask.l5 = dialog.AddLabel("Clash importance while pulling") ask.CI = dialog.AddSlider("Clash importance",pullingCI,0.3,1,2) ask.OK = dialog.AddButton("OK",1) ask.Cancel = dialog.AddButton("Cancel",0) if dialog.Show(ask) > 0 then if not allatonce or #Speclist > 0 then minBS=ask.BandsAbsMin.value maxBS=ask.BandsAbsMax.value SemiRandomStr=ask.SemiRandomStr.value end if not allatonce then maxLoss=ask.maxLoss.value Vrandom=ask.random.value Vworst=ask.worst.value doFuze=ask.doFuze.value else allBS=ask.allBS.value pullextrahydro=ask.hydro.value end maxLength=ask.maxLength.value pullingCI=ask.CI.value end end function PrintOptions() print("Options: ") print("minimum segment distance: "..minDist) --minimum segment distance print("minimum spatial distance: "..minLength) --minimum spatial distance print("maximum spatial distance: "..maxLength) --maximum spatial distance if fastQstab then print("fastQstab") end --1s1w then true, double if false print("Band should be "..compFrac.." Amstr. shorter") --how much shorter band should be -- Defaults here VVV if Vworst then print("start from worst scoring one") end if Vrandom then print("go it in random order") end -- if both are false then it will band form 1st to last if not Vworst and not Vrandom then print("band form 1st to last") end if multi==0 then print("Multirun (overrides all other options)") end print("Nr of segments to be treated in 1 go: "..Combinum)-- Nr of segments to be treated in 1 go print("Fuze when distance to Best < "..doFuze) -- (negative - run if gain after qstab) print("Pulling CI= "..pullingCI) --clash importance during pull print("Min band strength= "..minBS) --absolute minimum band strength print("Maximum band strength ="..maxBS) --absolute maximum band strength if SemiRandomStr then print ("Semi-random strength") end print("pull till loss < max "..maxLoss.." %") --pull till perc loss (ie 1 on 10`000 ptsy = pull till 100 pt loss after pull) -- New options if allatonce then print("all at once") end--false -- set to true if all at once print("multiplier for extra pull on hydro segments: "..pullextrahydro) if OrangeInside then print ("Hide hydrophobic chains") end if OrangeSidechain then print ("Band end of sidechains") end end loop=0 function MAIN() -- called by askMode() just above --thus dialog with user is already done just before StartScore=Score() save.Quicksave(3) print("Starting Void Crusher "..Version.." by BK, Tvdl and rav3n_pl") print("Start score: "..round3(StartScore)) PrintOptions() ssstr=(round(Score())) for step=1, 10000 do loop= loop+1 local sls= Score() local les=sls print("##########################") print("MAIN LOOP "..loop.."/10000") genScore=les gen= step print("") print("Generation: "..gen..", score: "..round(Score())..", gain: "..round(Score()-StartScore).." ("..(os.date())..")") if multi > 0 then allatonce=false for i=1,multi do for j=1,6 do Combinum=j KillVoids() end end else KillVoids() end if mutateOnce then structure.MutateSidechainsSelected(1) end les=Score() print("Loop "..loop.." gained "..round3(les-sls)) genEndScore=Score() genGain=genEndScore-genScore if gen>1 and (gen-1)==5*down((gen-1)/5) then -- New 18/1/2016 jeff101 log display ssstr=(ssstr..'\n ') -- start new line every 5 generations end if genGain>=0 then ssstr=(ssstr..' + '..round(genGain)) else ssstr=(ssstr..' - '..(-round(genGain))) end print(ssstr..' = '..round(genEndScore)) print("Total VC gain= "..round3(les-StartScore).." from "..round3(StartScore).." to "..round3(Score())) ChangeOptions() end end --- OPTIONS THERE! vvv useRegion={} useRegionBool={} minDist=15 --minimum segment distance minLength=10 --minimum spatial distance maxLength=50 --maximum spatial distance fastQstab = true --1s1w then true, double if false compFrac=3 --how much shorter band should be (in Amstroms) -- Defaults here VVV Vworst=false --start form worst scoring one Vrandom=true --true --go it in random order -- if both are false then it will band form 1st to last multi=0 -- Multirun overrides all other options Combinum=1 -- Nr of segments to be treated in 1 go doFuze=5 --run fuzes when close to saved best (negative - run if gain after qstab) pullingCI=0.90 --clash importance during pull Speclist={} minBS=0.12 --absolute minimum band strength maxBS=1 --absolute maximum band strength maxLoss=1 --pull till perc loss (ie 1 on 10`000 ptsy = pull till 100 pt loss after pull) -- New options allatonce=false --false -- set to true if all at once pullextrahydro=1.3 --multiplier strength extra pull on hydrophobic segments allBS=0.12 -- strength if all lastAllBS=0 lastBS=minBS SemiRandomStr= false OrangeInside= true -- band to hydrophobic sidechains to pull (could help to turn) OrangeSidechain=false targetList={} -- list of segments and endpoints, to be built later --END OF OPTIONS ^^^ function Cleanup(err) print("Resetting CI and best score, removing extra bands") save.Quickload(3) CI(1) if bandGetCount() >0 then bandDeleteAll() end SetNote(note_number, starting_score, recipename, loop_count) print(err) end xpcall(askMode,Cleanup)

Comments


Bruno Kestemont Lv 1

Band to symmetric even without user band (it extremely slow at start, but then it's ok)

4.2.1: calculating distances is quicker now

4.2.2: mutate, wiggle no filter (Note: band to symmetric still bugs)