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