| Class | Bio::RestrictionEnzyme::Range::SequenceRange |
| In: |
lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb
lib/bio/util/restriction_enzyme/range/sequence_range/fragment.rb lib/bio/util/restriction_enzyme/range/sequence_range/fragments.rb lib/bio/util/restriction_enzyme/range/sequence_range.rb |
| Parent: | Object |
A defined range over a nucleotide sequence.
This class accomadates having cuts defined on a sequence and returning the fragments made by those cuts.
| Bin | = | Struct.new(:c, :p) |
A Bio::RestrictionEnzyme::Range::SequenceRange::Bin holds an Array
of indexes for the primary and complement strands (p and
c accessors).
Example hash with Bin values:
{0=>#<struct Bio::RestrictionEnzyme::Range::SequenceRange::Bin c=[0, 1], p=[0]>,
2=>#<struct Bio::RestrictionEnzyme::Range::SequenceRange::Bin c=[], p=[1, 2]>,
3=>#<struct Bio::RestrictionEnzyme::Range::SequenceRange::Bin c=[2, 3], p=[]>,
4=>#<struct Bio::RestrictionEnzyme::Range::SequenceRange::Bin c=[4, 5], p=[3, 4, 5]>}
Note that the bin cannot be easily stored as a range since there may be nucleotides excised in the middle of a range. TODO: Perhaps store the bins as one-or-many ranges since missing nucleotides due to enzyme cutting is a special case. |
| c_left | [R] | Left-most index of complementary strand |
| c_right | [R] | Right-most index of complementary strand |
| cut_ranges | [R] | CutRanges in this SequenceRange |
| left | [R] | Left-most index of DNA sequence |
| p_left | [R] | Left-most index of primary strand |
| p_right | [R] | Right-most index of primary strand |
| right | [R] | Right-most index of DNA sequence |
| size | [R] | Size of DNA sequence |
# File lib/bio/util/restriction_enzyme/range/sequence_range.rb, line 56
56: def initialize( p_left = nil, p_right = nil, c_left = nil, c_right = nil )
57: raise ArgumentError if p_left == nil and c_left == nil
58: raise ArgumentError if p_right == nil and c_right == nil
59: (raise ArgumentError unless p_left <= p_right) unless p_left == nil or p_right == nil
60: (raise ArgumentError unless c_left <= c_right) unless c_left == nil or c_right == nil
61:
62: @p_left, @p_right, @c_left, @c_right = p_left, p_right, c_left, c_right
63: @left = [p_left, c_left].compact.sort.first
64: @right = [p_right, c_right].compact.sort.last
65: @size = (@right - @left) + 1 unless @left == nil or @right == nil
66: @cut_ranges = CutRanges.new
67: @__fragments_current = false
68: end
If the first object is HorizontalCutRange or VerticalCutRange, that is added to the SequenceRange. Otherwise this method builds a VerticalCutRange object and adds it to the SequenceRange.
Note: Cut occurs immediately after the index supplied. For example, a cut at ‘0’ would mean a cut occurs between bases 0 and 1.
Arguments
| Returns: | nothing |
# File lib/bio/util/restriction_enzyme/range/sequence_range.rb, line 86
86: def add_cut_range( p_cut_left=nil, p_cut_right=nil, c_cut_left=nil, c_cut_right=nil )
87: @__fragments_current = false
88: if p_cut_left.kind_of? CutRange # shortcut
89: @cut_ranges << p_cut_left
90: else
91: [p_cut_left, p_cut_right, c_cut_left, c_cut_right].each { |n| (raise IndexError unless n >= @left and n <= @right) unless n == nil }
92: @cut_ranges << VerticalCutRange.new( p_cut_left, p_cut_right, c_cut_left, c_cut_right )
93: end
94: end
Add a series of CutRange objects (HorizontalCutRange or VerticalCutRange).
Arguments
| Returns: | nothing |
# File lib/bio/util/restriction_enzyme/range/sequence_range.rb, line 102
102: def add_cut_ranges(*cut_ranges)
103: cut_ranges.flatten.each do |cut_range|
104: raise TypeError, "Not of type CutRange" unless cut_range.kind_of? CutRange
105: self.add_cut_range( cut_range )
106: end
107: end
Builds a HorizontalCutRange object and adds it to the SequenceRange.
Arguments
| Returns: | nothing |
# File lib/bio/util/restriction_enzyme/range/sequence_range.rb, line 116
116: def add_horizontal_cut_range( left, right=left )
117: @__fragments_current = false
118: @cut_ranges << HorizontalCutRange.new( left, right )
119: end
Calculates the fragments over this sequence range as defined after using the methods add_cut_range, add_cut_ranges, and/or add_horizontal_cut_range
Example return value:
[#<Bio::RestrictionEnzyme::Range::SequenceRange::Fragment:0x277bdc
@complement_bin=[0, 1],
@primary_bin=[0]>,
#<Bio::RestrictionEnzyme::Range::SequenceRange::Fragment:0x277bc8
@complement_bin=[],
@primary_bin=[1, 2]>,
#<Bio::RestrictionEnzyme::Range::SequenceRange::Fragment:0x277bb4
@complement_bin=[2, 3],
@primary_bin=[]>,
#<Bio::RestrictionEnzyme::Range::SequenceRange::Fragment:0x277ba0
@complement_bin=[4, 5],
@primary_bin=[3, 4, 5]>]
Arguments
| Returns: | Bio::RestrictionEnzyme::Range::SequenceRange::Fragments |
# File lib/bio/util/restriction_enzyme/range/sequence_range.rb, line 158
158: def fragments
159: return @__fragments if @__fragments_current == true
160: @__fragments_current = true
161:
162: num_txt = '0123456789'
163: num_txt_repeat = (num_txt * ( @size / num_txt.size.to_f ).ceil)[0..@size-1]
164: fragments = Fragments.new(num_txt_repeat, num_txt_repeat)
165:
166: cc = Bio::RestrictionEnzyme::Range::SequenceRange::CalculatedCuts.new(@size)
167: cc.add_cuts_from_cut_ranges(@cut_ranges)
168: cc.remove_incomplete_cuts
169:
170: create_bins(cc).sort.each { |k, bin| fragments << Fragment.new( bin.p, bin.c ) }
171: @__fragments = fragments
172: return fragments
173: end
Example:
cc = Bio::RestrictionEnzyme::Range::SequenceRange::CalculatedCuts.new(@size) cc.add_cuts_from_cut_ranges(@cut_ranges) cc.remove_incomplete_cuts bins = create_bins(cc)
Example return value:
{0=>#<struct Bio::RestrictionEnzyme::Range::SequenceRange::Bin c=[0, 1], p=[0]>,
2=>#<struct Bio::RestrictionEnzyme::Range::SequenceRange::Bin c=[], p=[1, 2]>,
3=>#<struct Bio::RestrictionEnzyme::Range::SequenceRange::Bin c=[2, 3], p=[]>,
4=>#<struct Bio::RestrictionEnzyme::Range::SequenceRange::Bin c=[4, 5], p=[3, 4, 5]>}
Arguments
| Returns: | Hash Keys are unique, values are Bio::RestrictionEnzyme::Range::SequenceRange::Bin objects filled with indexes of the sequence locations they represent. |
# File lib/bio/util/restriction_enzyme/range/sequence_range.rb, line 195
195: def create_bins(cc)
196: p_cut = cc.vc_primary
197: c_cut = cc.vc_complement
198: h_cut = cc.hc_between_strands
199:
200: if @circular
201: # NOTE
202: # if it's circular we should start at the beginning of a cut for orientation
203: # scan for it, hack off the first set of hcuts and move them to the back
204:
205: unique_id = 0
206: else
207: p_cut.unshift(-1) unless p_cut.include?(-1)
208: c_cut.unshift(-1) unless c_cut.include?(-1)
209: unique_id = -1
210: end
211:
212: p_bin_id = c_bin_id = unique_id
213: bins = {}
214: setup_new_bin(bins, unique_id)
215:
216: -1.upto(@size-1) do |idx| # NOTE - circular, for the future - should '-1' be replace with 'unique_id'?
217:
218: # if bin_ids are out of sync but the strands are attached
219: if (p_bin_id != c_bin_id) and !h_cut.include?(idx)
220: min_id, max_id = [p_bin_id, c_bin_id].sort
221: bins.delete(max_id)
222: p_bin_id = c_bin_id = min_id
223: end
224:
225: bins[ p_bin_id ].p << idx
226: bins[ c_bin_id ].c << idx
227:
228: if p_cut.include? idx
229: p_bin_id = (unique_id += 1)
230: setup_new_bin(bins, p_bin_id)
231: end
232:
233: if c_cut.include? idx # repetition
234: c_bin_id = (unique_id += 1) # repetition
235: setup_new_bin(bins, c_bin_id) # repetition
236: end # repetition
237:
238: end
239:
240: # Bin "-1" is an easy way to indicate the start of a strand just in case
241: # there is a horizontal cut at position 0
242: bins.delete(-1) unless @circular
243: bins
244: end
Modifies bins in place by creating a new element with key bin_id and initializing the bin.
# File lib/bio/util/restriction_enzyme/range/sequence_range.rb, line 248
248: def setup_new_bin(bins, bin_id)
249: bins[ bin_id ] = Bin.new
250: bins[ bin_id ].p = []
251: bins[ bin_id ].c = []
252: end