A pair of SingleStrand and SingleStrandComplement objects with methods to add utility to their relation.
FIXME needs better docs
complement | [R] | The complement strand |
cut_locations | [R] | Cut locations in 0-based index format, DoubleStranded::CutLocations object |
cut_locations_in_enzyme_notation | [R] | Cut locations in enzyme index notation, DoubleStranded::CutLocationsInEnzymeNotation object |
primary | [R] | The primary strand |
Enzyme index notation: | 1..n, value before 1 is -1 |
Examples of the allowable cut locations for raw_cut_pairs follows. ‘p’ and ‘c’ refer to a cut location on the ‘p‘rimary and ‘c‘omplement strands.
1, [3,2], [20,22], 57 p, [p,c], [p, c], p
Which is the same as:
1, (3..2), (20..22), 57 p, (p..c), (p..c), p
Examples of partial cuts:
1, [nil,2], [20,nil], 57 p, [p, c], [p, c], p
# File lib/bio/util/restriction_enzyme/double_stranded.rb, line 71 71: def initialize(erp, *raw_cut_pairs) 72: # 'erp' : 'E'nzyme / 'R'ebase / 'P'attern 73: k = erp.class 74: 75: if k == Bio::REBASE::EnzymeEntry 76: # Passed a Bio::REBASE::EnzymeEntry object 77: 78: unless raw_cut_pairs.empty? 79: err = "A Bio::REBASE::EnzymeEntry object was passed, however the cut locations contained values. Ambiguous or redundant.\n" 80: err += "inspect = #{raw_cut_pairs.inspect}" 81: raise ArgumentError, err 82: end 83: initialize_with_rebase( erp ) 84: 85: elsif erp.kind_of? String 86: # Passed something that could be an enzyme pattern or an anzyme name 87: 88: # Decide if this String is an enzyme name or a pattern 89: if Bio::RestrictionEnzyme.enzyme_name?( erp ) 90: # FIXME we added this to rebase... 91: # Check if it's a known name 92: known_enzyme = false 93: known_enzyme = true if Bio::RestrictionEnzyme.rebase[ erp ] 94: 95: # Try harder to find the enzyme 96: unless known_enzyme 97: re = %r"^#{erp}$"i 98: Bio::RestrictionEnzyme.rebase.each { |name, v| (known_enzyme = true; erp = name; break) if name =~ re } 99: end 100: 101: if known_enzyme 102: initialize_with_rebase( Bio::RestrictionEnzyme.rebase[erp] ) 103: else 104: raise IndexError, "No entry found for enzyme named '#{erp}'" 105: end 106: 107: else 108: # Not an enzyme name, so a pattern is assumed 109: if erp =~ re_cut_symbol 110: initialize_with_pattern_and_cut_symbols( erp ) 111: else 112: initialize_with_pattern_and_cut_locations( erp, raw_cut_pairs ) 113: end 114: end 115: 116: elsif k == NilClass 117: err = "Passed a nil value. Perhaps you tried to pass a Bio::REBASE::EnzymeEntry that does not exist?\n" 118: err += "inspect = #{erp.inspect}" 119: raise ArgumentError, err 120: else 121: err = "I don't know what to do with class #{k} for erp.\n" 122: err += "inspect = #{erp.inspect}" 123: raise ArgumentError, err 124: end 125: 126: end
# File lib/bio/util/restriction_enzyme/double_stranded.rb, line 129 129: def aligned_strands 130: AlignedStrands.align(@primary.pattern, @complement.pattern) 131: end
See AlignedStrands.align_with_cuts
# File lib/bio/util/restriction_enzyme/double_stranded.rb, line 134 134: def aligned_strands_with_cuts 135: AlignedStrands.align_with_cuts(@primary.pattern, @complement.pattern, @primary.cut_locations, @complement.cut_locations) 136: end
Returns true if the cut pattern creates blunt fragments. (opposite of sticky)
# File lib/bio/util/restriction_enzyme/double_stranded.rb, line 140 140: def blunt? 141: as = aligned_strands_with_cuts 142: ary = [as.primary, as.complement] 143: ary.collect! { |seq| seq.split( cut_symbol ) } 144: # convert the cut sections to their lengths 145: ary.each { |i| i.collect! { |c| c.length } } 146: ary[0] == ary[1] 147: end
Takes a RestrictionEnzyme object and a numerical offset to the sequence and returns an EnzymeAction
restriction_enzyme: | RestrictionEnzyme |
offset: | Numerical offset of where the enzyme action occurs on the seqeunce |
# File lib/bio/util/restriction_enzyme/double_stranded.rb, line 160 160: def create_action_at( offset ) 161: # x is the size of the fully aligned sequence with maximum padding needed 162: # to make a match on the primary and complement strand. 163: # 164: # For example - 165: # Note how EcoRII needs extra padding on the beginning and ending of the 166: # sequence 'ccagg' to make the match since the cut must occur between 167: # two nucleotides and can not occur on the very end of the sequence. 168: # 169: # EcoRII: 170: # :blunt: "0" 171: # :c2: "5" 172: # :c4: "0" 173: # :c1: "-1" 174: # :pattern: CCWGG 175: # :len: "5" 176: # :name: EcoRII 177: # :c3: "0" 178: # :ncuts: "2" 179: # 180: # -1 1 2 3 4 5 181: # 5' - n^c c w g g n - 3' 182: # 3' - n g g w c c^n - 5' 183: # 184: # (w == [at]) 185: 186: x = aligned_strands.primary.size 187: 188: enzyme_action = EnzymeAction.new( offset, 189: offset + x-1, 190: offset, 191: offset + x-1) 192: 193: @cut_locations.each do |cut_location_pair| 194: # cut_pair is a DoubleStranded::CutLocationPair 195: p, c = cut_location_pair.primary, cut_location_pair.complement 196: if c >= p 197: enzyme_action.add_cut_range(offset+p, nil, nil, offset+c) 198: else 199: enzyme_action.add_cut_range(nil, offset+p, offset+c, nil) 200: end 201: end 202: 203: enzyme_action 204: end
Returns true if the cut pattern creates sticky fragments. (opposite of blunt)
# File lib/bio/util/restriction_enzyme/double_stranded.rb, line 151 151: def sticky? 152: !blunt? 153: end
# File lib/bio/util/restriction_enzyme/double_stranded.rb, line 302 302: def create_cut_locations(raw_cl) 303: @cut_locations_in_enzyme_notation = CutLocationsInEnzymeNotation.new( *raw_cl.collect {|cl| CutLocationPairInEnzymeNotation.new(cl)} ) 304: @cut_locations = @cut_locations_in_enzyme_notation.to_array_index 305: end
# File lib/bio/util/restriction_enzyme/double_stranded.rb, line 297 297: def create_primary_and_complement(primary_seq, p_cuts, c_cuts) 298: @primary = SingleStrand.new( primary_seq, p_cuts ) 299: @complement = SingleStrandComplement.new( primary_seq.forward_complement, c_cuts ) 300: end
# File lib/bio/util/restriction_enzyme/double_stranded.rb, line 292 292: def initialize_with_pattern_and_cut_locations( s, raw_cl ) 293: create_cut_locations(raw_cl) 294: create_primary_and_complement( Bio::Sequence::NA.new(s), @cut_locations_in_enzyme_notation.primary, @cut_locations_in_enzyme_notation.complement ) 295: end
# File lib/bio/util/restriction_enzyme/double_stranded.rb, line 280 280: def initialize_with_pattern_and_cut_symbols( s ) 281: p_cl = SingleStrand::CutLocationsInEnzymeNotation.new( strip_padding(s) ) 282: s = Bio::Sequence::NA.new( strip_cuts_and_padding(s) ) 283: 284: # * Reflect cuts that are in enzyme notation 285: # * 0 is not a valid enzyme index, decrement 0 and all negative 286: c_cl = p_cl.collect {|n| (n >= s.length or n < 1) ? ((s.length - n) - 1) : (s.length - n)} 287: 288: create_cut_locations( p_cl.zip(c_cl) ) 289: create_primary_and_complement( s, p_cl, c_cl ) 290: end
# File lib/bio/util/restriction_enzyme/double_stranded.rb, line 307 307: def initialize_with_rebase( e ) 308: p_cl = [e.primary_strand_cut1, e.primary_strand_cut2] 309: c_cl = [e.complementary_strand_cut1, e.complementary_strand_cut2] 310: 311: # If there's no cut in REBASE it's represented as a 0. 312: # 0 is an invalid index, it just means no cut. 313: p_cl.delete(0) 314: c_cl.delete(0) 315: raise IndexError unless p_cl.size == c_cl.size 316: initialize_with_pattern_and_cut_locations( e.pattern, p_cl.zip(c_cl) ) 317: end