Icon representing a recipe

Recipe: Helix Rebuild 5.1

created by spvincent

Profile


Name
Helix Rebuild 5.1
ID
100725
Shared with
Public
Parent
HR 5.1
Children
Created on
February 24, 2015 at 02:24 AM UTC
Updated on
February 24, 2015 at 02:24 AM UTC
Description

see first comment

Best for


Code


-- Globals original_secondary_structure = {} fixed_residues = {} helix_starts = {} helix_ends = {} use_helix = {} n_helices = 0 n_residues = 0 loop_spacer = 4 n_rebuilds = 6 score_type = 1 original_slow_filters_setting = 0 best_score = 0 mutate_not_shake = false test_for_credit = false -- Quicksave slots kOriginalStructureOrNewBest = 1 -- the starting structure, or any subsequent improvement, will be stored in this quicksave slot kBestPostRebuild_a = 2 kBestPostRebuild_b = 3 kBestPostRebuild_a_post_wiggle = 4 kTemp = 5 kBestWithSpacers = 6 kWiggleDuration = 12 inner_cylinder = {} outer_cylinder = {} inner_cylinder_radius = 12 outer_cylinder_radius = 16 pw_threshold_value = 100 function r3 ( i ) -- printing convenience return i - i % 0.001 end function GetScore () if ( score_type == 1 ) then score = current.GetEnergyScore () elseif ( score_type == 2 ) then behavior.SetSlowFiltersDisabled ( false ) score = current.GetScore () behavior.SetSlowFiltersDisabled ( true ) end return score end function DoesPuzzleHaveSlowFilters () init_setting = behavior.GetSlowFiltersDisabled () if ( init_setting == false ) then score_without_sf = current.GetScore () behavior.SetSlowFiltersDisabled ( true ) score_with_sf = current.GetScore () else score_with_sf = current.GetScore () behavior.SetSlowFiltersDisabled ( false ) score_without_sf = current.GetScore () end behavior.SetSlowFiltersDisabled ( init_setting ) if ( math.abs ( score_without_sf - score_with_sf ) >1e-3 ) then return true else return false end end function IsPuzzleMutable () for i = 1 , n_residues do if ( structure.IsMutable ( i ) ) then return true end end return false end function GetHelices () 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 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.DeselectAll () selection.SelectRange ( k , k ) structure.SetSecondaryStructureSelected ( "L" ) end 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 GetListOfFixedResidues () for i = 1 , n_residues do fixed_residues [ i ] = false end for i = 1 , n_residues do seg_backbone_frozen, seg_sidechain_frozen = freeze.IsFrozen ( i ) if ( seg_backbone_frozen == true ) then fixed_residues [ i ] = true end s = structure.IsLocked ( i ) if ( s == true ) then fixed_residues [ i ] = true end end end function IsHelixFrozen ( start_idx , end_idx ) for i = start_idx , end_idx do if ( fixed_residues [ i ] == true ) then return true end end return false end function ConstructListOfResiduesWithinInnerCylinder ( start_idx , end_idx ) for i = 1 , n_residues do inner_cylinder [ i ] = false end for i = 1 , n_residues do for j = start_idx , end_idx do if ( structure.GetDistance ( i , j ) < inner_cylinder_radius ) then inner_cylinder [ i ] = true end end end end function SelectInnerCylinder () selection.DeselectAll () for i = 1 , n_residues do if ( inner_cylinder [ i ] == true ) then selection.Select ( i ) end end end function ConstructListOfResiduesWithinOuterCylinder ( start_idx , end_idx ) for i = 1 , n_residues do outer_cylinder [ i ] = false end for i = 1 , n_residues do for j = start_idx , end_idx do if ( structure.GetDistance ( i , j ) < outer_cylinder_radius ) then outer_cylinder [ i ] = true end end end end function SelectOuterCylinder () selection.DeselectAll () for i = 1 , n_residues do if ( outer_cylinder [ i ] == true ) then selection.Select ( i ) end end end function WiggleNudge ( init_score ) save.Quicksave ( kTemp ) structure.WiggleSelected ( kWiggleDuration ) score = GetScore () if ( score < init_score ) then save.Quickload ( kTemp ) -- Filters can cause reduction in score score = init_score end save.Quicksave ( kTemp ) score_in_temp = score behavior.SetClashImportance ( 0.1 ) structure.WiggleSelected ( 1 ) behavior.SetClashImportance ( 1 ) structure.WiggleSelected ( kWiggleDuration ) score = GetScore () if ( score < score_in_temp ) then save.Quickload ( kTemp ) -- Filters can cause reduction in score score = score_in_temp end return score end function SelectBestPostRebuild () save.Quickload ( kBestPostRebuild_a ) structure.WiggleSelected ( kWiggleDuration ) score_a = GetScore () save.Quicksave ( kBestPostRebuild_a_post_wiggle ) save.Quickload ( kBestPostRebuild_b ) structure.WiggleSelected ( kWiggleDuration ) score_b = GetScore () if ( score_a > score_b ) then save.Quickload ( kBestPostRebuild_a_post_wiggle ) return score_a else return score_b end end function ShakeLowCIWiggle ( init_score ) save.Quicksave ( kTemp ) behavior.SetClashImportance ( 0.10 ) structure.ShakeSidechainsSelected ( 1 ) behavior.SetClashImportance ( 1 ) structure.WiggleSelected ( kWiggleDuration ) score = GetScore () if ( score < init_score ) then save.Quickload ( kTemp ) score = init_score end return score end function ShakeWiggleNudge ( init_score ) save.Quicksave ( kTemp ) if ( mutate_not_shake == true ) then structure.MutateSidechainsSelected ( 1 ) else structure.ShakeSidechainsSelected ( 1 ) end score_after_shake = GetScore () if ( score_after_shake < init_score ) then save.Quickload( kTemp ) score_after_shake = init_score end return WiggleNudge ( score_after_shake ) end function DetermineSpacers ( 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 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 return start_idx , end_idx end function ConstructSpacers ( start_idx , start_helix , end_helix , end_idx ) if ( start_helix > 1 ) then ConvertToLoop ( start_idx , start_helix - 1 ) end if ( end_helix < n_residues ) then ConvertToLoop ( end_helix + 1 , end_idx ) end end function RebuildHelix ( helix_index , start_helix , end_helix ) best_score_after_rebuild_and_shake_a = -99999 best_score_after_rebuild_and_shake_b = -99999 improvement_made = false rb = rb + 1 start_idx , end_idx = DetermineSpacers ( start_helix , end_helix ) save.Quickload ( kOriginalStructureOrNewBest ) ConstructSpacers ( start_idx , start_helix , end_helix , end_idx ) save.Quicksave ( kBestWithSpacers ) ConstructListOfResiduesWithinInnerCylinder ( start_idx , end_idx ) ConstructListOfResiduesWithinOuterCylinder ( start_idx , end_idx ) print ( "rb : " .. rb .. " (" .. start_helix .. "-" .. end_helix .. ")" ) for i = 1 , n_rebuilds do if ( i > 1 ) then save.Quickload ( kBestWithSpacers ) end selection.DeselectAll () selection.SelectRange ( start_idx , end_idx ) structure.RebuildSelected ( 1 ) score_after_rebuild = GetScore () SelectInnerCylinder () structure.ShakeSidechainsSelected ( 1 ) structure.WiggleSelected ( 1 ) score_after_shake_wiggle = GetScore () if ( score_after_shake_wiggle > math.min ( best_score_after_rebuild_and_shake_a , best_score_after_rebuild_and_shake_b ) ) then if ( best_score_after_rebuild_and_shake_b < best_score_after_rebuild_and_shake_a ) then best_score_after_rebuild_and_shake_b = score_after_shake_wiggle save.Quicksave ( kBestPostRebuild_b ) else best_score_after_rebuild_and_shake_a = score_after_shake_wiggle save.Quicksave ( kBestPostRebuild_a ) end end end SelectOuterCylinder () c_score = SelectBestPostRebuild () score_below_best = best_score - c_score if ( score_below_best < pw_threshold_value ) then d_score = ShakeWiggleNudge ( c_score ) if ( ( d_score > best_score ) and ( test_for_credit == false or creditbest.AreConditionsMet () == true ) ) then e_score = ShakeLowCIWiggle ( d_score ) print ( " " .. r3 ( -score_below_best ) .. " " .. r3 ( d_score - c_score ) .. " " .. r3 ( e_score - d_score ) ) improvement_made = true best_score = e_score save.LoadSecondaryStructure () save.Quicksave ( kOriginalStructureOrNewBest ) print ( "Improvement to " .. r3 ( best_score ) ) else print ( " " .. r3 ( -score_below_best ) .. " " .. r3 ( d_score - c_score ) ) end else print ( " " .. r3 ( -score_below_best ) ) end save.LoadSecondaryStructure () end function GetParameters () local dlog = dialog.CreateDialog ( "Helix rebuild 5.1" ) dlog.loop_spacer = dialog.AddSlider ( "Loop spacer" , loop_spacer , 0 , 6 , 0 ) for i = 1 , n_helices do dlog [ "helix" .. i ] = dialog.AddCheckbox ( helix_starts [ i ] .. "-" .. helix_ends [ i ] , true ) end dlog.n_rebuilds = dialog.AddSlider ( "Rebuilds" , n_rebuilds , 1 , 20 , 0 ) dlog.pw_threshold = dialog.AddSlider ( "Post wiggle threshold" , pw_threshold_value , 0 , 200 , 0 ) design_puzzle = IsPuzzleMutable () if ( design_puzzle == true ) then dlog.mutate= dialog.AddCheckbox ( "Mutate not shake" , true ) end dlog.credit_check = dialog.AddCheckbox ( "Check conditions met " , test_for_credit ) dlog.pw_threshold = dialog.AddSlider ( "Post wiggle threshold" , pw_threshold_value , 0 , 200 , 0 ) if ( DoesPuzzleHaveSlowFilters () == true ) then score_type = 2 end dlog.score_type = dialog.AddSlider ( "Score type" , score_type , 1 , 2 , 0 ) dlog.tp = dialog.AddLabel ( "1 = Normal : 2 = Normal for Slow Filters" ) dlog.ok = dialog.AddButton ( "OK" , 1 ) dlog.cancel = dialog.AddButton ( "Cancel" , 0 ) if ( dialog.Show ( dlog ) > 0 ) then loop_spacer = dlog.loop_spacer.value for i = 1 , n_helices do use_helix [ i ] = dlog [ "helix" .. i ].value end if ( design_puzzle == true ) then mutate_not_shake = dlog.mutate.value end test_for_credit = dlog.credit_check.value n_rebuilds = dlog.n_rebuilds.value pw_threshold_value = dlog. pw_threshold.value score_type = dlog.score_type.value return true else return false end end function main () print ( "Helix rebuild 5.1" ) 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 ) GetHelices () GetListOfFixedResidues () -- Delete locked/frozen helices for i = n_helices , 1 , -1 do if ( IsHelixFrozen ( helix_starts [ i ] , helix_ends [ i ] ) == true ) then table.remove ( helix_starts , i ) table.remove ( helix_ends , i ) end end n_helices = #helix_starts print ( n_helices .. " helices" ) qs10_best_score = 0 original_slow_filters_setting = behavior.GetSlowFiltersDisabled () if ( GetParameters () == false ) then print ( "error" ) error () end best_score = GetScore () print ( "Start score : " .. r3 ( best_score ) ) if ( score_type == 1 ) then print ( "Score type : Normal" ) elseif ( score_type == 2 ) then print ( "Score type : Normal/Slow Filters" ) end -- 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 print ( "Helix " .. i .. " : (" .. helix_starts [ i ] .. "-" .. helix_ends [ i ] .. ")" ) end print ( "Loop spacer " .. loop_spacer ) print ( n_rebuilds .. " rebuilds" ) rb = 0 save.Quicksave ( kOriginalStructureOrNewBest ) while ( true ) do for i = 1 , n_helices do RebuildHelix ( i , helix_starts [ i ] , helix_ends [ i ] ) end end end function cleanup () print ( "Cleaning up" ) behavior.SetClashImportance ( 1.0 ) save.Quickload ( kOriginalStructureOrNewBest ) behavior.SetSlowFiltersDisabled ( original_slow_filters_setting ) band.EnableAll () end --main () xpcall ( main , cleanup )

