gfa 0.1.2 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/Gemfile +8 -2
- data/LICENSE +2 -2
- data/README.md +23 -15
- data/Rakefile +9 -8
- data/lib/gfa/common.rb +39 -42
- data/lib/gfa/field/char.rb +2 -2
- data/lib/gfa/field/float.rb +17 -1
- data/lib/gfa/field/hex.rb +17 -1
- data/lib/gfa/field/json.rb +18 -0
- data/lib/gfa/field/numarray.rb +38 -5
- data/lib/gfa/field/sigint.rb +14 -2
- data/lib/gfa/field/string.rb +11 -3
- data/lib/gfa/field.rb +89 -19
- data/lib/gfa/generator.rb +32 -28
- data/lib/gfa/graph.rb +14 -16
- data/lib/gfa/parser.rb +31 -22
- data/lib/gfa/record/comment.rb +15 -0
- data/lib/gfa/record/containment.rb +19 -13
- data/lib/gfa/record/header.rb +11 -10
- data/lib/gfa/record/jump.rb +45 -0
- data/lib/gfa/record/link.rb +42 -42
- data/lib/gfa/record/path.rb +14 -13
- data/lib/gfa/record/segment.rb +22 -18
- data/lib/gfa/record/walk.rb +20 -0
- data/lib/gfa/record.rb +53 -33
- data/lib/gfa/record_set/comment_set.rb +3 -0
- data/lib/gfa/record_set/containment_set.rb +4 -0
- data/lib/gfa/record_set/header_set.rb +3 -0
- data/lib/gfa/record_set/jump_set.rb +3 -0
- data/lib/gfa/record_set/link_set.rb +3 -0
- data/lib/gfa/record_set/path_set.rb +4 -0
- data/lib/gfa/record_set/segment_set.rb +4 -0
- data/lib/gfa/record_set/walk_set.rb +3 -0
- data/lib/gfa/record_set.rb +99 -0
- data/lib/gfa/version.rb +1 -1
- data/lib/gfa.rb +4 -4
- data/test/common_test.rb +5 -5
- data/test/field_test.rb +52 -26
- data/test/parser_test.rb +57 -20
- data/test/record_test.rb +7 -0
- data/test/test_helper.rb +10 -5
- metadata +33 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0e8e61ff97b34654b7a660b011826ad5549f66933a91a09658facf58c3fd56b1
|
4
|
+
data.tar.gz: 8f85f07955e71cd38a9dfa28011c70433473ad6a1137ed3e6e217d63eeba20a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b9f8fd92cd30d9e4e5c0263e938169141749c7be43011b574f937c9645608d8e72189bfe9072d7321e3acdf7e8288cecf42c90abe3ceef2bf001780bdb3e472
|
7
|
+
data.tar.gz: ee33c0b9c0dc9adb2df96d95b792b060b248e2f991ed5a0e4b4c136d66f04b9be6cf5ca58462bce046c6cfd9e7fed6c4c6949cb5e8923eb71e3d5f53f0da2703
|
data/Gemfile
CHANGED
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -13,20 +13,20 @@ This implementation follows the specifications of [GFA-spec][].
|
|
13
13
|
To parse a file in GFA format:
|
14
14
|
|
15
15
|
```ruby
|
16
|
-
require
|
16
|
+
require 'gfa'
|
17
17
|
|
18
|
-
my_gfa = GFA.load(
|
18
|
+
my_gfa = GFA.load('assembly.gfa')
|
19
19
|
```
|
20
20
|
|
21
21
|
To load GFA strings line-by-line:
|
22
22
|
|
23
23
|
```ruby
|
24
|
-
require
|
24
|
+
require 'gfa'
|
25
25
|
|
26
26
|
my_gfa = GFA.new
|
27
|
-
fh = File.open(
|
27
|
+
fh = File.open('assembly.gfa', 'r')
|
28
28
|
fh.each do |ln|
|
29
|
-
|
29
|
+
my_gfa << ln
|
30
30
|
end
|
31
31
|
fh.close
|
32
32
|
```
|
@@ -37,15 +37,15 @@ fh.close
|
|
37
37
|
After altering a GFA object, you can simply save it in a file as:
|
38
38
|
|
39
39
|
```ruby
|
40
|
-
my_gfa.save(
|
40
|
+
my_gfa.save('alt-assembly.gfa')
|
41
41
|
```
|
42
42
|
|
43
43
|
Or line-by-line as:
|
44
44
|
|
45
45
|
```ruby
|
46
|
-
fh = File.open(
|
46
|
+
fh = File.open('alt-assembly.gfa', 'w')
|
47
47
|
my_gfa.each_line do |ln|
|
48
|
-
|
48
|
+
fh.puts ln
|
49
49
|
end
|
50
50
|
fh.close
|
51
51
|
```
|
@@ -58,12 +58,12 @@ Any `GFA` object can be exported as an [`RGL`][rgl] graph using the methods
|
|
58
58
|
[tiny.gfa](https://github.com/lmrodriguezr/gfa/raw/master/data/tiny.gfa):
|
59
59
|
|
60
60
|
```ruby
|
61
|
-
require
|
62
|
-
require
|
61
|
+
require 'gfa'
|
62
|
+
require 'rgl/dot'
|
63
63
|
|
64
|
-
my_gfa = GFA.load(
|
64
|
+
my_gfa = GFA.load('data/tiny.gfa')
|
65
65
|
dg = my_gfa.implicit_graph
|
66
|
-
dg.write_to_graphic_file(
|
66
|
+
dg.write_to_graphic_file('jpg')
|
67
67
|
```
|
68
68
|
|
69
69
|

|
@@ -72,8 +72,8 @@ If you don't care about orientation, you can also build an undirected graph
|
|
72
72
|
without orientation:
|
73
73
|
|
74
74
|
```ruby
|
75
|
-
ug = my_gfa.implicit_graph(orient:false)
|
76
|
-
ug.write_to_graphic_file(
|
75
|
+
ug = my_gfa.implicit_graph(orient: false)
|
76
|
+
ug.write_to_graphic_file('jpg')
|
77
77
|
```
|
78
78
|
|
79
79
|

|
@@ -85,6 +85,14 @@ ug.write_to_graphic_file("jpg")
|
|
85
85
|
gem install gfa
|
86
86
|
```
|
87
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
|
+
|
88
96
|
|
89
97
|
# Author
|
90
98
|
|
@@ -96,5 +104,5 @@ gem install gfa
|
|
96
104
|
[Artistic License 2.0](LICENSE).
|
97
105
|
|
98
106
|
[GFA-spec]: https://github.com/pmelsted/GFA-spec
|
99
|
-
[lrr]:
|
107
|
+
[lrr]: https://rodriguez-r.com/
|
100
108
|
[rgl]: https://github.com/monora/rgl
|
data/Rakefile
CHANGED
@@ -1,16 +1,17 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
2
3
|
|
3
|
-
$:.unshift File.join(File.dirname(__FILE__),
|
4
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
4
5
|
|
5
|
-
require
|
6
|
+
require 'gfa/version'
|
6
7
|
|
7
|
-
SOURCES = FileList[
|
8
|
+
SOURCES = FileList['lib/**/*.rb']
|
8
9
|
|
9
|
-
desc
|
10
|
+
desc 'Default Task'
|
10
11
|
task :default => :test
|
11
12
|
|
12
13
|
Rake::TestTask.new do |t|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
t.libs << 'test'
|
15
|
+
t.pattern = 'test/*_test.rb'
|
16
|
+
t.verbose = true
|
16
17
|
end
|
data/lib/gfa/common.rb
CHANGED
@@ -1,45 +1,42 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require 'gfa/version'
|
2
|
+
require 'gfa/record_set'
|
3
|
+
require 'gfa/field'
|
4
4
|
|
5
5
|
class GFA
|
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
|
-
alias == eql?
|
44
|
-
|
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, :opts
|
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(opts = {})
|
26
|
+
@records = {}
|
27
|
+
@opts = { index: true, comments: false }.merge(opts)
|
28
|
+
GFA::Record.TYPES.each do |t|
|
29
|
+
@records[t] = GFA::RecordSet.name_class(t).new(self)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def empty?
|
34
|
+
records.empty? || records.values.all?(&:empty?)
|
35
|
+
end
|
36
|
+
|
37
|
+
def eql?(gfa)
|
38
|
+
records == gfa.records
|
39
|
+
end
|
40
|
+
|
41
|
+
alias == eql?
|
45
42
|
end
|
data/lib/gfa/field/char.rb
CHANGED
data/lib/gfa/field/float.rb
CHANGED
@@ -1,10 +1,26 @@
|
|
1
1
|
class GFA::Field::Float < GFA::Field
|
2
2
|
CODE = :f
|
3
|
-
REGEX =
|
3
|
+
REGEX = /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/
|
4
|
+
NATIVE_FUN = :to_f
|
5
|
+
|
6
|
+
def to_f
|
7
|
+
value
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_i
|
11
|
+
value.to_i
|
12
|
+
end
|
4
13
|
|
5
14
|
def initialize(f)
|
6
15
|
GFA.assert_format(f, regex, "Bad #{type}")
|
7
16
|
@value = f.to_f
|
8
17
|
end
|
9
18
|
|
19
|
+
def equivalent?(field)
|
20
|
+
if field.is_a?(GFA::Field::NumArray)
|
21
|
+
return field.size == 1 && field.first.to_f == value
|
22
|
+
end
|
23
|
+
|
24
|
+
super
|
25
|
+
end
|
10
26
|
end
|
data/lib/gfa/field/hex.rb
CHANGED
@@ -1,10 +1,26 @@
|
|
1
1
|
class GFA::Field::Hex < GFA::Field
|
2
2
|
CODE = :H
|
3
|
-
REGEX =
|
3
|
+
REGEX = /[0-9A-F]+/
|
4
|
+
NATIVE_FUN = :to_i
|
4
5
|
|
5
6
|
def initialize(f)
|
6
7
|
GFA.assert_format(f, regex, "Bad #{type}")
|
7
8
|
@value = f
|
8
9
|
end
|
9
10
|
|
11
|
+
def to_i
|
12
|
+
value.to_i(16)
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_f
|
16
|
+
to_i.to_f
|
17
|
+
end
|
18
|
+
|
19
|
+
def equivalent?(field)
|
20
|
+
if field.is_a? GFA::Field::NumArray
|
21
|
+
return field.size == 1 && field.first.to_i == value
|
22
|
+
end
|
23
|
+
|
24
|
+
super
|
25
|
+
end
|
10
26
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class GFA::Field::Json < GFA::Field
|
2
|
+
CODE = :J
|
3
|
+
REGEX = /[ !-~]+/
|
4
|
+
NATIVE_FUN = :to_s
|
5
|
+
|
6
|
+
def initialize(f)
|
7
|
+
GFA.assert_format(f, regex, "Bad #{type}")
|
8
|
+
@value = f
|
9
|
+
end
|
10
|
+
|
11
|
+
def equivalent?(field)
|
12
|
+
# TODO
|
13
|
+
# We should parse the contents when comparing two GFA::Field::Json to
|
14
|
+
# evaluate equivalencies such as 'J:{ "a" : 1 }' ~ 'J:{"a":1}' (spaces)
|
15
|
+
# or 'J:{"a":1,"b":2}' ~ 'J:{"b":2,"a":1}' (element order)
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
data/lib/gfa/field/numarray.rb
CHANGED
@@ -1,16 +1,49 @@
|
|
1
1
|
class GFA::Field::NumArray < GFA::Field
|
2
2
|
CODE = :B
|
3
|
-
REGEX =
|
3
|
+
REGEX = /[cCsSiIf](,[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)+/
|
4
|
+
NATIVE_FUN = :to_a
|
4
5
|
|
5
6
|
def initialize(f)
|
6
7
|
GFA.assert_format(f, regex, "Bad #{type}")
|
7
8
|
@value = f
|
8
9
|
end
|
9
10
|
|
10
|
-
def modifier
|
11
|
+
def modifier
|
12
|
+
value[0]
|
13
|
+
end
|
14
|
+
|
15
|
+
def modifier_fun
|
16
|
+
modifier == 'f' ? :to_f : :to_i
|
17
|
+
end
|
11
18
|
|
12
|
-
def array
|
13
|
-
|
14
|
-
|
19
|
+
def array
|
20
|
+
@array ||= value[2..-1].split(',').map(&modifier_fun)
|
21
|
+
end
|
22
|
+
|
23
|
+
alias to_a array
|
15
24
|
|
25
|
+
%i[empty? size count length first last].each do |i|
|
26
|
+
define_method(i) { array.send(i) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def number_type
|
30
|
+
{
|
31
|
+
c: 'int8_t', C: 'uint8_t',
|
32
|
+
s: 'int16_t', S: 'uint16_t',
|
33
|
+
i: 'int32_t', I: 'uint32_t',
|
34
|
+
f: 'float'
|
35
|
+
}[modifier.to_sym]
|
36
|
+
end
|
37
|
+
|
38
|
+
def equivalent?(field)
|
39
|
+
return true if eql?(field)
|
40
|
+
|
41
|
+
if field.respond_to?(:to_a)
|
42
|
+
field.to_a.map(&modifier_fun) == array
|
43
|
+
elsif size == 1 && field.respond_to?(modifier_fun)
|
44
|
+
field.send(modifier_fun) == first
|
45
|
+
else
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
16
49
|
end
|
data/lib/gfa/field/sigint.rb
CHANGED
@@ -1,10 +1,22 @@
|
|
1
1
|
class GFA::Field::SigInt < GFA::Field
|
2
2
|
CODE = :i
|
3
|
-
REGEX =
|
4
|
-
|
3
|
+
REGEX = /[-+]?[0-9]+/
|
4
|
+
NATIVE_FUN = :to_i
|
5
|
+
|
5
6
|
def initialize(f)
|
6
7
|
GFA.assert_format(f, regex, "Bad #{type}")
|
7
8
|
@value = f.to_i
|
8
9
|
end
|
9
10
|
|
11
|
+
def to_i
|
12
|
+
value
|
13
|
+
end
|
14
|
+
|
15
|
+
def equivalent?(field)
|
16
|
+
if field.is_a?(GFA::Field::NumArray)
|
17
|
+
return field.size == 1 && field.first.to_i == value
|
18
|
+
end
|
19
|
+
|
20
|
+
super
|
21
|
+
end
|
10
22
|
end
|
data/lib/gfa/field/string.rb
CHANGED
@@ -1,10 +1,18 @@
|
|
1
1
|
class GFA::Field::String < GFA::Field
|
2
2
|
CODE = :Z
|
3
|
-
REGEX =
|
4
|
-
|
3
|
+
REGEX = /[ !-~]+/
|
4
|
+
NATIVE_FUN = :to_s
|
5
|
+
|
6
|
+
def to_f
|
7
|
+
value.to_f
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_i(base = 10)
|
11
|
+
value.to_i(base)
|
12
|
+
end
|
13
|
+
|
5
14
|
def initialize(f)
|
6
15
|
GFA.assert_format(f, regex, "Bad #{type}")
|
7
16
|
@value = f
|
8
17
|
end
|
9
|
-
|
10
18
|
end
|
data/lib/gfa/field.rb
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
class GFA::Field
|
2
|
-
|
3
2
|
# Class-level
|
4
|
-
|
5
3
|
CODES = {
|
6
|
-
:
|
7
|
-
:
|
8
|
-
:
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
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
|
12
11
|
}
|
13
12
|
TYPES = CODES.values
|
14
|
-
|
15
13
|
TYPES.each { |t| require "gfa/field/#{t.downcase}" }
|
16
14
|
|
17
|
-
[
|
15
|
+
%i[CODES TYPES].each do |x|
|
18
16
|
define_singleton_method(x) { const_get(x) }
|
19
17
|
end
|
20
18
|
|
@@ -27,23 +25,95 @@ class GFA::Field
|
|
27
25
|
def self.name_class(name)
|
28
26
|
const_get(name)
|
29
27
|
end
|
30
|
-
|
28
|
+
|
29
|
+
def self.[](string)
|
30
|
+
code, value = string.split(':', 2)
|
31
|
+
code_class(code).new(value)
|
32
|
+
end
|
33
|
+
|
31
34
|
# Instance-level
|
32
35
|
|
33
36
|
attr :value
|
34
37
|
|
35
|
-
def type
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
def
|
40
|
-
|
41
|
-
|
38
|
+
def type
|
39
|
+
CODES[code]
|
40
|
+
end
|
41
|
+
|
42
|
+
def code
|
43
|
+
self.class::CODE
|
44
|
+
end
|
45
|
+
|
46
|
+
def regex
|
47
|
+
self.class::REGEX
|
48
|
+
end
|
49
|
+
|
50
|
+
def native_fun
|
51
|
+
self.class::NATIVE_FUN
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_native
|
55
|
+
native_fun == :to_s ? to_s(false) : send(native_fun)
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_s(with_type = true)
|
42
59
|
"#{"#{code}:" if with_type}#{value}"
|
43
60
|
end
|
44
|
-
|
61
|
+
|
45
62
|
def hash
|
46
63
|
value.hash
|
47
64
|
end
|
48
65
|
|
66
|
+
##
|
67
|
+
# Evaluate equivalency of contents. All the following fields are distinct but
|
68
|
+
# contain the same information, and are therefore considered equivalent:
|
69
|
+
# Z:123, i:123, f:123.0, B:i,123, H:7b
|
70
|
+
#
|
71
|
+
# Note that the information content is determined by the class of the first
|
72
|
+
# operator. For example:
|
73
|
+
# - 'i:123' ~ 'f:123.4' is true because values are compared as integers
|
74
|
+
# - 'f:123.4' ~ 'i:123' if false because values are compared as floats
|
75
|
+
def equivalent?(field)
|
76
|
+
return true if eql?(field) # Might be faster, so testing this first
|
77
|
+
|
78
|
+
if field.respond_to?(native_fun)
|
79
|
+
if field.is_a?(GFA::Field) && native_fun == :to_s
|
80
|
+
field.to_s(false) == to_native
|
81
|
+
else
|
82
|
+
field.send(native_fun) == to_native
|
83
|
+
end
|
84
|
+
else
|
85
|
+
field == value
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Non-equivalent to +field+, same as +!equivalent?+
|
91
|
+
def !~(field)
|
92
|
+
!self.~(field)
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# Same as +equivalent?+
|
97
|
+
def ~(field)
|
98
|
+
equivalent?(field)
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Evaluate equality. Note that fields with equivalent values evaluate as
|
103
|
+
# different. For example, the following fields have equivalent information,
|
104
|
+
# but they all evaluate as different: Z:123, i:123, f:123.0, B:i,123, H:7b.
|
105
|
+
# To test equivalency of contents instead, use +equivalent?+
|
106
|
+
def eql?(field)
|
107
|
+
if field.is_a?(GFA::Field)
|
108
|
+
type == field.type && value == field.value
|
109
|
+
else
|
110
|
+
field.is_a?(value.class) && value == field
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# Same as +eql?+
|
116
|
+
def ==(field)
|
117
|
+
eql?(field)
|
118
|
+
end
|
49
119
|
end
|
data/lib/gfa/generator.rb
CHANGED
@@ -1,31 +1,35 @@
|
|
1
1
|
class GFA
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
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]
|
6
15
|
end
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def to_s
|
27
|
-
o = ""
|
28
|
-
each_line{ |ln| o += ln + "\n" }
|
29
|
-
o
|
30
|
-
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
|
31
35
|
end
|