htslib 0.2.6 → 0.2.9
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 +4 -4
- data/README.md +78 -30
- data/TUTORIAL.md +61 -15
- data/lib/hts/bam/auxi.rb +82 -21
- data/lib/hts/bam/flag.rb +8 -6
- data/lib/hts/bam/header.rb +50 -8
- data/lib/hts/bam/record.rb +81 -11
- data/lib/hts/bam.rb +98 -54
- data/lib/hts/bcf/header.rb +10 -0
- data/lib/hts/bcf/record.rb +2 -2
- data/lib/hts/bcf.rb +83 -54
- data/lib/hts/faidx/sequence.rb +0 -2
- data/lib/hts/faidx.rb +13 -5
- data/lib/hts/libhts/bgzf.rb +1 -1
- data/lib/hts/libhts/constants.rb +13 -0
- data/lib/hts/libhts/cram.rb +113 -1
- data/lib/hts/libhts/hts.rb +1 -1
- data/lib/hts/libhts/sam.rb +38 -8
- data/lib/hts/libhts/tbx.rb +7 -0
- data/lib/hts/libhts/tbx_funcs.rb +7 -2
- data/lib/hts/libhts/vcf.rb +6 -0
- data/lib/hts/libhts/vcf_funcs.rb +2 -2
- data/lib/hts/libhts.rb +1 -1
- data/lib/hts/{tbx.rb → tabix.rb} +15 -21
- data/lib/hts/version.rb +1 -1
- data/lib/htslib.rb +1 -1
- metadata +9 -79
- /data/lib/hts/libhts/{faidx.rb → fai.rb} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c98f3937d65f091e9e834060f3a94578034d1bf55e7bc372e5ed388e618a6da4
|
4
|
+
data.tar.gz: 8e180044fef210935695bc60c0352b747b570b705f3ce9318b7538d19ddaf645
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5324913bdbe97580fee1e54b6268f22aed2a0b84d449c8a4f62529981c82a57d6ae5cea7cc77ff1be7332425eea259bfe5daa1107b6144e36ef40bb4997dd28f
|
7
|
+
data.tar.gz: 7b230700951223aeda09d64fac7cca44d734d54ec03a7836c5a0fb036e552854db80b9ecaf57aa478e317c684e4712f2f03244e02474fd2ea53a4b93346d1371
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# ruby-htslib
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/htslib)
|
4
|
-
](https://github.com/kojix2/ruby-htslib/actions/workflows/ci.yml)
|
5
5
|
[](LICENSE.txt)
|
6
6
|
[](https://zenodo.org/badge/latestdoi/247078205)
|
7
7
|
[](https://rubydoc.info/gems/htslib)
|
@@ -17,7 +17,7 @@ Ruby-htslib is the [Ruby](https://www.ruby-lang.org) bindings to [HTSlib](https:
|
|
17
17
|
- Ubuntu : `apt install libhts-dev`
|
18
18
|
- macOS : `brew install htslib`
|
19
19
|
- Windows : [mingw-w64-htslib](https://packages.msys2.org/base/mingw-w64-htslib) is automatically fetched when installing the gem ([RubyInstaller](https://rubyinstaller.org) only).
|
20
|
-
- Build from source code (see Development section)
|
20
|
+
- Build from source code (see the Development section)
|
21
21
|
|
22
22
|
## Installation
|
23
23
|
|
@@ -30,10 +30,10 @@ will automatically detect the location of the shared library. If pkg-config does
|
|
30
30
|
Alternatively, you can specify the directory of the shared library by setting the environment variable `HTSLIBDIR`.
|
31
31
|
|
32
32
|
```sh
|
33
|
-
export HTSLIBDIR="/your/path/to/htslib" # libhts.so
|
33
|
+
export HTSLIBDIR="/your/path/to/htslib" # Directory where libhts.so is located
|
34
34
|
```
|
35
35
|
|
36
|
-
ruby-htslib also works on Windows
|
36
|
+
ruby-htslib also works on Windows. If you use RubyInstaller, htslib will be prepared automatically.
|
37
37
|
|
38
38
|
## Usage
|
39
39
|
|
@@ -64,12 +64,24 @@ end
|
|
64
64
|
bam.close
|
65
65
|
```
|
66
66
|
|
67
|
+
With a block
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
HTS::Bam.open("test/fixtures/moo.bam") do |bam|
|
71
|
+
bam.each do |r|
|
72
|
+
puts r.to_s
|
73
|
+
end
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
67
77
|
### HTS::Bcf - VCF / BCF - Variant Call Format file
|
68
78
|
|
69
79
|
Reading fields
|
70
80
|
|
71
81
|
```ruby
|
72
|
-
|
82
|
+
require 'htslib'
|
83
|
+
|
84
|
+
bcf = HTS::Bcf.open("test/fixtures/test.bcf")
|
73
85
|
|
74
86
|
bcf.each do |r|
|
75
87
|
p chrom: r.chrom,
|
@@ -86,27 +98,38 @@ end
|
|
86
98
|
bcf.close
|
87
99
|
```
|
88
100
|
|
101
|
+
With a block
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
HTS::Bcf.open("test/fixtures/test.bcf") do |bcf|
|
105
|
+
bcf.each do |r|
|
106
|
+
puts r.to_s
|
107
|
+
end
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
89
111
|
### HTS::Faidx - FASTA / FASTQ - Nucleic acid sequence
|
90
112
|
|
91
113
|
```ruby
|
92
|
-
fa = HTS::Faidx.open("
|
93
|
-
fa.seq("chr1:1-10")
|
114
|
+
fa = HTS::Faidx.open("test/fixtures/moo.fa")
|
115
|
+
fa.seq("chr1:1-10") # => CGCAACCCGA # 1-based
|
116
|
+
fa.close
|
94
117
|
```
|
95
118
|
|
96
|
-
### HTS::
|
119
|
+
### HTS::Tabix - GFF / BED - TAB-delimited genome position file
|
97
120
|
|
98
121
|
```ruby
|
99
|
-
tb = HTS::
|
100
|
-
tb.query("
|
101
|
-
|
122
|
+
tb = HTS::Tabix.open("test/fixtures/test.vcf.gz")
|
123
|
+
tb.query("poo", 2000, 3000) do |line|
|
124
|
+
puts line.join("\t")
|
102
125
|
end
|
126
|
+
tb.close
|
103
127
|
```
|
104
128
|
|
105
|
-
Note: Faidx or Tbx should not be explicitly closed. See [#27](https://github.com/kojix2/ruby-htslib/issues/27)
|
106
|
-
|
107
129
|
### Low-level API
|
108
130
|
|
109
|
-
|
131
|
+
Middle architectural layer between high-level Ruby code and low-level C code.
|
132
|
+
`HTS::LibHTS` provides native C functions using [Ruby-FFI](https://github.com/ffi/ffi).
|
110
133
|
|
111
134
|
```ruby
|
112
135
|
require 'htslib'
|
@@ -117,26 +140,31 @@ p b[:category]
|
|
117
140
|
p b[:format]
|
118
141
|
```
|
119
142
|
|
120
|
-
|
143
|
+
The low-level API makes it possible to perform detailed operations, such as calling CRAM-specific functions.
|
121
144
|
|
122
|
-
|
145
|
+
#### Macro functions
|
123
146
|
|
124
|
-
|
147
|
+
HTSlib is designed to improve performance with many macro functions. However, it is not possible to call C macro functions directly from Ruby-FFI. To overcome this, important macro functions have been re-implemented in Ruby, allowing them to be called in the same way as native functions.
|
125
148
|
|
126
|
-
|
149
|
+
#### Garbage Collection and Memory Freeing
|
150
|
+
|
151
|
+
A small number of commonly used structs, such as `Bam1` and `Bcf1`, are implemented using FFI's `ManagedStruct`. This allows for automatic memory release when Ruby's garbage collection is triggered. On the other hand, other structs are implemented using `FFI::Struct`, and they will require manual memory release.
|
127
152
|
|
128
153
|
### Need more speed?
|
129
154
|
|
130
|
-
Try Crystal. [HTS.cr](https://github.com/bio-cr/hts.cr) is implemented in Crystal language and provides an API compatible with ruby-htslib.
|
155
|
+
Try Crystal. [HTS.cr](https://github.com/bio-cr/hts.cr) is implemented in Crystal language and provides an API compatible with ruby-htslib.
|
131
156
|
|
132
157
|
## Documentation
|
133
158
|
|
134
159
|
- [TUTORIAL.md](TUTORIAL.md)
|
135
160
|
- [API Documentation (develop branch)](https://kojix2.github.io/ruby-htslib/)
|
136
|
-
- [
|
161
|
+
- [API Documentation (released gem)](https://rubydoc.info/gems/htslib)
|
137
162
|
|
138
163
|
## Development
|
139
164
|
|
165
|
+
#### Compile from source code
|
166
|
+
|
167
|
+
[GNU Autotools](https://en.wikipedia.org/wiki/GNU_Autotools) is required to compile htslib.
|
140
168
|
To get started with development:
|
141
169
|
|
142
170
|
```sh
|
@@ -147,21 +175,41 @@ bundle exec rake htslib:build
|
|
147
175
|
bundle exec rake test
|
148
176
|
```
|
149
177
|
|
150
|
-
|
178
|
+
#### Macro functions are reimplemented
|
151
179
|
|
152
180
|
HTSlib has many macro functions. These macro functions cannot be called from FFI and must be reimplemented in Ruby.
|
153
181
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
182
|
+
#### Use the latest Ruby
|
183
|
+
|
184
|
+
Use Ruby 3 or newer to take advantage of new features. This is possible because we have a small number of users.
|
185
|
+
|
186
|
+
#### Keep compatibility with Crystal language
|
187
|
+
|
188
|
+
Compatibility with Crystal language is important for Ruby-htslib development.
|
189
|
+
|
190
|
+
- [HTS.cr](https://github.com/bio-cr/hts.cr) - HTSlib bindings for Crystal
|
191
|
+
|
192
|
+
Return value
|
193
|
+
|
194
|
+
The most challenging part is the return value. In the Crystal language, methods are expected to return only one type. On the other hand, in the Ruby language, methods that return multiple classes are very common. For example, in the Crystal language, the compiler gets confused if the return value is one of six types: Int32, Int64, Float32, Float64, Nil, or String. In fact Crystal allows you to do that. But the code gets a little messy. In Ruby, this is very common and doesn't cause any problems.
|
195
|
+
|
196
|
+
Memory management
|
197
|
+
|
198
|
+
Ruby and Crystal are languages that use garbage collection. However, the memory release policy for allocated C structures is slightly different: in Ruby-FFI, you can define a `self.release` method in `FFI::Struct`. This method is called when GC. So you don't have to worry about memory in high-level APIs like Bam::Record or Bcf::Record, etc. Crystal requires you to define a finalize method on each class. So you need to define it in Bam::Record or Bcf::Record.
|
199
|
+
|
200
|
+
Macro functions
|
201
|
+
|
202
|
+
In ruby-htslib, C macro functions are added to `LibHTS`, but in Crystal, `LibHTS` is a Lib, so methods cannot be added. methods are added to `LibHTS2`.
|
203
|
+
|
204
|
+
#### Naming convention
|
205
|
+
|
206
|
+
If you are not sure about the naming of a method, follow the Rust-htslib API. This is a very weak rule. if a more appropriate name is found later in Ruby, it will replace it.
|
159
207
|
|
160
|
-
|
208
|
+
#### Support for bitfields of structures
|
161
209
|
|
162
|
-
|
210
|
+
Since Ruby-FFI does not support structure bit fields, the following extensions are used.
|
163
211
|
|
164
|
-
- [ffi-bitfield](https://github.com/kojix2/ffi-bitfield)
|
212
|
+
- [ffi-bitfield](https://github.com/kojix2/ffi-bitfield) - Extension of Ruby-FFI to support bitfields.
|
165
213
|
|
166
214
|
#### Automatic validation
|
167
215
|
|
@@ -180,7 +228,7 @@ Ruby-htslib is a library under development, so even minor improvements like typo
|
|
180
228
|
- [financial contributions](https://github.com/sponsors/kojix2)
|
181
229
|
|
182
230
|
```markdown
|
183
|
-
# Ownership and
|
231
|
+
# Ownership and Commit Rights
|
184
232
|
|
185
233
|
Do you need commit rights to the ruby-htslib repository?
|
186
234
|
Do you want to get admin rights and take over the project?
|
data/TUTORIAL.md
CHANGED
@@ -38,7 +38,7 @@ class Bcf{
|
|
38
38
|
+each() Enumerable
|
39
39
|
+query()
|
40
40
|
}
|
41
|
-
class
|
41
|
+
class Tabix~Hts~{
|
42
42
|
+@hts_file : FFI::Struct
|
43
43
|
}
|
44
44
|
class `Bam::Header`{
|
@@ -46,32 +46,46 @@ class `Bam::Header`{
|
|
46
46
|
+struct()
|
47
47
|
+target_count()
|
48
48
|
+target_names()
|
49
|
+
+name2tid()
|
50
|
+
+tid2name()
|
49
51
|
+to_s()
|
50
52
|
}
|
51
53
|
class `Bam::Record` {
|
52
54
|
+@bam1 : FFI::Struct
|
53
55
|
+@header : Bam::Header
|
54
56
|
+struct()
|
57
|
+
+qname()
|
58
|
+
+qname=()
|
55
59
|
+tid()
|
56
60
|
+tid=()
|
57
61
|
+mtid()
|
58
62
|
+mtid=()
|
59
63
|
+pos()
|
60
64
|
+pos=()
|
61
|
-
+mpos()
|
62
|
-
+mpos=()
|
65
|
+
+mpos() +mate_pos()
|
66
|
+
+mpos=() +mate_pos=()
|
63
67
|
+bin()
|
64
68
|
+bin=()
|
65
|
-
+
|
66
|
-
+
|
67
|
-
+
|
69
|
+
+endpos()
|
70
|
+
+chorm() +contig()
|
71
|
+
+mate_chrom() +mate_contig()
|
72
|
+
+strand()
|
73
|
+
+mate_strand()
|
74
|
+
+isize() +insert_size()
|
75
|
+
+isize=() +insert_size=()
|
68
76
|
+mapq()
|
77
|
+
+mapq=()
|
69
78
|
+cigar()
|
70
|
-
+
|
71
|
-
+
|
72
|
-
+seq()
|
79
|
+
+qlen()
|
80
|
+
+rlen()
|
81
|
+
+seq() +sequence()
|
82
|
+
+len()
|
83
|
+
+base(n)
|
73
84
|
+qual()
|
74
85
|
+qual_string()
|
86
|
+
+base_qual(n)
|
87
|
+
+flag()
|
88
|
+
+flag=()
|
75
89
|
+aux()
|
76
90
|
+to_s()
|
77
91
|
}
|
@@ -91,12 +105,19 @@ class `Bcf::Record`{
|
|
91
105
|
+@bcf1 : FFI::Struct
|
92
106
|
+@header : Bcf::Header
|
93
107
|
+struct()
|
108
|
+
+rid()
|
109
|
+
+rid=()
|
94
110
|
+chrom()
|
95
111
|
+pos()
|
112
|
+
+pos=()
|
96
113
|
+id()
|
97
|
-
+
|
114
|
+
+id=()
|
115
|
+
+clear_id()
|
98
116
|
+ref()
|
99
117
|
+alt()
|
118
|
+
+alleles()
|
119
|
+
+qual()
|
120
|
+
+qual=()
|
100
121
|
+filter()
|
101
122
|
+info()
|
102
123
|
+format()
|
@@ -164,6 +185,20 @@ class Faidx{
|
|
164
185
|
|
165
186
|
```
|
166
187
|
|
188
|
+
## Installation
|
189
|
+
|
190
|
+
```
|
191
|
+
gem install htslib
|
192
|
+
```
|
193
|
+
|
194
|
+
You can check which shared libraries are used by ruby-htslib as follows
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
require "htslib"
|
198
|
+
puts HTS.lib_path
|
199
|
+
# => "/home/kojix2/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/htslib-0.2.6/vendor/libhts.so"
|
200
|
+
```
|
201
|
+
|
167
202
|
## HTS::Bam - SAM / BAM / CRAM - Sequence Alignment Map file
|
168
203
|
|
169
204
|
Reading fields
|
@@ -194,9 +229,8 @@ bam.close
|
|
194
229
|
Open with block
|
195
230
|
|
196
231
|
```ruby
|
197
|
-
HTS::Bam.open("test/fixtures/moo.bam") do |
|
198
|
-
|
199
|
-
do |r|
|
232
|
+
HTS::Bam.open("test/fixtures/moo.bam") do |bam|
|
233
|
+
bam.each do |record|
|
200
234
|
# ...
|
201
235
|
end
|
202
236
|
end
|
@@ -220,6 +254,18 @@ in.close
|
|
220
254
|
out.close
|
221
255
|
```
|
222
256
|
|
257
|
+
Create index
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
HTS::Bam.open("foo.bam", build_index: true)
|
261
|
+
```
|
262
|
+
|
263
|
+
```
|
264
|
+
b = HTS::Bam.open("foo.bam")
|
265
|
+
.build_index
|
266
|
+
.load_index
|
267
|
+
```
|
268
|
+
|
223
269
|
## HTS::Bcf - VCF / BCF - Variant Call Format file
|
224
270
|
|
225
271
|
Reading fields
|
@@ -245,8 +291,8 @@ bcf.close
|
|
245
291
|
Open with block
|
246
292
|
|
247
293
|
```ruby
|
248
|
-
HTS::Bcf.open("b.bcf") do |
|
249
|
-
|
294
|
+
HTS::Bcf.open("b.bcf") do |bcf|
|
295
|
+
bcf.each do |record|
|
250
296
|
# ...
|
251
297
|
end
|
252
298
|
end
|
data/lib/hts/bam/auxi.rb
CHANGED
@@ -3,8 +3,11 @@
|
|
3
3
|
# Q. Why is the file name auxi.rb and not aux.rb?
|
4
4
|
#
|
5
5
|
# A. This is for compatibility with Windows.
|
6
|
+
#
|
6
7
|
# In Windows, aux is a reserved word
|
7
|
-
# You cannot create a file named aux.
|
8
|
+
# You cannot create a file named aux.
|
9
|
+
#
|
10
|
+
# What?! That's crazy!
|
8
11
|
|
9
12
|
module HTS
|
10
13
|
class Bam < Hts
|
@@ -15,6 +18,7 @@ module HTS
|
|
15
18
|
# Ruby's Aux class references a part of it. There is no one-to-one
|
16
19
|
# correspondence between C structures and Ruby's Aux class.
|
17
20
|
class Aux
|
21
|
+
include Enumerable
|
18
22
|
attr_reader :record
|
19
23
|
|
20
24
|
def initialize(record)
|
@@ -26,27 +30,10 @@ module HTS
|
|
26
30
|
# which provides methods like `get_int`, `get_float`, etc.
|
27
31
|
# I think they are better than `fetch_int`` and `fetch_float`.
|
28
32
|
def get(key, type = nil)
|
29
|
-
|
30
|
-
return nil if
|
31
|
-
|
32
|
-
type = type ? type.to_s : aux.read_string(1)
|
33
|
+
aux_ptr = LibHTS.bam_aux_get(@record.struct, key)
|
34
|
+
return nil if aux_ptr.null?
|
33
35
|
|
34
|
-
|
35
|
-
# f (real number), H (hexadecimal array),
|
36
|
-
# i (integer), or Z (string).
|
37
|
-
|
38
|
-
case type
|
39
|
-
when "i", "I", "c", "C", "s", "S"
|
40
|
-
LibHTS.bam_aux2i(aux)
|
41
|
-
when "f", "d"
|
42
|
-
LibHTS.bam_aux2f(aux)
|
43
|
-
when "Z", "H"
|
44
|
-
LibHTS.bam_aux2Z(aux)
|
45
|
-
when "A" # char
|
46
|
-
LibHTS.bam_aux2A(aux).chr
|
47
|
-
else
|
48
|
-
raise NotImplementedError, "type: #{t}"
|
49
|
-
end
|
36
|
+
get_ruby_aux(aux_ptr, type)
|
50
37
|
end
|
51
38
|
|
52
39
|
# For compatibility with HTS.cr.
|
@@ -67,6 +54,80 @@ module HTS
|
|
67
54
|
def [](key)
|
68
55
|
get(key)
|
69
56
|
end
|
57
|
+
|
58
|
+
def first
|
59
|
+
aux_ptr = first_pointer
|
60
|
+
return nil if aux_ptr.null?
|
61
|
+
|
62
|
+
get_ruby_aux(aux_ptr)
|
63
|
+
end
|
64
|
+
|
65
|
+
def each
|
66
|
+
return enum_for(__method__) unless block_given?
|
67
|
+
|
68
|
+
aux_ptr = first_pointer
|
69
|
+
return nil if aux_ptr.null?
|
70
|
+
|
71
|
+
loop do
|
72
|
+
yield get_ruby_aux(aux_ptr)
|
73
|
+
aux_ptr = LibHTS.bam_aux_next(@record.struct, aux_ptr)
|
74
|
+
break if aux_ptr.null?
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_h
|
79
|
+
h = {}
|
80
|
+
aux_ptr = first_pointer
|
81
|
+
return h if aux_ptr.null?
|
82
|
+
|
83
|
+
loop do
|
84
|
+
key = FFI::Pointer.new(aux_ptr.address - 2).read_string(2)
|
85
|
+
h[key] = get_ruby_aux(aux_ptr)
|
86
|
+
aux_ptr = LibHTS.bam_aux_next(@record.struct, aux_ptr)
|
87
|
+
break if aux_ptr.null?
|
88
|
+
end
|
89
|
+
h
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def first_pointer
|
95
|
+
LibHTS.bam_aux_first(@record.struct)
|
96
|
+
end
|
97
|
+
|
98
|
+
def get_ruby_aux(aux_ptr, type = nil)
|
99
|
+
type = type ? type.to_s : aux_ptr.read_string(1)
|
100
|
+
|
101
|
+
# A (character), B (general array),
|
102
|
+
# f (real number), H (hexadecimal array),
|
103
|
+
# i (integer), or Z (string).
|
104
|
+
|
105
|
+
case type
|
106
|
+
when "i", "I", "c", "C", "s", "S"
|
107
|
+
LibHTS.bam_aux2i(aux_ptr)
|
108
|
+
when "f", "d"
|
109
|
+
LibHTS.bam_aux2f(aux_ptr)
|
110
|
+
when "Z", "H"
|
111
|
+
LibHTS.bam_aux2Z(aux_ptr)
|
112
|
+
when "A" # char
|
113
|
+
LibHTS.bam_aux2A(aux_ptr).chr
|
114
|
+
when "B" # array
|
115
|
+
t2 = aux_ptr.read_string(2)[1] # just a little less efficient
|
116
|
+
l = LibHTS.bam_auxB_len(aux_ptr)
|
117
|
+
case t2
|
118
|
+
when "c", "C", "s", "S", "i", "I"
|
119
|
+
# FIXME : Not efficient.
|
120
|
+
Array.new(l) { |i| LibHTS.bam_auxB2i(aux_ptr, i) }
|
121
|
+
when "f", "d"
|
122
|
+
# FIXME : Not efficient.
|
123
|
+
Array.new(l) { |i| LibHTS.bam_auxB2f(aux_ptr, i) }
|
124
|
+
else
|
125
|
+
raise NotImplementedError, "type: #{type} #{t2}"
|
126
|
+
end
|
127
|
+
else
|
128
|
+
raise NotImplementedError, "type: #{type}"
|
129
|
+
end
|
130
|
+
end
|
70
131
|
end
|
71
132
|
end
|
72
133
|
end
|
data/lib/hts/bam/flag.rb
CHANGED
@@ -69,27 +69,29 @@ module HTS
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def &(other)
|
72
|
-
|
72
|
+
self.class.new(@value & other.to_i)
|
73
73
|
end
|
74
74
|
|
75
75
|
def |(other)
|
76
|
-
|
76
|
+
self.class.new(@value | other.to_i)
|
77
77
|
end
|
78
78
|
|
79
79
|
def ^(other)
|
80
|
-
|
80
|
+
self.class.new(@value ^ other.to_i)
|
81
81
|
end
|
82
82
|
|
83
83
|
def ~
|
84
|
-
|
84
|
+
# FIXME: Only 12bits are used for flags
|
85
|
+
# The result is different from the Crystal version.
|
86
|
+
self.class.new(~@value)
|
85
87
|
end
|
86
88
|
|
87
89
|
def <<(f)
|
88
|
-
|
90
|
+
self.class.new(@value << f.to_i)
|
89
91
|
end
|
90
92
|
|
91
93
|
def >>(other)
|
92
|
-
|
94
|
+
self.class.new(@value >> other.to_i)
|
93
95
|
end
|
94
96
|
|
95
97
|
def to_i
|
data/lib/hts/bam/header.rb
CHANGED
@@ -6,8 +6,8 @@ module HTS
|
|
6
6
|
class Bam < Hts
|
7
7
|
# A class for working with alignment header.
|
8
8
|
class Header
|
9
|
-
def self.parse(
|
10
|
-
new(LibHTS.sam_hdr_parse(
|
9
|
+
def self.parse(text)
|
10
|
+
new(LibHTS.sam_hdr_parse(text.size, text))
|
11
11
|
end
|
12
12
|
|
13
13
|
def initialize(arg = nil)
|
@@ -21,6 +21,8 @@ module HTS
|
|
21
21
|
else
|
22
22
|
raise TypeError, "Invalid argument"
|
23
23
|
end
|
24
|
+
|
25
|
+
yield self if block_given?
|
24
26
|
end
|
25
27
|
|
26
28
|
def struct
|
@@ -31,11 +33,23 @@ module HTS
|
|
31
33
|
@sam_hdr.to_ptr
|
32
34
|
end
|
33
35
|
|
36
|
+
def targets
|
37
|
+
Array.new(target_count) do |i|
|
38
|
+
name = LibHTS.sam_hdr_tid2name(@sam_hdr, i)
|
39
|
+
len = LibHTS.sam_hdr_tid2len(@sam_hdr, i)
|
40
|
+
{ name:, len: }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
34
44
|
def target_count
|
35
45
|
# FIXME: sam_hdr_nref
|
36
46
|
@sam_hdr[:n_targets]
|
37
47
|
end
|
38
48
|
|
49
|
+
def target_name(tid)
|
50
|
+
tid2name(tid)
|
51
|
+
end
|
52
|
+
|
39
53
|
def target_names
|
40
54
|
Array.new(target_count) do |i|
|
41
55
|
LibHTS.sam_hdr_tid2name(@sam_hdr, i)
|
@@ -48,15 +62,20 @@ module HTS
|
|
48
62
|
end
|
49
63
|
end
|
50
64
|
|
51
|
-
|
52
|
-
|
53
|
-
LibHTS.sam_hdr_add_lines(@sam_hdr, str, 0)
|
65
|
+
def write(...)
|
66
|
+
add_lines(...)
|
54
67
|
end
|
55
68
|
|
56
69
|
# experimental
|
57
|
-
def
|
58
|
-
|
59
|
-
|
70
|
+
def <<(obj)
|
71
|
+
case obj
|
72
|
+
when Array, Hash
|
73
|
+
args = obj.flatten(-1).map { |i| i.to_a if i.is_a?(Hash) }
|
74
|
+
add_line(*args)
|
75
|
+
else
|
76
|
+
add_lines(obj.to_s)
|
77
|
+
end
|
78
|
+
self
|
60
79
|
end
|
61
80
|
|
62
81
|
# experimental
|
@@ -87,8 +106,31 @@ module HTS
|
|
87
106
|
LibHTS.sam_hdr_str(@sam_hdr)
|
88
107
|
end
|
89
108
|
|
109
|
+
# experimental
|
110
|
+
def get_tid(name)
|
111
|
+
name2tid(name)
|
112
|
+
end
|
113
|
+
|
90
114
|
private
|
91
115
|
|
116
|
+
def name2tid(name)
|
117
|
+
LibHTS.sam_hdr_name2tid(@sam_hdr, name)
|
118
|
+
end
|
119
|
+
|
120
|
+
def tid2name(tid)
|
121
|
+
LibHTS.sam_hdr_tid2name(@sam_hdr, tid)
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_lines(str)
|
125
|
+
LibHTS.sam_hdr_add_lines(@sam_hdr, str, 0)
|
126
|
+
end
|
127
|
+
|
128
|
+
def add_line(*args)
|
129
|
+
type = args.shift
|
130
|
+
args = args.flat_map { |arg| [:string, arg] }
|
131
|
+
LibHTS.sam_hdr_add_line(@sam_hdr, type, *args, :pointer, FFI::Pointer::NULL)
|
132
|
+
end
|
133
|
+
|
92
134
|
def initialize_copy(orig)
|
93
135
|
@sam_hdr = LibHTS.sam_hdr_dup(orig.struct)
|
94
136
|
end
|