Comments


spvincent Lv 1

As 5.0 but fixed some problems related to Secondary structure (thanks LociOiling)

This script is probably most useful in the early/middle game (although the chess analogy can be pushed too far). Best used at Low or Auto Wiggle Power I think: the script never terminates.

Algorithm outline

For each helix
    For however many rebuilds specified
        Bracket it with a loop on either end
        Rebuild once
        Shake and wiggle briefly
        Record score
    end
    Take two best poses from above
    Wiggle each
    Take the best scoring pose, shake (optionally mutate) and wiggle.
    If the score looks as if it might result in a new best
        Wiggle at Low CI
        Wiggle
        If score is better than the current best  
            Shake at Low CI
            Wiggle
        end
        Record any gain
    end
end


Selection is restricted to the local vicinity of the helix for the sake of efficiency.
See values of inner_cylinder_radius and outer_cylinder_radius, which are probably unnecessarily conservative.

Loop spacer

Specifies the length of the loops at either end of the helix. The greater the value, the more freedom there is for the helix to adopt new configurations but the less likely you are to get small refinements.

Helix List

Initially all are selected. Helices with locked or frozen backbones will not appear in this list: frozen sidechains are allowable though.

Rebuilds

How many times to rebuild each helix

Mutate not shake

For puzzles with mutable residues only

Post wiggle threshold

Threshold that specifies the maximum allowable difference between the score after shake/wiggle and the best score to allow before proceeding with the mini-fuses. An optimization: the default value is perhaps a bit permissive.

Check conditions met

If set, check that conditions are met before accepting any improvement. For puzzles with RMSD conditions, etc.

Score type

Default is Normal. Normal/Slow Filters is for slow design/symmetry puzzles (for such puzzles the score type defaults to this mode): it toggles slow filters apart from scoring.

When running, the script will print out from one to three values after each helix rebuild set. The first value, which is usually negative, shows the difference between the score after Shake(or Mutate)/Wiggle and the best current score. This could be used to fine tune the threshold value above. The second value (which will only happen if the first value is numerically below the threshold value) will show the gain from LowCI Wiggle/Wiggle. The third value, if present, shows the gain, if any, from Low CI Shake/WiggleL in this case there will be a score improvement.