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 +5 -5
- data/Gemfile +9 -0
- data/LICENSE +201 -0
- data/README.md +108 -0
- data/Rakefile +17 -0
- data/lib/gfa/common.rb +39 -0
- data/lib/gfa/field/char.rb +9 -0
- data/lib/gfa/field/float.rb +9 -0
- data/lib/gfa/field/hex.rb +9 -0
- data/lib/gfa/field/json.rb +9 -0
- data/lib/gfa/field/numarray.rb +24 -0
- data/lib/gfa/field/sigint.rb +9 -0
- data/lib/gfa/field/string.rb +9 -0
- data/lib/gfa/field.rb +47 -0
- data/lib/gfa/generator.rb +35 -0
- data/lib/gfa/graph.rb +99 -0
- data/lib/gfa/parser.rb +46 -0
- data/lib/gfa/record/comment.rb +10 -0
- data/lib/gfa/record/containment.rb +29 -0
- data/lib/gfa/record/header.rb +12 -0
- data/lib/gfa/record/jump.rb +45 -0
- data/lib/gfa/record/link.rb +49 -0
- data/lib/gfa/record/path.rb +19 -0
- data/lib/gfa/record/segment.rb +25 -0
- data/lib/gfa/record/walk.rb +20 -0
- data/lib/gfa/record.rb +96 -0
- data/lib/gfa/version.rb +7 -0
- data/lib/gfa.rb +4 -0
- data/test/common_test.rb +34 -0
- data/test/field_test.rb +50 -0
- data/test/parser_test.rb +47 -0
- data/test/record_test.rb +73 -0
- data/test/test_helper.rb +6 -0
- metadata +56 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cde4a3e432409c7a2967832dcebd502ddc54b1f6cb25856b6d9d21ce53f67b32
|
4
|
+
data.tar.gz: 91213d63365dd3608c28e30115cbfc8621e78bbe34936832bcee2ac7e6f460fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 321634c28ec8927bd38286a84a02783b9f915dcbabb7941233583dda7f41b66e952ff9611c9158bd7baca09d7d3d6c254a036f1c9f2169e5e24e6e964d292e71
|
7
|
+
data.tar.gz: 3698d16ab5953ffd70bf2c102d154bc1f61e5a13a752bc317a756df13762c3668c1bf6e8144821e53e395783f36c45185249c7fc206694be19145200310c3f48
|
data/Gemfile
ADDED
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,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
|
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
|