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