Class Bio::RestrictionEnzyme::Range::SequenceRange::CalculatedCuts
In: lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb
Parent: Object

cc = CalculatedCuts.new(@size) cc.add_cuts_from_cut_ranges(@cut_ranges) cc.remove_incomplete_cuts

   1 2 3 4 5 6 7
   G A|T T A C A
      +-----+
   C T A A T|G T
   1 2 3 4 5 6 7

Primary cut = 2 Complement cut = 5 Horizontal cuts = 3, 4, 5

Methods

Included Modules

CutSymbol StringFormatting

Attributes

circular  [RW]  Set to true if the fragment CalculatedCuts is working on is circular
size  [R]  Size of the sequence being digested.
strands_for_display_current  [R]  If false the strands_for_display method needs to be called to update the contents of @strands_for_display. Becomes out of date whenever add_cuts_from_cut_ranges is called.

Public Class methods

[Source]

    # File lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb, line 87
87:   def initialize(size=nil, circular=false)
88:     @size = size
89:     @circular = circular
90:     @vc_primary = SortedNumArray[]
91:     @vc_complement = SortedNumArray[]
92:     @hc_between_strands = SortedNumArray[]
93:   end

Public Instance methods

Accepts an Array of CutRange type objects and applies them to @vc_complement, @vc_primary, and @hc_between_strands.


Arguments

Returns:nothing

[Source]

     # File lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb, line 102
102:   def add_cuts_from_cut_ranges(cut_ranges)
103:     @strands_for_display_current = false
104: 
105:     @vc_primary = @vc_primary.dup
106:     @vc_complement = @vc_complement.dup
107: 
108:     cut_ranges.each do |cut_range|
109:       @vc_primary.concat [cut_range.p_cut_left, cut_range.p_cut_right]
110:       @vc_complement.concat [cut_range.c_cut_left, cut_range.c_cut_right]
111: 
112:       # Add horizontal cut ranges.  This may happen from cuts made inbetween a
113:       # VerticalCutRange or may be specifically defined by a HorizontalCutRange.
114:       if cut_range.class == VerticalCutRange
115:         ( cut_range.min + 1 ).upto( cut_range.max ){|i| @hc_between_strands << i} if cut_range.min < cut_range.max
116:       elsif cut_range.class == HorizontalCutRange
117:         ( cut_range.hcuts.first ).upto( cut_range.hcuts.last ){|i| @hc_between_strands << i}
118:       end
119:     end
120:     clean_all
121:     #return
122:   end

Array of horizontal cuts between strands in 0-based index notation

[Source]

    # File lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb, line 61
61:   def hc_between_strands
62:     #$stderr.puts caller[0].inspect ###DEBUG
63:     @hc_between_strands.to_a
64:   end

Returns the same contents as hc_between_strands, but returns original data structure used in the class.

[Source]

    # File lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb, line 68
68:   def hc_between_strands_as_original_class
69:     @hc_between_strands
70:   end

There may be incomplete cuts made, this method removes the cuts that don‘t create sub-sequences for easier processing.

For example, stray horizontal cuts that do not end with a left and right separation:

  G A T T A C A
     +--  ---
  C T|A A T G T

Or stray vertical cuts:

  G A T T A C A
     +--   +
  C T|A A T|G T

However note that for non-circular sequences this would be a successful cut which would result in a floating ‘GT’ sub-sequence:

  G A T T A C A
           +---
  C T A A T|G T

Blunt cuts are also complete cuts.


Arguments

  • size: (optional) Size of the sequence being digested. Defined here or during initalization of CalculatedCuts.
Returns:nothing

[Source]

     # File lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb, line 152
152:   def remove_incomplete_cuts(size=nil)
153:     @strands_for_display_current = false
154:     @size = size if size
155:     raise IndexError, "Size of the strand must be provided here or during initalization." if !@size.kind_of?(Fixnum) and not @circular
156: 
157:     vcuts = @vc_primary + @vc_complement
158:     hcuts = @hc_between_strands
159:     last_index = @size - 1
160:     good_hcuts = SortedNumArray[]
161:     potential_hcuts = []
162: 
163:     if @circular
164:     # NOTE
165:     # if it's circular we should start at the beginning of a cut for orientation,
166:     # scan for it, hack off the first set of hcuts and move them to the back
167:     else
168:       vcuts.unshift(-1) unless vcuts.include?(-1)
169:       vcuts.push(last_index) unless vcuts.include?(last_index)
170:     end
171: 
172:     hcuts.each do |hcut|
173:       raise IndexError if hcut < -1 or hcut > last_index
174:       # skipped a nucleotide
175:       potential_hcuts.clear if !potential_hcuts.empty? and (hcut - potential_hcuts.last).abs > 1
176: 
177:       if potential_hcuts.empty?
178:         if vcuts.include?( hcut ) and vcuts.include?( hcut - 1 )
179:           good_hcuts << hcut
180:         elsif vcuts.include?( hcut - 1 )
181:           potential_hcuts << hcut
182:         end
183:       else
184:         if vcuts.include?( hcut )
185:           good_hcuts.concat(potential_hcuts)
186:           good_hcuts << hcut
187:           potential_hcuts.clear
188:         else
189:           potential_hcuts << hcut
190:         end
191:       end
192:     end
193: 
194:     check_vc = lambda do |vertical_cuts, opposing_vcuts|
195:       # opposing_vcuts is here only to check for blunt cuts, so there shouldn't
196:       # be any out-of-order problems with this
197:       good_vc = SortedNumArray[]
198:       vertical_cuts.each { |vc| good_vc << vc if good_hcuts.include?( vc ) or good_hcuts.include?( vc + 1 ) or opposing_vcuts.include?( vc ) }
199:       good_vc
200:     end
201: 
202:     @vc_primary = check_vc.call(@vc_primary, @vc_complement)
203:     @vc_complement = check_vc.call(@vc_complement, @vc_primary)
204:     @hc_between_strands = good_hcuts
205: 
206:     clean_all
207:   end

