module RGFA::Multiplication
Method for the RGFA
class, which allow to split a segment into multiple copies.
Public Instance Methods
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
# 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
# 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
# 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
# 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