Class: RGFA::Line::Link

Inherits:
RGFA::Line show all
Defined in:
lib/rgfa/line/link.rb

Overview

A link connects two segments, or a segment to itself.

Constant Summary collapse

RECORD_TYPE =
:L
REQFIELDS =
[:from, :from_orient, :to, :to_orient, :overlap]
PREDEFINED_OPTFIELDS =
[:MQ, :NM, :RC, :FC, :KC]
DATATYPE =
{
   :from => :lbl,
   :from_orient => :orn,
   :to => :lbl,
   :to_orient => :orn,
   :overlap => :cig,
   :MQ => :i,
   :NM => :i,
   :RC => :i,
   :FC => :i,
   :KC => :i,
}

Constants inherited from RGFA::Line

DELAYED_PARSING_DATATYPES, DIRECTION, FIELD_DATATYPE, OPTFIELD_DATATYPE, ORIENTATION, RECORD_TYPES, RECORD_TYPE_LABELS, REQFIELD_DATATYPE, SEPARATOR

Instance Method Summary collapse

Methods inherited from RGFA::Line

#==, #clone, #delete, #field_to_s, #fieldnames, #get, #get!, #get_datatype, #initialize, #method_missing, #optional_fieldnames, #real!, #record_type, #required_fieldnames, #respond_to?, #set, #set_datatype, subclass, #tags, #to_a, #to_rgfa_line, #to_s, #validate!, #validate_field!, #virtual?

Constructor Details

This class inherits a constructor from RGFA::Line

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class RGFA::Line

Instance Method Details

#circular?Boolean

Returns is the from and to segments are equal.

Returns:

  • (Boolean)

    is the from and to segments are equal



43
44
45
# File 'lib/rgfa/line/link.rb', line 43

def circular?
  from.to_sym == to.to_sym
end

#circular_same_end?Boolean

Returns is the from and to segments are equal.

Returns:

  • (Boolean)

    is the from and to segments are equal



48
49
50
# File 'lib/rgfa/line/link.rb', line 48

def circular_same_end?
  from_end == to_end
end

#compatible?(other_oriented_from, other_oriented_to, other_overlap = [], equivalent = true) ⇒ Boolean

Compares a link and optionally the reverse link, with two oriented_segments and optionally an overlap.

Parameters:

Returns:

  • (Boolean)

    does the link or, if equivalent, the reverse link go from the first oriented segment to the second with an overlap equal to the provided one (if not empty)?



335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/rgfa/line/link.rb', line 335

def compatible?(other_oriented_from, other_oriented_to, other_overlap = [],
                equivalent = true)
  other_overlap = other_overlap.to_cigar
  is_direct = compatible_direct?(other_oriented_from, other_oriented_to,
                                 other_overlap)
  if is_direct
    return true
  elsif equivalent
    return compatible_reverse?(other_oriented_from, other_oriented_to,
                        other_overlap)
  else
    return false
  end
end

#compatible_direct?(other_oriented_from, other_oriented_to, other_overlap = []) ⇒ Boolean

Compares a link with two oriented segments and optionally an overlap.

Parameters:

Returns:

  • (Boolean)

    does the link go from the first oriented segment to the second with an overlap equal to the provided one (if not empty)?



357
358
359
360
361
362
# File 'lib/rgfa/line/link.rb', line 357

def compatible_direct?(other_oriented_from, other_oriented_to,
                       other_overlap = [])
  (oriented_from == other_oriented_from and
   oriented_to == other_oriented_to) and
   (overlap.empty? or other_overlap.empty? or (overlap == other_overlap))
end

#compatible_reverse?(other_oriented_from, other_oriented_to, other_overlap = []) ⇒ Boolean

Compares the reverse link with two oriented segments and optionally an overlap.

Parameters:

Returns:

  • (Boolean)

    does the reverse link go from the first oriented segment to the second with an overlap equal to the provided one (if not empty)?



372
373
374
375
376
377
# File 'lib/rgfa/line/link.rb', line 372

def compatible_reverse?(other_oriented_from, other_oriented_to,
                        other_overlap = [])
  (oriented_to == other_oriented_from.invert_orient and
   oriented_from == other_oriented_to.invert_orient) and
   (overlap.empty? or other_overlap.empty? or (overlap == other_overlap))
end

#eql?(other) ⇒ Boolean

Note:

Inverting the strand of both links and reversing the CIGAR operations (order/type), one obtains a reverse but equivalent link.

Compares two links and determine their equivalence. Thereby, optional fields are not considered.

Parameters:

Returns:

  • (Boolean)

    are self and other equivalent?

