Icon representing a recipe

Recipe: nbl_hinge v1.5

created by LociOiling

Profile


Name
nbl_hinge v1.5
ID
100081
Shared with
Public
Parent
nbl_hinge_v1.2
Children
Created on
October 13, 2014 at 23:50 PM UTC
Updated on
October 13, 2014 at 23:50 PM UTC
Description

Freezes the surrounds of a segment, then proceeds to wiggles with bands. Version 1.5 adds standard score reporting and cleanup.

Best for


Code


--[[ NBL_hinge Author: Nicobul2 - april 2014 Contributors: Ch Garnier, Yoyo, Bruno Kestemont Original recipe: Glycine hinge by Tlaloc (LUA v1) Converted from v1 lua by Rav3n_pl v1 to v2 converter Copyright (C) 2011 tlaloc <http://fold.it/portal/user/57765> Copyright (C) 2011 rav3n_pl <http://fold.it/portal/user/174969> Copyright (C) 2011 Seagat2011 <http://fold.it/port/user/1992490> Copyright (C) 2011 thom001 <http://fold.it/port/user/172510> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. version 1.5 2014/10/11 LociOiling * add model reporting (ChunquePoint package) * reworked score reporting: report gain or >5 minutes with no gain * restructured to use cleanup routine * process multiple ranges * elminate some dead code * remove "local" from items that appear to have global scope anyway * added "local" to items that appear to have local scope * added "loops only" option * numerous small random acts of vandalism ]]-- -- -- globals section -- -- -- model 001 -- standard recipe name and version -- Recipe = "NBL_hinge" Version = "1.5" ReVersion = Recipe .. " v." .. Version segCnt = structure.GetCount() flagligand = false segCnt2 = segCnt -- cas de ligands while structure.GetSecondaryStructure ( segCnt2 ) == "M" do segCnt2 = segCnt2-1 flagligand = true end -- -- dialog options and related variables -- hinge_width = 1 nbrun = 1 random = false loop_only = false range_min = 3 -- minimum segment number to process range_max = segCnt2 - 3 -- maximum segment number to process ranges = {} -- ranges to process -- -- end of dialog options and related varibles -- ici = 1.0 -- initial clashing importance ibs = 1.0 -- initial band strength startChunque = nil -- initial chunquePoint -- -- end of globals section -- _options = { -- -- User Options Begin -- wiggle_count = 1, -- #iters (flex) wiggle_out_count = 30, -- #iters (unflex) band_strength = 0.25, -- band strength allow_float_wiggle_count = false, -- allows "floating" via random number generation of wiggle_count wiggle_count_upper = wiggle_count, -- max possible #iters. iff allow_float_wiggle_count, -- then this value must be defined. (disabled by default) wiggle_count_lower = wiggle_count, -- min possible #iters. iff allow_float_wiggle_count, -- then this value must be defined. (disabled by default) wiggle_count_bounds = wiggle_count, -- allowed variance for #iters. iff allow_float_wiggle_count, -- then this value must be defined. (disabled by default) global_wiggle = true, -- perform wa. iff false, then perform lws (local_wiggle) freeze_backbone = true, -- freeze bb freeze_sidechains = false, -- freeze sc (disabled by default) ci = 0.30, -- clashing importance allow_ci_float = false, -- allows "floating" via random number generation of ci. -- Iff true, ci_upper and ci_lower must be defined. (disabled by default) ci_upper = ci, -- U_ci_value. iff allow_ci_float == true, -- then this value must be defined. (disabled by default) ci_lower = ci, -- L_ci_value. iff allow_ci_float == true, -- then this value must be defined. (disabled by default) ci_bounds = ci, -- allowed variance for ci. ff allow_ci_float == true, -- then this value must be defined. (disabled by default) qs_recent_best = 3, -- iff exploratory == true, then recent best is saved into this saveslot freeze_hinge_instead = false, -- allows for the hinge to be frozen instead of the rods. (disabled by default) -- -- User Options End -- score = 0, ranked_score = 0, multiplier = 0, } flag = {selected = false, mutate = false} uo = {mutateAlways = false} -- -- begin chunquePoint Beta package version 0.2 -- CSVoutput = false function beginChunque ( startChunque, prefix, scoreFunc, pose ) local chunque = chunquePoint ( prefix, scoreFunc, pose ) if startChunque == nil then chunquePrint ( chunque ) else local gain = chunque [ 2 ] - startChunque [ 2 ] chunquePrint ( chunque, gain ) end return chunque end function endChunque ( startChunque, prefix, scoreFunc, pose ) local chunque = chunquePoint ( prefix, scoreFunc, pose ) chunqueGain ( startChunque, chunque ) end function chunquePoint ( prefix, scoreFunc, pose ) if prefix == nil then prefix = "" end if scoreFunc == nil then scoreFunc = current.GetEnergyScore end local score = 0 if pose == nil then score = scoreFunc () else score = scoreFunc ( pose ) end local runDate, runClock, runTime runDate = os.date () runClock = os.clock() runTime = os.time() return { prefix, score, runDate, runClock, runTime } end function chunquePrint ( chunque, gain ) local function round ( ii ) return ii - ii % 0.001 end if gain == nil then if CSVOutput then print ( chunque [ 1 ] .. "," .. round ( chunque [ 2 ] ) .. "," .. chunque [ 3 ] ) else print ( chunque [ 1 ] .. ", score: " .. round ( chunque [ 2 ] ) .. ", " .. chunque [ 3 ] ) end else if CSVOutput then print ( chunque [ 1 ] .. "," .. round ( chunque [ 2 ] ) .. "," .. round ( gain ) .. "," .. chunque [ 3 ] ) else print ( chunque [ 1 ] .. ", score: " .. round ( chunque [ 2 ] ) .. ", total gain: " .. round ( gain ) .. ", " .. chunque [ 3 ] ) end end end function chunqueGain ( startChunk, endChunk ) local function round ( ii ) return ii - ii % 0.001 end local Clocktime = os.difftime ( endChunk [ 5 ], startChunk [ 5 ] ) local gain = round ( endChunk [ 2 ] - startChunk [ 2 ] ) local hours = Clocktime / ( 60 * 60 ) local pph = gain / hours if CSVOutput then print ( endChunk [ 1 ] .. "," .. round ( endChunk [ 2 ] ) .. "," .. round ( gain ) .. "," .. round ( hours ) .. "," .. round ( pph ) .. "," .. endChunk [ 3 ] ) else print ( endChunk [ 1 ] .. ", score: " .. round ( endChunk [ 2 ] ) .. ", gain: " .. round ( gain ) .. ", " .. endChunk [ 3 ] ) print ( endChunk [ 1 ] .. ", hours: " .. round ( hours ) .. ", points per hour: " .. round ( pph ) ) end end -- -- end chunquePoint Beta package version 0.2 -- function SegmentListToSet(list) -- retirer doublons 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) -- faire une liste a partir d'une zone 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) -- verifier si segment est dans la liste 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) --verifie si segment est dans la zone 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) -- fusionner 2 listes de segments 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) --fusionner (ajouter) 2 zones return SegmentListToSet(SegmentJoinList(SegmentSetToList(set1),SegmentSetToList(set2))) end function SegmentCommList(list1,list2) -- chercher intersection de 2 listes 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) -- intersection de 2 zones 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 SegmentPrintListToSet(list) -- NEW BK 14/04/2014 prints a list in a set format SegmentPrintSet(SegmentListToSet(list)) end function SegmentSetToString(set) -- pour pouvoir imprimer 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)--verifier si zone est dans suite 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) -- vrai ou faux pour chaque segment utilisable ou non local result={} for i=1,structure.GetCount() do result[i]=SegmentInSet(set,i) end return result end --- End of Segment Set module function InitWORKONbool() WORKONbool=SegmentSetToBool(WORKON) end function ShuffleTable(tab) --randomize order of elements local cnt=#tab for i=1,cnt do local r=math.random(cnt) tab[i],tab[r]=tab[r],tab[i] end return tab end function get_value ( m, l, u ) --> mean, lower, upper local upper local lower upper = m+u lower = m-l return math._random (lower,upper) end function get_value2 ( m, b ) --> mean, bounds (symmetrical) local upper local lower upper = m+b lower = m-b return math._random (lower,upper) end _prot = { -- READ ONLY L_idx = 1, -- end of left-hand side rod L_idx2 = 1, -- beginning of left-hand side rod R_idx = 1, -- beginning of right-hand side rod R_idx2 = 1, -- end of right-hand side rod n = 1, -- local index (SS temp) k = 1, -- segment_count next_group = 0, -- local index rebuild_forward = true, -- direction indicator. true = right-side; false = left-side bands_enabled = true, } function get_ss_group(r) local tmp while ( 1 ) do if r.rebuild_forward == true then tmp = structure.GetSecondaryStructure(r.R_idx2) else tmp = structure.GetSecondaryStructure(r.L_idx) end if tmp == r.n then if r.rebuild_forward == true then if r.R_idx2 < r.k then r.R_idx2 = r.R_idx2 + 1 else r.R_idx2 = r.k break end else if r.L_idx > 1 then r.L_idx = r.L_idx - 1 else r.L_idx = 1 break end end else if r.rebuild_forward == true then r.next_group = r.R_idx2 r.R_idx2 = r.R_idx2 - 1 else r.next_group = r.L_idx r.L_idx = r.L_idx + 1 end break end end -- while ( 1 ) return r end function build_hinge(prot,options,i,hw) local glycine_idx prot.k = structure.GetCount() glycine_idx = i -- (internally) focus on the right side.. prot.R_idx2 = glycine_idx + 1 + hw prot.R_idx = glycine_idx + hw prot.rebuild_forward = true prot.n = structure.GetSecondaryStructure(glycine_idx + 1 ) prot = get_ss_group(prot ) -- (internally) focus on the left side.. prot.L_idx = glycine_idx - 2 prot.L_idx2 = glycine_idx - 1 prot.rebuild_forward = false prot.n = structure.GetSecondaryStructure(glycine_idx - 1 ) prot = get_ss_group(prot ) return prot end function save_recent_best(options ) -- if ( options.exploratory == true ) then -- save.Quicksave(options.qs_recent_best ) -- else recentbest.Save() -- end end function recall_recent_best(options ) -- if ( options.exploratory == true ) then -- save.Quickload(options.qs_recent_best ) -- else recentbest.Restore() -- end end function ncWiggle ( zone, iters, iter ) how = "wa" -- -- mode forced to "wa", so shake code in ncWiggle appears to be unused -- iters = iters or 1 iter = iter or 1 local step = .001 local ws = 0 --if flag.selected then ws = ws+1 end if uo.mutateAlways or flag.mutate then ws = ws + 10 end local function wShake() if ws==0 then structure.ShakeSidechainsAll(1) --elseif ws==1 then structure.ShakeSidechainsSelected(1) elseif ws==10 then structure.MutateSidechainsAll(1) --elseif ws==11 then structure.MutateSidechainsSelected(1) end end local function wWiggle() local b, s = true, true if how == 'wb' then s = false end --if ws==1 then --structure.WiggleSelected(iters, b, s) --else if zone == 'a' then structure.WiggleAll ( iters, b, s ) else structure.LocalWiggleAll ( iters, b, s ) end --end end if how == 's' then local sp = current.GetScore() wShake () if current.GetScore () - sp > step * ( 1 + iter ) then wShake() end else local sp = current.GetScore() wWiggle() if current.GetScore () - sp > step * ( 1 + iter ) then ncWiggle(how, iters+1, iter+1) end end end function wiggle(prot,options ) local do_wiggle local iter -- establish if this is a global or local operation if ( options.global_wiggle == true ) then do_wiggle = ncWiggle('a') else do_wiggle = ncWiggle('l') end -- establish how to execute wiggle if ( options.allow_float_wiggle_count == true ) then local mean local upper local lower local bounds mean = options.wiggle_count upper = options.wiggle_count_upper lower = options.wiggle_count_lower bounds = options.wiggle_count_bounds iter = get_value2(mean,bounds ) --iter = get_value ( mean, lower, upper ) else if ( prot.bands_enabled ) then -- are we flexing ? iter = options.wiggle_count else iter = options.wiggle_out_count end end if ( options.verbose == true ) then -- print ( "Performing Wiggle | iters = ", iter ) end ncWiggle('a', iters, iter) end function show_score ( options, reportTime, lastOp ) local function round ( ii ) return ii - ii % 0.001 end local s if ( options.exploratory == true ) then s = current.GetScore() local n = { [true] = "Yes", [false] = "No", } print ( "Stabilization Score = ", current.GetEnergyScore()) print ( "Ranking score = ", current.GetScore()) print ( "Multiplier: ", current.GetExplorationMultiplier() ) print ( "Conditions met: ", n [current.AreConditionsMet()] ) if ( s > options.ranked_score ) then save.Quicksave(options.qs_recent_best ) -- -- model 050 - print gain or period without gain -- if ( options.ranked_score ~= 0 ) then local gain = s - options.ranked_score if gain > 0 then print ( lastOp .. ", gain = " .. round ( gain ) .. ", ranking score = " .. round ( s ) ) reportTime = os.time () end end options.score = current.GetEnergyScore() options.ranked_score = s options.multiplier = current.GetExplorationMultiplier() else local checkTime = os.time () if checkTime - reportTime >= 300 then reportTime = checkTime print ( "no gain after " .. lastOp ) end end else s = current.GetEnergyScore() -- -- model 050 - print gain or period without gain -- if ( s > options.score ) then if ( options.score ~= 0 ) then local gain = s - options.score print ( lastOp .. ", gain = " .. round ( gain ) .. ", score = " .. round ( s ) ) reportTime = os.time () end options.score = s else local checkTime = os.time () if checkTime - reportTime >= 300 then reportTime = checkTime print ( "no gain after " .. lastOp ) end end end return options, reportTime end function freeze_rods(prot,options ) local r_idx local r_idx2 local l_idx local l_idx2 local freeze_sc local freeze_bb selection.DeselectAll() r_idx = prot.R_idx r_idx2 = prot.R_idx2 l_idx = prot.L_idx l_idx2 = prot.L_idx2 freeze_sc = options.freeze_sidechains freeze_bb = options.freeze_backbone selection.SelectRange(r_idx,r_idx2 ) selection.SelectRange(l_idx,l_idx2 ) if ( options.verbose == true ) then local _s = { [true] = "true", [false] = "false", } -- print ( "Freezing backbone.." ) -- print ( "backbone = ", _s [freeze_bb] ) -- print ( "sidechains = ", _s [freeze_sc] ) end freeze.FreezeSelected(freeze_bb, freeze_sc ) selection.SelectAll() end function rod_add_bands(prot,options ) local idx local idx2 local str local k idx = prot.R_idx idx2 = prot.L_idx2 k = structure.GetCount() + 1 str = options.band_strength if ( options.verbose == true ) then -- print ( "Placing bands.." ) -- print ( "Setting band strength: ", str ) end for i = 0,3 do local n local n2 n = idx + i n2 = idx2 - i if (( n < k ) and ( n2 > 0 )) then band.AddBetweenSegments(n,n2 ) band.SetStrength(i+1,str ) end end end function set_clash_importance(options ) local ci if ( options.allow_ci_float == true ) then local mean local upper local lower local bounds mean = options.ci upper = options.ci_upper lower = options.ci_lower bounds = options.ci_bounds ci = get_value2(mean,bounds ) --ci = get_value(mean, lower, upper ) else ci = options.ci end if ( options.verbose == true ) then --print ( "Setting clash importance: ", ci ) end behavior.SetClashImportance(ci ) end function reset_clash_importance(options ) if ( options.verbose == true ) then -- print ( "Resetting clash importance: ", 1 ) end behavior.SetClashImportance(1) end function turn_bands_on(prot, options ) if ( options.verbose == true ) then --print ( "Enabling bands.." ) end band.EnableAll() prot.bands_enabled = true set_clash_importance(options ) return prot end function turn_bands_off(prot, options ) if ( options.verbose == true ) then --print ( "Disabling bands.." ) end band.DisableAll() prot.bands_enabled = false reset_clash_importance ( options ) return prot end function unfreeze_rods(prot,options ) freeze.UnfreezeAll() end function freeze_hinge(prot,options ) local glycine_idx local freeze_bb local freeze_sc selection.DeselectAll() glycine_idx = glycine_locator(prot,options ) freeze_sc = options.freeze_sidechains freeze_bb = options.freeze_backbone selection.Select(glycine_idx ) freeze.FreezeSelected(freeze_bb,freeze_sc ) selection.SelectAll() end function unfreeze_hinge(prot,options ) freeze.UnfreezeAll() end function check_preconditions(prot, options ) if options.freeze_hinge_instead == true then turn_bands_on(options ) wiggle(prot,options ) turn_bands_off(options ) unfreeze_rods(prot,options ) freeze_hinge(prot,options ) end end function nbl_hinge ( seg, hw, prot, options ) local lastOp = "" if hw == 1 then lastOp = "segment: " .. seg else lastOp = "segments: " .. seg .. "-" .. seg + hw - 1 end if loop_only then for ii = seg, seg + hw - 1 do if structure.GetSecondaryStructure ( seg ) ~= 'L' then return lastOp end end end prot = build_hinge ( prot, options, seg, hw ) freeze_rods ( prot, options ) rod_add_bands ( prot, options ) save_recent_best ( options ) check_preconditions ( prot, options ) prot = turn_bands_on ( prot, options ) wiggle ( prot, options ) prot = turn_bands_off ( prot, options ) wiggle ( prot, options ) recall_recent_best ( options ) --options = show_score ( options ) freeze.UnfreezeAll () band.DeleteAll () return lastOp end 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 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 function bkh ( hinge_width, prot, options ) --print ("Segs aleatoires") print ( "Random segments" ) -- -- convert ranges to a list (may contain duplicates) -- local workList = SegmentSetToList ( ranges ) for run = 1, nbrun do -- -- model 040 - start cycle - print cycle #, current score -- local runName = "hinge run " .. run .. "/" .. nbrun local begChunque = beginChunque ( startChunque, runName ) -- print ("Boucle " .. run .. " sur " .. nbrun) ShuffleTable ( workList ) -- NEW 24/9/2013 mix the segment table randomly local reportTime = os.time () for jj = 1, #workList do local lastOp = nbl_hinge ( workList [ jj ], hinge_width, prot, options ) options, reportTime = show_score ( options, reportTime, lastOp ) end -- -- model 070 - end cycle - print cycle #, time, gain -- endChunque ( begChunque, "end ".. runName ) end end function nblh ( hinge_width, prot, options ) for run = 1, nbrun do if (run > 1) then local rci = math.random() / 5 options.ci = ici + rci - 0.1 local rbs = math.random() / 10 options.band_strength = ibs + rbs - 0.05 end -- -- model 040 - start cycle - print cycle #, current score -- local runName = "hinge run " .. run .. "/" .. nbrun local begChunque = beginChunque ( startChunque, runName ) -- print ("Boucle " .. run .. " sur " .. nbrun) print ( "CI = " .. options.ci .. ", band strength = " .. options.band_strength ) local reportTime = os.time () for ii = 1, #ranges do for jj = ranges [ ii ] [ 1 ], ranges [ ii ] [ 2 ] do local lastOp = nbl_hinge ( jj, hinge_width, prot, options ) options, reportTime = show_score ( options, reportTime, lastOp ) end end -- -- model 070 - end cycle - print cycle #, time, gain -- endChunque ( begChunque, "end ".. runName ) end end function GetParams () local askresult = 0 local rangetext = "" local errtext = "" local ask = dialog.CreateDialog ( ReVersion ) repeat --ask.hinge_width = dialog.AddSlider("Taille charnieres: ",1,1,2,0) ask.hinge_width = dialog.AddSlider ( "Hinges size: ", hinge_width, 1, 2, 0 ) --ask.keep_trying = dialog.AddCheckbox("Toute la nuit ", true) ask.nbrun = dialog.AddSlider ("Number of runs ", nbrun, 1, 100, 0 ) --ask.random = dialog.AddCheckbox("Segs aleatoires ", false) ask.random = dialog.AddCheckbox ( "Random order? ", random ) ask.loop_only = dialog.AddCheckbox ( "Loops only? ", loop_only ) --ask.range = dialog.AddTextbox("Zone forcee", "") ask.range = dialog.AddTextbox ( "Range ", rangetext ) if errtext ~= "" then ask.l1 = dialog.AddLabel ( errtext) end ask.OK = dialog.AddButton ( "OK", 1 ) ask.Cancel = dialog.AddButton ( "Cancel", 0 ) askresult = dialog.Show ( ask ) if askresult ~= 0 then hinge_width = ask.hinge_width.value nbrun = ask.nbrun.value random = ask.random.value loop_only = ask.loop_only.value if ask.range.value ~= "" then rangetext = ask.range.value local rangelist = ReadSegmentSet ( rangetext ) if Errfound or #rangelist == 0 then askresult = 2 errtext = "error in range(s), please re-enter" else print ( #rangelist .. " ranges" ) for jj = 1, #rangelist do local sRange = rangelist [ jj ] [ 1 ] local eRange = rangelist [ jj ] [ 2 ] if eRange < sRange then sRange, eRange = eRange, sRange end if sRange < range_min then sRange = range_min end if eRange > range_max then eRange = range_max end ranges [ #ranges + 1 ] = { sRange, eRange } end end else ranges [ #ranges + 1 ] = { range_min, range_max } end end until askresult < 2 return askresult > 0 end function main () local options = _options local prot = _prot ici = options.ci ibs = options.band_strength math.randomseed(os.time()%1000000) math.random(100) freeze.UnfreezeAll() band.DeleteAll() options.score = current.GetEnergyScore() if options.exploratory == true then options.ranked_score = current.GetScore() end if GetParams () then -- -- model 010 - startup - print recipe name, puzzle name, track -- print ( ReVersion ) print ( "Puzzle: " .. puzzle.GetName () ) print ( "Track: " .. ui.GetTrackName () ) -- -- model 020 - startup - print recipe parms -- print ( "options:" ) print ( "number of runs = " .. nbrun ) print ( "hinge width = " .. hinge_width ) print ( "random order = " .. tostring ( random ) ) print ( "loops only = " .. tostring ( loop_only ) ) print ( "segment range(s) = " .. SegmentSetToString ( ranges ) ) -- -- model 030 - startup - print start time, start score -- startChunque = beginChunque ( nil, "Start" ) if random then bkh ( hinge_width, prot, options ) else nblh ( hinge_width, prot, options ) end -- -- model 090 - exit via the cleanup routine -- cleanup () end end function cleanup ( error ) print ( "---" ) -- -- model 100 - print recipe name, puzzle, track, time, score, and gain -- local reason local start, stop, line, msg if error == nil then reason = "complete" else -- -- model 120 - civilized error reporting, -- thanks to Bruno K. and Jean-Bob -- start, stop, line, msg = error:find ( ":(%d+):%s()" ) if msg ~= nil then error = error:sub ( msg, #error ) end if error:find ( "Cancelled" ) ~= nil then reason = "cancelled" else reason = "error" end end print ( ReVersion .. " " .. reason ) print ( "Puzzle: " .. puzzle.GetName () ) print ( "Track: " .. ui.GetTrackName () ) if reason == "error" then print ( "Unexpected error detected" ) print ( "Error line: " .. line ) print ( "Error: \"" .. error .. "\"" ) end -- -- model 130 - reset clash importance, clear selections, restore structures, etc. -- behavior.SetClashImportance ( 1 ) selection.DeselectAll () freeze.UnfreezeAll () if error ~= nil then recentbest.Restore () end band.DeleteAll () -- want to do this *after* restoring best! -- -- model 150 - report the final time, score, gain, elapsed time, and points per hour -- if startChunque ~= nil then endChunque ( startChunque, "Final" ) end end -- main call xpcall ( main, cleanup ) --end of script

Comments


LociOiling Lv 1

Version 1.5 of nbl_hinge implements the guidelines discussed in the "Model Recipes" wiki article:

http://foldit.wikia.com/wiki/Model_Recipes

The main hinging logic did not change, but there some changes to other parts of the recipe:

  • multiple ranges can now be specified and used, previously only
    the first range specified was processed

    • as before, ranges are specified in standard "TvdL" format, for example:

      10,14 27,39 76,85

      specifies three ranges (other syntax variations may work)

    • ranges may overlap; this means segments may be tried more than
      once for both regular and random mode

    • in some cases, an incorrect range specification will result in an
      in-dialog error message (some errors may still escape)

  • the score is not reported for each segment, but only if:
    • a gain has occurred, or
    • five minutes have elapsed since the last report
  • the number of runs is now selectable via a slider, previous options were
    one run or one hundred runs if "keep trying" was selected

  • a "loops only" option has been added to skip segments where the hinge point
    or points are not loop ('L')

  • the internal logic of the "random order" option has been simplified

LociOiling Lv 1

Version 1.5 of nbl_hinge implements the guidelines discussed in the "Model Recipes" wiki article:

http://foldit.wikia.com/wiki/Model_Recipes

The main hinging logic did not change, but there some changes to other parts of the recipe:

  • multiple ranges can now be specified and used, previously only
    the first range specified was processed

    • as before, ranges are specified in standard "TvdL" format, for example:

      10,14 27,39 76,85

      specifies three ranges (other syntax variations may work)

    • ranges may overlap; this means segments may be tried more than
      once for both regular and random mode

    • in some cases, an incorrect range specification will result in an
      in-dialog error message (some errors may still escape)

  • the score is not reported for each segment, but only if:
    • a gain has occurred, or
    • five minutes have elapsed since the last report
  • the number of runs is now selectable via a slider, previous options were
    one run or one hundred runs if "keep trying" was selected

  • a "loops only" option has been added to skip segments where the hinge point
    or points are not loop ('L')

  • the internal logic of the "random order" option has been simplified

Hanto Lv 1

Operation limited by requirement to use GUI to input variables. As a result recipe CANNOT be used in prolonged situations or combined with other routines in mixed environment. Please rectify.