Code
-- Globals
original_secondary_structure = {}
helix_starts = {}
helix_ends = {}
use_helix = {}
n_helices = 0
closest_helix = {}
n_residues = 0
loop_spacer = 3
co_twist = false
clk_twist = true
band_length = 5
band_strength = 1
mutate_not_shake = false
test_for_credit = false
keep_trying = false
-- Quicksave slots
kOriginalStructureOrNewBest = 1 -- the starting structure, or any subsequent improvement, will be stored in this quicksave slot
function r3 ( i )
-- printing convenience
return i - i % 0.001
end
function GetScore ()
score = current.GetEnergyScore ()
return score
end
function IsPuzzleMutable ()
for i = 1 , n_residues do
if ( structure.IsMutable ( i ) ) then
return true
end
end
return false
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 GetClosestHelix ( i )
-- From the list of selected helices, choose the one closest to helix i
-- Very crude, looks at the distance between helix centres
mid_i = ( helix_starts [ i ] + helix_ends [ i ] ) / 2
closest_j = -1
closest_distance = 99999
for j = 1 , n_helices do
if ( j ~=i ) then
mid_j = ( helix_starts [ j ] + helix_ends [ j ] ) / 2
d = structure.GetDistance ( mid_i , mid_j )
if ( d < closest_distance ) then
closest_distance = d
closest_j = j
end
end
end
return closest_j
end
function IsWithinASelectedHelix ( residue )
for i = 1 , n_helices do
if ( use_helix [ i ] == true ) then
if ( ( residue >= helix_starts [ i ] ) and ( residue >= helix_ends [ i ] ) ) then
return true
end
end
end
return false
end
function ConvertToLoop ( first , last )
for k = first , last do
if ( original_secondary_structure [ k ] ~= "L" ) then
if ( IsWithinASelectedHelix ( k ) == false ) then
selection.SelectRange ( k , k )
structure.SetSecondaryStructureSelected ( "L" )
end
end
end
end
function nudge ()
selection.SelectAll ()
recentbest.Save ()
behavior.SetClashImportance ( 0.4 )
structure.WiggleSelected ( 1 )
behavior.SetClashImportance ( 1 )
structure.WiggleSelected ( 8 )
recentbest.Restore ()
end
function ConstructSpacers ( start_helix , end_helix )
local i
local ok
start_idx = start_helix - loop_spacer
if ( start_idx < 1 ) then
start_idx = 1
end
i = start_helix - 1
ok = true
while ( i >= start_idx and ok == true ) do
if ( structure.IsLocked ( i ) == true ) then
ok = false
start_idx = i + 1
else
i = i -1
end
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
i = end_helix + 1
ok = true
while ( i <= end_idx and ok == true ) do
if ( structure.IsLocked ( i ) == true ) then
ok = false
end_idx = i - 1
else
i = i +1
end
end
if ( end_helix < n_residues ) then
ConvertToLoop ( end_helix + 1 , end_idx )
end
return start_idx , end_idx
end
function ConstructBands ( start_helix , end_helix )
for i = math.max ( start_helix , 2 ) , math.min ( end_helix , n_residues - 1 ) do
if ( clk_twist ) then
band.Add ( i , i + 1 , i - 1 , band_length , math.pi/2 , math.rad ( 315 ) )
else
band.Add ( i , i - 1 , i + 1 , band_length , math.pi/2 , math.rad ( 315 ) )
end
end
if ( math.abs ( band_strength - 1.0 ) > 1e-3 ) then
n_bands = band.GetCount ()
for i = 1 , n_bands do
band.SetStrength ( i , band_strength )
end
end
end
function TwistHelix ( helix_index , start_helix , end_helix , closest_helix_idx )
if ( clk_twist == true ) then
print ( "H " .. helix_index .. " (c)" )
else
print ( "H " .. helix_index .. " (a)" )
end
improvement_made = false
save.Quickload ( kOriginalStructureOrNewBest )
best_score = GetScore ()
selection.DeselectAll ()
start_idx , end_idx = ConstructSpacers ( start_helix , end_helix )
ConstructBands ( start_helix , end_helix )
selection.SelectRange ( start_idx , end_idx )
if ( closest_helix_idx ~= 0 ) then
start_idx , end_idx = ConstructSpacers ( helix_starts [ closest_helix_idx ] , helix_ends [ closest_helix_idx ] )
ConstructBands ( helix_starts [ closest_helix_idx ] , helix_ends [ closest_helix_idx ] )
selection.SelectRange ( start_idx , end_idx )
end
structure.WiggleSelected ( 1 )
score_after_wiggle= GetScore ()
if ( math.abs ( score_after_wiggle - best_score ) < 1e-5 ) then
-- If the scores are still equal we probably have a locked segment
print ( "Possible issue with helix " .. helix_index .. " (" .. start_helix .. "-" .. end_helix .. ")" )
-- Trying to unfreeze: if successful rebuild will work next time this function is called
for i = start_idx , end_idx do
freeze.Unfreeze ( i , true , true )
end
return false
end
band.DeleteAll ()
selection.SelectAll ()
if ( mutate_not_shake == true ) then
structure.MutateSidechainsSelected ( 1 )
else
structure.ShakeSidechainsSelected ( 1 )
end
structure.WiggleSelected ( 2 , false , true ) -- sidechains
structure.WiggleSelected ( 12 )
selection.SelectAll ()
curr_score = GetScore ()
if ( ( curr_score > best_score ) and
( test_for_credit == false or creditbest.AreConditionsMet () == true ) ) then
improvement_made = true
best_score = curr_score
save.LoadSecondaryStructure ()
save.Quicksave ( kOriginalStructureOrNewBest )
print ( "Improvement to " .. r3 ( best_score ) )
end
save.LoadSecondaryStructure ()
return true
end
function get_parameters ()
local dlog = dialog.CreateDialog ( "Helix twister 1.0" )
dlog.loop_spacer = dialog.AddSlider ( "Loop spacer" , loop_spacer , 0 , 6 , 0 )
dlog.band_length = dialog.AddSlider ( "Band length" , band_length , 0.01 , 20 , 2 )
dlog.band_strength = dialog.AddSlider ( "Band strength" , band_strength , 0.01 , 10 , 2 )
for i = 1 , n_helices do
dlog [ "helix" .. i ] = dialog.AddCheckbox ( helix_starts [ i ] .. "-" .. helix_ends [ i ] , true )
end
dlog.co_twist = dialog.AddCheckbox ( "Co-twist" , co_twist )
design_puzzle = IsPuzzleMutable ()
if ( design_puzzle == true ) then
dlog.mutate= dialog.AddCheckbox ( "Mutate not shake" , false )
end
dlog.clk = dialog.AddCheckbox ( "Clockwise " , clk_twist )
dlog.credit_check = dialog.AddCheckbox ( "Check conditions met " , test_for_credit )
dlog.keep_trying = dialog.AddCheckbox ( "Keep trying " , keep_trying )
dlog.ok = dialog.AddButton ( "OK" , 1 )
dlog.cancel = dialog.AddButton ( "Cancel" , 0 )
if ( dialog.Show ( dlog ) > 0 ) then
loop_spacer = dlog.loop_spacer.value
band_length = dlog.band_length.value
band_strength = dlog.band_strength.value
for i = 1 , n_helices do
use_helix [ i ] = dlog [ "helix" .. i ].value
end
clk_twist = dlog.clk.value
co_twist = dlog.co_twist.value
if ( design_puzzle == true ) then
mutate_not_shake = dlog.mutate.value
end
test_for_credit = dlog.credit_check.value
keep_trying = dlog.keep_trying.value
return true
else
return false
end
end
function main ()
print ( "Helix twister 1" )
band.DeleteAll ()
n_residues = structure.GetCount ()
for i = 1, n_residues do
original_secondary_structure [ i ] = structure.GetSecondaryStructure ( i )
end
save.SaveSecondaryStructure ()
save.Quicksave ( kOriginalStructureOrNewBest )
behavior.SetClashImportance ( 1 )
best_score = GetScore ()
print ( "Start score : " .. r3 ( best_score ) )
get_helices ()
print ( n_helices .. " helices" )
qs10_best_score = 0
if ( get_parameters () == false ) then
print ( "error" )
error ()
end
print ( "Band length : " .. r3 ( band_length ) )
print ( "Band strength : " .. r3 ( band_strength ) )
-- Delete unused helices
for i = n_helices , 1 , -1 do
if ( use_helix [ i ] == false ) then
table.remove ( helix_starts , i )
table.remove ( helix_ends , i )
end
end
n_helices = #helix_starts
if ( n_helices == 0 ) then
print ( "No helix selected" )
error ()
end
for i = 1 , n_helices do
if ( co_twist == true ) then
closest_helix [ i ] = GetClosestHelix ( i )
if ( closest_helix [ i ] == -1 ) then
print ( "Co-rebuild needs more then one selected helix" )
error ()
end
else
closest_helix [ i ] = 0
end
end
for i = 1 , n_helices do
if ( co_twist == true ) then
print ( "Helix " .. i .. " : (" .. helix_starts [ i ] .. "-" .. helix_ends [ i ] .. ")" .. " + (" .. helix_starts [ closest_helix [ i ] ] .. " - " .. helix_ends [ closest_helix [ i ] ] .. " )" )
else
print ( "Helix " .. i .. " : (" .. helix_starts [ i ] .. "-" .. helix_ends [ i ] .. ")" )
end
end
for i = 1 , n_helices do
TwistHelix ( i , helix_starts [ i ] , helix_ends [ i ] , closest_helix [ i ] )
end
clk_twist = not clk_twist
for i = 1 , n_helices do
TwistHelix ( i , helix_starts [ i ] , helix_ends [ i ] , closest_helix [ i ] )
end
if ( keep_trying == true ) then
original_band_length = band_length
original_band_strength = band_strength
while ( true ) do
band_length = original_band_length + 0.5*( math.random () - 0.5 )
band_strength = original_band_strength + 0.2*( math.random () - 0.5 )
clk_twist = true
for i = 1 , n_helices do
TwistHelix ( i , helix_starts [ i ] , helix_ends [ i ] , closest_helix [ i ] )
end
clk_twist = false
for i = 1 , n_helices do
TwistHelix ( i , helix_starts [ i ] , helix_ends [ i ] , closest_helix [ i ] )
end
end
end
band.DeleteAll ()
save.Quickload ( kOriginalStructureOrNewBest )
end
function cleanup ()
print ( "Cleaning up" )
behavior.SetClashImportance ( 1.0 )
save.Quickload ( kOriginalStructureOrNewBest )
band.EnableAll ()
end
--main ()
xpcall ( main , cleanup )