Icon representing a recipe

Recipe: Tvdl VoidCrushers 4.1.5

created by Bruno Kestemont

Profile


Name
Tvdl VoidCrushers 4.1.5
ID
101510
Shared with
Public
Parent
Tvdl VoidCrushers 3.1.2
Children
Created on
April 18, 2019 at 21:43 PM UTC
Updated on
April 18, 2019 at 21:43 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 ]]-- Version="4.1.5" 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 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 ') CIfactor=1 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 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 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 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 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 #distancesb<1 or distScore ~= Score() then distScore=Score() distancesb[1]=0 print("Calculating distances to end bands...") for i=1,segCnt do --filling table if DIST2USERBANDS then -- New 15/12/2015 for j=1,ExistingBands do distancesb[i*segCnt+j]=dist2band(i,j) end 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 targetList={} -- reset list of segments and endpoints for first = 1,segCnt do targetList[#targetList + 1] = {"s",i} end if DIST2USERBANDS then -- New 15/12/2015 for i = 1,ExistingBands do targetList[#targetList + 1] = {"b",i} end end end function mkBand(a) --make band if found void in area of that segment print("Banding segment "..a) getDist() -- distances between all segments getDist2Band() -- distances between all end band and all segs local t={}--there we store possible segments local ts={}--there we store possible voids between symmetrics local first=1 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 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 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 print("Found "..tt.." possible bands across voids") else print("No voids found") end if voids then --print("Found "..#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) 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("Found "..#ts.." possible bands across voids (seg to end band)") 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 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={} getDist() --calculate distances now getDist2Band() -- calculate distances of all segs with ends of all existing bands 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 DIST2USERBANDS then ask.DIST2USERBANDS=dialog.AddCheckbox("Band to end of user bands",DIST2USERBANDS) end 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 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 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 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

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
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)

heyubob Lv 1

I don't understand how you made this recipe, and I would not understand if you told me. However, it is AWESOME. 5 stars to you. BTW:I gave you a five and page reports a 4!

malphis Lv 1

Hi Bruno, thanks for all the helpful scripts!

I noticed that parts of this script run much more quickly when objectives are disabled. Is it possible that toggling objectives at key points in the script might improve the overall speed without losing effectiveness? If so, it would really help on larger proteins with objectives.

malphis Lv 1

Oh, sorry. I forgot to ask whether or not adding mutate at potentially helpful spots would be possible too as an option.