Icon representing a recipe

Recipe: Local Mutate 3.0

created by spvincent

Profile


Name
Local Mutate 3.0
ID
103229
Shared with
Public
Parent
None
Children
Created on
January 13, 2020 at 21:36 PM UTC
Updated on
January 13, 2020 at 21:36 PM UTC
Description

See first comment

Best for


Code


min_residue = 1 max_residue = 999 n_residues = 0 n_mutations = 0 delta_residue = 9 kMaxDelta = 20 best_score = 0 clash_importance_during_modify = 0.09 kWiggleIterations = 15 modify_count = 10 original_slow_filters_setting = 0 score_type = 1 loss_from_modify = {} original_residues = {} new_residues = {} scores = {} ids = {} start_time = 0 wiggle_sidechains_first = false -- Amino acids. Hydrophobics first. single_letter_codes = { "g","a","v","l","i","m","f","w","p","s","t","c","y","n","q","d","e","k","r","h"} three_letter_codes = { "Gly","Ala","Val","Leu","Ile","Met","Phe","Trp","Pro","Ser","Thr","Cys","Tyr","Asn","Gln","Asp","Glu","Lys","Arg","His"} -- Use of quicksave slots kOriginalStructureOrNewBest = 10 base_primary_sequence = {} n_sequence_changes = 0 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 behavior.SetFiltersDisabled ( false ) score = current.GetScore () behavior.SetFiltersDisabled ( true ) end return score end function aa1_to_aa3 ( k ) for j = 1, 20 do if ( k == single_letter_codes [ j ] ) then return three_letter_codes [ j ] end end return "Unk" end function get_aa3 ( i ) k = structure.GetAminoAcid ( i ) for j = 1, 20 do if ( k == single_letter_codes [ j ] ) then return three_letter_codes [ j ] end end return "Unk" end function GetBasePrimarySequence () for i = 1, n_residues do base_primary_sequence [ i ] = structure.GetAminoAcid ( i ) end end function GetNumberOfPrimarySequenceChanges () n_changes = 0 for i = 1, n_residues do if ( base_primary_sequence [ i ] ~= structure.GetAminoAcid ( i ) ) then n_changes = n_changes + 1 end end return n_changes end function ShellSort () -- Adapted from Numerical Recipes in C inc = 1 repeat inc = inc * 3 + 1 until inc > n_residues repeat inc = inc / 3 inc = inc - inc % 1 for i = inc + 1 , n_residues do v = scores [ i ] w = ids [ i ] j = i flag = false while ( flag == false and scores [ j - inc ] > v ) do scores [ j ] = scores [ j - inc ] ids [ j ] = ids [ j - inc ] j = j - inc if ( j <= inc ) then flag = true end end scores [ j ] = v ids [ j ] = w end until inc <= 1 end function PostModify ( i ) behavior.SetClashImportance ( 1.0 ) selection.SelectAll () if ( wiggle_sidechains_first == true ) then structure.WiggleSelected ( 1 , false , true ) -- sidechains end score_before_wiggle = GetScore () structure.WiggleSelected ( kWiggleIterations ) score_after_wiggle = GetScore () end function MutateResidue ( i ) local j local k save.Quickload ( kOriginalStructureOrNewBest ) for j = 1 , n_residues do scores [ j ] = structure.GetDistance ( i , j ) ids [ j ] = j end ShellSort () selection.DeselectAll () for j = 1 , modify_count do selection.Select ( ids [ j ] ) end behavior.SetClashImportance ( clash_importance_during_modify ) structure.MutateSidechainsSelected ( 1 ) score = GetScore () table.insert ( loss_from_modify , best_score - score ) n_mutations = GetNumberOfPrimarySequenceChanges () -- print ( "Hid " .. r3 ( scores [ modify_count ] ) .. " lim " .. r3 ( best_score - score ) .. " nc " .. n_mutations ) print ( " lom " .. r3 ( best_score - score ) .. " nc " .. n_mutations ) for k = 1, n_residues do if ( base_primary_sequence [ k ] ~= structure.GetAminoAcid ( k ) ) then print ( " " .. k .. " " .. aa1_to_aa3 ( base_primary_sequence [ k ] ) .. " -> " .. aa1_to_aa3 ( structure.GetAminoAcid ( k ) ) ) end end if ( math.abs ( score - best_score ) > 0.5 ) then PostModify ( i ) score = GetScore () if ( score > best_score ) then save.Quicksave ( kOriginalStructureOrNewBest ) GetBasePrimarySequence () best_score = score print ( "Improvement to " .. r3 ( best_score ) ) end end end function MutateAll () n = 1 for start_idx = 1 , delta_residue do i = min_residue - 1 + start_idx while ( i <= max_residue ) do print ( get_aa3 (i) .. " " .. i .. " (" .. n .. "/" .. max_residue - min_residue + 1 .. ")" ) MutateResidue ( i ) i = i + delta_residue n = n + 1 end end end function GetParameters () local dlog = dialog.CreateDialog ( "Local Mutate 3.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.delta_residue = dialog.AddSlider ( "Delta residue" , delta_residue , 1 , kMaxDelta , 0 ) dlog.cidm = dialog.AddSlider ( "Clash importance" , clash_importance_during_modify , 0 , 1.0 , 2 ) dlog.modify_count = dialog.AddSlider ( "Modify count" , modify_count , 1 , 40 , 0 ) dlog.score_type = dialog.AddSlider ( "Score type" , score_type , 1 , 2 , 0 ) dlog.tp2 = dialog.AddLabel ( "1 = Normal : 2 = Normal for Filters" ) dlog.ok = dialog.AddButton ( "OK" , 1 ) dlog.cancel = dialog.AddButton ( "Cancel" , 0 ) if ( dialog.Show ( dlog ) > 0 ) then min_residue = dlog.min_residue.value max_residue = dlog.max_residue.value delta_residue = dlog.delta_residue.value clash_importance_during_modify = dlog.cidm.value modify_count = dlog.modify_count.value score_type = dlog.score_type.value return true else return false end end function main () band.DisableAll () n_residues = structure.GetCount () save.Quicksave ( kOriginalStructureOrNewBest ) GetBasePrimarySequence () original_slow_filters_setting = behavior.GetSlowFiltersDisabled () if ( GetParameters () == false ) then return -- graceful exit end print ( "Local Mutate 3.0" ) max_residue = math.min ( n_residues , max_residue ) min_residue = math.max ( 1 , min_residue ) print ( "Mutate range " .. min_residue .. " to " .. max_residue ) if ( max_residue < min_residue ) then print ( "Mutate range error." ) return end print ( "Delta " .. delta_residue ) print ( "CI on modify " .. r3 ( clash_importance_during_modify ) ) print ( "Modify count " .. modify_count ) print ( "Score type " .. score_type ) print ( "" ) best_score = GetScore () print ( "Start score : " .. r3 ( best_score ) ) for i = 1 , n_residues do original_residues [ i ] = structure.GetAminoAcid ( i ) end start_time = os.time () MutateAll () cleanup () end function cleanup () print ( "Cleaning up" ) behavior.SetClashImportance ( 1.0 ) save.Quickload ( kOriginalStructureOrNewBest ) selection.SelectAll () band.EnableAll () behavior.SetSlowFiltersDisabled ( original_slow_filters_setting ) if ( #loss_from_modify > 1 ) then table.sort ( loss_from_modify ) mid_pt = math.ceil ( #loss_from_modify / 2 ) print ( "Median loss from modify " .. r3 ( loss_from_modify [ mid_pt ] ) ) end for i = 1 , n_residues do new_residues [ i ] = structure.GetAminoAcid ( i ) end for i = 1 , n_residues do if ( new_residues [ i ] ~= original_residues [ i ] ) then print ( i .. " : " .. aa1_to_aa3 ( original_residues [ i ] ) .. " -> " .. aa1_to_aa3 ( new_residues [ i ] ) ) end end end_time = os.time () print ( "Elapsed time : " .. os.difftime ( end_time , start_time ) .. " secs" ) end --main () xpcall ( main , cleanup )

Comments


spvincent Lv 1

Fairly minor update, changing a few parameters so that the defaults work well under most circumstances. I've found this a most useful midgame script.

A script similar in style to Rav Mutate, intended for design puzzles.

Algorithm outline

For each amino acid
Set the Clash Importance to something low
Select everything in the immediate neighbourhood of that residue
Mutate
Set the CI to 1 and select the whole protein
Wiggle
Record any improvement
end

Dialog settings

Min residue, Max residue

The range to be mutated : by default the whole protein.

Delta residue

Processing each residue in turn is inefficient: the selection in each case will be largely duplicated. This setting indicates the difference between successive residues. For example, if the min and max residues above are 1 and 100 respectively and the delta value is 5, then residues will be processed in the order 1,5,10,15,etc…..2,6,11 and so on.

Clash importance

The value during the initial mutate. Something that reduces the energy score by about 200 seems about right (the median reduction is printed out at the end of the script)

Modify count

Determines how many amino acids will be mutated at each step. They will be the closest (as measured by the distance between alpha carbons) to the residue being processed. Fewer means faster processi8ng.

Score type

If set to 2, filters are toggled on to determine the score only: other operations such as wiggle are done with filters off. If set to 1 (default), the initial filter setting will be used throughout.