htslib 0.2.6 → 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +77 -29
- data/TUTORIAL.md +61 -15
- data/lib/hts/bam/auxi.rb +76 -19
- data/lib/hts/bam/header.rb +8 -0
- data/lib/hts/bam/record.rb +15 -11
- data/lib/hts/bam.rb +98 -54
- data/lib/hts/bcf/header.rb +8 -0
- data/lib/hts/bcf/record.rb +2 -2
- data/lib/hts/bcf.rb +81 -52
- 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/sam.rb +18 -6
- 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 -9
- /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: caaf2dd527c9570e2e4c72b22e5252a1ef69adbf983fbfe3e815c3a9bc1b91c0
|
4
|
+
data.tar.gz: b7e0b6ecf736142ea9b43e4ed7f80513b1c0d002ea40b2565e218be3a40d2fac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6fe725489c93915fc5afa5d58dd2a5a0030b82546f473b6cae4245898b01f60919494d64b31f3442c3ea316a25fb31c0b46cfdd447230c253c21818ca3da9fb8
|
7
|
+
data.tar.gz: f5bed585f7bded73022ea0ad9a1dc2eb6a10c13e63772cac267a3c23497b521d82d5ab82763e512b452d47f59be8c47dcf5ff2046c96dcc492604931799cf2b2
|
data/README.md
CHANGED
@@ -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)
|
@@ -29,24 +33,7 @@ module HTS
|
|
29
33
|
aux = LibHTS.bam_aux_get(@record.struct, key)
|
30
34
|
return nil if aux.null?
|
31
35
|
|
32
|
-
|
33
|
-
|
34
|
-
# A (character), B (general array),
|
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, type)
|
50
37
|
end
|
51
38
|
|
52
39
|
# For compatibility with HTS.cr.
|
@@ -67,6 +54,76 @@ module HTS
|
|
67
54
|
def [](key)
|
68
55
|
get(key)
|
69
56
|
end
|
57
|
+
|
58
|
+
def first
|
59
|
+
aux = LibHTS.bam_aux_first(@record.struct)
|
60
|
+
return nil if aux.null?
|
61
|
+
|
62
|
+
get_ruby_aux(aux)
|
63
|
+
end
|
64
|
+
|
65
|
+
def each
|
66
|
+
return enum_for(__method__) unless block_given?
|
67
|
+
|
68
|
+
aux = LibHTS.bam_aux_first(@record.struct)
|
69
|
+
return nil if aux.null?
|
70
|
+
|
71
|
+
loop do
|
72
|
+
yield get_ruby_aux(aux)
|
73
|
+
aux = LibHTS.bam_aux_next(@record.struct, aux)
|
74
|
+
break if aux.null?
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_h
|
79
|
+
h = {}
|
80
|
+
aux = LibHTS.bam_aux_first(@record.struct)
|
81
|
+
return h if aux.null?
|
82
|
+
|
83
|
+
loop do
|
84
|
+
key = FFI::Pointer.new(aux.address - 2).read_string(2)
|
85
|
+
h[key] = get_ruby_aux(aux)
|
86
|
+
aux = LibHTS.bam_aux_next(@record.struct, aux)
|
87
|
+
break if aux.null?
|
88
|
+
end
|
89
|
+
h
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def get_ruby_aux(aux, type = nil)
|
95
|
+
type = type ? type.to_s : aux.read_string(1)
|
96
|
+
|
97
|
+
# A (character), B (general array),
|
98
|
+
# f (real number), H (hexadecimal array),
|
99
|
+
# i (integer), or Z (string).
|
100
|
+
|
101
|
+
case type
|
102
|
+
when "i", "I", "c", "C", "s", "S"
|
103
|
+
LibHTS.bam_aux2i(aux)
|
104
|
+
when "f", "d"
|
105
|
+
LibHTS.bam_aux2f(aux)
|
106
|
+
when "Z", "H"
|
107
|
+
LibHTS.bam_aux2Z(aux)
|
108
|
+
when "A" # char
|
109
|
+
LibHTS.bam_aux2A(aux).chr
|
110
|
+
when "B" # array
|
111
|
+
t2 = aux.read_string(2)[1] # just a little less efficient
|
112
|
+
l = LibHTS.bam_auxB_len(aux)
|
113
|
+
case t2
|
114
|
+
when "c", "C", "s", "S", "i", "I"
|
115
|
+
# FIXME : Not efficient.
|
116
|
+
Array.new(l) { |i| LibHTS.bam_auxB2i(aux, i) }
|
117
|
+
when "f", "d"
|
118
|
+
# FIXME : Not efficient.
|
119
|
+
Array.new(l) { |i| LibHTS.bam_auxB2f(aux, i) }
|
120
|
+
else
|
121
|
+
raise NotImplementedError, "type: #{type} #{t2}"
|
122
|
+
end
|
123
|
+
else
|
124
|
+
raise NotImplementedError, "type: #{type}"
|
125
|
+
end
|
126
|
+
end
|
70
127
|
end
|
71
128
|
end
|
72
129
|
end
|
data/lib/hts/bam/header.rb
CHANGED
data/lib/hts/bam/record.rb
CHANGED
@@ -12,8 +12,8 @@ module HTS
|
|
12
12
|
|
13
13
|
attr_reader :header
|
14
14
|
|
15
|
-
def initialize(
|
16
|
-
@bam1 = bam1_t
|
15
|
+
def initialize(header, bam1_t = nil)
|
16
|
+
@bam1 = bam1_t || LibHTS.bam_init1
|
17
17
|
@header = header
|
18
18
|
end
|
19
19
|
|
@@ -32,6 +32,10 @@ module HTS
|
|
32
32
|
LibHTS.bam_get_qname(@bam1).read_string
|
33
33
|
end
|
34
34
|
|
35
|
+
def qname=(name)
|
36
|
+
LibHTS.bam_set_qname(@bam1, name)
|
37
|
+
end
|
38
|
+
|
35
39
|
# Get the chromosome ID of the alignment. -1 if not mapped.
|
36
40
|
# @return [Integer] chromosome ID
|
37
41
|
def tid
|
@@ -178,7 +182,7 @@ module HTS
|
|
178
182
|
def seq
|
179
183
|
r = LibHTS.bam_get_seq(@bam1)
|
180
184
|
seq = String.new
|
181
|
-
|
185
|
+
len.times do |i|
|
182
186
|
seq << SEQ_NT16_STR[LibHTS.bam_seqi(r, i)]
|
183
187
|
end
|
184
188
|
seq
|
@@ -195,8 +199,8 @@ module HTS
|
|
195
199
|
# @param [Integer] i index
|
196
200
|
# @return [String] base
|
197
201
|
def base(n)
|
198
|
-
n +=
|
199
|
-
return "." if (n >=
|
202
|
+
n += len if n < 0
|
203
|
+
return "." if (n >= len) || (n < 0) # eg. base(-1000)
|
200
204
|
|
201
205
|
r = LibHTS.bam_get_seq(@bam1)
|
202
206
|
SEQ_NT16_STR[LibHTS.bam_seqi(r, n)]
|
@@ -206,7 +210,7 @@ module HTS
|
|
206
210
|
# @return [Array] base qualities
|
207
211
|
def qual
|
208
212
|
q_ptr = LibHTS.bam_get_qual(@bam1)
|
209
|
-
q_ptr.read_array_of_uint8(
|
213
|
+
q_ptr.read_array_of_uint8(len)
|
210
214
|
end
|
211
215
|
|
212
216
|
# Get the base qualities as a string. (a.k.a QUAL)
|
@@ -220,8 +224,8 @@ module HTS
|
|
220
224
|
# @param [Integer] i index
|
221
225
|
# @return [Integer] base quality
|
222
226
|
def base_qual(n)
|
223
|
-
n +=
|
224
|
-
return 0 if (n >=
|
227
|
+
n += len if n < 0
|
228
|
+
return 0 if (n >= len) || (n < 0) # eg. base_qual(-1000)
|
225
229
|
|
226
230
|
q_ptr = LibHTS.bam_get_qual(@bam1)
|
227
231
|
q_ptr.get_uint8(n)
|
@@ -256,11 +260,11 @@ module HTS
|
|
256
260
|
end
|
257
261
|
end
|
258
262
|
|
259
|
-
# TODO: add a method to get the
|
263
|
+
# TODO: add a method to get the auxiliary fields as a hash.
|
260
264
|
|
261
|
-
# TODO: add a method to set the
|
265
|
+
# TODO: add a method to set the auxiliary fields.
|
262
266
|
|
263
|
-
# TODO: add a method to remove the
|
267
|
+
# TODO: add a method to remove the auxiliary fields.
|
264
268
|
|
265
269
|
# TODO: add a method to set variable length data (qname, cigar, seq, qual).
|
266
270
|
|
data/lib/hts/bam.rb
CHANGED
@@ -114,29 +114,12 @@ module HTS
|
|
114
114
|
def write(record)
|
115
115
|
check_closed
|
116
116
|
|
117
|
-
# record = record.dup
|
118
117
|
r = LibHTS.sam_write1(@hts_file, header, record)
|
119
118
|
raise "Failed to write record" if r < 0
|
120
119
|
end
|
121
120
|
|
122
|
-
def <<(
|
123
|
-
write(
|
124
|
-
end
|
125
|
-
|
126
|
-
def each(copy: false, &block)
|
127
|
-
if copy
|
128
|
-
each_record_copy(&block)
|
129
|
-
else
|
130
|
-
each_record_reuse(&block)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def query(region, copy: false, &block)
|
135
|
-
if copy
|
136
|
-
query_copy(region, &block)
|
137
|
-
else
|
138
|
-
query_reuse(region, &block)
|
139
|
-
end
|
121
|
+
def <<(record)
|
122
|
+
write(record)
|
140
123
|
end
|
141
124
|
|
142
125
|
# @!macro [attach] define_getter
|
@@ -158,9 +141,10 @@ module HTS
|
|
158
141
|
alias isize insert_size
|
159
142
|
alias mpos mate_pos
|
160
143
|
|
144
|
+
# FXIME: experimental
|
161
145
|
def aux(tag)
|
162
|
-
warn "experimental"
|
163
146
|
check_closed
|
147
|
+
|
164
148
|
position = tell
|
165
149
|
ary = map { |r| r.aux(tag) }
|
166
150
|
seek(position)
|
@@ -185,8 +169,8 @@ module HTS
|
|
185
169
|
alias each_isize each_insert_size
|
186
170
|
alias each_mpos each_mate_pos
|
187
171
|
|
172
|
+
# FIXME: experimental
|
188
173
|
def each_aux(tag)
|
189
|
-
warn "experimental"
|
190
174
|
check_closed
|
191
175
|
return to_enum(__method__, tag) unless block_given?
|
192
176
|
|
@@ -197,47 +181,44 @@ module HTS
|
|
197
181
|
self
|
198
182
|
end
|
199
183
|
|
200
|
-
|
184
|
+
def each(copy: false, &block)
|
185
|
+
if copy
|
186
|
+
each_record_copy(&block)
|
187
|
+
else
|
188
|
+
each_record_reuse(&block)
|
189
|
+
end
|
190
|
+
end
|
201
191
|
|
202
|
-
def
|
192
|
+
def query(region, beg = nil, end_ = nil, copy: false, &block)
|
203
193
|
check_closed
|
204
194
|
raise "Index file is required to call the query method." unless index_loaded?
|
205
|
-
return to_enum(__method__, region) unless block_given?
|
206
|
-
|
207
|
-
qiter = LibHTS.sam_itr_querys(@idx, header, region)
|
208
|
-
raise "Failed to query region: #{region}" if qiter.null?
|
209
195
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
196
|
+
if beg && end_
|
197
|
+
tid = header.name2tid(region)
|
198
|
+
queryi(tid, beg, end_, copy:, &block)
|
199
|
+
elsif beg.nil? && end_.nil?
|
200
|
+
querys(region, copy:, &block)
|
201
|
+
else
|
202
|
+
raise ArgumentError, "beg and end_ must be specified together"
|
216
203
|
end
|
217
|
-
self
|
218
204
|
end
|
219
205
|
|
220
|
-
|
221
|
-
check_closed
|
222
|
-
raise "Index file is required to call the query method." unless index_loaded?
|
223
|
-
return to_enum(__method__, region) unless block_given?
|
206
|
+
private
|
224
207
|
|
225
|
-
|
226
|
-
|
208
|
+
def queryi(tid, beg, end_, copy: false, &block)
|
209
|
+
if copy
|
210
|
+
queryi_copy(tid, beg, end_, &block)
|
211
|
+
else
|
212
|
+
queryi_reuse(tid, beg, end_, &block)
|
213
|
+
end
|
214
|
+
end
|
227
215
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
raise if slen < -1
|
234
|
-
|
235
|
-
yield Record.new(bam1, header)
|
236
|
-
end
|
237
|
-
ensure
|
238
|
-
LibHTS.hts_itr_destroy(qiter)
|
216
|
+
def querys(region, copy: false, &block)
|
217
|
+
if copy
|
218
|
+
querys_copy(region, &block)
|
219
|
+
else
|
220
|
+
querys_reuse(region, &block)
|
239
221
|
end
|
240
|
-
self
|
241
222
|
end
|
242
223
|
|
243
224
|
def each_record_reuse
|
@@ -247,7 +228,7 @@ module HTS
|
|
247
228
|
return to_enum(__method__) unless block_given?
|
248
229
|
|
249
230
|
bam1 = LibHTS.bam_init1
|
250
|
-
record = Record.new(
|
231
|
+
record = Record.new(header, bam1)
|
251
232
|
yield record while LibHTS.sam_read1(@hts_file, header, bam1) != -1
|
252
233
|
self
|
253
234
|
end
|
@@ -257,10 +238,73 @@ module HTS
|
|
257
238
|
return to_enum(__method__) unless block_given?
|
258
239
|
|
259
240
|
while LibHTS.sam_read1(@hts_file, header, bam1 = LibHTS.bam_init1) != -1
|
260
|
-
record = Record.new(
|
241
|
+
record = Record.new(header, bam1)
|
261
242
|
yield record
|
262
243
|
end
|
263
244
|
self
|
264
245
|
end
|
246
|
+
|
247
|
+
def queryi_reuse(tid, beg, end_, &block)
|
248
|
+
return to_enum(__method__, region, beg, end_) unless block_given?
|
249
|
+
|
250
|
+
qiter = LibHTS.sam_itr_queryi(@idx, tid, beg, end_)
|
251
|
+
raise "Failed to query region: #{tid} #{beg} #{end_}" if qiter.null?
|
252
|
+
|
253
|
+
query_reuse_yield(qiter, &block)
|
254
|
+
self
|
255
|
+
end
|
256
|
+
|
257
|
+
def queryi_copy(tid, beg, end_, &block)
|
258
|
+
return to_enum(__method__, tid, beg, end_) unless block_given?
|
259
|
+
|
260
|
+
qiter = LibHTS.sam_itr_queryi(@idx, tid, beg, end_)
|
261
|
+
raise "Failed to query region: #{tid} #{beg} #{end_}" if qiter.null?
|
262
|
+
|
263
|
+
query_copy(qiter, &block)
|
264
|
+
self
|
265
|
+
end
|
266
|
+
|
267
|
+
def querys_reuse(region, &block)
|
268
|
+
return to_enum(__method__, region) unless block_given?
|
269
|
+
|
270
|
+
qiter = LibHTS.sam_itr_querys(@idx, header, region)
|
271
|
+
raise "Failed to query region: #{region}" if qiter.null?
|
272
|
+
|
273
|
+
query_reuse_yield(qiter, &block)
|
274
|
+
self
|
275
|
+
end
|
276
|
+
|
277
|
+
def querys_copy(region, &block)
|
278
|
+
return to_enum(__method__, region) unless block_given?
|
279
|
+
|
280
|
+
qiter = LibHTS.sam_itr_querys(@idx, header, region)
|
281
|
+
raise "Failed to query region: #{region}" if qiter.null?
|
282
|
+
|
283
|
+
query_copy(qiter, &block)
|
284
|
+
self
|
285
|
+
end
|
286
|
+
|
287
|
+
def query_reuse_yield(qiter)
|
288
|
+
bam1 = LibHTS.bam_init1
|
289
|
+
record = Record.new(header, bam1)
|
290
|
+
begin
|
291
|
+
yield record while LibHTS.sam_itr_next(@hts_file, qiter, bam1) > 0
|
292
|
+
ensure
|
293
|
+
LibHTS.hts_itr_destroy(qiter)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
def query_copy(qiter)
|
298
|
+
loop do
|
299
|
+
bam1 = LibHTS.bam_init1
|
300
|
+
slen = LibHTS.sam_itr_next(@hts_file, qiter, bam1)
|
301
|
+
break if slen == -1
|
302
|
+
raise if slen < -1
|
303
|
+
|
304
|
+
yield Record.new(header, bam1)
|
305
|
+
end
|
306
|
+
ensure
|
307
|
+
LibHTS.hts_itr_destroy(qiter)
|
308
|
+
end
|
265
309
|
end
|
266
310
|
end
|
data/lib/hts/bcf/header.rb
CHANGED
data/lib/hts/bcf/record.rb
CHANGED
data/lib/hts/bcf.rb
CHANGED
@@ -63,7 +63,7 @@ module HTS
|
|
63
63
|
warn "Create index for #{@file_name}"
|
64
64
|
end
|
65
65
|
case LibHTS.bcf_index_build3(@file_name, index_name, min_shift, (@nthreads || threads))
|
66
|
-
when 0 #
|
66
|
+
when 0 # successful
|
67
67
|
when -1 then raise "indexing failed"
|
68
68
|
when -2 then raise "opening #{@file_name} failed"
|
69
69
|
when -3 then raise "format not indexable"
|
@@ -98,7 +98,7 @@ module HTS
|
|
98
98
|
def write_header(header)
|
99
99
|
check_closed
|
100
100
|
|
101
|
-
@header = header.
|
101
|
+
@header = header.clone
|
102
102
|
LibHTS.bcf_hdr_write(@hts_file, header)
|
103
103
|
end
|
104
104
|
|
@@ -130,35 +130,6 @@ module HTS
|
|
130
130
|
header.samples
|
131
131
|
end
|
132
132
|
|
133
|
-
def each(copy: false, &block)
|
134
|
-
if copy
|
135
|
-
each_record_copy(&block)
|
136
|
-
else
|
137
|
-
each_record_reuse(&block)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
def query(...)
|
142
|
-
querys(...) # Fixme
|
143
|
-
end
|
144
|
-
|
145
|
-
# def queryi
|
146
|
-
# end
|
147
|
-
|
148
|
-
def querys(region, copy: false, &block)
|
149
|
-
if copy
|
150
|
-
querys_copy(region, &block)
|
151
|
-
else
|
152
|
-
querys_reuse(region, &block)
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
# private def queryi_copy
|
157
|
-
# end
|
158
|
-
|
159
|
-
# private def queryi_reuse
|
160
|
-
# end
|
161
|
-
|
162
133
|
# @!macro [attach] define_getter
|
163
134
|
# @method $1
|
164
135
|
# Get $1 array
|
@@ -230,20 +201,71 @@ module HTS
|
|
230
201
|
end
|
231
202
|
end
|
232
203
|
|
233
|
-
|
204
|
+
def each(copy: false, &block)
|
205
|
+
if copy
|
206
|
+
each_record_copy(&block)
|
207
|
+
else
|
208
|
+
each_record_reuse(&block)
|
209
|
+
end
|
210
|
+
end
|
234
211
|
|
235
|
-
def
|
212
|
+
def query(region, beg = nil, end_ = nil, copy: false, &block)
|
236
213
|
check_closed
|
237
214
|
|
238
215
|
raise "query is only available for BCF files" unless file_format == "bcf"
|
239
216
|
raise "Index file is required to call the query method." unless index_loaded?
|
217
|
+
|
218
|
+
if beg && end_
|
219
|
+
tid = header.name2id(region)
|
220
|
+
queryi(tid, beg, end_, copy:, &block)
|
221
|
+
elsif beg.nil? && end_.nil?
|
222
|
+
querys(region, copy:, &block)
|
223
|
+
else
|
224
|
+
raise ArgumentError, "beg and end must be specified together"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
private
|
229
|
+
|
230
|
+
def queryi(tid, beg, end_, copy: false, &block)
|
231
|
+
if copy
|
232
|
+
queryi_copy(tid, beg, end_, &block)
|
233
|
+
else
|
234
|
+
queryi_reuse(tid, beg, end_, &block)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def querys(region, copy: false, &block)
|
239
|
+
if copy
|
240
|
+
querys_copy(region, &block)
|
241
|
+
else
|
242
|
+
querys_reuse(region, &block)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def queryi_reuse(tid, beg, end_, &block)
|
247
|
+
return to_enum(__method__, tid, beg, end_) unless block_given?
|
248
|
+
|
249
|
+
qiter = LibHTS.bcf_itr_queryi(@idx, tid, beg, end_)
|
250
|
+
raise "Failed to query region #{tid} #{beg} #{end_}" if qiter.null?
|
251
|
+
|
252
|
+
query_reuse_yield(qiter, &block)
|
253
|
+
self
|
254
|
+
end
|
255
|
+
|
256
|
+
def querys_reuse(region, &block)
|
240
257
|
return to_enum(__method__, region) unless block_given?
|
241
258
|
|
242
259
|
qiter = LibHTS.bcf_itr_querys(@idx, header, region)
|
243
260
|
raise "Failed to query region #{region}" if qiter.null?
|
244
261
|
|
262
|
+
query_reuse_yield(qiter, &block)
|
263
|
+
self
|
264
|
+
end
|
265
|
+
|
266
|
+
def query_reuse_yield(qiter)
|
245
267
|
bcf1 = LibHTS.bcf_init
|
246
|
-
record = Record.new(
|
268
|
+
record = Record.new(header, bcf1)
|
247
269
|
begin
|
248
270
|
loop do
|
249
271
|
slen = LibHTS.hts_itr_next(@hts_file[:fp][:bgzf], qiter, bcf1, ::FFI::Pointer::NULL)
|
@@ -255,32 +277,39 @@ module HTS
|
|
255
277
|
ensure
|
256
278
|
LibHTS.bcf_itr_destroy(qiter)
|
257
279
|
end
|
258
|
-
self
|
259
280
|
end
|
260
281
|
|
261
|
-
def
|
262
|
-
|
282
|
+
def queryi_copy(tid, beg, end_, &block)
|
283
|
+
return to_enum(__method__, tid, beg, end_) unless block_given?
|
263
284
|
|
264
|
-
|
265
|
-
raise "
|
285
|
+
qiter = LibHTS.bcf_itr_queryi(@idx, tid, beg, end_)
|
286
|
+
raise "Failed to query region #{tid} #{beg} #{end_}" if qiter.null?
|
287
|
+
|
288
|
+
query_copy_yield(qiter, &block)
|
289
|
+
self
|
290
|
+
end
|
291
|
+
|
292
|
+
def querys_copy(region, &block)
|
266
293
|
return to_enum(__method__, region) unless block_given?
|
267
294
|
|
268
295
|
qiter = LibHTS.bcf_itr_querys(@idx, header, region)
|
269
296
|
raise "Failed to query region #{region}" if qiter.null?
|
270
297
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
slen = LibHTS.hts_itr_next(@hts_file[:fp][:bgzf], qiter, bcf1, ::FFI::Pointer::NULL)
|
275
|
-
break if slen == -1
|
276
|
-
raise if slen < -1
|
298
|
+
query_copy_yield(qiter, &block)
|
299
|
+
self
|
300
|
+
end
|
277
301
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
LibHTS.
|
302
|
+
def query_copy_yield(qiter)
|
303
|
+
loop do
|
304
|
+
bcf1 = LibHTS.bcf_init
|
305
|
+
slen = LibHTS.hts_itr_next(@hts_file[:fp][:bgzf], qiter, bcf1, ::FFI::Pointer::NULL)
|
306
|
+
break if slen == -1
|
307
|
+
raise if slen < -1
|
308
|
+
|
309
|
+
yield Record.new(header, bcf1)
|
282
310
|
end
|
283
|
-
|
311
|
+
ensure
|
312
|
+
LibHTS.bcf_itr_destroy(qiter)
|
284
313
|
end
|
285
314
|
|
286
315
|
def each_record_reuse
|
@@ -289,7 +318,7 @@ module HTS
|
|
289
318
|
return to_enum(__method__) unless block_given?
|
290
319
|
|
291
320
|
bcf1 = LibHTS.bcf_init
|
292
|
-
record = Record.new(
|
321
|
+
record = Record.new(header, bcf1)
|
293
322
|
yield record while LibHTS.bcf_read(@hts_file, header, bcf1) != -1
|
294
323
|
self
|
295
324
|
end
|
@@ -300,7 +329,7 @@ module HTS
|
|
300
329
|
return to_enum(__method__) unless block_given?
|
301
330
|
|
302
331
|
while LibHTS.bcf_read(@hts_file, header, bcf1 = LibHTS.bcf_init) != -1
|
303
|
-
record = Record.new(
|
332
|
+
record = Record.new(header, bcf1)
|
304
333
|
yield record
|
305
334
|
end
|
306
335
|
self
|
data/lib/hts/faidx/sequence.rb
CHANGED
data/lib/hts/faidx.rb
CHANGED
@@ -26,7 +26,8 @@ module HTS
|
|
26
26
|
end
|
27
27
|
|
28
28
|
@file_name = file_name
|
29
|
-
@fai =
|
29
|
+
@fai = case File.extname(@file_name)
|
30
|
+
when ".fq", ".fastq"
|
30
31
|
LibHTS.fai_load_format(@file_name, 2)
|
31
32
|
else
|
32
33
|
LibHTS.fai_load(@file_name)
|
@@ -40,7 +41,14 @@ module HTS
|
|
40
41
|
end
|
41
42
|
|
42
43
|
def close
|
44
|
+
return if closed?
|
45
|
+
|
43
46
|
LibHTS.fai_destroy(@fai)
|
47
|
+
@fai = nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def closed?
|
51
|
+
@fai.nil? || @fai.null?
|
44
52
|
end
|
45
53
|
|
46
54
|
def file_format
|
@@ -100,14 +108,14 @@ module HTS
|
|
100
108
|
rlen = FFI::MemoryPointer.new(:int)
|
101
109
|
|
102
110
|
if start.nil? && stop.nil?
|
103
|
-
result = LibHTS.
|
111
|
+
result = LibHTS.fai_fetch64(@fai, name, rlen)
|
104
112
|
else
|
105
113
|
start < 0 && raise(ArgumentError, "Expect start to be >= 0")
|
106
114
|
stop < 0 && raise(ArgumentError, "Expect stop to be >= 0")
|
107
115
|
start > stop && raise(ArgumentError, "Expect start to be <= stop")
|
108
116
|
stop >= seq_len(name) && raise(ArgumentError, "Expect stop to be < seq_len")
|
109
117
|
|
110
|
-
result = LibHTS.
|
118
|
+
result = LibHTS.faidx_fetch_seq64(@fai, name, start, stop, rlen)
|
111
119
|
end
|
112
120
|
|
113
121
|
case rlen.read_int
|
@@ -125,14 +133,14 @@ module HTS
|
|
125
133
|
rlen = FFI::MemoryPointer.new(:int)
|
126
134
|
|
127
135
|
if start.nil? && stop.nil?
|
128
|
-
result = LibHTS.
|
136
|
+
result = LibHTS.fai_fetchqual64(@fai, name, rlen)
|
129
137
|
else
|
130
138
|
start < 0 && raise(ArgumentError, "Expect start to be >= 0")
|
131
139
|
stop < 0 && raise(ArgumentError, "Expect stop to be >= 0")
|
132
140
|
start > stop && raise(ArgumentError, "Expect start to be <= stop")
|
133
141
|
stop >= seq_len(name) && raise(ArgumentError, "Expect stop to be < seq_len")
|
134
142
|
|
135
|
-
result = LibHTS.
|
143
|
+
result = LibHTS.faidx_fetch_qual64(@fai, name, start, stop, rlen)
|
136
144
|
end
|
137
145
|
|
138
146
|
case rlen.read_int
|
data/lib/hts/libhts/bgzf.rb
CHANGED
@@ -41,7 +41,7 @@ module HTS
|
|
41
41
|
:ssize_t
|
42
42
|
|
43
43
|
# Write _length_ bytes from _data_ to the file, the index will be used to
|
44
|
-
# decide the amount of uncompressed data to be
|
44
|
+
# decide the amount of uncompressed data to be written to each bgzip block.
|
45
45
|
attach_function \
|
46
46
|
:bgzf_block_write,
|
47
47
|
[BGZF, :pointer, :size_t],
|
data/lib/hts/libhts/sam.rb
CHANGED
@@ -440,10 +440,22 @@ module HTS
|
|
440
440
|
[SamHdr, Bam1, :pointer], # hts_filter_t
|
441
441
|
:int
|
442
442
|
|
443
|
+
# Return a pointer to a BAM record's first aux field
|
444
|
+
attach_function \
|
445
|
+
:bam_aux_first,
|
446
|
+
[Bam1],
|
447
|
+
:pointer
|
448
|
+
|
449
|
+
# Return a pointer to a BAM record's next aux field
|
450
|
+
attach_function \
|
451
|
+
:bam_aux_next,
|
452
|
+
[Bam1, :pointer],
|
453
|
+
:pointer
|
454
|
+
|
443
455
|
# Return a pointer to an aux record
|
444
456
|
attach_function \
|
445
457
|
:bam_aux_get,
|
446
|
-
[Bam1, :string], #
|
458
|
+
[Bam1, :string], # const char tag[2]
|
447
459
|
:pointer
|
448
460
|
|
449
461
|
# Get an integer aux value
|
@@ -570,17 +582,17 @@ module HTS
|
|
570
582
|
[:bam_plp],
|
571
583
|
:void
|
572
584
|
|
573
|
-
callback :
|
585
|
+
callback :bam_plp_callback_function, [:pointer, Bam1, BamPileupCd], :int
|
574
586
|
|
575
587
|
# sets a callback to initialise any per-pileup1_t fields.
|
576
588
|
attach_function \
|
577
589
|
:bam_plp_constructor,
|
578
|
-
%i[bam_plp
|
590
|
+
%i[bam_plp bam_plp_callback_function],
|
579
591
|
:void
|
580
592
|
|
581
593
|
attach_function \
|
582
594
|
:bam_plp_destructor,
|
583
|
-
%i[bam_plp
|
595
|
+
%i[bam_plp bam_plp_callback_function],
|
584
596
|
:void
|
585
597
|
|
586
598
|
# Get pileup padded insertion sequence
|
@@ -632,12 +644,12 @@ module HTS
|
|
632
644
|
|
633
645
|
attach_function \
|
634
646
|
:bam_mplp_constructor,
|
635
|
-
%i[bam_mplp
|
647
|
+
%i[bam_mplp bam_plp_callback_function],
|
636
648
|
:void
|
637
649
|
|
638
650
|
attach_function \
|
639
651
|
:bam_mplp_destructor,
|
640
|
-
%i[bam_mplp
|
652
|
+
%i[bam_mplp bam_plp_callback_function],
|
641
653
|
:void
|
642
654
|
|
643
655
|
attach_function \
|
data/lib/hts/libhts.rb
CHANGED
data/lib/hts/{tbx.rb → tabix.rb}
RENAMED
@@ -5,7 +5,7 @@ require_relative "../htslib"
|
|
5
5
|
require_relative "hts"
|
6
6
|
|
7
7
|
module HTS
|
8
|
-
class
|
8
|
+
class Tabix < Hts
|
9
9
|
include Enumerable
|
10
10
|
|
11
11
|
attr_reader :file_name, :index_name, :mode, :nthreads
|
@@ -22,9 +22,9 @@ module HTS
|
|
22
22
|
file
|
23
23
|
end
|
24
24
|
|
25
|
-
def initialize(file_name,
|
25
|
+
def initialize(file_name, index: nil, threads: nil, build_index: false)
|
26
26
|
if block_given?
|
27
|
-
message = "HTS::
|
27
|
+
message = "HTS::Tabix.new() dose not take block; Please use HTS::Tabix.open() instead"
|
28
28
|
raise message
|
29
29
|
end
|
30
30
|
|
@@ -32,17 +32,14 @@ module HTS
|
|
32
32
|
|
33
33
|
@file_name = file_name
|
34
34
|
@index_name = index
|
35
|
-
@mode =
|
35
|
+
@mode = "r"
|
36
36
|
@nthreads = threads
|
37
|
-
@hts_file
|
37
|
+
@hts_file = LibHTS.hts_open(@file_name, @mode)
|
38
38
|
|
39
39
|
raise Errno::ENOENT, "Failed to open #{@file_name}" if @hts_file.null?
|
40
40
|
|
41
41
|
set_threads(threads) if threads
|
42
42
|
|
43
|
-
# return if @mode[0] == "w"
|
44
|
-
raise "Not implemented" if @mode[0] == "w"
|
45
|
-
|
46
43
|
# build_index(index) if build_index
|
47
44
|
@idx = load_index(index)
|
48
45
|
end
|
@@ -63,7 +60,7 @@ module HTS
|
|
63
60
|
!@idx.null?
|
64
61
|
end
|
65
62
|
|
66
|
-
def
|
63
|
+
def name2id(name)
|
67
64
|
LibHTS.tbx_name2id(@idx, name)
|
68
65
|
end
|
69
66
|
|
@@ -79,7 +76,7 @@ module HTS
|
|
79
76
|
raise "Index file is required to call the query method." unless index_loaded?
|
80
77
|
|
81
78
|
if start && end_
|
82
|
-
queryi(
|
79
|
+
queryi(name2id(region), start, end_, &block)
|
83
80
|
else
|
84
81
|
querys(region, &block)
|
85
82
|
end
|
@@ -87,36 +84,33 @@ module HTS
|
|
87
84
|
|
88
85
|
private
|
89
86
|
|
90
|
-
def queryi(id, start, end_)
|
87
|
+
def queryi(id, start, end_, &block)
|
91
88
|
return to_enum(__method__, id, start, end_) unless block_given?
|
92
89
|
|
93
90
|
qiter = LibHTS.tbx_itr_queryi(@idx, id, start, end_)
|
94
|
-
|
95
91
|
raise "Failed to query region: #{id}:#{start}-#{end_}" if qiter.null?
|
96
92
|
|
97
|
-
|
98
|
-
begin
|
99
|
-
yield r[:s] while LibHTS.tbx_itr_next(@hts_file, @idx, qiter, r) > 0
|
100
|
-
ensure
|
101
|
-
LibHTS.hts_itr_destroy(qiter)
|
102
|
-
end
|
93
|
+
query_yield(qiter, &block)
|
103
94
|
self
|
104
95
|
end
|
105
96
|
|
106
|
-
def querys(region)
|
97
|
+
def querys(region, &block)
|
107
98
|
return to_enum(__method__, region) unless block_given?
|
108
99
|
|
109
100
|
qiter = LibHTS.tbx_itr_querys(@idx, region)
|
110
|
-
|
111
101
|
raise "Failed to query region: #{region}" if qiter.null?
|
112
102
|
|
103
|
+
query_yield(qiter, &block)
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
def query_yield(qiter)
|
113
108
|
r = LibHTS::KString.new
|
114
109
|
begin
|
115
110
|
yield r[:s].split("\t") while LibHTS.tbx_itr_next(@hts_file, @idx, qiter, r) > 0
|
116
111
|
ensure
|
117
112
|
LibHTS.hts_itr_destroy(qiter)
|
118
113
|
end
|
119
|
-
self
|
120
114
|
end
|
121
115
|
end
|
122
116
|
end
|
data/lib/hts/version.rb
CHANGED
data/lib/htslib.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: htslib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kojix2
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -122,7 +122,7 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
-
description:
|
125
|
+
description:
|
126
126
|
email:
|
127
127
|
- 2xijok@gmail.com
|
128
128
|
executables: []
|
@@ -155,7 +155,7 @@ files:
|
|
155
155
|
- lib/hts/libhts/bgzf.rb
|
156
156
|
- lib/hts/libhts/constants.rb
|
157
157
|
- lib/hts/libhts/cram.rb
|
158
|
-
- lib/hts/libhts/
|
158
|
+
- lib/hts/libhts/fai.rb
|
159
159
|
- lib/hts/libhts/hfile.rb
|
160
160
|
- lib/hts/libhts/hts.rb
|
161
161
|
- lib/hts/libhts/kfunc.rb
|
@@ -166,7 +166,7 @@ files:
|
|
166
166
|
- lib/hts/libhts/thread_pool.rb
|
167
167
|
- lib/hts/libhts/vcf.rb
|
168
168
|
- lib/hts/libhts/vcf_funcs.rb
|
169
|
-
- lib/hts/
|
169
|
+
- lib/hts/tabix.rb
|
170
170
|
- lib/hts/version.rb
|
171
171
|
- lib/htslib.rb
|
172
172
|
homepage: https://github.com/kojix2/ruby-htslib
|
@@ -174,7 +174,7 @@ licenses:
|
|
174
174
|
- MIT
|
175
175
|
metadata:
|
176
176
|
msys2_mingw_dependencies: htslib
|
177
|
-
post_install_message:
|
177
|
+
post_install_message:
|
178
178
|
rdoc_options: []
|
179
179
|
require_paths:
|
180
180
|
- lib
|
@@ -189,8 +189,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
189
189
|
- !ruby/object:Gem::Version
|
190
190
|
version: '0'
|
191
191
|
requirements: []
|
192
|
-
rubygems_version: 3.4.
|
193
|
-
signing_key:
|
192
|
+
rubygems_version: 3.4.10
|
193
|
+
signing_key:
|
194
194
|
specification_version: 4
|
195
195
|
summary: HTSlib bindings for Ruby
|
196
196
|
test_files: []
|
File without changes
|