See Also:



255
256
257
# File 'lib/rgfa/line/link.rb', line 255

def eql?(other)
  same?(other) or reverse?(other)
end

#eql_optional?(other) ⇒ Boolean

Note:

This method shall be overridden if custom optional fields are defined, which have a “reverse” operation which determines their value in the equivalent but reverse link.

Compares the optional fields of two links.

Parameters:

Returns:

  • (Boolean)

    are self and other equivalent?

See Also:



268
269
270
271
# File 'lib/rgfa/line/link.rb', line 268

def eql_optional?(other)
  (self.optional_fieldnames.sort == other.optional_fieldnames.sort) and
    optional_fieldnames.each {|fn| self.get(fn) == other.get(fn)}
end

#from_endRGFA::SegmentEnd

Returns the segment end represented by the from/from_orient fields.

Returns:

  • (RGFA::SegmentEnd)

    the segment end represented by the from/from_orient fields



66
67
68
# File 'lib/rgfa/line/link.rb', line 66

def from_end
  [from, from_orient == :+ ? :E : :B].to_segment_end
end

#from_nameSymbol

The from segment name, in both cases where from is a segment name (Symbol) or a segment (RGFA::Line::Segment)

Returns:



104
105
106
# File 'lib/rgfa/line/link.rb', line 104

def from_name
  from.to_sym
end

#hashObject

Computes an hash for including a link in an Hash tables, so that the hash of a link and its reverse is the same. Thereby, optional fields are not considered.

See Also:



321
322
323
# File 'lib/rgfa/line/link.rb', line 321

def hash
  from_end.hash + to_end.hash + overlap.hash + reverse_overlap.to_s.hash
end

#normal?Boolean

Returns true if the link is normal, false otherwise

Each link has an equivalent reverse link. Consider a link of A to B with a overlap 1M1I2M:

from+ to to+ (1M1I2M) == to- to from- (2M1D1M)
from- to to- (1M1I2M) == to+ to from+ (2M1D1M)
from+ to to- (1M1I2M) == to+ to from- (2M1D1M)
from- to to+ (1M1I2M) == to- to from+ (2M1D1M)

Consider also the special case, where from == to and the overlap is not specified, or equal to its reverse:

from+ to from+ (*) == from- to from- (*) # left has a +; right has no +
from- to from- (*) == from+ to from+ (*) # left has no +; right has a +
from+ to from- (*) == from+ to from- (*) # left == right
from- to from+ (*) == from- to from+ (*) # left == right

Thus we define a link as normal if:

  • from < to (lexicographical comparison of segments)

  • from == to and overlap.to_s < reverse_overlap.to_s

  • from == to, overlap == reverse_overlap and at least one orientation is +

Returns:

  • (Boolean)


142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/rgfa/line/link.rb', line 142

def normal?
  if from_name < to_name
    return true
  elsif from_name > to_name
    return false
  else
    overlap_s = overlap.to_s
    reverse_overlap_s = reverse_overlap.to_s
    if overlap_s < reverse_overlap_s
      return true
    elsif overlap_s > reverse_overlap_s
      return false
    else
      return [from_orient, to_orient].include?(:+)
    end
  end
end

#normalize!RGFA::Line::Link

Note:

The path references are not corrected by this method; therefore the method shall be used before the link is embedded in a graph.

Returns the unchanged link if the link is normal, otherwise reverses the link and returns it.

Returns:



167
168
169
# File 'lib/rgfa/line/link.rb', line 167

def normalize!
  reverse! if !normal?
end

#oriented_fromRGFA::OrientedSegment

Returns the oriented segment represented by the from/from_orient fields.

Returns:



54
55
56
# File 'lib/rgfa/line/link.rb', line 54

def oriented_from
  [from, from_orient].to_oriented_segment
end

#oriented_toRGFA::OrientedSegment

Returns the oriented segment represented by the to/to_orient fields.

Returns:



60
61
62
# File 'lib/rgfa/line/link.rb', line 60

def oriented_to
  [to, to_orient].to_oriented_segment
end

#other(segment) ⇒ Symbol

The other segment of a link

Parameters:

Returns:

  • (Symbol)

    the name of the other segment of the link if circular, then segment

Raises:



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/rgfa/line/link.rb', line 29

def other(segment)
  segment_name =
    (segment.kind_of?(RGFA::Line::Segment) ? segment.name : segment.to_sym)
  if segment_name == from.to_sym
    to
  elsif segment_name == to.to_sym
    from
  else
    raise RGFA::LineMissingError,
      "Link #{self} does not involve segment #{segment_name}"
  end
end

