1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
|
require_relative "error"
#
# Methods for the RGFA class, which allow to handle segments in the graph.
#
module RGFA::Segments
def add_segment(gfa_line)
gfa_line = gfa_line.to_rgfa_line(validate: @validate)
segment_name = gfa_line.name
if @paths.has_key?(segment_name)
raise RGFA::DuplicatedLabelError,
"Error when adding line: #{gfa_line}\n"+
"a path already exists with the name: #{segment_name}\n"+
"Path: #{@paths[segment_name]}"
elsif @segments.has_key?(segment_name)
if @segments[segment_name].virtual?
@segments[segment_name].real!(gfa_line)
else
raise RGFA::DuplicatedLabelError,
"Error when adding line: #{gfa_line}\n"+
"a segment already exists with the name: #{segment_name}\n"+
"Segment: #{@segments[segment_name]}"
end
else
@segments[segment_name] = gfa_line
end
end
protected :add_segment
# Delete a segment from the RGFA graph
# @return [RGFA] self
# @param s [String, RGFA::Line::Segment] segment name or instance
def delete_segment(s, cascade=true)
s = segment!(s)
if cascade
connected_segments(s).each {|cs| unconnect_segments(s, cs)}
[:+, :-].each do |o|
s.paths[o].each {|pt| delete_path(pt)}
end
end
@segments.delete(s.name)
return self
end
# All segment lines of the graph
# @return [Array<RGFA::Line::Segment>]
def segments
@segments.values
end
# @!macro [new] segment
# Searches the segment with name equal to +segment_name+.
# @param s [String, RGFA::Line::Segment] a segment or segment name
# @return [RGFA::Line::Segment] if a segment is found
# @return [nil] if no such segment exists in the RGFA instance
#
def segment(s)
return s if s.kind_of?(RGFA::Line)
@segments[s.to_sym]
end
# @!macro segment
# @raise [RGFA::LineMissingError] if no such segment exists
def segment!(s)
seg = segment(s)
if seg.nil?
raise RGFA::LineMissingError, "No segment has name #{s}"+
"#{segment_names.size < 10 ?
"\nSegment names: "+segment_names.inspect : ''}"
end
seg
end
# @return [Array<String>] list of names of segments connected to +segment+
# by links or containments
def connected_segments(segment)
(neighbours([segment, :B]).map{|s, e| s} +
neighbours([segment, :E]).map{|s, e| s} +
contained_in(segment).map{|c| c.to} +
containing(segment).map{|c| c.from}).uniq
end
# Delete all links/containments involving two segments
# @return [RGFA] self
# @param segment1 [String, RGFA::Line::Segment] segment 1 name or instance
# @param segment2 [String, RGFA::Line::Segment] segment 2 name or instance
def unconnect_segments(segment1, segment2)
containments_between(segment1, segment2).each {|c| delete_containment(c)}
containments_between(segment2, segment1).each {|c| delete_containment(c)}
[[:B, :E], [:B, :B], [:E, :B], [:E, :E]].each do |end1, end2|
links_between([segment1, end1], [segment2, end2]).each do |l|
delete_link(l)
end
end
return self
end
end
|