Code
--Quaking Remix 13/02/2014 Bruno Kestemont based on spvincent
--Outlines: on several zones of X segments, remix, shake, take Y bests, further improve, take best, rebuild it, quake the rebuild result
--Added loop counter and timestamps in output, progress reported in segment Note, changed default ss_control to 2, commented out some print lines
--Added dialog box Bruno Kestemont 02/02/2014
--changed wiggles by recursive wiggles for New Chapter --03/02/2014
--minor adaptations 05/02/2014
--tvdl WORKON dialog added by BK 06/02/2014
--13/02/2014 fixed dialog box options display
--added remix command, experimental
--19/02/2014 implemented remix on mutable puzzles
--01/03/2014 options skip quake skip rebuild
--26/4/2016 v1.0 shake after each remix
--3/5/2016 v1.1 new remix command used
-- v1.2 fixed remix action !
-- v1.3 loop option on first dialog, only loop as default, user bands management, all remixes considered 16/5/2016
-- v1.3.1 fixed NeverDisableMyBands, disable cut option (it does not work with new remix tool)
-- v1.3.2 fixed recipe name in set note
-- v1.4.0 shakeCI default = 0.31 in wiggleSimple (to be change manually in recipe, not in dialog)
-- and normal shake (CI=1) on a sphere SelectAround(ss,se,radius,nodeselect)
-- rebuild 1 if no remix found (rebuild is a remix of length 3)
-- this version should be slow, but it might gain more
-- added Fast option (skipping all above, only one local shake after each remix)
--v1.4.1 optimized Fast option and adding option for number of best remixes to be refined (low is quick, default 4)
-- optional RebuildOnRemix (option in the code only), if false then rebuild this segments on the credited score
-- but the quake is always on rebuild result (like in Ebola).
--v1.4.2 fixed bug fast
--v1.4.3 jeff101 display, retired fast, adding NoWiggle (wiggle is dangerous for rama map if the AAs are not the right ones)
--v1.4.4 undo.SetUndo
--TO DO ! default all protein (not only loops) & select where to work doen't work !?
recipename="Quaking Remix 1.4.4"
undo.SetUndo(false)
--WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
--OPTIONS FOR DEFAULT SETTINGS to be edited in the code
ss_control = 1
-- ss_control == 1 Only rebuilds/remix loops
-- ss_control == 2 Rebuilds everything. Helices and sheets will be temporarily converted to loops
-- ss_control == 3 Rebuild/remix loops but allows 1+1 non-loop residues in the rebuild segment.
if ss_control==1 then
DefaultOption="Default: Only rebuilds loops"
elseif ss_control==2 then
DefaultOption="Default: Rebuilds everything converted to loops"
elseif ss_control==3 then
DefaultOption="Default: Work on loops with 1 non-loop allowed"
end
print(DefaultOption)
print("Default can easilly be edited in the code")
--of course you can edit other default options bellow
--I could add a dialog box for bands later on, but I suppose default options are ok.
--WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
-- Handy shorts module from tvdl 03/02/2014
normal= (current.GetExplorationMultiplier() == 0)
segCnt=structure.GetCount()
segCnt2=segCnt
while structure.GetSecondaryStructure(segCnt2)=="M" do segCnt2=segCnt2-1 end
-- end Handy shorts module
-- 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
-- 05-02-2014 BK enhanced (also Free for non commercial purposes)
-- a list is {1,2,3,8,9,10}. A set is {{1,4},{8,10}} or something like that in a 2-dimentional table:
--i {[1],[2]}
--___________
--1 { 1 , 4 }
--2 { 8 , 10}
allowcut= false -- with the new remix tool, I think it's not necessary any more
CUTWORST= false -- not used
shakeCI= 0.31 -- to be changed here manually, not in dialog. Note that there are still shakes at CI=1 occuring
Fast= false -- if true, does only one shake on each remix, and no rebuild if no solution
MaxNbBest= 4 -- we take only the best 4 remixes
NbBest= MaxNbBest -- we take only the best 4 remixes
RebuildOnRemix= true -- rebuild starts on the best remix solution (not on best score)
NoWiggle= false -- if true: never wiggle backbones (protects the rama map), experimental
function cutRange(segFrom, segTo) -- 26/4/2016
if (allowcut or CUTWORST) and not freeze.IsFrozen(segFrom) then
if segFrom==segCnt then segFrom=segCnt-1 end
structure.InsertCut(segFrom)
end -- else nothing !
if (allowcut or CUTWORST) and not freeze.IsFrozen(segTo) then
if segTo==segCnt then segTo=segCnt-1 end
structure.InsertCut(segTo)
end -- else nothing !
end
function uncut() -- 18/2/2016
if (allowcut or CUTWORST) then
for i=1, segCnt do
structure.DeleteCut(i)
end
end
end
function SegmentExtendSet(set,x,y) -- New BK 05/02/2014 x, y= nb of seg to add before and after each zone
local result={}
local x,y=x or 1, y or 1
for i=1,#set do
if set[i][1]<1+x then --first segment
result[i]={set[i][1],set[i][2]+y}
elseif set[i][2]>set[#set][2]-y then --last segment
result[i]={set[i][1]-x,set[i][2]}
else
result[i]={(set[i][1]-x and set[i][1]>x) or set[i][1] , (set[i][2]<=set[#set][2]-y and set[i][2]+y) or set[i][2]}
result[i]={set[i][1]-x ,set[i][2]+y}
end
end
return result -- overlaps are possible
end
function SegmentListToSet(list) --note: clean duplicates
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) -- clean duplicates
-- Makes it well formed and clean duplicates
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) -- duplicates allowed
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) -- no duplicates, no overlap
return SegmentListToSet(SegmentJoinList(SegmentSetToList(set1),SegmentSetToList(set2)))
end
function SegmentCommList(list1,list2) -- what is common to 2 lists
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) -- what is common to set 1 and set 2 (no duplicate)
return SegmentListToSet(SegmentCommList(SegmentSetToList(set1),SegmentSetToList(set2)))
end
function SegmentSetMinus(set1,set2) -- set1 minus set2 (set1 minus what is common to set 1 and set2)(no duplicate)
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 FindMutablesList()
local result={}
for i=1,segCnt2 do if structure.IsMutable(i) then result[#result+1]=i end end
return result
end
function FindMutables()
return SegmentListToSet(FindMutablesList())
end
function FindFrozenList()
local result={}
for i=1,segCnt2 do if freeze.IsFrozen(i) then result[#result+1]=i end end
return result
end
function FindFrozen()
return SegmentListToSet(FindFrozenList())
end
function FindLockedList()
local result={}
for i=1,segCnt2 do if structure.IsLocked(i) then result[#result+1]=i end end
return result
end
function FindLocked()
return SegmentListToSet(FindLockedList())
end
function FindSelectedList()
local result={}
for i=1,segCnt do if selection.IsSelected(i) then result[#result+1]=i end end
return result
end
function FindSelected()
return SegmentListToSet(FindSelectedList())
end
function FindAAtypeList(aa)
local result={}
for i=1,segCnt2 do
if structure.GetSecondaryStructure(i)== aa then result[#result+1]=i end
end
return result
end
function FindAAtype(aa)
return SegmentListToSet(FindAAtypeList(aa))
end
function FindAminotype(at) --NOTE: only this one gives a list not a set
local result={}
for i=1,segCnt2 do
if structure.GetAminoAcid(i) == at then result[#result+1]=i end
end
return result
end
-- end Module Find Segment Types
function SortBest(tab,items) --BACWARD bubble sorting - best on top, only needed items
for x=1,items do --items do
for y=x+1,#tab do
if tab[x][1]<tab[y][1] then
tab[x],tab[y]=tab[y],tab[x]
end
end
end
return tab
end
function SelectAround(ss,se,radius,nodeselect)
if nodeselect~=true then selection.DeselectAll() end
for i=1, segCnt2 do
for x=ss,se do
if structure.GetDistance(x,i)<radius then selection.Select(i) break end
end
end
end
--PRIMARY Quaking Rebuild options (renamed)
total_rebuild_loops = 9999 -- exit after rb # exceeds total_rebuild_loops
From_rebuild_length = 9 -- Maximum rebuild length.
To_rebuild_length = 3 -- - Better less than or equal to From_rebuild_length. Suggest not going below 3 for rebuild.
maxFrom_rebuild_length = 11 --28/4/2016
maxTo_rebuild_length = 8--03/02/2014
number_of_rebuilds = 0 -- default 0 for remix; suggested 8 for the best score from this number of rebuilds. Change to taste.
-- if nor remix is found, set at least number_of_rebuilds to 1 if you want a rebuild on this section
number_of_remix=85 --remix is quick here 01/03/2014, we are limited by the 100 available slots
start_idx = 0 -- if this is a residue id, use it as the start point. If not
-- use a semi-random number computed from the score
--ss_control = 3 see top for edit recipe default option
-- they'll be temporarily converted to loops
loop_forever = true -- just keep going. Good for overnight running.
min_residue = 1 -- Change these if you want to rebuild part of a protein only. For example, to
-- rebuild 53-64, set min_residue to 53 and max_residue to 64. To restore, set to
-- 1 and 9999 (or any large number) respectively
max_residue = 999
kClashImportanceDuringRebuild = 1 -- Might try reducing this to get more a different rebuild than the highest scoring -- one, which might overstate
-- the importance of clashing which can be remedied by a quick shake.
-- If, after rebuild, shake, wiggle, etc. , the score is close enough to the starting score, attempt some quakes.
-- close enough is defined by the entry in kQuakingThresholds indexed by the size of segment being rebuilt
kQuakingThresholds = { 8 , 8 , 8 , 15 , 25 , 30 , 35 }
nQuakingThresholds = 7
-- Use of quicksave slots
kOriginalStructureOrNewBest = 1
kBestPostRebuild = 2
-- Stores the best non-improved structure in Quicksave slot 10 (but can change this below) . The structure that's saved
-- is the best before WS etc, so if this script fails to produce (or even if it does) you can load the structure in
-- slot 10 and try WS in different ways.
kBestNonImprovedStructure = 10
kbestremixslot1=15 -- starting slot, others are 16, 17 ... 100
original_secondary_structure = {}
n_residues = structure.GetCount ()
curr_score = 0
multiplier = 1
-----
-- The Local Quake bit. Copied from LQ1.2 for expediency
-- Bands radiate from a segment to spatially close neighbours
-- Foregoes Fuses and generally tries to optimize for speed
use_ranked_score = 1 -- if 1, use the score being used for ranking (best normally). If 0, use the
-- old style scoring system
max_bands_per_residue = 6 -- Increase this for more bands at each segment
start_idx = 0 -- Set to a valid residue to start with that residue: otherwise
-- start with a semi-random one,
second_offset = 3 -- Set to 0 for a single centre. This is the most likely one to change.
opposite_centre = false -- overrides second_offset if true
target_wiggle_reduction = 120 -- On wiggle, try and reduce the score by this amount after creating the bands.
-- If it's wildly out, reduce/increase band strength
-- for the next try (don't try to adjust for the current scramble).
max_segment_length = 20 -- Don't create bands greater than this length. Set to 999 or something if you're
-- not worried about the potential for long bands creeping in,
min_exclusion = 999 -- These can be set to establish an "exclusion zone", within which no bands will
-- be created. This might be used to prevent banding to a wayward loop.
-- If min_exclusion > max_exclusion no exclusion will be set.
max_exclusion = 1
n_quakes = 10 -- A reasonable number 10
band_to_minima = true -- Band to minima or maxima in the distance. See bands_from_segment for meaning.
do_second_shake = false -- After creating the bands and pulling with them do a Shake/Wiggle/Shake
-- if do_second_shake is false (best I think) don't do the last shake.
-- Speeds things up quite a bit
scale_band_strength = true -- If true, band strength will be scaled inversely with length
monit = false -- prints more info
---------- A few more globals
candidate_ids_start = {}
candidate_ids_end = {}
candidate_distances = {}
n_candidates = 0
recent_best_score = 0-- recent best to compare to and see if score was improved
normal= (current.GetExplorationMultiplier() == 0)--03/02/2014
function report_time(start_clock,start_time,clock_msg,time_msg)
local seconds,minutes,hours,days
if clock_msg==nil then clock_msg="CPU time" end
if time_msg==nil then time_msg="Elasped time" end
print(string.format("%s",os.date()))
days,remainder=math.modf((os.clock()-start_clock)/(24*60*60))
hours,remainder=math.modf(remainder*24)
minutes,remainder=math.modf(remainder*60)
seconds,remainder=math.modf(remainder*60)
print(string.format("%s(%02id:%02ih:%02im:%02is)",clock_msg,days,hours,minutes,seconds))
days,remainder=math.modf(os.difftime(os.time(),start_time)/(24*60*60))
hours,remainder=math.modf(remainder*24)
minutes,remainder=math.modf(remainder*60)
seconds,remainder=math.modf(remainder*60)
print(string.format("%s(%02id:%02ih:%02im:%02is)",time_msg,days,hours,minutes,seconds))
end
-- 2 Score functions -- NEW from tvd for exploration puzzles BK 03/02/2014
function GetScore(pose)--03/02/2014
if pose==nil then pose=current end
local total= pose.GetEnergyScore()
-- FIX for big negatives
if total < -999999 and total > -1000001 then total=SegScore(pose) end
if normal then
return total
else
return total*pose.GetExplorationMultiplier()
end
end
function SegScore(pose)--03/02/2014
if pose==nil then pose=current end
local total=8000
for i=segStart, segCnt2 do
total=total+pose.GetSegmentEnergyScore(i)
end
return total
end
-- END score functions
global_ci=1 --03/02/2014
function CI(val)--03/02/2014
global_ci=val
behavior.SetClashImportance(global_ci)
end
function WiggleSimple(val,how) -- Bruno Kestemont 02/02/2014
local val, how = val or 1, how or "wa" -- new BK 02/02/2014
if how == "s" then CI(shakeCI) structure.ShakeSidechainsSelected(1) CI(global_ci)
elseif how == "wb" then structure.WiggleSelected(val, true, false) -- backbones
elseif how == "ws" then structure.WiggleSelected(val, false, true) -- sidechains
elseif how == "wa" then structure.WiggleSelected(val, true, true) -- all
elseif how== "lw" then structure.LocalWiggleSelected(val) -- local wiggle
end
end
function WiggleNC(ss, how, iters, minppi)-- 19/8/2016 (ss is useless here), with NoWiggle option
local valiter=2
local val=1
if how==nil then how="wa" end
if (how=="wa" or how=="lw") and NoWiggle then how="ws" end
if iters==nil then iters=30 end
minppi=(recent_best_score-GetScore ())/100 -- 03/02/2014
if ((minppi==nil) or (minppi<0.001)) then
minppi=0.001 -- put higher to save time
end
if global_ci==1.00 then val=valiter end
if iters>0 then
iters=iters-1
local sp=GetScore()-- 03/02/2014
WiggleSimple(val,how)
local ep = GetScore()-- 03/02/2014
local ig=ep-sp
if how~="s" then
if ig > minppi then WiggleNC(ss, how, iters, minppi) end
end
how="wa"
iters=30
end
end
--[[ 03/02/2014 (old score function)
function GetScore ()
if ( use_ranked_score == 1 ) then
return current.GetScore ()
else
return current.GetEnergyScore ()
end
end]]--
function Coprime ( n )
if ( n < 31 ) then
return 1
elseif ( n >= 31*37 ) then
return 1
elseif ( n%31 ~= 0 ) then
return 31
else
return 37
end
end
function pseudorandom ( score )
-- Returns a pseudorandom number >= 0 and < 1.
-- Based on the fractional part of the score
if ( score >= 0 ) then
return score % 1
else
return (-score ) % 1
end
end
function roundto3 ( i )
-- printing convenience
return i - i % 0.001
end
function roundto6 ( i )
-- printing convenience
return i - i % 0.000001
end
function delete_all_bands () -- unless user bands 16/5/2016
ManageBands ()
end
function ShellSort ( ids , distances , n )
-- Adapted from Numerical Recipes in C
local inc = 1
repeat
inc = inc * 3 + 1
until inc > n
repeat
inc = inc / 3
inc = inc - inc % 1
for i = inc + 1 , n do
v = distances [ i ]
w = ids [ i ]
j = i
flag = false
while ( flag == false and distances [ j - inc ] > v ) do
distances [ j ] = distances [ j - inc ]
ids [ j ] = ids [ j - inc ]
j = j - inc
if ( j <= inc ) then
flag = true
end
end
distances [ j ] = v
ids [ j ] = w
end
until inc <= 1
end
function test_for_minimum ( i , seg , seg_distances )
if ( ( i ~= seg ) and
( seg_distances [ i ] <= seg_distances [ i - 1 ] ) and
( seg_distances [ i ] <= seg_distances [ i - 2 ] ) and
( seg_distances [ i ] <= seg_distances [ i + 1 ] ) and
( seg_distances [ i ] <= seg_distances [ i + 2 ] ) ) then
return true
else
return false
end
end
function test_for_maximum ( i , seg , seg_distances )
if ( ( seg_distances [ i ] >= seg_distances [ i - 1 ] ) and
( seg_distances [ i ] >= seg_distances [ i - 2 ] ) and
( seg_distances [ i ] >= seg_distances [ i + 1 ] ) and
( seg_distances [ i ] >= seg_distances [ i + 2 ] ) ) then
return true
else
return false
end
end
function get_band_segment_data ( seg )
seg_distances = {}
-- Get the function that looks like this:
-- x = residue number
-- y = distance of that segment from seg
-- ignore the degenerate minimum
n_segments = 0
segment_ids = {}
segment_distances = {}
for i = 1, n_residues do
segment_distances [ i ] = structure.GetDistance ( seg , i )
end
for i = 3 , n_residues - 3 do
k = segment_distances [ i ]
if ( ( band_to_minima == true ) and
( test_for_minimum ( i , seg , segment_distances ) == true ) ) then
n_segments = n_segments + 1
segment_ids [ n_segments ] = i
segment_distances [ n_segments ] = segment_distances [ i ]
elseif ( ( band_to_minima == false ) and
( test_for_maximum ( i , seg , segment_distances ) == true ) ) then
n_segments = n_segments + 1
segment_ids [ n_segments ] = i
segment_distances [ n_segments ] = segment_distances [ i ]
end
end
ShellSort ( segment_ids , segment_distances , n_segments )
if ( n_segments >= max_bands_per_residue ) then
n_c = max_bands_per_residue
else
n_c = n_segments
end
for i = 1 , n_c do
if ( ( segment_distances [ i ] <= max_segment_length ) and
( seg < min_exclusion or seg > max_exclusion ) and
( segment_ids [ i ] < min_exclusion or segment_ids [ i ] > max_exclusion ) ) then
n_candidates = n_candidates + 1
candidate_ids_start [ n_candidates ] = seg
candidate_ids_end [ n_candidates ] = segment_ids [ i ]
candidate_distances [ n_candidates ] = segment_distances [ i ]
end
end
most_distant_minimum = segment_ids [ n_segments ]
end
function create_bands ()
if ( scale_band_strength == true ) then
total_band_length = 0
for i = 1 , n_candidates do
total_band_length = total_band_length + candidate_distances [ i ]
end
average_band_length = total_band_length / n_candidates
end
for i = 1 , n_candidates do
band.AddBetweenSegments ( candidate_ids_start [ i ] , candidate_ids_end [ i ] )
if ( scale_band_strength == true ) then
band.SetStrength ( i , band_strength * average_band_length / candidate_distances [ i ] )
else
band.SetStrength ( i , band_strength )
end
end
end
function Quake ( seg )
selection.SelectAll ()
init_score = GetScore ()
--structure.WiggleSelected ( 1 )
WiggleNC(seg, "wa", 30) -- 02/02/2014
score_after_wiggle = GetScore ()
score_reduction_after_wiggle = init_score - score_after_wiggle
-- Adaptively change band strength based on how much the previous wiggle overshot/undershot the target. Could
-- be made much more elaborate.
if ( score_reduction_after_wiggle > target_wiggle_reduction * 1.2 ) then
band_strength = band_strength * ( 0.85 + 0.1 *pseudorandom ( score_after_wiggle ) )
elseif ( score_reduction_after_wiggle < target_wiggle_reduction * 0.8 ) then
band_strength = band_strength + ( 1 - band_strength ) * ( 0.05 + 0.1 *pseudorandom ( score_after_wiggle ) )
end
delete_all_bands ()
structure.ShakeSidechainsSelected ( 1 )
gas = GetScore () - score_after_wiggle
if ( monit ) then
print ( "law " .. roundto3 ( init_score - score_after_wiggle ) .. " gas " .. roundto3 ( gas ) .. " band_strength " .. roundto3 ( band_strength ) )
end
--structure.WiggleSelected ( 8 )
WiggleNC(seg, "wa", 30) -- 02/02/2014
if ( do_second_shake == true ) then
score_a2w = GetScore ()
structure.ShakeSidechainsSelected ( 1 )
score_a2s = GetScore ()
if ( score_a2s - score_a2w > 1 ) then
--structure.WiggleSelected ( 4 )
WiggleNC(seg, "wa", 30) -- 02/02/2014
end
end
end
function local_quake ( start_idx )
band_strength = 0.5
CI ( 1 )
recentbest.Save ()
best_score_lq = GetScore ()
inc = Coprime ( n_residues )
idx_lq = start_idx
print("Quaking from seg "..start_idx.." and score: "..roundto3(curr_score))
for i = 1, n_quakes do
recentbest.Restore ()
-- Need to record any improvements from the previous iteration,.
score_lq = GetScore()
if ( score_lq > best_score_lq ) then
best_score_lq = score_lq
-- print ( " Gain to " .. roundto3 ( score_lq - score_lq % 0.01 ) )
end
delete_all_bands ()
n_candidates = 0 -- ??
get_band_segment_data ( idx_lq )
if ( opposite_centre == true ) then
second_idx = most_distant_minimum
get_band_segment_data ( most_distant_minimum )
elseif ( second_offset ~= 0 ) then
second_idx = idx_lq + second_offset
while ( second_idx > n_residues ) do
second_idx = second_idx - n_residues
end
get_band_segment_data ( second_idx )
end
if ( n_candidates > 0 ) then -- ?? it's always zero in this loop ??!?
create_bands ()
if ( second_offset ~= 0 ) then
-- print ( " i: " .. i .. " seg ".. idx_lq .. "," .. second_idx )
else
-- print ( " i: " .. i .. " seg ".. idx_lq )
end
Quake ( idx_lq )
end
idx_lq = idx_lq + inc
if ( idx_lq > n_residues ) then
idx_lq = idx_lq - n_residues
end
end -- for
recentbest.Restore ()
delete_all_bands ()
end
------
function IsSegmentALoop ( first , last )
-- Returns number of non-loop residues (helices or sheets)
n_non_loops = 0
for i = first , last do
if ( structure.GetSecondaryStructure ( i ) ~= "L" ) then
n_non_loops = n_non_loops + 1
end
end
return n_non_loops
end
function ConvertToLoop ( first , last )
for k = first , last do
if ( original_secondary_structure [ k ] ~= "L" ) then
selection.DeselectAll ( )
selection.Select ( k )
structure.SetSecondaryStructureSelected ( "L" )
end
end
end
function RestoreStructure ( first , last )
for k = first, last do
selection.DeselectAll ()
selection.Select ( k )
structure.SetSecondaryStructureSelected ( original_secondary_structure [ k ] )
end
end
function pseudorandom ( score )
-- Returns a pseudorandom number >= 0 and < 1.
-- Based on the fractional part of the score
if ( score >= 0 ) then
return score % 1
else
return (-score ) % 1
end
end
function nudge ( score )
selection.SelectAll ()
--recentbest.Save ()
CI ( 0.2 + 0.2 * pseudorandom ( score ) )
--structure.WiggleSelected ( 1 )
WiggleNC(seg, "wa", 2) -- 02/02/2014
CI ( 1 )
-- structure.WiggleSelected ( 8 )
WiggleNC(seg, "wa", 30) -- 02/02/2014
recentbest.Restore ()
end
function WiggleShakeWiggle ( start_idx , end_idx )
-- returns the score after doing a WSW: shortcircuiting if things don't look promising
score_a = GetScore ()
--structure.WiggleSelected ( 15 )
WiggleNC(seg, "wa", 30) -- 02/02/2014
recentbest.Restore ()
score_after_wiggle = GetScore ()
if ( score_after_wiggle - score_a < 10*multiplier and recent_best_score - score_after_wiggle > 30*multiplier ) then
-- The wiggle got stuck and didn't achieve anything
nudge ( score_after_wiggle )
score_after_wiggle = GetScore ()
end
if ( monit ) then
--print ( "After first wiggle (bb) : ".. roundto3 ( recent_best_score - score_after_wiggle ) )
end
if ( recent_best_score - score_after_wiggle > 100*multiplier ) then
-- Not worth continuing
return score_after_wiggle
end
structure.ShakeSidechainsSelected ( 1 )
score_after_second_shake = GetScore ()
if ( true ) then --score_after_second_shake - score_after_wiggle > 0.5 ) then
--structure.WiggleSelected ( 10 )
WiggleNC(seg, "wa", 30) -- 02/02/2014
recentbest.Restore ()
score_after_second_wiggle = GetScore ()
if ( true ) then -- score_after_second_wiggle - score_after_second_shake < 1 and recent_best_score - score_after_second_wiggle < 50*multiplier ) then
-- The second shake did something but the subsequent wiggle didn't
nudge ( score_after_second_wiggle )
score = GetScore ()
return score
else
return score_after_second_wiggle
end
else
return score_after_second_shake
end
end
function post_rebuild ( score_after_rebuild , start_idx , end_idx )
-- Tries to recover after a rebuild.
if ( recent_best_score - score_after_rebuild > 3000*multiplier ) then
structure.ShakeSidechainsSelected ( 2 )
elseif ( recent_best_score - score_after_rebuild > 1500*multiplier ) then
structure.ShakeSidechainsSelected ( 1 )
end
-- First try WSW
curr_score = WiggleShakeWiggle ( start_idx , end_idx )
end
function updatebest(curr_score)-- 22/02/2014 and print improvements
if ( curr_score > recent_best_score ) then
local gain=curr_score - recent_best_score
print ( "Improvement to ".. roundto3(curr_score) .. ". This gain "..roundto6(gain))
structure.SetNote(note_number,string.format("(%s) %.3f + %s (%i) %.3f",user.GetPlayerName(), starting_score, recipename, rb,roundto3(curr_score)))
jeff101Display(recent_best_score, curr_score, rb)
recent_best_score = curr_score -- note that we work only with "recent best" - TO DO: verify
improvement_made = true
save.Quicksave(kOriginalStructureOrNewBest)
end
end
function updatebestRemix(curr_score) -- not to be used too early (kbestremixslot1 is needed on start remix)
if curr_score>bestremixscore then
bestremixscore=curr_score
save.Quicksave(kbestremixslot1) -- we keep here the very best remix
end
end
function checkLoop(start_idx , end_idx)
if IsSegmentALoop ( start_idx , end_idx ) > 0 then return false end
return true
end
function AfterRemix( start_idx , end_idx ) -- on selected
recentbest.Save()
WiggleNC(ss, "ws", 2, 0.1)
WiggleNC(ss, "s", 1, 0.1) -- with CI= 0.31
WiggleNC(ss, "lw", 1, 0.1) -- it's very slow !
--WiggleNC(ss, "wa", 2, 0.1) -- selected
selection.DeselectAll ()
SelectAround(start_idx,end_idx,9)
structure.ShakeSidechainsSelected(1) -- on a sphere with CI=1
recentbest.Restore()
selection.DeselectAll ()
selection.SelectRange ( start_idx , end_idx )
end
function rebuild_seg ( start_idx , end_idx ) -- remix is here (with or without additional rebuild)
local rebuild_lengthseg = end_idx - start_idx + 1 --22/02/2014 initialization
local remixscores= {}
local remixdone= false
-- return codes
--
-- 0 rebuild had no effect: seg probably locked
-- 1 no improvement
-- 2 improvement
selection.DeselectAll ()
selection.SelectRange ( start_idx , end_idx )
-- for some reason, do_local_rebuild ( 1) often leaves the protein unchanged
-- Compute a value delta which will be used later to determine if we are
-- "sufficiently" close to our original best score. If it turns out later that
-- we are, then nudge it around
rebuild_length = end_idx - start_idx + 1 -- duplicate but it's safe because we need it here (could be local)
if ( rebuild_length > nQuakingThresholds ) then
delta = kQuakingThresholds [ nQuakingThresholds ] * multiplier -- sanity check for lengthy rebuild segs
else
delta = kQuakingThresholds [ rebuild_length ] * multiplier -- multiplier = 1 most of the time
end
k = 0
repeat
k = k + 1
if do_remix and rebuild_lengthseg>2 and rebuild_lengthseg< 10 and ss_control~=2 then -- 16/5/2016
save.LoadSecondaryStructure () --19/02/2014
print("Remixing",start_idx,"-",end_idx,". Length=",rebuild_lengthseg)
recentbest.Save () --19/02/2014
cutRange( start_idx -1 , end_idx +1) --26/4/2016
save.Quicksave(kbestremixslot1) -- starting and best remix score will be here
--save.Quicksave(kstartremixslot)
bestremixscore=GetScore ()-900000 -- threshold to be adapted
remixdone= false
remixscores= {}
local nfound=structure.RemixSelected(kbestremixslot1, number_of_remix) -- saves different remix results in max x (10?) slots
print("Nr of remix found "..nfound)
if nfound ~= 0 then --16/5/2016
if nfound >= MaxNbBest then NbBest= MaxNbBest else NbBest=nfound end
noRemix=false
for i=1 , nfound do --15/5/2016
save.Quickload(kbestremixslot1+i-1)
--structure.RemixSelected()
structure.ShakeSidechainsSelected(1)
curr_score = GetScore ()
remixscores[#remixscores+1]={curr_score, i}
--print("Score after remix ",i,":",roundto3(curr_score))
save.Quicksave(kbestremixslot1+i-1) -- replace the old value by this shaked one
end
SortBest(remixscores,NbBest) -- sort only to find the needed best
bestremix=0
print ("Selecting", NbBest, "best remixes:")
for i= 1, NbBest do
save.Quickload(kbestremixslot1+remixscores[i][2]-1)
print("Remix ", remixscores[i][2], "score:", roundto3(remixscores[i][1]))
if not Fast then
AfterRemix( start_idx , end_idx )
end
curr_score = GetScore ()
if curr_score>bestremixscore then
bestremixscore=curr_score
bestremix= remixscores[i][2]
save.Quicksave(kbestremixslot1) -- we keep here the very best remix
end
end
save.Quickload(kbestremixslot1) -- We take ONLY the best one (TO DO: second best etc ?)
uncut()--26/4/2016
curr_score= GetScore ()
if curr_score ~= recent_best_score then --16/5/2016
updatebestRemix(curr_score)
structure.ShakeSidechainsSelected(1)
curr_score = GetScore ()
print("Best score after remix round and fix: "..roundto3(curr_score).." on remix "..bestremix)
updatebestRemix(curr_score)
save.Quickload(kbestremixslot1)
WiggleNC(ss, "wa", 2, 0.1)
curr_score = GetScore ()
updatebestRemix(curr_score)
save.Quickload(kbestremixslot1)
updatebest(curr_score) -- 22/02/2014 and print improvements
end
else --16/5/2016
uncut()
save.Quickload(kOriginalStructureOrNewBest)
noRemix=true
end
end
score_after_remix = GetScore ()
until score_after_remix ~= recent_best_score or k > 2
if ( score_after_remix == recent_best_score ) then
-- If the scores are still equal we probably have a locked segment
print("Remix didn't change anything")
return 0 -- WARNING then no rebuild, no quake !?! TO DO: evaluate or optional ?
end
if not RebuildOnRemix or score_after_remix < recent_best_score - delta then
recentbest.Restore () -- 22/02/2014 further rebuilds not on loosing remixed
end
recentbest.Save ()
score_before_rebuild = GetScore ()
if ( number_of_rebuilds > 0 ) then
print("Rebuilding "..start_idx.."-"..end_idx.." on score "..roundto3(score_before_rebuild))
CI ( kClashImportanceDuringRebuild )
ConvertToLoop ( start_idx , end_idx )--
structure.RebuildSelected ( number_of_rebuilds)
CI ( 1 )
recentbest.Restore ()
structure.ShakeSidechainsSelected(1) -- with CI=1 on the best rebuild only
recentbest.Restore ()
end
-- Now do the post rebuild wiggle and shakes
score_after_rebuild = GetScore ()
selection.SelectAll ()
save.Quicksave ( kBestPostRebuild )
post_rebuild ( score_after_rebuild , start_idx , end_idx ) -- it calculates also the resulting curr_score
if ( recent_best_score - curr_score < delta ) then
print ( " cur score " .. roundto3 ( curr_score ) )
local_quake ( start_idx )
end
--if ( ss_control > 1 ) then
save.LoadSecondaryStructure ()
--end
curr_score = GetScore ()
updatebest(curr_score) -- 22/02/2014 and print improvements
if ( curr_score > qs10_best_score and improvement_made == false ) then
recentbest.Save ()
qs10_best_score = curr_score
save.Quickload ( kBestPostRebuild )
-- Bracket the area with frozen segments for easy recognition
selection.DeselectAll ()
if ( start_idx > 1 ) then
selection.Select ( start_idx - 1 )
end
if ( end_idx < n_residues ) then
selection.Select ( end_idx + 1 )
end
freeze.FreezeSelected ( true , false )
save.Quicksave ( kBestNonImprovedStructure )
recentbest.Restore ()
end
if ( improvement_made == true ) then
return 2
else
return 1
end
end
function rebuild ( rebuild_length )
n_possible_segs = n_residues - rebuild_length + 1 -- max number of potential zones
inc = Coprime ( n_possible_segs ) -- mostly 1, or 31 or 37 don't ask me why
-- The point of this Coprime, start_idx business is so we go through the protein in a
-- nonuniform way. Rather than rebuilding 1-4, 2-5 , 3-6 for example, we might do 21 4, 53-57, 3-6
-- or something like that
-- example: 100 residues, length 9 => n_possible_segs= 91
-- inc = 31
-- it tries 91 times from seg 1, 32, 64, 112-91= 20, 51, 82, 113-91= 22, 53, 84, 115-91= 24 etc
for i = 1 , n_possible_segs do -- it tries everything but it verifies afterwards if it is in the right zone (WORKONbool)
improvement_made = false -- global updated in rebuild_seg (similar to k)
end_idx = start_idx + rebuild_length - 1
if WORKONbool[start_idx] and WORKONbool[end_idx] then -- 05/02/2014
if ( start_idx >= min_residue and end_idx <= max_residue and
( ss_control == 2 or
( ss_control == 1 and IsSegmentALoop ( start_idx , end_idx ) == 0 ) or -- nb loops =0
( ss_control == 3 and IsSegmentALoop ( start_idx , end_idx ) < 2 ) ) ) then
rb = rb + 1
if rb > total_rebuild_loops then return end
print (string.format("rb %i/%i %i-%i (%i/%i) Score: %.3f Best score: %.3f",rb,total_rebuild_loops,start_idx,end_idx,i,n_possible_segs,current.GetScore(),recent_best_score))
if rb%10==0 then report_time(start_clock,start_time) end
save.Quickload ( kOriginalStructureOrNewBest )
if ( ss_control > 1 ) then
ConvertToLoop ( start_idx , end_idx )
end
recent_best_score = GetScore () -- reinitialises the recent best here
k = rebuild_seg ( start_idx, end_idx ) -- k= 1 if no improvement, 2 if improvement, 0 if rebuild failure
print("0=failure; 2=improvement:",k)
--if ( ss_control > 1 ) then
save.LoadSecondaryStructure ()
--end
end
end
start_idx = start_idx + inc -- look for the next possible zone
if ( start_idx > n_possible_segs ) then
repeat
start_idx = start_idx - n_possible_segs
until start_idx<=n_possible_segs -- starts again from the first segments
end
end -- for i
end
start_clock=os.clock()
start_time=os.time()
print(string.format("%s",os.date()))
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 results in Note for segment %i",note_number))
starting_score=current.GetScore()
--archiving user bands
ubandlist={}
USERBANDS=false
function archivebands() -- to keep user bands
--if you want to keep your own bands, for example between well formed sheets
ubcount=band.GetCount() -- global
for i=1, ubcount do
ubandlist[i]=i
end
if #ubandlist==0 then
USERBANDS=false
else
USERBANDS=true
end
return ubandlist
end
NeverDisableMyBands= true
function ManageBands() --if bands can't be saved, prevent qr from deleting them
if ubcount==0 or ubcount==nil then band.DeleteAll()
else
local bands=band.GetCount()
if bands>ubcount then
for i=bands, ubcount+1, -1 do band.Delete(i) end -- TO DO: il reste peut etre une bande ici
end
end
if not NeverDisableMyBands then band.DisableAll() end
end
-- Tidy up if necessary
archivebands()
ManageBands ()
n_residues = structure.GetCount ()
--if ( ss_control > 1 ) then
for i = 1, n_residues do
original_secondary_structure [ i ] = structure.GetSecondaryStructure ( i )
end
--end
save.SaveSecondaryStructure ()
rb = 0
save.Quicksave ( kOriginalStructureOrNewBest )
CI ( 1 )
recent_best_score = GetScore ()
print ( "Start score : " .. roundto3 ( recent_best_score ) )
if ( recent_best_score == 0 ) then
print ( "Suggest quitting as starting score < = 0" )
end
function print_ss_control()
if ( ss_control == 1 ) then
print ( "Loops only" )
elseif ( ss_control == 2 ) then
print ( "Loops, sheets, and helices" )
else
print ( "Loops with one non-loop allowed" )
end
end
if ( max_residue > n_residues ) then
max_residue = n_residues
end
if ( min_residue < 1 ) then
min_residue = 1
end
if ( max_residue <= min_residue ) then
print ( "Rebuild range error" )
loop_forever = false
end
multiplier = current.GetExplorationMultiplier ()
if ( multiplier <1 ) then
multiplier = 1
end
if ( true ) then -- min_residue > 1 or max_residue < n_residues ) then
print ( "Rebuild range " .. min_residue .. " to " .. max_residue )
else
print ( "Rebuild all" )
end
qs10_best_score = 0
if ( start_idx < 1 or start_idx > n_residues ) then
r = pseudorandom ( recent_best_score )
start_idx = 1 + n_residues * r
start_idx = start_idx - start_idx % 1
end
--START jeff101 display (copy this after the starting score and edit it)
function round(x)--cut all afer 3-rd place
return x-x%0.001
end
function down(x)
return x-x%1
end
ssstr=round(recent_best_score) -- init jeff101 function 19/8/2016
function jeff101Display(genScore, genEndScore, gen)
local genGain=genEndScore-genScore
if gen>1 and (gen-1)==5*down((gen-1)/5) then
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))
end
--END jeff101 display
function AskOptions()--03/02/2014
WORKON={{1,structure.GetCount()}} -- all segments 06/02/2014
if ss_control~=2 then --06/02/2014
WORKON=SegmentSetMinus(WORKON,FindAAtype("E"))
WORKON=SegmentSetMinus(WORKON,FindAAtype("H"))
end
if ss_control==3 then
WORKON=SegmentExtendSet(WORKON,1,1)
end
local ask=dialog.CreateDialog("Quaking remix Options")
repeat
ask.l1=dialog.AddLabel("Remix_length:")
ask.From_rebuild_length=dialog.AddSlider("From", From_rebuild_length, 1, maxFrom_rebuild_length, 0)
ask.To_rebuild_length=dialog.AddSlider("To", To_rebuild_length, 1, maxTo_rebuild_length, 0)
ask.number_of_remix=dialog.AddSlider("Max nb of remix",number_of_remix, 0, 85, 0)
--ask.allowcut=dialog.AddCheckbox("Cut before remix ",allowcut)
--ask.Fast=dialog.AddCheckbox("Fast (only 1 local shake after remix)",Fast)
ask.MaxNbBest=dialog.AddSlider("Work on best:",MaxNbBest, 0, number_of_remix, 0)
ask.NoWiggle=dialog.AddCheckbox("Never wiggle backbones",NoWiggle)
ask.number_of_rebuilds=dialog.AddSlider("Nb of rebuilds",number_of_rebuilds, 0, 30, 0)
ask.n_quakes=dialog.AddSlider("Nb of quakes",n_quakes, 0, 15, 0)
ask.ss_control=dialog.AddCheckbox("Include 1 seg before & after loops",false) -- 16/5/2016
ask.SEL= dialog.AddCheckbox("(Re)select where to work on ",false) -- 05/02/2014
ask.second_offset=dialog.AddSlider("Max Nb centres",second_offset, 0, 3, 0)--not sure it's useful
if USERBANDS then
ask.NeverDisableMyBands= dialog.AddCheckbox("Never disable my bands",true) -- 16/5/2016
end
ask.ok = dialog.AddButton("OK", 1)
ask.cancel = dialog.AddButton("Cancel", 0)
askresult=dialog.Show(ask)
if askresult > 0 then
To_rebuild_length=ask.To_rebuild_length.value
From_rebuild_length=ask.From_rebuild_length.value
second_offset=ask.second_offset.value
n_quakes=ask.n_quakes.value
number_of_rebuilds=ask.number_of_rebuilds.value
--Fast=ask.Fast.value
NoWiggle=ask.NoWiggle.value
--if HASMUTABLE then--19/02/2014
--do_remix=ask.remix.value --13/02/2014
number_of_remix=ask.number_of_remix.value
MaxNbBest=ask.MaxNbBest.value
if number_of_remix> 0 then do_remix=true else do_remix=false end
--allowcut=ask.allowcut.value
if USERBANDS then
NeverDisableMyBands=ask.NeverDisableMyBands.value -- 16/5/2016
end
if ask.ss_control.value then ss_control=3 end
--end
if ask.SEL.value then -- 05/02/2014
local SelMode={}
SelMode.askignorefrozen=false
SelMode.defignorefrozen=true
SelMode.askignorelocks=false
SelMode.defignorelocks=true
SelMode.askligands=false
SelMode.defligands=false
WORKON=AskForSelections("tvdl Select where to work on",SelMode) -- Reinitialization of WORKON
print("Selection is now, reselect if not ok:")
print(SegmentSetToString(WORKON)) -- 05/02/2014
ask.l4=dialog.AddLabel("Selection is now, reselect if not ok:")
ask.l5=dialog.AddLabel(SegmentSetToString(WORKON))
if askresult==1 then askresult=4 end --to force return to main menu
end
-- Do not try to rebuild frozen or locked parts or ligands
WORKON=SegmentSetMinus(WORKON,FindFrozen()) -- duplicates will be removed here
WORKON=SegmentSetMinus(WORKON,FindLocked())
WORKON=SegmentSetMinus(WORKON,FindAAtype("M"))
end
until askresult<2
return askresult > 0
end
-- Module AskSelections
-- 02-05-2012 Timo van der Laan, Free to use for non commercial purposes
function AskForSelections(title,mode) -- 05/02/2014
local result={{1,structure.GetCount()}} -- All segments, reinitialize always
if mode == nil then mode={} end --what will be in the dialog or not
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.askExtendZones==nil then mode.askExtendZones=true end -- 05/02/20
if mode.askligands==nil then mode.askligands=false end
if mode.askselected==nil then mode.askselected=false end
if mode.asknonselected==nil then mode.asknonselected=false end
if mode.askmutateonly==nil then mode.askmutateonly=false end
if mode.askignorelocks==nil then mode.askignorelocks=false end
if mode.askignorefrozen==nil then mode.askignorefrozen=false end
if mode.askranges==nil then mode.askranges=true end
if mode.defloops==nil then mode.defloops=true end -- default settings on screen
if mode.defsheets==nil then mode.defsheets=false end
if mode.defhelixes==nil then mode.defhelixes=false end
if mode.defExtendZones==nil then mode.defExtendZones=true end -- 05/02/20
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
if ss_control==1 then -- note: default ss_control must be initialized in the code above
mode.defloops, mode.defExtendZones=true, false
elseif ss_control==2 then
mode.defloops, mode.defsheets, mode.defhelixes, mode.defExtendZones=true, true, true, false
elseif ss_control==3 then
mode.defloops, mode.defExtendZones=true, true
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.askExtendZones then
ask.ExtendZones = dialog.AddCheckbox("Include 1 seg before & after structure",mode.defExtendZones)
elseif not mode.defExtendZones then
ask.noExtendZones= dialog.AddLabel("No additional seg")
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.askExtendZones then mode.defExtendZones=ask.ExtendZones.value end -- BK 05/02/2014
if mode.defExtendZones then
result=SegmentExtendSet(result,1,1) -- will extend loops etc with 1 seg before and 1 after
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
WORKON={{1,segCnt2}} -- for To Do
WORKONbool={}
function InitWORKONbool()
WORKONbool=SegmentSetToBool(WORKON)
end
function ZoneTest() --05/02/2014
maxlenght=0--the longest zone
local currenlenght=0
for i= min_residue, max_residue do
if WORKONbool[i] then
currenlenght = currenlenght + 1
if currenlenght>maxlenght then
maxlenght=currenlenght
end
else
currenlenght=0--end of this zone, reset for further zone
end
end
print("Longer zone=",maxlenght)
return maxlenght
end
function DumpErr(err) --03/02/2014
start,stop,line,msg=err:find(":(%d+):%s()")
err=err:sub(msg,#err)
p('---')
if err:find('Cancelled')~=nil then
p("User stop.")
else
p("unexpected error detected.")
p("Error line:", line)
p("Error:", err)
end
LastWish()
end
function LastWish()--03/02/2014
undo.SetUndo(true)
print("Restoring CI, best result and structures")
CI(1)
save.Quickload ( kOriginalStructureOrNewBest )
recentbest.Restore()
end
MutList=FindMutablesList()--19/02/2014 NOT USED
HASMUTABLE= (#MutList>0)
if HASMUTABLE then print("Mutables found") end
function MAIN()
InitWORKONbool() -- WORKON is known from call, here list of available segments
print_ss_control()
--if ss_control==(1 or 3) then
local check_length=ZoneTest()
if check_length < To_rebuild_length or check_length < From_rebuild_length then
print("Adjusting to available length")
if check_length < To_rebuild_length then
To_rebuild_length=check_length
maxTo_rebuild_length = check_length
end
if check_length < From_rebuild_length then
From_rebuild_length=check_length
maxFrom_rebuild_length = check_length
end
end
--end
if From_rebuild_length<To_rebuild_length then increment=1 else increment=-1 end
repeat
for rebuild_length = From_rebuild_length , To_rebuild_length , increment do
rebuild ( rebuild_length )
if rb > total_rebuild_loops then break end
end
if rb > total_rebuild_loops then break end
until loop_forever == false
end
if AskOptions() then
xpcall(MAIN,DumpErr)
end
save.Quickload ( kOriginalStructureOrNewBest )
report_time(start_clock,start_time)