#other_end(segment_end) ⇒ RGFA::SegmentEnd

Returns the other segment end.

Parameters:

Returns:

Raises:

  • (ArgumentError)

    if segment_end is not a valid segment end representation

  • (RuntimeError)

    if segment_end is not a segment end of the link



89
90
91
92
93
94
95
96
97
98
99
# File 'lib/rgfa/line/link.rb', line 89

def other_end(segment_end)
  segment_end = segment_end.to_segment_end
  if (from_end == segment_end)
    return to_end
  elsif (to_end == segment_end)
    return from_end
  else
    raise "Segment end '#{segment_end.inspect}' not found\n"+
          "(from=#{from_end.inspect};to=#{to_end.inspect})"
  end
end

#pathsArray<Array<(RGFA::Line::Path, Boolean)>>

Paths for which the link is required.

The return value is an empty array if the link is not embedded in a graph.

Otherwise, an array of tuples path/boolean is returned. The boolean value tells if the link is used in direct (true) or reverse direction (false) in the path.

Returns:



230
231
232
233
# File 'lib/rgfa/line/link.rb', line 230

def paths
  @paths ||= []
  @paths
end

#reverseRGFA::Line::Link

Note:

The path references are not copied to the reverse link.

Note:

This method shall be overridden if custom optional fields are defined, which have a “reverse” operation which determines their value in the equivalent but reverse link.

Creates a link with both strands of the sequences inverted. The CIGAR operations (order/type) are inverted as well. Optional fields are left unchanged.

Returns:



182
183
184
185
186
187
188
189
190
# File 'lib/rgfa/line/link.rb', line 182

def reverse
  l = self.clone
  l.from = to
  l.from_orient = (to_orient == :+ ? :- : :+)
  l.to = from
  l.to_orient = (from_orient == :+ ? :- : :+)
  l.overlap = reverse_overlap
  l
end

#reverse!RGFA::Line::Link

Note:

The path references are not reversed by this method; therefore the method shall be used before the link is embedded in a graph.

Note:

This method shall be overridden if custom optional fields are defined, which have a “reverse” operation which determines their value in the equivalent but reverse link.

Reverses the link inplace, i.e. sets:

from = to
from_orient = other_orient(to_orient)
to = from
to_orient = other_orient(from_orient)
overlap = reverse_overlap.

The optional fields are left unchanged.

Returns:



209
210
211
212
213
214
215
216
217
218
# File 'lib/rgfa/line/link.rb', line 209

def reverse!
  tmp = self.from
  self.from = self.to
  self.to = tmp
  tmp = self.from_orient
  self.from_orient = (self.to_orient == :+) ? :- : :+
  self.to_orient = (tmp == :+) ? :- : :+
  self.overlap = self.reverse_overlap
  return self
end

#reverse?(other) ⇒ Boolean

Compares the reverse of the link to another link and determine their equivalence. Thereby, optional fields are not considered.

Parameters:

Returns:

  • (Boolean)

    are the reverse of self and other equivalent?

See Also:



311
312
313
314
315
# File 'lib/rgfa/line/link.rb', line 311

def reverse?(other)
  (from_end == other.to_end and
    to_end == other.from_end and
    overlap == other.reverse_overlap)
end

#reverse_overlapRGFA::CIGAR

Compute the overlap when the strand of both sequences is inverted.

Returns:



238
239
240
# File 'lib/rgfa/line/link.rb', line 238

def reverse_overlap
  self.overlap.reverse
end

#same?(other) ⇒ Boolean

Compares two links and determine their equivalence. Thereby, optional fields are not considered.

Parameters:

Returns:

  • (Boolean)

    are self and other equivalent?

See Also:



296
297
298
299
300
# File 'lib/rgfa/line/link.rb', line 296

def same?(other)
  (from_end == other.from_end and
    to_end == other.to_end and
    overlap == other.overlap)
end

#segment_ends_sObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Signature of the segment ends, for debugging



78
79
80
# File 'lib/rgfa/line/link.rb', line 78

def segment_ends_s
  [from_end.to_s, to_end.to_s].join("---")
end

#to_endRGFA::SegmentEnd

Returns the segment end represented by the to/to_orient fields.

Returns:



72
73
74
# File 'lib/rgfa/line/link.rb', line 72

def to_end
  [to, to_orient == :+ ? :B : :E].to_segment_end
end

#to_nameSymbol

The to segment name, in both cases where to is a segment name (Symbol) or a segment (RGFA::Line::Segment)

Returns:



111
112
113
# File 'lib/rgfa/line/link.rb', line 111

def to_name
  to.to_sym
end