Icon representing a recipe

Recipe: Loop rebuild 5.4

created by spvincent

Profile


Name
Loop rebuild 5.4
ID
49363
Shared with
Public
Parent
None
Children
Created on
June 11, 2014 at 15:44 PM UTC
Updated on
June 11, 2014 at 15:44 PM UTC
Description

See first comment

Best for


Code


-- Copyright notice. -- You may copy and paste at will. Plagiarize shamelessly! -- End copyright notice -- Changes since 5.2 -- 1) Added threshold parameters -- 2) Removed performance monitoring : it was cluttering up the code too much. -- 3) Added different score types -- Mostly user-configurable globals rebuild_length = 6 -- Length of sections to rebuild. number_of_rebuilds = 8 -- It'll look for the best score from this number of rebuilds. 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 loops_only = true -- If true, will still allow a single non-loop residue in the rebuild segment -- If false, non-loop residues will be temporarily converted to loops convert_to_loop = true test_for_credit = false -- If true, test that all conditions are satisfied before registering an improvement min_residue = 1 max_residue = 999 inner_sphere = {} outer_sphere = {} kInnerSphereRadius = 12 kOuterSphereRadius = 18 kDefaultWiggleDuration = 12 pw_threshold_value = 30 score_type = 1 -- Use of quicksave slots kOriginalStructureOrNewBest = 1 kBestPostRebuild_a = 2 kBestPostRebuild_b = 3 kBestPostRebuild_a_post_wiggle = 4 kTemp = 5 -- Globals original_secondary_structure = {} fixed_residues = {} n_residues = 0 best_score = 0 score_after_bc_wiggle = 0 -- Controls whether we should do a mini-fuze ( Shake at Low CI, Wiggle at CI of 1) after completion of the Rebuild sequence -- A value of 0 means do it iff there's an overall improvement: a high negative value would mean do it always: a high positive -- value would mean do it always. post_rebuild_threshold = 0 -- For design mutate_not_shake = false -- Begin function r3 ( x ) -- Round to 3 decimal places t = 10 ^ 3 return math.floor ( x*t + 0.5 ) / t end function GetScore () if ( score_type == 1 ) then score = current.GetScore () elseif ( score_type == 2 ) then score = current.GetEnergyScore () elseif ( score_type == 3 ) then score = current.GetScore () score = score * current.GetExplorationMultiplier () elseif ( score_type == 4 ) then score = 0 for i = 1 , n_residues do score = score + current.GetSegmentEnergySubscore ( i , "hiding" ) end elseif ( score_type == 5 ) then score = 0 for i = 1 , n_residues do score = score + current.GetSegmentEnergySubscore ( i , "bonding" ) end end return score end function IsPuzzleMutable () for i = 1 , n_residues do if ( structure.IsMutable ( i ) ) then return true end end return false end function Coprime ( n ) local primes = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101} i = #primes -- find the highest prime < 70% of the residue count and which is coprime with the number of residues while ( i >= 1 ) do if ( primes [ i ] < n*0.7 and n % primes [ i ] ~= 0 ) then return primes [ i ] end i = i - 1 end return 1 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 ) if ( IsSegmentALoop ( first , last ) > 0 ) then selection.DeselectAll ( ) selection.SelectRange ( first , last ) structure.SetSecondaryStructureSelected ( "L" ) 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 DoesSectionContainFixedResidues ( 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 NudgeWiggle () recentbest.Save () behavior.SetClashImportance ( 0.10 ) structure.ShakeSidechainsSelected ( 1 ) behavior.SetClashImportance ( 1 ) structure.WiggleSelected ( kDefaultWiggleDuration ) score = GetScore () recentbest.Restore () end function WiggleNIN () -- NIN = Nudge If Necessary aa_score = GetScore () structure.WiggleSelected ( kDefaultWiggleDuration ) score = GetScore () if ( ( score - aa_score ) < 1 ) then recentbest.Save () behavior.SetClashImportance ( 0.1 ) structure.WiggleSelected ( 1 ) behavior.SetClashImportance ( 1 ) structure.WiggleSelected ( kDefaultWiggleDuration ) recentbest.Restore () end end function WiggleTwoBestCandidatesAndSelectBest () save.Quickload ( kBestPostRebuild_a ) structure.WiggleSelected ( kDefaultWiggleDuration ) score_a = GetScore () save.Quicksave ( kBestPostRebuild_a_post_wiggle ) save.Quickload ( kBestPostRebuild_b ) structure.WiggleSelected ( kDefaultWiggleDuration ) score_b = GetScore () if ( score_a > score_b ) then save.Quickload ( kBestPostRebuild_a_post_wiggle ) end end function PostWiggle () init_score = GetScore () if ( score_type > 3 ) then return 1 -- Hiding or bonding elseif ( best_score - init_score < pw_threshold_value ) then if ( mutate_not_shake == true ) then structure.MutateSidechainsSelected ( 1 ) else structure.ShakeSidechainsSelected ( 1 ) end WiggleNIN ( kDefaultWiggleDuration ) return 1 else return 0 end end function FinalFuse ( start_x , end_x ) -- After rebuilding, if we've got a new best score (tweak able by adjusting post_rebuild_threshold ) , -- do a shake at low CI followed by a wiggle init_score = GetScore () score_below_best = best_score - init_score if ( score_type > 3 ) then return 1 -- Hiding or bonding elseif ( score_below_best < post_rebuild_threshold ) then NudgeWiggle () return 1 else return 0 end end function RecordImprovement () curr_score = GetScore () if ( ( test_for_credit == false ) or ( creditbest.AreConditionsMet () == true ) ) then best_score = curr_score save.LoadSecondaryStructure () save.Quicksave ( kOriginalStructureOrNewBest ) print ( "Improvement to ".. r3 ( best_score ) ) return 1 else return 0 end end function ConstructListOfResiduesWithinInnerSphere ( start_idx , end_idx ) for i = 1 , n_residues do inner_sphere [ i ] = false end for i = 1 , n_residues do for j = start_idx , end_idx do if ( structure.GetDistance ( i , j ) < kInnerSphereRadius ) then inner_sphere [ i ] = true end end end end function SelectInnerSphere () selection.DeselectAll () for i = 1 , n_residues do if ( inner_sphere [ i ] == true ) then selection.Select ( i ) end end end function ConstructListOfResiduesWithinOuterSphere ( start_idx , end_idx ) for i = 1 , n_residues do outer_sphere [ i ] = false end for i = 1 , n_residues do for j = start_idx , end_idx do if ( structure.GetDistance ( i , j ) < kOuterSphereRadius ) then outer_sphere [ i ] = true end end end end function SelectOuterSphere () selection.DeselectAll () for i = 1 , n_residues do if ( outer_sphere [ i ] == true ) then selection.Select ( i ) end end end function RebuildSeg ( start_idx , end_idx ) best_score_after_rebuild_and_shake_a = -99999 best_score_after_rebuild_and_shake_b = -99999 good_rebuild_found = false ConstructListOfResiduesWithinInnerSphere ( start_idx , end_idx ) ConstructListOfResiduesWithinOuterSphere ( start_idx , end_idx ) for i = 1 , number_of_rebuilds do save.Quickload ( kOriginalStructureOrNewBest ) if ( convert_to_loop == true ) then ConvertToLoop ( start_idx , end_idx ) end selection.DeselectAll () selection.SelectRange ( start_idx , end_idx ) structure.RebuildSelected ( 1 ) score_after_rebuild = GetScore () if ( math.abs ( score_after_rebuild - best_score ) >= 1e-5 ) then good_rebuild_found = true SelectInnerSphere () 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 end -- for i if ( good_rebuild_found == true ) then return 1 else return 0 end end function RebuildAllAtSpecifiedLength ( rebuild_length ) local inc max_possible_residue = max_residue - rebuild_length + 1 n_possible_segs = max_possible_residue - min_residue + 1 r = pseudorandom ( best_score ) start_idx = min_residue + n_possible_segs * r start_idx = start_idx - start_idx % 1 inc = Coprime ( n_possible_segs ) -- 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-24, 53-57, 3-6 -- or something like that candidate_section_found = false for i = 1 , n_possible_segs do end_idx = start_idx + rebuild_length - 1 assert ( start_idx >= min_residue and end_idx <= max_residue , "Range error" ) save.LoadSecondaryStructure () if ( ( DoesSectionContainFixedResidues ( start_idx , end_idx ) == false ) and ( loops_only == false or ( loops_only == true and IsSegmentALoop ( start_idx , end_idx ) < 2 ) ) ) then candidate_section_found = true rb = rb + 1 print ( "rb ".. rb .. " " .. start_idx .."-" .. end_idx .. " (" ..i .. "/" .. n_possible_segs .. ")" ) if ( RebuildSeg ( start_idx , end_idx ) == 1 ) then SelectOuterSphere () WiggleTwoBestCandidatesAndSelectBest () score_after_bc_wiggle = GetScore () if ( PostWiggle () == 1 ) then score_after_post_wiggle = GetScore () if ( FinalFuse ( start_idx , end_idx ) == 1 ) then score_after_final_fuse = GetScore () print ( " " .. r3 ( score_after_bc_wiggle - best_score ) .. " " .. r3 ( score_after_post_wiggle - score_after_bc_wiggle ) .. " " .. r3 ( score_after_final_fuse - score_after_post_wiggle ) ) RecordImprovement () else print ( " " .. r3 ( score_after_bc_wiggle - best_score ) .. " " .. r3 ( score_after_post_wiggle - score_after_bc_wiggle ) ) end else print ( " " .. r3 ( score_after_bc_wiggle - best_score ) ) end else print ( "Issue with section " .. start_idx .."-" .. end_idx ) end end start_idx = start_idx + inc if ( start_idx > max_possible_residue ) then start_idx = start_idx - n_possible_segs end end -- for i if ( candidate_section_found == false ) then print ( "No rebuildable sections found" ) exit (0) end end function GetParameters () local dlog = dialog.CreateDialog ( "Loop rebuild 5.4" ) dlog.rb_length = dialog.AddSlider ( "Rebuild length" , rebuild_length , 3 , 10 , 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.loops = dialog.AddCheckbox ( "Loops only" , loops_only ) dlog.cnvt_loops = dialog.AddCheckbox ( "Convert to loops" , convert_to_loop ) dlog.n_rebuilds = dialog.AddSlider ( "N rebuilds" , number_of_rebuilds , 2 , 50 , 0 ) dlog.div_1 = dialog.AddLabel ( "__________________________________________" ) design_puzzle = IsPuzzleMutable () if ( design_puzzle == true ) then dlog.mutate= dialog.AddCheckbox ( "Mutate" , true ) end dlog.pw_threshold = dialog.AddSlider ( "Post wiggle threshold" , pw_threshold_value , 0 , 200 , 0 ) dlog.score_type = dialog.AddSlider ( "Score type" , score_type , 1 , 5 , 0 ) dlog.tp = dialog.AddLabel ( "1 = Normal : 2 = Energy : 3 = Explore : 4 = Hiding" ) dlog.tp_2 = dialog.AddLabel ( "5 = Bonding" ) dlog.credit_check = dialog.AddCheckbox ( "Check conditions met " , test_for_credit ) dlog.ok = dialog.AddButton ( "OK" , 1 ) dlog.cancel = dialog.AddButton ( "Cancel" , 0 ) if ( dialog.Show ( dlog ) > 0 ) then rebuild_length = dlog.rb_length.value min_residue = dlog.min_residue.value max_residue = dlog.max_residue.value loops_only = dlog.loops.value convert_to_loop = dlog.cnvt_loops.value number_of_rebuilds = dlog.n_rebuilds.value if ( design_puzzle == true ) then mutate_not_shake = dlog.mutate.value end pw_threshold_value = dlog. pw_threshold.value score_type = dlog.score_type.value test_for_credit = dlog.credit_check.value return true else return false end end function main() band.DisableAll () n_residues = structure.GetCount () for i = 1, n_residues do original_secondary_structure [ i ] = structure.GetSecondaryStructure ( i ) end save.SaveSecondaryStructure () rb = 0 save.Quicksave ( kOriginalStructureOrNewBest ) behavior.SetClashImportance ( 1 ) if ( current.GetExplorationMultiplier () > 0 ) then score_type = 3 end if ( GetParameters () == false ) then return -- graceful exit end print ( "Loop rebuild 5.4" ) best_score = GetScore () if ( score_type == 1 ) then print ( "Score type : Normal" ) elseif ( score_type == 2 ) then print ( "Score type : Energy" ) elseif ( score_type == 3 ) then print ( "Score type : Exploration" ) elseif ( score_type == 4 ) then print ( "Score type : Hiding" ) elseif ( score_type == 5 ) then print ( "Score type : Bonding" ) end print ( "Start score : " .. r3 ( best_score ) ) print ( "Rebuild length : " .. rebuild_length ) if ( loops_only == true ) then print ( "Loops only" ) else print ( "Loops, sheets, and helices" ) if ( convert_to_loop == true ) then print ( "Converting to loops" ) end end max_residue = math.min ( n_residues , max_residue ) min_residue = math.max ( 1 , min_residue ) if ( max_residue < min_residue + rebuild_length - 1 ) then print ( "Rebuild range error." ) print ( "Max residue (" .. max_residue .. ") must be greater than or equal to Min residue (" .. min_residue .. ")" ) print ( "plus Rebuild Length (" .. rebuild_length .. ")" ) return end print ( "Rebuild range " .. min_residue .. " to " .. max_residue ) GetListOfFixedResidues () while true do RebuildAllAtSpecifiedLength ( rebuild_length ) end save.Quickload ( kOriginalStructureOrNewBest ) band.EnableAll () end function cleanup () print ( "Cleaning up" ) behavior.SetClashImportance ( 1.0 ) save.Quickload ( kOriginalStructureOrNewBest ) if ( convert_to_loop == true ) then save.LoadSecondaryStructure () end band.EnableAll () end --main () xpcall ( main , cleanup )

