Icon representing a recipe

Recipe: Loop rebuild 5.2

created by spvincent

Profile


Name
Loop rebuild 5.2
ID
48734
Shared with
Public
Parent
None
Children
None
Created on
March 29, 2014 at 20:07 PM UTC
Updated on
March 29, 2014 at 20:07 PM UTC
Description

See first comment

Best for


Code


-- Copyright notice. -- You may copy and paste at will. Plagiarize shamelessly! -- End copyright notice -- 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 exploration_puzzle = false 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 -- 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 -- 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 -- Performance monitoring. Result intended for import into Excel as comma-delimited text monit = false monit_best_score = 0 monit_score_below_best = 0 monit_gain_from_shake = 0 monit_gain_from_nudge_wiggle = 0 monit_gain_from_fuse= 0 -- Begin function r3 ( x ) -- Round to 3 decimal places t = 10 ^ 3 return math.floor ( x*t + 0.5 ) / t end function GetScore () score = current.GetEnergyScore () if ( exploration_puzzle == true ) then score = score * current.GetExplorationMultiplier () 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.07 ) 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 SelectBestPostRebuildNew () 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 init_score = GetScore () 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 WiggleNIN ( kDefaultWiggleDuration ) end end function RecoveryNew ( start_x , end_x ) -- After rebuilding, if we're within striking distance of the new best score , -- do a nudge/wiggle init_score = GetScore () score_below_best = best_score - init_score if ( monit ) then monit_score_below_best = score_below_best end if ( score_below_best < post_rebuild_threshold ) then NudgeWiggle () curr_score = GetScore () if ( monit == false ) then print ( " " .. r3 ( score_below_best ) .. " " .. r3 ( curr_score - init_score ) ) end if ( ( curr_score > best_score ) and ( test_for_credit == false or creditbest.AreConditionsMet () == true ) ) then best_score = curr_score save.LoadSecondaryStructure () save.Quicksave ( kOriginalStructureOrNewBest ) if ( monit == false ) then print ( "Improvement to ".. r3 ( best_score ) ) end end elseif ( monit == false ) then print ( " " .. r3 ( score_below_best ) ) 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 SelectOuterSphere () SelectBestPostRebuildNew () 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 if ( monit ) then monit_best_score = best_score monit_score_below_best = 0 monit_gain_from_shake = 0 monit_gain_from_nudge_wiggle = 0 monit_gain_from_fuse = 0 end candidate_section_found = true rb = rb + 1 if ( monit == false ) then print ( "rb ".. rb .. " " .. start_idx .."-" .. end_idx .. " (" ..i .. "/" .. n_possible_segs .. ")" ) end if ( RebuildSeg ( start_idx , end_idx ) == 1 ) then RecoveryNew ( start_idx , end_idx ) if ( monit ) then print ( r3 ( monit_best_score ) .. " , " .. start_idx .. " , " .. end_idx .. " , " .. r3 ( monit_score_below_best ) .. " , " .. r3 ( monit_gain_from_shake ) .. " , " .. r3 ( monit_gain_from_nudge_wiggle ) .. " , " .. r3 ( monit_gain_from_fuse ) ) end 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.2" ) 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 if ( exploration_puzzle == true ) then dlog.exploration = dialog.AddCheckbox ( "Exploration score" , true ) end 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 if ( exploration_puzzle == true ) then exploration_puzzle = dlog.exploration end 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 exploration_puzzle = true end if ( GetParameters () == false ) then return -- graceful exit end best_score = GetScore () 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 () if ( monit ) then print ( "Start score" .. " , " .. "Start idx" .. " , " .. "End idx" .. " , " .. "Score below best" .. " , " .. "Gain from shake" .. " , " .. "Gain from nudge wiggle" .. " , " .. "Gain from fuse" ) end 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.0

LR 5.0 didn't work terrible well with the new wiggle scheme: tended to get stuck too easily. This should hopefully be improved here (tested on Auto WP)

1) Doesn't get stuck so easily
2) Removed superfluous sliders: the parameters they control are now constants and can of course be changed if desired.
3) Default number of rebuilds reduced as FoldIt's Rebuild function seems to do a better job.


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.

Best used at high 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
   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.

   If we've gained an overall improvement
      Shake at low CI
      Wiggle at normal CI
      Record overall improvement
  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.

Check conditions met:

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