Sets @strands_for_display_current to true and populates @strands_for_display.


Arguments

  • +str1+: (optional) For displaying a primary strand. If nil a numbered sequence will be used in place.
  • +str2+: (optional) For displaying a complementary strand. If nil a numbered sequence will be used in place.
  • vcp: (optional) An array of vertical cut locations on the primary strand. If nil the contents of @vc_primary is used.
  • vcc: (optional) An array of vertical cut locations on the complementary strand. If nil the contents of @vc_complementary is used.
  • hc: (optional) An array of horizontal cut locations between strands. If nil the contents of @hc_between_strands is used.
Returns:Array An array with the primary strand with vertical cuts, the horizontal cuts, and the complementary strand with vertical cuts.

[Source]

     # File lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb, line 220
220:   def strands_for_display(str1 = nil, str2 = nil, vcp=nil, vcc=nil, hc=nil)
221:     return @strands_for_display if @strands_for_display_current
222:     vcs = '|'   # Vertical cut symbol
223:     hcs = '-'   # Horizontal cut symbol
224:     vhcs = '+'  # Intersection of vertical and horizontal cut symbol
225:       
226:     num_txt_repeat = lambda { num_txt = '0123456789'; (num_txt * (@size.div(num_txt.size) + 1))[0..@size-1] }
227:     (str1 == nil) ? a = num_txt_repeat.call : a = str1.dup
228:     (str2 == nil) ? b = num_txt_repeat.call : b = str2.dup
229: 
230:     if vcp and !vcp.is_a?(SortedNumArray) then
231:       vcp = SortedNumArray.new.concat(vcp)
232:     end
233:     if vcc and !vcc.is_a?(SortedNumArray) then
234:       vcc = SortedNumArray.new.concat(vcc)
235:     end
236:     if hc and !hc.is_a?(SortedNumArray) then
237:       hc = SortedNumArray.new.concat(hc)
238:     end
239: 
240:     vcp = @vc_primary if vcp==nil
241:     vcc = @vc_complement if vcc==nil
242:     hc = @hc_between_strands if hc==nil
243: 
244:     vcp.reverse_each { |c| a.insert(c+1, vcs) }
245:     vcc.reverse_each { |c| b.insert(c+1, vcs) }
246: 
247:     between = ' ' * @size
248:     hc.each {|hcut| between[hcut,1] = hcs }
249: 
250:     s_a = add_spacing(a, vcs)
251:     s_b = add_spacing(b, vcs)
252:     s_bet = add_spacing(between)
253: 
254:     # NOTE watch this for circular
255:     i = 0
256:     0.upto( s_a.size-1 ) do
257:       if (s_a[i,1] == vcs) or (s_b[i,1] == vcs)
258:         s_bet[i] = vhcs 
259:       elsif i != 0 and s_bet[i-1,1] == hcs and s_bet[i+1,1] == hcs
260:         s_bet[i] = hcs 
261:       end
262:       i+=1
263:     end
264: 
265:     @strands_for_display_current = true
266:     @strands_for_display = [s_a, s_bet, s_b]
267:   end

Array of vertical cuts on the complementary strand in 0-based index notation

[Source]

    # File lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb, line 49
49:   def vc_complement
50:     #$stderr.puts caller[0].inspect ###DEBUG
51:     @vc_complement.to_a
52:   end

Returns the same contents as vc_complement, but returns original data structure used in the class.

[Source]

    # File lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb, line 56
56:   def vc_complement_as_original_class
57:     @vc_complement
58:   end

Array of vertical cuts on the primary strand in 0-based index notation

[Source]

    # File lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb, line 37
37:   def vc_primary
38:     #$stderr.puts caller[0].inspect ###DEBUG
39:     @vc_primary.to_a
40:   end

Returns the same contents as vc_primary, but returns original data structure used in the class.

[Source]

    # File lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb, line 44
44:   def vc_primary_as_original_class
45:     @vc_primary
46:   end

Protected Instance methods

remove nil values, remove duplicate values, and sort @vc_primary, @vc_complement, and @hc_between_strands

[Source]

     # File lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb, line 275
275:   def clean_all
276:     [@vc_primary, @vc_complement, @hc_between_strands].collect { |a| a.delete(nil); a.uniq!; a.sort! }
277:   end

[Validate]