Comments


spvincent Lv 1

Changes since 5.2

1) Added threshold value for post-rebuild threshold improvements at low CI.
2) Alternate score functions


The default settings work pretty well if you don't want to be bothered reading this.

Given a number of rebuilds, which is the best one to use? Not necessarily the best-scoring one, or even the best-scoring one at low CI (see http://proteinoftheday.wordpress.com ), or the best -scoring after shake, but probably the best-scoring after shake and wiggle, which is what's going on here. Since Shake and wiggle are computationally expensive, considerable effort is made to work only with the relevant sub-section of the protein.

Tested and best used at Auto WP.

Algorithm outline


For each section to rebuild
   For each rebuild (defined by N Rebuilds)
      Rebuild once
      Set selection to that defined by Inner sphere
      Shake
      Wiggle for a fixed number of iterations
   end
   
   For each pose corresponding to the two best scores above
      Set selection to that defined by Outer sphere
      Wiggle adaptively in the NC-approved way
   end

   Take the best pose from the two above

   if initial score minus current score is less than threshold value
      Set selection to that defined by Outer sphere
      Shake (or Mutate if a design puzzle and that option chosen)
      Wiggle again if the Shake or Mutate gained anything.
      Wiggle at low CI
      Wiggle

      If we've gained an overall improvement
         Shake at low CI
         Wiggle at normal CI
         Record overall improvement
      end
   end

end

Dialog settings

Rebuild Length

How big a section to rebuild. Values from 4 to 6 are typically most useful.

Min residue, Max residue

The range to be rebuilt: by default the entire protein. These values can be usefully changed to whatever region of the protein you're working on: it's often desirable to set them to the start and end of a loop you're working on.

Loops only

When set, only loops will be rebuilt, although a single non-loop residue is allowed, This effectively means that the end residue of a helix or sheet will be treated as a loop for rebuild purposes.

Convert to Loops

Meaningful if and only if Loops nnly above is unchecked. If checked, non-loops will be converted to loops before rebuilding: if not the secondary structure will be maintained.

So for example, if you had a helix from 35-40 and you wished to rebuild it as a helix with, say , a loop spacer 2 residues wide on either end, suitable settings would be:

Rebuild Length 10
Min residue 33
Max residue 42
Loops only unchecked
Convert to loops unchecked

Number of rebuilds

How many rebuilds to attempt. The default is a bit of a compromise: too small a value means that not enough poses will be created: too many and there's a high probability of ending up working on a pose which is extremely similar to the starting structure.

Mutate not shake

This checkbox will appear if and only if the puzzle contains mutable residues. If set, the side chain wiggle in the algorithm will be replaced by a mutate.

Post wiggle threshold

An optimization used to prevent doing unnecessary shake/mutates. If the score after the best rebuild/shake/wiggle (as described in the algorithm) is below the best by more than this amount, then skip the subsequent fuze-like processing as an overall gain is unlikely,

The default value works quite well: it might be worth lowering it to say 10 for endgame running or raising it yo 60 or aso at the beginning, particular for dimer puzzles where overall scores are greater than usual.

Score type

Allows different scoring functions to be used - the values are:

1) Normal. Self-explanatory: the value as described by the program. Most of the time this is what you'll want

2) Exploration score. Oerhaps one day there will be another exploration puzzle.

3) Energy score. Design puzzles without those filters.

4) Hiding. Just use the hiding component of the score

5) Bonding. Just use the bonding component of the score

In the last two cases, no fuzing will be done, irrespective of the threshold value.

Check conditions met

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


After each rebuild sequence, up to three numbers are printed.

The first is the difference between the starting score and the best score after a rebuild/shake/wiggle sequence.

The second, which will only be shown if the number above plus the threshold value is greater than zero, shows the gain from the subsequent Shake/Wiggle/Wiggle at Low CI/Wiggle
sequence. Watching this value provides a clue as to what value to set the threshold slider: ideally the slider should be set to the maximum likely gain value .

The third, which will only be shown if the previous processes resulted in an overall gain, is the gain from doing the final Shake at low CI/Wiggle sequence.