module RGFA::Multiplication

Method for the RGFA class, which allow to split a segment into multiple copies.

Public Instance Methods

multiply(segment, factor, copy_names: :lowcase, conserve_components: true) click to toggle source

Create multiple copies of a segment.

Automatic computation of the copy names

  • Can be overridden, by providing an array of copy names.

  • First, it is checked if the name of the original segment ends with a relevant string, i.e. a lower case letter (for :lowcase), an upper case letter (for :upcase), a digit (for :number), or the string +“_copy”+ plus one or more optional digits (for :copy).

  • If so, it is assumed, it was already a copy, and it is not altered.

  • If not, then a (for :lowcase), A (for :upcase), 1 (for :number), _copy (for :copy) is appended to the string.

  • Then, in all cases, next (*) is called on the string, until a valid, non-existant name is found for each of the segment copies

  • (*) = except for :copy, where for the first copy no digit is present, but for the following is, i.e. the segment names will be :copy, :copy2, :copy3, etc.

@param [Integer] factor multiplication factor; if 0, delete the segment;

if 1; do nothing; if > 1; number of copies to create

@param segment [String, RGFA::Line::Segment] segment name or instance @param [:lowcase, :upcase, :number, :copy, Array<String>] copy_names

<i>(Defaults to: +:lowcase+)</i>
Array of names for the copies of the segment,
or a symbol, which defines a system to compute the names from the name of
the original segment. See "automatic computation of the copy names".

@param [Boolean] conserve_components (Defaults to: true)

If factor == 0 (i.e. deletion), delete segment only if
{#cut_segment?}(segment) is +false+.

@return [RGFA] self

# File lib/rgfa/multiplication.rb, line 43
def multiply(segment, factor, copy_names: :lowcase,
             conserve_components: true)
  segment_name = segment.kind_of?(RGFA::Line) ? segment.name : segment
  if factor < 2
    return self if factor == 1
    return self if cut_segment?(segment_name) and conserve_components
    return delete_segment(segment_name)
  end
  s = segment!(segment_name)
  divide_segment_and_connection_counts(s, factor)
  copy_names = compute_copy_names(copy_names, segment_name, factor)
  copy_names.each {|cn| clone_segment_and_connections(s, cn)}
  return self
end

Private Instance Methods

clone_segment_and_connections(segment, clone_name) click to toggle source
# File lib/rgfa/multiplication.rb, line 139
def clone_segment_and_connections(segment, clone_name)
  cpy = segment.clone
  cpy.name = clone_name
  self << cpy
  [:links,:containments].each do |rt|
    [:from,:to].each do |dir|
      [:+, :-].each do |o|
        segment.send(rt)[dir][o].each do |l|
          lc = l.clone
          lc.set(dir, clone_name)
          self << lc
        end
      end
    end
  end
end
compute_copy_names(copy_names, segment_name, factor) click to toggle source
# File lib/rgfa/multiplication.rb, line 60
def compute_copy_names(copy_names, segment_name, factor)
  return nil if factor < 2
  accepted = [:lowcase, :upcase, :number, :copy]
  if copy_names.kind_of?(Array)
    return copy_names
  elsif !accepted.include?(copy_names)
    raise ArgumentError,
      "copy_names shall be an array of names or one of: "+
      accepted.inspect
  end
  retval = []
  next_name = segment_name.to_s
  case copy_names
  when :lowcase
    if next_name =~ /^.*[a-z]$/
      next_name = next_name.next
    else
      next_name += "b"
    end
  when :upcase
    if next_name =~ /^.*[A-Z]$/
      next_name = next_name.next
    else
      next_name += "B"
    end
  when :number
    if next_name =~ /^.*[0-9]$/
      next_name = next_name.next
    else
      next_name += "2"
    end
  when :copy
    if next_name =~ /^.*_copy(\d*)$/
      next_name += "1" if $1 == ""
      next_name = next_name.next
      copy_names = :number
    else
      next_name += "_copy"
    end
  end
  while retval.size < (factor-1)
    while retval.include?(next_name) or
          @segments.has_key?(next_name.to_sym) or
          @paths.has_key?(next_name.to_sym)
      if copy_names == :copy
        next_name += "1"
        copy_names = :number
      end
      next_name = next_name.next
    end
    retval << next_name
  end
  return retval
end
divide_counts(gfa_line, factor) click to toggle source
# File lib/rgfa/multiplication.rb, line 115
def divide_counts(gfa_line, factor)
  [:KC, :RC, :FC].each do |count_tag|
    if gfa_line.optional_fieldnames.include?(count_tag)
      value = (gfa_line.get(count_tag).to_f / factor)
      gfa_line.set(count_tag, value.to_i)
    end
  end
end
divide_segment_and_connection_counts(segment, factor) click to toggle source
# File lib/rgfa/multiplication.rb, line 124
def divide_segment_and_connection_counts(segment, factor)
  divide_counts(segment, factor)
  [:links,:containments].each do |rt|
    [:from,:to].each do |dir|
      [:+, :-].each do |o|
        segment.send(rt)[dir][o].each do |l|
          # circular link counts shall be divided only ones
          next if dir == :to and l.from == l.to
          divide_counts(l, factor)
        end
      end
    end
  end
end