Code
monit = false -- prints debug and performance info.
kBest = 1 -- the starting structure, or any subsequent improvement, will be stored in this quicksave slot
kQs10 = 10 -- the rebuilt structure that comes closest in score to the original without actually exceeding it
-- will be stored here
original_secondary_structure = {}
helix_starts = {}
helix_ends = {}
n_helices = 0
loop_spacer = 2
min_residue = 1
max_residue = 999
function roundto3 ( i )
-- printing convenience
return i - i % 0.001
end
function GetScore ()
score = current.GetEnergyScore ()
return score
end
function get_helices ()
within_helix = false
for i = 1, n_residues do
if ( structure.GetSecondaryStructure ( i ) == "H" ) then
if ( within_helix == false ) then
-- start of a new helix
within_helix = true
n_helices = n_helices + 1
helix_starts [ n_helices ] = i
end
elseif ( within_helix == true ) then
-- end of a helix
within_helix = false
helix_ends [ n_helices ] = i -1
end
end -- for i
if ( within_helix == true ) then
helix_ends [ n_helices ] = n_residues
end
end
function IsSegmentALoop ( first , last )
non_loop_found = false
for i = first , last do
if ( structure.GetSecondaryStructure ( i ) ~= "L" ) then
non_loop_found= true
end
end
return not non_loop_found
end
function ConvertToLoop ( first , last )
for k = first , last do
if ( original_secondary_structure [ k ] ~= "L" ) then
selection.DeselectAll ( )
selection.SelectRange ( k , k )
structure.SetSecondaryStructureSelected ( "L" )
end
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 ()
behavior.SetClashImportance ( 0.2 + 0.2 * pseudorandom ( score ) )
structure.WiggleSelected ( 1 )
behavior.SetClashImportance ( 1 )
structure.WiggleSelected ( 8 )
recentbest.Restore ()
end
function ShakeWiggleShakeNudge ()
-- returns the score after doing a SWSW: short-circuiting if things don't look promising
structure.ShakeSidechainsSelected ( 2 )
score_after_first_shake = GetScore ()
structure.WiggleSelected ( 15 )
score_after_wiggle = GetScore ()
if ( score_after_wiggle - score_after_first_shake < 10 and best_score - score_after_wiggle > 30 ) then
-- The wiggle got stuck and didn't achieve anything
nudge ( score_after_wiggle )
score_after_wiggle = GetScore ()
end
structure.ShakeSidechainsSelected ( 1 )
score_after_second_shake = GetScore ()
if ( score_after_second_shake - score_after_wiggle > 0.5 ) then
nudge ( score_after_second_shake )
score = GetScore ()
return score
else
return score_after_second_shake
end
end
function rebuild_helix ( start_helix , end_helix )
if ( start_helix < min_residue or end_helix > max_residue ) then
return false
end
improvement_made = false
save.Quickload ( kBest )
rb = rb + 1
print ( "rb : " .. rb .. " (" .. start_helix .. "-" .. end_helix .. ")" )
best_score = GetScore ()
start_idx = start_helix - loop_spacer
if ( start_idx < 1 ) then
start_idx = 1
end
if ( start_helix > 1 ) then
ConvertToLoop ( start_idx , start_helix - 1 )
end
end_idx = end_helix + loop_spacer
if ( end_idx > n_residues ) then
end_idx = n_residues
end
if ( end_helix < n_residues ) then
ConvertToLoop ( end_helix + 1 , end_idx )
end
selection.DeselectAll ()
selection.SelectRange ( start_idx , end_idx )
-- for some reason, do_local_rebuild ( 1) often leaves the protein unchanged
k = 0
repeat
k = k + 1
structure.RebuildSelected ( k )
score_after_rebuild = GetScore ()
until math.abs ( score_after_rebuild - best_score ) >= 1e-5 or k > 2
if ( math.abs ( score_after_rebuild - best_score ) < 1e-5 ) then
-- If the scores are still equal we probably have a locked segment
return false
end
selection.SelectAll ()
curr_score = ShakeWiggleShakeNudge ()
if ( curr_score > best_score ) then
improvement_made = true
best_score = curr_score
save.Quicksave ( kBest )
print ( "Improvement to " .. roundto3 ( best_score ) )
end
curr_score = GetScore ()
if ( curr_score > qs10_best_score and improvement_made == false ) then
qs10_best_score = curr_score
-- 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 ( kQs10 )
print ( "Storing " .. roundto3 ( qs10_best_score ) .. " in " .. kQs10 )
end
save.LoadSecondaryStructure ()
return true
end
function get_parameters ()
local dlog = dialog.CreateDialog ( "Helix rebuild" )
dlog.loop_spacer= dialog.AddSlider ( "Loop spacer" , loop_spacer , 0 , 6 , 0 )
dlog.min_residue = dialog.AddSlider ( "Min residue" , 1 , 1 , n_residues , 0 )
dlog.max_residue = dialog.AddSlider ( "Max residue" , n_residues , 1 , n_residues , 0 )
dlog.ok = dialog.AddButton ( "OK" , 1 )
dlog.cancel = dialog.AddButton ( "Cancel" , 0 )
if ( dialog.Show ( dlog ) > 0 ) then
loop_spacer = dlog.loop_spacer.value
min_residue = dlog.min_residue.value
max_residue = dlog.max_residue.value
return true
else
return false
end
end
print ( "Helix rebuild" )
-- Tidy up if necessary
band.DisableAll ()
n_residues = structure.GetCount ()
for i = 1, n_residues do
original_secondary_structure [ i ] = structure.GetSecondaryStructure ( i )
end
save.SaveSecondaryStructure ()
behavior.SetClashImportance ( 1 )
best_score = GetScore ()
print ( "Start score : " .. roundto3 ( best_score ) )
if ( start_score == 0 ) then
print ( "Suggest quitting as starting score < = 0" )
end
if ( get_parameters () == false ) then
return -- graceful exit
end
rb = 0
save.Quicksave ( kBest )
get_helices ()
for i = 1 , n_helices do
print ( "Helix " .. i .." : " .. helix_starts [ i ] .. " -" .. helix_ends [ i ] )
end
qs10_best_score = 0
while ( true ) do
for i = 1 , n_helices do
rebuild_helix ( helix_starts [ i ] , helix_ends [ i ] )
end
end
-- Well it'll never get here as things stand but the tidying up below would be nice to do
save.Quickload ( kBest )
band.EnableAll ()
monit = false -- prints debug and performance info.
kBest = 1 -- the starting structure, or any subsequent improvement, will be stored in this quicksave slot
kQs10 = 10 -- the rebuilt structure that comes closest in score to the original without actually exceeding it
-- will be stored here
original_secondary_structure = {}
helix_starts = {}
helix_ends = {}
n_helices = 0
loop_spacer = 2
min_residue = 1
max_residue = 999
function roundto3 ( i )
-- printing convenience
return i - i % 0.001
end
function GetScore ()
score = current.GetEnergyScore ()
return score
end
function get_helices ()
within_helix = false
for i = 1, n_residues do
if ( structure.GetSecondaryStructure ( i ) == "H" ) then
if ( within_helix == false ) then
-- start of a new helix
within_helix = true
n_helices = n_helices + 1
helix_starts [ n_helices ] = i
end
elseif ( within_helix == true ) then
-- end of a helix
within_helix = false
helix_ends [ n_helices ] = i -1
end
end -- for i
if ( within_helix == true ) then
helix_ends [ n_helices ] = n_residues
end
end
function IsSegmentALoop ( first , last )
non_loop_found = false
for i = first , last do
if ( structure.GetSecondaryStructure ( i ) ~= "L" ) then
non_loop_found= true
end
end
return not non_loop_found
end
function ConvertToLoop ( first , last )
for k = first , last do
if ( original_secondary_structure [ k ] ~= "L" ) then
selection.DeselectAll ( )
selection.SelectRange ( k , k )
structure.SetSecondaryStructureSelected ( "L" )
end
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 ()
behavior.SetClashImportance ( 0.2 + 0.2 * pseudorandom ( score ) )
structure.WiggleSelected ( 1 )
behavior.SetClashImportance ( 1 )
structure.WiggleSelected ( 8 )
recentbest.Restore ()
end
function ShakeWiggleShakeNudge ()
-- returns the score after doing a SWSW: short-circuiting if things don't look promising
structure.ShakeSidechainsSelected ( 2 )
score_after_first_shake = GetScore ()
structure.WiggleSelected ( 15 )
score_after_wiggle = GetScore ()
if ( score_after_wiggle - score_after_first_shake < 10 and best_score - score_after_wiggle > 30 ) then
-- The wiggle got stuck and didn't achieve anything
nudge ( score_after_wiggle )
score_after_wiggle = GetScore ()
end
structure.ShakeSidechainsSelected ( 1 )
score_after_second_shake = GetScore ()
if ( score_after_second_shake - score_after_wiggle > 0.5 ) then
nudge ( score_after_second_shake )
score = GetScore ()
return score
else
return score_after_second_shake
end
end
function rebuild_helix ( start_helix , end_helix )
if ( start_helix < min_residue or end_helix > max_residue ) then
return false
end
improvement_made = false
save.Quickload ( kBest )
rb = rb + 1
print ( "rb : " .. rb .. " (" .. start_helix .. "-" .. end_helix .. ")" )
best_score = GetScore ()
start_idx = start_helix - loop_spacer
if ( start_idx < 1 ) then
start_idx = 1
end
if ( start_helix > 1 ) then
ConvertToLoop ( start_idx , start_helix - 1 )
end
end_idx = end_helix + loop_spacer
if ( end_idx > n_residues ) then
end_idx = n_residues
end
if ( end_helix < n_residues ) then
ConvertToLoop ( end_helix + 1 , end_idx )
end
selection.DeselectAll ()
selection.SelectRange ( start_idx , end_idx )
-- for some reason, do_local_rebuild ( 1) often leaves the protein unchanged
k = 0
repeat
k = k + 1
structure.RebuildSelected ( k )
score_after_rebuild = GetScore ()
until math.abs ( score_after_rebuild - best_score ) >= 1e-5 or k > 2
if ( math.abs ( score_after_rebuild - best_score ) < 1e-5 ) then
-- If the scores are still equal we probably have a locked segment
return false
end
selection.SelectAll ()
curr_score = ShakeWiggleShakeNudge ()
if ( curr_score > best_score ) then
improvement_made = true
best_score = curr_score
save.Quicksave ( kBest )
print ( "Improvement to " .. roundto3 ( best_score ) )
end
curr_score = GetScore ()
if ( curr_score > qs10_best_score and improvement_made == false ) then
qs10_best_score = curr_score
-- 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 ( kQs10 )
print ( "Storing " .. roundto3 ( qs10_best_score ) .. " in " .. kQs10 )
end
save.LoadSecondaryStructure ()
return true
end
function get_parameters ()
local dlog = dialog.CreateDialog ( "Helix rebuild" )
dlog.loop_spacer= dialog.AddSlider ( "Loop spacer" , loop_spacer , 0 , 6 , 0 )
dlog.min_residue = dialog.AddSlider ( "Min residue" , 1 , 1 , n_residues , 0 )
dlog.max_residue = dialog.AddSlider ( "Max residue" , n_residues , 1 , n_residues , 0 )
dlog.ok = dialog.AddButton ( "OK" , 1 )
dlog.cancel = dialog.AddButton ( "Cancel" , 0 )
if ( dialog.Show ( dlog ) > 0 ) then
loop_spacer = dlog.loop_spacer.value
min_residue = dlog.min_residue.value
max_residue = dlog.max_residue.value
return true
else
return false
end
end
print ( "Helix rebuild" )
-- Tidy up if necessary
band.DisableAll ()
n_residues = structure.GetCount ()
for i = 1, n_residues do
original_secondary_structure [ i ] = structure.GetSecondaryStructure ( i )
end
save.SaveSecondaryStructure ()
behavior.SetClashImportance ( 1 )
best_score = GetScore ()
print ( "Start score : " .. roundto3 ( best_score ) )
if ( start_score == 0 ) then
print ( "Suggest quitting as starting score < = 0" )
end
if ( get_parameters () == false ) then
return -- graceful exit
end
rb = 0
save.Quicksave ( kBest )
get_helices ()
for i = 1 , n_helices do
print ( "Helix " .. i .." : " .. helix_starts [ i ] .. " -" .. helix_ends [ i ] )
end
qs10_best_score = 0
while ( true ) do
for i = 1 , n_helices do
rebuild_helix ( helix_starts [ i ] , helix_ends [ i ] )
end
end
-- Well it'll never get here as things stand but the tidying up below would be nice to do
save.Quickload ( kBest )
band.EnableAll ()