Code
--[[
]]--
version = "2.5"
--service functions
function ScoreReturn()
x = current.GetEnergyScore()
return x-x%0.1
end
function roundX(x)--cut all afer 3-rd place
return x-x%0.1
end
function ScoreBBReturn()
x = 0
for i=1, proteinLength do
x = x + current.GetSegmentEnergySubscore(i, "Clashing")
--x = x + current.GetSegmentEnergySubscore(i, "Backbone") + current.GetSegmentEnergySubscore(i, "Bonding") + current.GetSegmentEnergySubscore(i, "Ideality") + current.GetSegmentEnergySubscore(i, "Pairwise") + current.GetSegmentEnergySubscore(i, "Packing") + current.GetSegmentEnergySubscore(i, "Hiding")
-- no:
-- print (i, "subscore:",x)
end
x = current.GetEnergyScore() - x
return x-x%1
end
--Dialog
function RequestOptions()
ask=dialog.CreateDialog("Options: Rebuild/Remix selected v"..version)
ask.maxRebuildCount = dialog.AddSlider("Solutions to search",15,1,36,0) --up to 98 slots possible (change 36 to 98 if needed)
ask.slotsToFuze = dialog.AddSlider("Slots to fuze",slotsToFuze,1,maxRebuildCount,0)
ask.remixNotRebuild=dialog.AddCheckbox("Remix instead of Rebuild", remixNotRebuild)
--ask.remixNotRebuild.value=false
ask.convertLoop=dialog.AddCheckbox("Convert to Loop", convertLoop)
--selections
--ask.s1 = dialog.AddLabel("Selections")
ask.selectionStart1 = dialog.AddSlider("Start segment",selectionStartArr[1],0,proteinLength,0)
ask.selectionEnd1 = dialog.AddSlider("End segment",selectionEndArr[1],1,proteinLength,0)
if selDialog>1 then
if selNum < 2 then
selectionStartArr[2]=7
selectionEndArr[2]=10
end
ask.s2 = dialog.AddLabel("Selection2")
ask.selectionStart2 = dialog.AddSlider("Selection2 Start",selectionStartArr[2],1,proteinLength,0)
ask.selectionEnd2 = dialog.AddSlider("Selection2 End",selectionEndArr[2],1,proteinLength,0)
end
if selDialog>2 then
if selNum < 3 then
selectionStartArr[3]=12
selectionEndArr[3]=15
end
ask.s3 = dialog.AddLabel("Selection3")
ask.selectionStart3 = dialog.AddSlider("Selection3 Start",selectionStartArr[3],1,proteinLength,0)
ask.selectionEnd3 = dialog.AddSlider("Selection3 End",selectionEndArr[3],1,proteinLength,0)
end
if selDialog>3 then
if selNum < 4 then
selectionStartArr[4]=12
selectionEndArr[4]=15
end
ask.s4 = dialog.AddLabel("Selection4")
ask.selectionStart4 = dialog.AddSlider("Selection4 Start",selectionStartArr[4],1,proteinLength,0)
ask.selectionEnd4 = dialog.AddSlider("Selection4 End",selectionEndArr[4],1,proteinLength,0)
end
if selDialog>4 then
if selNum < 5 then
selectionStartArr[5]=12
selectionEndArr[5]=15
end
ask.s5 = dialog.AddLabel("Selection5")
ask.selectionStart5 = dialog.AddSlider("Selection5 Start",selectionStartArr[5],1,proteinLength,0)
ask.selectionEnd5 = dialog.AddSlider("Selection5 End",selectionEndArr[5],1,proteinLength,0)
end
if selDialog>5 then
ask.s6 = dialog.AddLabel("(not showing more than 5 selections, but Rebuilding)")
end
--fuze options
ask.l1 = dialog.AddLabel("Fuze:")
ask.shakeOnRank=dialog.AddCheckbox("Shake each solution on Rebuild (longer)", shakeOnRank)
ask.forceChange=dialog.AddCheckbox("Force Changes (loss)", forceChange)
ask.turboMode=dialog.AddCheckbox("Turbo Mode (no Fuze, so very fast)", turboMode)
--ask.fastFuze2=dialog.AddCheckbox("Fuze longer", fastFuze2)
--ask.fastFuze2.value=false
--ask.l2 = dialog.AddLabel("How much to report")
ask.reportLevel = dialog.AddSlider("Report detalization", reportLevel,1,4,0)
ask.fullProtein=dialog.AddCheckbox("Full protein Rebuild (selections ignored)", fullProtein)
ask.infiniteExecution=dialog.AddCheckbox("Infinite Execution", infiniteExecution)
ask.OK = dialog.AddButton("OK",1)
ask.addSelections = dialog.AddButton("AddSelection",2)
ask.selectLoops = dialog.AddButton("SelLoops",3)
ask.Cancel = dialog.AddButton("Cancel",0)
returnVal=dialog.Show(ask)
if returnVal > 0 then
if returnVal==1 then maxRebuildCount=ask.maxRebuildCount.value end
remixNotRebuild=ask.remixNotRebuild.value
infiniteExecution=ask.infiniteExecution.value
turboMode=ask.turboMode.value
fullProtein=ask.fullProtein.value
slotsToFuze=ask.slotsToFuze.value
selectionStartArr[1]=ask.selectionStart1.value
selectionEndArr[1]=ask.selectionEnd1.value
if (selectionStartArr[1]==0) and not (fullProtein) then selectionStartArr[1]=1 end
if selDialog>1 then
selectionStartArr[2]=ask.selectionStart2.value
selectionEndArr[2]=ask.selectionEnd2.value
end
if selDialog>2 then
selectionStartArr[3]=ask.selectionStart3.value
selectionEndArr[3]=ask.selectionEnd3.value
end
if selDialog>3 then
selectionStartArr[4]=ask.selectionStart4.value
selectionEndArr[4]=ask.selectionEnd4.value
end
if selDialog>4 then
selectionStartArr[5]=ask.selectionStart5.value
selectionEndArr[5]=ask.selectionEnd5.value
end
--selNum=selDialog
forceChange=ask.forceChange.value
shakeOnRank=ask.shakeOnRank.value
reportLevel=ask.reportLevel.value
if turboMode then --force very simple fuze settings in Turbo Mode
shakeOnRank=false
slotsToFuze=1
if (reportLevel>2) then print ("(fuze settings are ignored in Turbo Mode)") end
end
if remixNotRebuild then action="Remix" end
--if Full Protein Rebuild/Remix is pressed then rebuilding the whole protein: markup selections and run as OK button was pressed
if fullProtein then
if (remixNotRebuild) and (selectionEndArr[1]>9) then
selectionEndArr[1]=9
if reportLevel>1 then print ("Max selection length for Remix is 9 segs") end
end --cut selection length to max (9 residues) when Remix is choosen
selectionLength=selectionEndArr[1]
overlap=selectionStartArr[1]
if overlap>=selectionLength then overlap=selectionLength-1 end
if reportLevel>1 then
print ("Full Protein "..action..". Length and overlap from selection 1")
print (action.." Length "..selectionLength..", Overlap "..overlap)
end
SelectProteinOverlap()
end
if slotsToFuze==1 then shakeOnRank=false end
else
print ("Canceled")
end
return returnVal
end
--script content functions
--selection
function FindSelection()
selNum=0
for k=1, proteinLength do
if selection.IsSelected(k) then
--find for selection start
if k==1 then
selNum=selNum+1
selectionStartArr[selNum]=k
else
if not selection.IsSelected(k-1) then
selNum=selNum+1
selectionStartArr[selNum]=k
end
end
--find the selection end
if k==proteinLength then
selectionEndArr[selNum]=k
else
if not selection.IsSelected(k+1) then selectionEndArr[selNum]=k end
end
end
end
--if no selection, select residues 3-6
if selNum==0 then
--print ("aaa")
selectionStartArr[1]=math.min(5,proteinLength)
selectionEndArr[1]=math.min(13,proteinLength)
end
end
function SetSelection()
selection.DeselectAll()
for k=1, proteinLength do
if (k>=selectionStart) and (k<=selectionEnd) then
selection.Select (k)
end
end
end
function SelectLoops()
selection.DeselectAll()
looplength=0
--select all loops with length >= 3
for k=1, proteinLength do
--print (structure.GetSecondaryStructure(k))
if structure.GetSecondaryStructure(k) == 'L' then
looplength=looplength+1
selection.Select (k)
else
if (looplength>0) and (looplength<3) then --deselect if loop is too short
for j=1, looplength do
selection.Deselect (k-j)
end
end
looplength=0
end
if (k==proteinLength) and (looplength==1) then selection.Deselect (k) end
end
end
--markup selection of the full protein with some overlap
function SelectProteinOverlap ()
k=0 -- used here as selection number
activeAA=startingAA --startingAA is set in main when running this function
if (overlap>=selectionLength) or (overlap<0) then overlap=selectionLength-1 end
if (startingAA+selectionLength-1 <= 1) then startingAA=1 end -- reset selection markup position counter (startingAA) to 1st protein residue if it is too low
--make first selections
while (activeAA<1) do
if (activeAA+selectionLength-1>=3) then --if next selection length is >=3
k=k+1
selectionStartArr[k]=1
selectionEndArr[k]=activeAA+selectionLength-1
end
activeAA=activeAA+selectionLength-overlap
end
--make further selections
while activeAA+selectionLength-1 < proteinLength do
k=k+1
selectionStartArr[k]=activeAA
selectionEndArr[k]=activeAA+selectionLength-1
activeAA=selectionEndArr[k]-overlap+1
end
--make last selections
while (proteinLength-activeAA+1>=3) do --if next selection length is >=3
k=k+1
selectionStartArr[k]=activeAA
selectionEndArr[k]=proteinLength
activeAA=activeAA+selectionLength-overlap
end
selNum=k
end
function SetAllSelections()
selection.DeselectAll()
for j=1, selNum do
selectionStart=selectionStartArr[j]
selectionEnd=selectionEndArr[j]
if (selectionEnd-selectionStart < 0) then
temp = selectionStart
selectionStart = selectionEnd
selectionEnd = temp
end
if (reportLevel>3) then print ("Setting selection"..j.."/"..selNum..": ", selectionStart.."-"..selectionEnd) end
for k=1, proteinLength do
if (k>=selectionStart) and (k<=selectionEnd) then
selection.Select (k)
end
end
end
end
function SelectionSphere()
--dump selection to array
selectedSegs={}
for k=1, proteinLength do
if selection.IsSelected(k) then
selectedSegs[k]=1
else
selectedSegs[k]=0
end
end
for k=1, proteinLength do
for j=1, proteinLength do
dist_str = structure.GetDistance(k, j)
if (selectedSegs[j] == 1) and (dist_str < sphereRadius) then
selection.Select(k)
end
end
end
end
function printSelections()
strOutput2=""
print ("Found "..selNum.." selections")
for j=1, selNum do
if (selNum>5) then
strOutput2=strOutput2.." "..selectionStartArr[j].."-"..selectionEndArr[j]
if (math.fmod(j, 7)==6) then strOutput2=strOutput2.."\n" end
else
print (selectionStartArr[j].."-"..selectionEndArr[j])
end
end
if (selNum>5) then print(strOutput2) end
end
--Fuze
function TinyFuze()
SelectionSphere()
behavior.SetClashImportance(0.05)
structure.ShakeSidechainsSelected(1)
behavior.SetClashImportance(1)
SetSelection()
end
function FastFuze()
SelectionSphere()
behavior.SetClashImportance(CI)
structure.LocalWiggleSelected (2, 0, 1)
SetSelection()
structure.WiggleAll(5)
behavior.SetClashImportance(1)
structure.LocalWiggleAll(3, 0, 1) --wiggle sidechains
undo.SetUndo(true) --disable undo for everything except fuze
structure.WiggleAll(5)
undo.SetUndo(false)
end
function Fuze()
currentScore1=ScoreReturn()
CI=0.05
behavior.SetClashImportance(0.05)
structure.ShakeSidechainsAll (1)
structure.WiggleAll (2)
if reportLevel>3 then print ("CI = "..CI..". Score is "..ScoreReturn(), "Backbone score "..ScoreBBReturn()) end
CI=0.25
behavior.SetClashImportance(0.25)
structure.WiggleAll (2, 0, 1)
structure.WiggleAll (2)
if reportLevel>3 then print ("CI = "..CI..". Score is "..ScoreReturn(), "Backbone score "..ScoreBBReturn()) end
CI=1
behavior.SetClashImportance(1)
structure.ShakeSidechainsAll (1)
undo.SetUndo(true)
structure.WiggleAll (5, 1, 0)
if reportLevel>3 then print ("CI = "..CI..". Score is "..ScoreReturn(), "Backbone score "..ScoreBBReturn()) end
undo.SetUndo(false)
if ScoreReturn() > currentScore1 then
save.Quicksave(bestSlot)
currentScore1=ScoreReturn()
end
CI=0.07
if reportLevel>3 then print ("...last shake") end
behavior.SetClashImportance(0.07)
structure.ShakeSidechainsAll (1)
CI=1
behavior.SetClashImportance(1)
undo.SetUndo(true)
structure.WiggleAll (20)
if reportLevel>3 then print ("CI = "..CI..". Score is "..ScoreReturn(), "Backbone score "..ScoreBBReturn()) end
undo.SetUndo(false)
if ScoreReturn() > currentScore1 then
save.Quicksave(bestSlot)
else save.Quickload(bestSlot) end
end
--Rebuild/Remix
function SortByBackbone()
bestEnergySlot=0
--add few best energy score for solutions
table.sort(remixBBScores, function(a,b) return a.score > b.score end)
for i, remixBBScores in ipairs(remixBBScores) do
if i <= bestSelectNum then remixBBScores.rank=(bestSelectNum-i)/energy2BBScoreRatio end --add rank points to top energy solutions half to bb points by default
end
--add few best backbone score solutions
table.sort(remixBBScores, function(a,b) return a.scoreBB > b.scoreBB end)
for i, remixBBScores in ipairs(remixBBScores) do
if i <= bestSelectNum then remixBBScores.rank=remixBBScores.rank+bestSelectNum+1-i end --add rank points to best backbone solutions
end
--sort by rank
table.sort(remixBBScores, function(a,b) return a.rank > b.rank end)
for i, remixBBScores in ipairs(remixBBScores) do
if (i<=bestSelectNum) then
if reportLevel>3 then print("Backbone score", remixBBScores.scoreBB, "from slot", remixBBScores.id, "score: "..remixBBScores.score, "/"..remixBBScores.rank) end
end
end
end
function CheckRepeats()
currentScore=ScoreReturn()
isDuplicate=false
remixNum=#rebuildScores
for k=1, remixNum do
if rebuildScores[k] == currentScore then isDuplicate=true end
end
if not isDuplicate then
solutionsFound = solutionsFound+1
rebuildScores[solutionsFound] = currentScore
save.Quicksave(solutionsFound)
if shakeOnRank then TinyFuze() end --makes a small shake before ranking energy score of rebuild (if checkbox was selected).
currentScore=ScoreReturn()
remixBBScores[solutionsFound-1] = {id = solutionsFound, scoreBB=ScoreBBReturn(), score=currentScore, rank=0}
if reportLevel>2 then print ( "Slot", solutionsFound, "backbone", ScoreBBReturn(), "score", currentScore) end
--if reportLevel==2 then io.write(".") end
else
if reportLevel>2 then print (currentScore, "is duplicated to already found.") end
end
return isDuplicate
end
function RebuildToSlots()
j=0
rebuildIter=1
while (j<maxRebuildCount) and (rebuildIter<7) do
j=j+1
structure.RebuildSelected(rebuildIter)
if CheckRepeats() then
j=j-1
rebuildIter = rebuildIter+1
else
rebuildIter=1
save.Quicksave(j+1)
end
--print (k, remixNum, currentScore)
save.Quickload(100)
end
--if reportLevel==2 then io.write("\n") end
--print (maxRebuildCount, rebuildIter, j)
end
function remixBBscoreList()
for i=1, remixNum do
save.Quickload(i+1)
if shakeOnRank then --makes a small shake before ranking energy score of rebuild (if checkbox was selected).
TinyFuze()
save.Quicksave(i+1)
end
currentScore=ScoreReturn()
if reportLevel>2 then print ( "Slot", i+1, "score", currentScore, "backbone", ScoreBBReturn()) end
--if reportLevel==2 then io.write(".") end
remixBBScores[i] = {id = i, scoreBB=ScoreBBReturn(), score=currentScore, rank=0}
end
--if reportLevel==2 then io.write("\n") end
end
function RebuildRemixSelected()
if remixNotRebuild then
remixNum = structure.RemixSelected(2, maxRebuildCount)
if (remixNum>0) then remixBBscoreList() end
else
RebuildToSlots()
remixNum=#rebuildScores-1
end
end
function Cleanup()
currentScore=ScoreReturn()
undo.SetUndo(true)
if (currentScore > startScore) then save.Quicksave(100)
else save.Quickload(100) end
currentScore=ScoreReturn()
if (currentScore > initScore) then
print ("Total gain:", roundX(currentScore-initScore))
else
save.Quickload(1)
print("No improve. Restored to "..ScoreReturn())
end
if not infiniteExecution then SetAllSelections() end
if convertLoop then save.LoadSecondaryStructure() end
end
-----------------------------------------------------------------------------------------------init
maxRebuildCount=36
sphereRadius=8
reportLevel=2
slotsToFuze=4
shakeOnRank=true
turboMode=false
fullProtein=false
CI=0.1
energy2BBScoreRatio=2
selectionLength=10
overlap=5
startingAA=1
bestScore=-999999
rebuildScores = {}
remixBBScores = {}, {}
rebuildScores[1]=bestScore
rebuildRetryNo=0
bestSelectNum=0
solutionsFound = 1
remixNum = #rebuildScores
undo.SetUndo(false)
remixNotRebuild = false
infiniteExecution = false
selectionPresent=false
convertLoop=true
forceChange=false
bestSlot=0
bestEnergySlot=0
selectionEnd=0
selectionStart=0
selNum=0
selDialog=selNum
selectionStartArr={}
selectionEndArr={}
structureSS={}
action="Rebuild"
proteinLength=structure.GetCount ()
startScore=ScoreReturn()
initScore=ScoreReturn() --the real start score that doesn't changes
print ("+++Starting score "..startScore.." saved to slot 1")
save.Quicksave(1)
recentbest.Save()
-----------------------------------------------------------------------------------------------main
function main()
FindSelection()
tempSelNum=selNum
if selNum==0 then selNum=1 end
selDialog=selNum
--Request options from user
while requestResult~=1 do
requestResult = RequestOptions()
if requestResult == 0 then return end -- cancel button pressed by user
if requestResult == 2 then selDialog=selDialog+1 end
if requestResult == 3 then
SelectLoops()
FindSelection()
--print (selNum,selDialog)
selDialog=selNum
end
if selDialog>5 then selDialog=5 end
end
selNum=math.max(tempSelNum, selDialog, selNum)
SetAllSelections()
if convertLoop then
save.SaveSecondaryStructure()
structure.SetSecondaryStructureSelected("L")
end
save.Quicksave(100)
--Report settings in output window
strOutput=action..": "..maxRebuildCount.." /"..slotsToFuze
if turboMode then strOutput=strOutput.." TURBO" end
if fullProtein then strOutput=strOutput..", full protein" end
if forceChange then strOutput=strOutput..", force changes" end
if infiniteExecution then strOutput=strOutput..", infinite" end
if shakeOnRank then strOutput=strOutput..", shake" end
if reportLevel>2 then strOutput=strOutput..". ReportLevel="..reportLevel end
if (reportLevel>1) then print (strOutput) end
if (reportLevel>1) and (selNum>0) then
printSelections()
end
loopIter=1
while loopIter>0 do --for Infinite execution option
startScore2=ScoreReturn() --used in Turbo Mode only
loopIter=loopIter + 1
if not infiniteExecution then loopIter=0 end --break while if not infinite execution
print ("-------------------------------------------------")
if (infiniteExecution) and (reportLevel>1) then print("Iteration", (loopIter-1)..".") end
if fullProtein and (loopIter>2) then
startingAA=startingAA-1
if reportLevel>1 then
--print ("Overlap changed to "..overlap)
end
SelectProteinOverlap()
end
for m=1, selNum do
bestScore=-999999
bestSlot=0
selectionStart=selectionStartArr[m]
selectionEnd=selectionEndArr[m]
startScore=ScoreReturn()
solutionsFound = 1
print(m.."/"..selNum..": "..action.."ing segs: "..selectionStart.."-"..selectionEnd..". Score "..ScoreReturn().." bb "..ScoreBBReturn())
--switch selectionStart and selectionEnd
SetSelection()
if (selectionEnd-selectionStart > 8) and (remixNotRebuild) then
print("Selections larger 9 segments not allowed for Remix")
remixNum=0
else
RebuildRemixSelected()
end
bestSelectNum = slotsToFuze
if bestSelectNum > remixNum then bestSelectNum=remixNum end
if reportLevel>1 then print(remixNum, "solutions found on "..action..". Ranking best "..bestSelectNum) end
--if there are some solutions then rebuild, else go to the next iteration on 'for' loop
if remixNum > 0 then
SortByBackbone()
--Fuze slots and score best
for i, remixBBScores in ipairs(remixBBScores) do
if i <=bestSelectNum then
save.Quickload(remixBBScores.id)
if turboMode then --save solution in Undo stack when in Turbo Mode
undo.SetUndo(true)
undo.SetUndo(false)
end
if bestSelectNum>1 then --fuze on scoring stage only when 'slotsToFuze' setting is >1
FastFuze()
end
save.Quicksave(remixBBScores.id)
currentScore=ScoreReturn()
improve = roundX(currentScore-startScore)
textBest=""
if (currentScore > bestScore) then
bestScore=currentScore
bestSlot=remixBBScores.id
textBest="*"
if (improve > 0) or (turboMode) then save.Quicksave(100) end --just accept and save best (and the only) rebuild solution when in Turbo Mode
end
if reportLevel>1 then print ("Stabilized slot", remixBBScores.id, " to bb "..ScoreBBReturn()," score", currentScore, textBest) end
end
end
end
--continue previous 'if' but with new condition: turboMode is here to enter this fuze section when 0 solutions found on last Remix in Turbo Mode.
if (remixNum > 0) or turboMode then
-- Finalize
save.Quickload(bestSlot)
if (not turboMode) or (m==selNum) then --Run full Fuze if not in Turbo Mode or after last selection rebuild in Turbo Mode
if reportLevel>2 then print("Fuzing best solution from slot", bestSlot) end
currentScore=ScoreReturn()
Fuze()
if currentScore < ScoreReturn() then --accept Fuze results if score is improved
save.Quicksave(bestSlot)
else
save.Quickload(bestSlot)
end
if turboMode then startScore=startScore2 end
currentScore=ScoreReturn()
improve = roundX(currentScore-startScore)
if (improve > 0) or (forceChange) then
if reportLevel>0 then print ("Gained ", improve.." points. New score: "..currentScore) end
if reportLevel>1 then print ("Total gain:", roundX(currentScore-initScore)) end
save.Quicksave(100)
if turboMode then save.Quicksave(1) end
else
currentScore=ScoreReturn()
save.Quickload(100)
if turboMode then
save.Quickload(1)
save.Quicksave(100)
end
if reportLevel>2 then print("No improve ("..currentScore.."). Restored to "..ScoreReturn()) end
end
if reportLevel>1 and (m==selNum) and (improve<=0) then --print 'Total gain' at the end of the round but prevent double print it when improve>0
currentScore=ScoreReturn()
if (currentScore-initScore)>0 then
print ("Change: ", improve.." points. Restored "..currentScore)
print ("Total gain:", roundX(currentScore-initScore))
end
end
end --if for full Fuze
end --if remixNum>0
print ("-------------------------------------------------")
end --for
end --while
Cleanup()
end -- function main()
xpcall ( main , Cleanup )