gfa 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d8694c80555e4fae39fb77a245428ec8e7ce19a2
4
- data.tar.gz: ab29f1249a26d28082e0380fc96edec934acb0e5
2
+ SHA256:
3
+ metadata.gz: cde4a3e432409c7a2967832dcebd502ddc54b1f6cb25856b6d9d21ce53f67b32
4
+ data.tar.gz: 91213d63365dd3608c28e30115cbfc8621e78bbe34936832bcee2ac7e6f460fb
5
5
  SHA512:
6
- metadata.gz: fe2d1bb08aeaca8cb0b3d588a6b02965ec612d6201bf19b96927df9a2f18b4c2974829a6f9b6da608fae5ac8fd4f9c62b2acd3c8d29718ec2251afdb08ceccba
7
- data.tar.gz: c5ce23b34bc1b890e8d9c7de19a1f4cd0a2766897530b9e2563f667d5d81017b5c1245fd39bb52db3f3960513fb47670210df39124c556753874e01feeac03c0
6
+ metadata.gz: 321634c28ec8927bd38286a84a02783b9f915dcbabb7941233583dda7f41b66e952ff9611c9158bd7baca09d7d3d6c254a036f1c9f2169e5e24e6e964d292e71
7
+ data.tar.gz: 3698d16ab5953ffd70bf2c102d154bc1f61e5a13a752bc317a756df13762c3668c1bf6e8144821e53e395783f36c45185249c7fc206694be19145200310c3f48
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ group :test do
5
+ gem "simplecov"
6
+ gem "codeclimate-test-reporter", "~> 1.0.0"
7
+ end
8
+
9
+ gem 'rake', '~> 13.0'
data/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ The Artistic License 2.0
2
+
3
+ Copyright (c) 2016-2023 Luis M Rodriguez-R
4
+
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+ Preamble
9
+
10
+ This license establishes the terms under which a given free software
11
+ Package may be copied, modified, distributed, and/or redistributed.
12
+ The intent is that the Copyright Holder maintains some artistic
13
+ control over the development of that Package while still keeping the
14
+ Package available as open source and free software.
15
+
16
+ You are always permitted to make arrangements wholly outside of this
17
+ license directly with the Copyright Holder of a given Package. If the
18
+ terms of this license do not permit the full use that you propose to
19
+ make of the Package, you should contact the Copyright Holder and seek
20
+ a different licensing arrangement.
21
+
22
+ Definitions
23
+
24
+ "Copyright Holder" means the individual(s) or organization(s)
25
+ named in the copyright notice for the entire Package.
26
+
27
+ "Contributor" means any party that has contributed code or other
28
+ material to the Package, in accordance with the Copyright Holder's
29
+ procedures.
30
+
31
+ "You" and "your" means any person who would like to copy,
32
+ distribute, or modify the Package.
33
+
34
+ "Package" means the collection of files distributed by the
35
+ Copyright Holder, and derivatives of that collection and/or of
36
+ those files. A given Package may consist of either the Standard
37
+ Version, or a Modified Version.
38
+
39
+ "Distribute" means providing a copy of the Package or making it
40
+ accessible to anyone else, or in the case of a company or
41
+ organization, to others outside of your company or organization.
42
+
43
+ "Distributor Fee" means any fee that you charge for Distributing
44
+ this Package or providing support for this Package to another
45
+ party. It does not mean licensing fees.
46
+
47
+ "Standard Version" refers to the Package if it has not been
48
+ modified, or has been modified only in ways explicitly requested
49
+ by the Copyright Holder.
50
+
51
+ "Modified Version" means the Package, if it has been changed, and
52
+ such changes were not explicitly requested by the Copyright
53
+ Holder.
54
+
55
+ "Original License" means this Artistic License as Distributed with
56
+ the Standard Version of the Package, in its current version or as
57
+ it may be modified by The Perl Foundation in the future.
58
+
59
+ "Source" form means the source code, documentation source, and
60
+ configuration files for the Package.
61
+
62
+ "Compiled" form means the compiled bytecode, object code, binary,
63
+ or any other form resulting from mechanical transformation or
64
+ translation of the Source form.
65
+
66
+
67
+ Permission for Use and Modification Without Distribution
68
+
69
+ (1) You are permitted to use the Standard Version and create and use
70
+ Modified Versions for any purpose without restriction, provided that
71
+ you do not Distribute the Modified Version.
72
+
73
+
74
+ Permissions for Redistribution of the Standard Version
75
+
76
+ (2) You may Distribute verbatim copies of the Source form of the
77
+ Standard Version of this Package in any medium without restriction,
78
+ either gratis or for a Distributor Fee, provided that you duplicate
79
+ all of the original copyright notices and associated disclaimers. At
80
+ your discretion, such verbatim copies may or may not include a
81
+ Compiled form of the Package.
82
+
83
+ (3) You may apply any bug fixes, portability changes, and other
84
+ modifications made available from the Copyright Holder. The resulting
85
+ Package will still be considered the Standard Version, and as such
86
+ will be subject to the Original License.
87
+
88
+
89
+ Distribution of Modified Versions of the Package as Source
90
+
91
+ (4) You may Distribute your Modified Version as Source (either gratis
92
+ or for a Distributor Fee, and with or without a Compiled form of the
93
+ Modified Version) provided that you clearly document how it differs
94
+ from the Standard Version, including, but not limited to, documenting
95
+ any non-standard features, executables, or modules, and provided that
96
+ you do at least ONE of the following:
97
+
98
+ (a) make the Modified Version available to the Copyright Holder
99
+ of the Standard Version, under the Original License, so that the
100
+ Copyright Holder may include your modifications in the Standard
101
+ Version.
102
+
103
+ (b) ensure that installation of your Modified Version does not
104
+ prevent the user installing or running the Standard Version. In
105
+ addition, the Modified Version must bear a name that is different
106
+ from the name of the Standard Version.
107
+
108
+ (c) allow anyone who receives a copy of the Modified Version to
109
+ make the Source form of the Modified Version available to others
110
+ under
111
+
112
+ (i) the Original License or
113
+
114
+ (ii) a license that permits the licensee to freely copy,
115
+ modify and redistribute the Modified Version using the same
116
+ licensing terms that apply to the copy that the licensee
117
+ received, and requires that the Source form of the Modified
118
+ Version, and of any works derived from it, be made freely
119
+ available in that license fees are prohibited but Distributor
120
+ Fees are allowed.
121
+
122
+
123
+ Distribution of Compiled Forms of the Standard Version
124
+ or Modified Versions without the Source
125
+
126
+ (5) You may Distribute Compiled forms of the Standard Version without
127
+ the Source, provided that you include complete instructions on how to
128
+ get the Source of the Standard Version. Such instructions must be
129
+ valid at the time of your distribution. If these instructions, at any
130
+ time while you are carrying out such distribution, become invalid, you
131
+ must provide new instructions on demand or cease further distribution.
132
+ If you provide valid instructions or cease distribution within thirty
133
+ days after you become aware that the instructions are invalid, then
134
+ you do not forfeit any of your rights under this license.
135
+
136
+ (6) You may Distribute a Modified Version in Compiled form without
137
+ the Source, provided that you comply with Section 4 with respect to
138
+ the Source of the Modified Version.
139
+
140
+
141
+ Aggregating or Linking the Package
142
+
143
+ (7) You may aggregate the Package (either the Standard Version or
144
+ Modified Version) with other packages and Distribute the resulting
145
+ aggregation provided that you do not charge a licensing fee for the
146
+ Package. Distributor Fees are permitted, and licensing fees for other
147
+ components in the aggregation are permitted. The terms of this license
148
+ apply to the use and Distribution of the Standard or Modified Versions
149
+ as included in the aggregation.
150
+
151
+ (8) You are permitted to link Modified and Standard Versions with
152
+ other works, to embed the Package in a larger work of your own, or to
153
+ build stand-alone binary or bytecode versions of applications that
154
+ include the Package, and Distribute the result without restriction,
155
+ provided the result does not expose a direct interface to the Package.
156
+
157
+
158
+ Items That are Not Considered Part of a Modified Version
159
+
160
+ (9) Works (including, but not limited to, modules and scripts) that
161
+ merely extend or make use of the Package, do not, by themselves, cause
162
+ the Package to be a Modified Version. In addition, such works are not
163
+ considered parts of the Package itself, and are not subject to the
164
+ terms of this license.
165
+
166
+
167
+ General Provisions
168
+
169
+ (10) Any use, modification, and distribution of the Standard or
170
+ Modified Versions is governed by this Artistic License. By using,
171
+ modifying or distributing the Package, you accept this license. Do not
172
+ use, modify, or distribute the Package, if you do not accept this
173
+ license.
174
+
175
+ (11) If your Modified Version has been derived from a Modified
176
+ Version made by someone other than you, you are nevertheless required
177
+ to ensure that your Modified Version complies with the requirements of
178
+ this license.
179
+
180
+ (12) This license does not grant you the right to use any trademark,
181
+ service mark, tradename, or logo of the Copyright Holder.
182
+
183
+ (13) This license includes the non-exclusive, worldwide,
184
+ free-of-charge patent license to make, have made, use, offer to sell,
185
+ sell, import and otherwise transfer the Package with respect to any
186
+ patent claims licensable by the Copyright Holder that are necessarily
187
+ infringed by the Package. If you institute patent litigation
188
+ (including a cross-claim or counterclaim) against any party alleging
189
+ that the Package constitutes direct or contributory patent
190
+ infringement, then this Artistic License to you shall terminate on the
191
+ date that such litigation is filed.
192
+
193
+ (14) Disclaimer of Warranty:
194
+ THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
195
+ IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
196
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
197
+ NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
198
+ LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
199
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
200
+ DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
201
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,108 @@
1
+ [![Code Climate](https://codeclimate.com/github/lmrodriguezr/gfa/badges/gpa.svg)](https://codeclimate.com/github/lmrodriguezr/gfa)
2
+ [![Test Coverage](https://codeclimate.com/github/lmrodriguezr/gfa/badges/coverage.svg)](https://codeclimate.com/github/lmrodriguezr/gfa/coverage)
3
+ [![Build Status](https://travis-ci.org/lmrodriguezr/gfa.svg?branch=master)](https://travis-ci.org/lmrodriguezr/gfa)
4
+ [![Gem Version](https://badge.fury.io/rb/gfa.svg)](https://badge.fury.io/rb/gfa)
5
+
6
+ # Graphical Fragment Assembly (GFA) for Ruby
7
+
8
+ This implementation follows the specifications of [GFA-spec][].
9
+
10
+
11
+ ## Parsing GFA
12
+
13
+ To parse a file in GFA format:
14
+
15
+ ```ruby
16
+ require 'gfa'
17
+
18
+ my_gfa = GFA.load('assembly.gfa')
19
+ ```
20
+
21
+ To load GFA strings line-by-line:
22
+
23
+ ```ruby
24
+ require 'gfa'
25
+
26
+ my_gfa = GFA.new
27
+ fh = File.open('assembly.gfa', 'r')
28
+ fh.each do |ln|
29
+ my_gfa << ln
30
+ end
31
+ fh.close
32
+ ```
33
+
34
+
35
+ ## Saving GFA
36
+
37
+ After altering a GFA object, you can simply save it in a file as:
38
+
39
+ ```ruby
40
+ my_gfa.save('alt-assembly.gfa')
41
+ ```
42
+
43
+ Or line-by-line as:
44
+
45
+ ```ruby
46
+ fh = File.open('alt-assembly.gfa', 'w')
47
+ my_gfa.each_line do |ln|
48
+ fh.puts ln
49
+ end
50
+ fh.close
51
+ ```
52
+
53
+
54
+ ## Visualizing GFA
55
+
56
+ Any `GFA` object can be exported as an [`RGL`][rgl] graph using the methods
57
+ `adjacency_graph` and `implicit_graph`. For example, you can render
58
+ [tiny.gfa](https://github.com/lmrodriguezr/gfa/raw/master/data/tiny.gfa):
59
+
60
+ ```ruby
61
+ require "gfa"
62
+ require "rgl/dot"
63
+
64
+ my_gfa = GFA.load("data/tiny.gfa")
65
+ dg = my_gfa.implicit_graph
66
+ dg.write_to_graphic_file("jpg")
67
+ ```
68
+
69
+ ![tiny_dg](https://github.com/lmrodriguezr/gfa/raw/master/data/tiny.jpg)
70
+
71
+ If you don't care about orientation, you can also build an undirected graph
72
+ without orientation:
73
+
74
+ ```ruby
75
+ ug = my_gfa.implicit_graph(orient:false)
76
+ ug.write_to_graphic_file("jpg")
77
+ ```
78
+
79
+ ![tiny_ug](https://github.com/lmrodriguezr/gfa/raw/master/data/tiny_undirected.jpg)
80
+
81
+
82
+ # Installation
83
+
84
+ ```
85
+ gem install gfa
86
+ ```
87
+
88
+ Or add the following line to your Gemfile:
89
+
90
+ ```ruby
91
+ gem "gfa"
92
+ ```
93
+
94
+ and run `bundle install` from your shell.
95
+
96
+
97
+ # Author
98
+
99
+ [Luis M. Rodriguez-R][lrr].
100
+
101
+
102
+ # License
103
+
104
+ [Artistic License 2.0](LICENSE).
105
+
106
+ [GFA-spec]: https://github.com/pmelsted/GFA-spec
107
+ [lrr]: https://rodriguez-r.com/
108
+ [rgl]: https://github.com/monora/rgl
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
5
+
6
+ require 'gfa/version'
7
+
8
+ SOURCES = FileList['lib/**/*.rb']
9
+
10
+ desc 'Default Task'
11
+ task :default => :test
12
+
13
+ Rake::TestTask.new do |t|
14
+ t.libs << 'test'
15
+ t.pattern = 'test/*_test.rb'
16
+ t.verbose = true
17
+ end
data/lib/gfa/common.rb ADDED
@@ -0,0 +1,39 @@
1
+ require 'gfa/version'
2
+ require 'gfa/record'
3
+ require 'gfa/field'
4
+
5
+ class GFA
6
+ # Class-level
7
+ def self.assert_format(value, regex, message)
8
+ unless value =~ regex
9
+ raise "#{message}: #{value}."
10
+ end
11
+ end
12
+
13
+ # Instance-level
14
+ attr :gfa_version, :records
15
+
16
+ GFA::Record.TYPES.each do |r_type|
17
+ plural = "#{r_type.downcase}s"
18
+ singular = "#{r_type.downcase}"
19
+
20
+ define_method(plural) { records[r_type] }
21
+ define_method(singular) { |k| records[r_type][k] }
22
+ define_method("add_#{singular}") { |v| @records[r_type] << v }
23
+ end
24
+
25
+ def initialize
26
+ @records = {}
27
+ GFA::Record.TYPES.each { |t| @records[t] = [] }
28
+ end
29
+
30
+ def empty?
31
+ records.empty? || records.values.all?(&:empty?)
32
+ end
33
+
34
+ def eql?(gfa)
35
+ records == gfa.records
36
+ end
37
+
38
+ alias == eql?
39
+ end
@@ -0,0 +1,9 @@
1
+ class GFA::Field::Char < GFA::Field
2
+ CODE = :A
3
+ REGEX = /^[!-~]$/
4
+
5
+ def initialize(f)
6
+ GFA.assert_format(f, regex, "Bad #{type}")
7
+ @value = f
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class GFA::Field::Float < GFA::Field
2
+ CODE = :f
3
+ REGEX = /^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/
4
+
5
+ def initialize(f)
6
+ GFA.assert_format(f, regex, "Bad #{type}")
7
+ @value = f.to_f
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class GFA::Field::Hex < GFA::Field
2
+ CODE = :H
3
+ REGEX = /^[0-9A-F]+$/
4
+
5
+ def initialize(f)
6
+ GFA.assert_format(f, regex, "Bad #{type}")
7
+ @value = f
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class GFA::Field::Json < GFA::Field
2
+ CODE = :J
3
+ REGEX = /^[ !-~]+$/
4
+
5
+ def initialize(f)
6
+ GFA.assert_format(f, regex, "Bad #{type}")
7
+ @value = f
8
+ end
9
+ end
@@ -0,0 +1,24 @@
1
+ class GFA::Field::NumArray < GFA::Field
2
+ CODE = :B
3
+ REGEX = /^[cCsSiIf](,[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)+$/
4
+
5
+ def initialize(f)
6
+ GFA.assert_format(f, regex, "Bad #{type}")
7
+ @value = f
8
+ end
9
+
10
+ def modifier ; value[0] ; end
11
+
12
+ def array ; value[2..-1].split(/,/) ; end
13
+
14
+ alias as_a array
15
+
16
+ def number_type
17
+ {
18
+ c: 'int8_t', C: 'uint8_t',
19
+ s: 'int16_t', S: 'uint16_t',
20
+ i: 'int32_t', I: 'uint32_t',
21
+ f: 'float'
22
+ }[modifier.to_sym]
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ class GFA::Field::SigInt < GFA::Field
2
+ CODE = :i
3
+ REGEX = /^[-+]?[0-9]+$/
4
+
5
+ def initialize(f)
6
+ GFA.assert_format(f, regex, "Bad #{type}")
7
+ @value = f.to_i
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class GFA::Field::String < GFA::Field
2
+ CODE = :Z
3
+ REGEX = /^[ !-~]+$/
4
+
5
+ def initialize(f)
6
+ GFA.assert_format(f, regex, "Bad #{type}")
7
+ @value = f
8
+ end
9
+ end
data/lib/gfa/field.rb ADDED
@@ -0,0 +1,47 @@
1
+ class GFA::Field
2
+ # Class-level
3
+ CODES = {
4
+ A: :Char,
5
+ i: :SigInt,
6
+ f: :Float,
7
+ Z: :String,
8
+ J: :Json, # Excluding new-line and tab characters
9
+ H: :Hex,
10
+ B: :NumArray
11
+ }
12
+ TYPES = CODES.values
13
+ TYPES.each { |t| require "gfa/field/#{t.downcase}" }
14
+
15
+ [:CODES, :TYPES].each do |x|
16
+ define_singleton_method(x) { const_get(x) }
17
+ end
18
+
19
+ def self.code_class(code)
20
+ name = CODES[code.to_sym]
21
+ raise "Unknown field type: #{code}." if name.nil?
22
+ name_class(name)
23
+ end
24
+
25
+ def self.name_class(name)
26
+ const_get(name)
27
+ end
28
+
29
+ # Instance-level
30
+
31
+ attr :value
32
+
33
+ def type ; CODES[code] ; end
34
+
35
+ def code ; self.class::CODE ; end
36
+
37
+ def regex ; self.class::REGEX ; end
38
+
39
+ def to_s(with_type=true)
40
+ "#{"#{code}:" if with_type}#{value}"
41
+ end
42
+
43
+ def hash
44
+ value.hash
45
+ end
46
+
47
+ end
@@ -0,0 +1,35 @@
1
+ class GFA
2
+ def save(file)
3
+ fh = File.open(file, 'w')
4
+ each_line do |ln|
5
+ fh.puts ln
6
+ end
7
+ fh.close
8
+ end
9
+
10
+ def each_line(&blk)
11
+ set_version_header('1.1') if gfa_version.nil?
12
+ GFA::Record.TYPES.each do |r_type|
13
+ records[r_type].each do |record|
14
+ blk[record.to_s]
15
+ end
16
+ end
17
+ end
18
+
19
+ def set_version_header(v)
20
+ unset_version
21
+ @records[:Header] << GFA::Record::Header.new("VN:Z:#{v}")
22
+ @gfa_version = v
23
+ end
24
+
25
+ def unset_version
26
+ @records[:Header].delete_if { |o| !o.fields[:VN].nil? }
27
+ @gfa_version = nil
28
+ end
29
+
30
+ def to_s
31
+ o = ''
32
+ each_line { |ln| o += ln + "\n" }
33
+ o
34
+ end
35
+ end
data/lib/gfa/graph.rb ADDED
@@ -0,0 +1,99 @@
1
+ require 'rgl/adjacency'
2
+ require 'rgl/implicit'
3
+
4
+ class GFA
5
+
6
+ ##
7
+ # Generates a RGL::ImplicitGraph object describing the links in the GFA.
8
+ # The +opts+ argument is a hash with any of the following key-value pairs:
9
+ #
10
+ # * :orient => bool. If false, ignores strandness of the links. By default
11
+ # true.
12
+ # * :directed => bool. If false, ignores direction of the links. By defaut
13
+ # the same value as :orient.
14
+ def implicit_graph(opts = {})
15
+ rgl_implicit_graph(opts)
16
+ end
17
+
18
+ ##
19
+ # Generates a RGL::DirectedAdjacencyGraph or RGL::AdjacencyGraph object.
20
+ # The +opts+ argument is a hash with the same supported key-value pairs as
21
+ # in #implicit_graph.
22
+ def adjacency_graph(opts = {})
23
+ implicit_graph(opts).to_adjacency
24
+ end
25
+
26
+ private
27
+
28
+ def segment_names_with_orient
29
+ segments.flat_map do |s|
30
+ %w[+ -].map { |orient| GFA::GraphVertex.idx(s, orient) }
31
+ end.to_set
32
+ end
33
+
34
+ def segment_names
35
+ segments.map do |s|
36
+ GFA::GraphVertex.idx(s, nil)
37
+ end.to_set
38
+ end
39
+
40
+ def rgl_implicit_graph(opts)
41
+ opts = rgl_implicit_options(opts)
42
+ RGL::ImplicitGraph.new do |g|
43
+ g.vertex_iterator do |b|
44
+ (opts[:orient] ? segment_names_with_orient :
45
+ segment_names).each(&b)
46
+ end
47
+ g.adjacent_iterator do |x, b|
48
+ rgl_implicit_adjacent_iterator(x, b, opts)
49
+ end
50
+ g.directed = opts[:directed]
51
+ end
52
+ end
53
+
54
+ def rgl_implicit_options(opts)
55
+ opts[:orient] = true if opts[:orient].nil?
56
+ opts[:directed] = opts[:orient] if opts[:directed].nil?
57
+ opts
58
+ end
59
+
60
+ def rgl_implicit_adjacent_iterator(x,b,opts)
61
+ links.each do |l|
62
+ if l.from?(x.segment, x.orient)
63
+ orient = opts[:orient] ? l.to_orient : nil
64
+ b.call(GFA::GraphVertex.idx(l.to, orient))
65
+ elsif opts[:orient] && l.to?(x.segment, orient_rc(x.orient))
66
+ orient = orient_rc(l.from_orient.value)
67
+ b.call(GFA::GraphVertex.idx(l.from, orient))
68
+ end
69
+ end
70
+ end
71
+
72
+ def orient_rc(o)
73
+ o == '+' ? '-' : '+'
74
+ end
75
+ end
76
+
77
+
78
+ class GFA::GraphVertex # :nodoc:
79
+ # Class-level
80
+ @@idx = {}
81
+ def self.idx(segment, orient)
82
+ n = GFA::GraphVertex.new(segment, orient)
83
+ @@idx[n.to_s] ||= n
84
+ @@idx[n.to_s]
85
+ end
86
+
87
+ # Instance-level
88
+ attr :segment, :orient
89
+
90
+ def initialize(segment, orient)
91
+ @segment = segment.is_a?(GFA::Record::Segment) ? segment.name.value :
92
+ segment.is_a?(GFA::Field) ? segment.value : segment
93
+ @orient = orient.is_a?(GFA::Field) ? orient.value : orient
94
+ end
95
+
96
+ def to_s
97
+ "#{segment}#{orient}"
98
+ end
99
+ end