Profile


Name
iwdn worm 1.1
ID
104669
Shared with
Public
Parent
None
Children
Created on
April 28, 2021 at 12:27 PM UTC
Updated on
April 28, 2021 at 12:27 PM UTC
Description

Worm for wms

Best for


Code


--iwdn worm --version 1.1 28.04.2021 --Script to perform local wiggles/mutates/shakes along the protein. --What it does: --Performs local wiggle/mutate/shake along a protein. --If the user has selected residues before this recipe is run, then the worm will only run along these segments. Otherwise all non-locked segments will be treated. --The advantage of this worm-implementation is that it will not only act on the sidechains on the protein but also on adjacent sidechains for example on a target-binder. Set this via the "Radius" slider. --Also, point- and objective-loss is monitored and it is reverted to a previous state so that no point- and especially objective-loss is possible. --This recipe can sometimes gain many points in short times while keeping the structure intact. --Just play around with it and see what it can do for you. --Happy folding to all! --version history --1.0: --Initial version. Only for internal use. Imlementation of basic functionality. --1.1: --Brushed up for release. Changed a few settings. --28.04.2012 Bugfix: Removed unused code around the error-source "toWorkON". --Variables and Constants version = "1.1" dia = {} --Global GUI --************* Change if desired ******************* qs_idx = 33 --Index to start for quicksave slots --*********** End: Change if desired **************** function wait(seconds) local start = os.time() repeat until os.time() > start + seconds end function round(inNum) return inNum-inNum%0.001 end --Determine which sidechains shall be processed. The user needs to select them before running this recipe! toWorkOn = {} toWorkOnIdx = 1 function findToWorkOn() residues = structure.GetCount() for m=1,residues do if (selection.IsSelected(m) == true) then toWorkOn[toWorkOnIdx] = m toWorkOnIdx = toWorkOnIdx+1 end end --If user has not selected anything beforehand then choose all non-locked residues. if (toWorkOnIdx == 1) then for m=1,residues do if (structure.IsLocked(m) == false) then toWorkOn[toWorkOnIdx] = m toWorkOnIdx = toWorkOnIdx+1 end end end --If still toWorkOn is empty then this is an error. if (toWorkOnIdx == 1) then print("Error. No residues to work on could be found!") return end end function getScore() if (metrics_enable == 1) then tmpVal = metric.GetBonusTotal()+current.GetScore() return tmpVal else return current.GetScore() end end function mysplit(inputstr, sep) if sep == nil then sep = "%s" end local t={} for str in string.gmatch(inputstr, "([^"..sep.."]+)") do table.insert(t, str) end return t end function checkFilters() --Check the objectives and store for later reference. local currFilters = {} local filterNames = filter.GetNames() local filterBonus_tmp = nil if (filterNames[1] ~= nil) then for m=1,#filterNames do local filterName = filterNames[m] if (filter.HasBonus(filterName)) then --Store here filters that may not degrade in score. These will be protected with the save/restore-scheme. if (string.find(string.lower(filterName), "core") ~= nil and string.find(string.lower(filterName), "existence") ~= nil) then filterBonus_tmp = filter.GetBonus(filterName) currFilters[#currFilters+1] = {filterBonus_tmp, filterName} --print(round(currFilters[#currFilters][1]) .. " Pts: " .. currFilters[#currFilters][2]) elseif (string.find(string.lower(filterName), "ideal") ~= nil and string.find(string.lower(filterName), "loop") ~= nil) then filterBonus_tmp = filter.GetBonus(filterName) currFilters[#currFilters+1] = {filterBonus_tmp, filterName} --print(round(currFilters[#currFilters][1]) .. " Pts: " .. currFilters[#currFilters][2]) elseif (string.find(string.lower(filterName), "hydrogen") ~= nil and string.find(string.lower(filterName), "network") ~= nil) then filterBonus_tmp = filter.GetBonus(filterName) currFilters[#currFilters+1] = {filterBonus_tmp, filterName} --print(round(currFilters[#currFilters][1]) .. " Pts: " .. currFilters[#currFilters][2]) elseif (string.find(string.lower(filterName), "disulfide") ~= nil and string.find(string.lower(filterName), "count") ~= nil) then filterBonus_tmp = filter.GetBonus(filterName) currFilters[#currFilters+1] = {filterBonus_tmp, filterName} --print(round(currFilters[#currFilters][1]) .. " Pts: " .. currFilters[#currFilters][2]) elseif (string.find(string.lower(filterName), "buried") ~= nil and string.find(string.lower(filterName), "unsats") ~= nil) then if (dia.cbx04.value == true) then filterBonus_tmp = filter.GetBonus(filterName) currFilters[#currFilters+1] = {filterBonus_tmp, filterName} --print(round(currFilters[#currFilters][1]) .. " Pts: " .. currFilters[#currFilters][2]) end end end end --print(round(filter.GetBonusTotal()) .. " Pts: Total Filter Bonus") end return currFilters end function worm(w_toWorkOn, w_modus, w_startIdx, w_step, w_radius, w_iters, w_prot) --Instead of wiggling globally, this function wiggles locally multiple times at different positions. --Objectives are monitored so that none degrades. Especially core and loops. Uses qs33. --Changed this so that this function always only does 1 turn. If you want to run multiple turns then just call this function again. --w_prot=0: unprotected. 1: Objectives only are monitored. 2: Score is monitored. 3: Objectives and score are monitored. local w_startFilters = checkFilters() local w_currScore = getScore() local w_residues = structure.GetCount() --Store solution for later restore save.Quicksave(qs_idx) --Start the worm-loop --Go through the residues to process and wiggle in the vicinity. local w_currCenter = nil local w_currVici = {} for n=w_startIdx,#w_toWorkOn,w_step do w_currCenter = w_toWorkOn[n] w_currVici = {} --Determine which segments are in the vicinity of the center w_currVici[#w_currVici+1] = w_currCenter for o=1,w_residues do if (o ~= w_currCenter) then w_currDist = structure.GetDistance(w_currCenter, o) if (w_currDist < w_radius) then w_currVici[#w_currVici+1] = o end end end --End: Determine vicinity --Now apply the desired operation onto all segments in the vicinity. selection.DeselectAll() for o=1,#w_currVici do selection.Select(w_currVici[o]) --select residues in the vicinity end if (w_modus == 1) then --wiggle structure.LocalWiggleSelected(w_iters, true, true) --backbone, sidechains elseif (w_modus == 2) then --mutate structure.MutateSidechainsSelected(w_iters) else --shake structure.ShakeSidechainsSelected(w_iters) end selection.DeselectAll() --Restore previous solution if loops were damaged or core-bonus lost. local w_currFilters = checkFilters() local w_doRestore = 0 for o=1,#w_currFilters do if (w_currFilters[o][1] < w_startFilters[o][1]) then w_doRestore = 1 break elseif (w_currFilters[o][1] > w_startFilters[o][1]) then --Update the risen objective so that it will not be lost again in later turns. --startFilters[o][1] = currFilters[o][1] --This may lead to problems?! end --print(round(currFilters[o][1]) .. " Pts: " .. currFilters[o][2]) end if (w_prot == 0) then --unprotected. May decrease in score. save.Quicksave(qs_idx) w_currScore = getScore() elseif (w_prot == 1) then --Protected objectives. May decrease in score. if (w_doRestore == 1) then save.Quickload(qs_idx) else save.Quicksave(qs_idx) w_currScore = getScore() end elseif (w_prot == 2) then --Protected score if (getScore() <= w_currScore) then save.Quickload(qs_idx) else save.Quicksave(qs_idx) w_currScore = getScore() end else --Protected objectives AND score if (w_doRestore == 1) then save.Quickload(qs_idx) --Reload previous quicksave since we lost some bonus. else if (getScore() <= w_currScore) then save.Quickload(qs_idx) --If we did not increase in score then fall-back to previous solution. else save.Quicksave(qs_idx) --Overwrite previous highscore-solution with this one since we achieved an improvement. w_currScore = getScore() end end end end --End: Main worm-loop end --End: worm function main() print("Running iwdn worm version " .. version .. "...") findToWorkOn() --Is required in the GUI --Show GUI dia = dialog.CreateDialog("Iwdn worm " .. version) --dia.txb01 = dialog.AddTextbox("ToWorkOn", "0.4 0.3 0.2 0.15 0.1 0.09 0.08 0.07 0.06 0.05 0.04 0.03") dia.lbl01 = dialog.AddLabel("Settings for worm operations (just choose one of the next 3):") dia.cbx01 = dialog.AddCheckbox("Do Wiggle", true) dia.cbx02 = dialog.AddCheckbox("Do Mutate", false) dia.cbx03 = dialog.AddCheckbox("Do Shake", false) dia.sli01 = dialog.AddSlider("Iters", 6, 1, 100, 0) dia.sli02 = dialog.AddSlider("Radius", 8, 1, 20, 0) dia.sli05 = dialog.AddSlider("Step", 3, 1, 20, 0) dia.sli03 = dialog.AddSlider("Total turns", 1, 1, 30, 0) dia.cbx04 = dialog.AddCheckbox("Avoid BUNs", false) dia.but01 = dialog.AddButton("OK", 1) dia.but02 = dialog.AddButton("Cancel", 0) tmpBack = dialog.Show(dia) if (tmpBack ~= 0) then else print("Iwdn worm " .. version .. " has finished.") return end --Run the worm local w_stIdx = 1 for m=1,dia.sli03.value do --Total turns loop if (dia.cbx01.value == true) then --Wiggle print("Wiggle worm protected (" .. dia.sli01.value .. ") turn " .. m .. "/" .. dia.sli03.value .. "...") worm(toWorkOn, 1, w_stIdx, dia.sli05.value, dia.sli02.value, dia.sli01.value, 3) --Protect score and objectives. elseif (dia.cbx02.value == true) then --Mutate print("Mutate worm protected (" .. dia.sli01.value .. ") turn " .. m .. "/" .. dia.sli03.value .. "...") worm(toWorkOn, 2, w_stIdx, dia.sli05.value, dia.sli02.value, dia.sli01.value, 3) --Protect score and objectives. elseif (dia.cbx03.value == true) then --Shake print("Shake worm protected (" .. dia.sli01.value .. ") turn " .. m .. "/" .. dia.sli03.value .. "...") worm(toWorkOn, 3, w_stIdx, dia.sli05.value, dia.sli02.value, dia.sli01.value, 3) --Protect score and objectives. end w_stIdx = w_stIdx+1 --Wrap the start-index if (w_stIdx >= dia.sli05.value) then w_stIdx = 1 end end print("Iwdn worm " .. version .. " has finished.") end --main --xpcall(main, cleanup) main()

Comments


ichwilldiesennamen Lv 1

-Performs (protected) local wiggle/mutate/shake along the protein.
-Avoids loss in score and objective-bonus.
-All sidechains (also on a binder-target) are acted upon along the protein. Change the width of the action-area by changing the "Radius" option to higher values.
-This tool has served me well and maybe it can be helpful to you too. Just play around with it and see what it can do.

Happy folding to all, iwdn

phi16 Lv 1

Love the idea. The second time I run the script I get error message: 282: attempt to index global 'toWorkON' (a nil value). Don't know what it means. Working on Puzzle 1980. Script worked earlier on same track. phi16

ichwilldiesennamen Lv 1

Hello phi16,

thanks for the positive feedback and for pointing me to this problem!

You are right that this is a bug. This bug actually is a typo but it's origin is situated anyway in a segment of code that is not used. Nevertheless it outputs this error. Forgot to clean it out before release.

I updated the 1.1 release (date 28.04.2021 in the header of the recipe) and this error should be fixed now.

Also look out for the upcoming 1.2 release of this recipe. It will let you choose the objectives you want to protect via GUI and will be overall a bit more sophisticated.

Happy folding, iwdn