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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35551ff5a5cd81937063363c243bc2ac3d12ce09ec69697cd0eedd93945526bd
4
- data.tar.gz: ec16e4f3cee66c50a582c4580d6cf266c0f349f8f6bc985864eda3d41b41e412
3
+ metadata.gz: caaf2dd527c9570e2e4c72b22e5252a1ef69adbf983fbfe3e815c3a9bc1b91c0
4
+ data.tar.gz: b7e0b6ecf736142ea9b43e4ed7f80513b1c0d002ea40b2565e218be3a40d2fac
5
5
  SHA512:
6
- metadata.gz: f534244d9b6dfd8a741cf21f639205207df612a3107ce563640db7dadd591c140dba92cf6eaa68ae1a440ab9b958697d0a04fac8217ff0ca7dcea796557fe30b
7
- data.tar.gz: ac305efbbdd989f8f44e691499a0aa978aa4ed17e24546fd48826a25c2591a8f70a8ec0411456e123248597c518e4c41dc057fbd6738be49b96fc5198ba643cd
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; if you use RubyInstaller, htslib will be prepared automatically.
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
- bcf = HTS::Bcf.open("b.bcf")
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("c.fa")
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::Tbx - Tabix - gff, bed, sam, vcf
119
+ ### HTS::Tabix - GFF / BED - TAB-delimited genome position file
97
120
 
98
121
  ```ruby
99
- tb = HTS::Tbx.open("test.vcf.gz")
100
- tb.query("chr1", 10000, 20000) do |line|
101
- p line
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
- `HTS::LibHTS` provides native C functions.
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
- Macro functions
143
+ The low-level API makes it possible to perform detailed operations, such as calling CRAM-specific functions.
121
144
 
122
- htslib has a lot of macro functions for speed. Ruby-FFI cannot call C macro functions. However, essential functions are reimplemented in Ruby, and you can call them.
145
+ #### Macro functions
123
146
 
124
- Structs
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
- Only a small number of C structs are implemented with FFI's ManagedStruct, which frees memory when Ruby's garbage collection fires. Other structs will need to be freed manually.
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. Crystal language is not as flexible as Ruby language. You can not use `eval` methods and must always be careful with the types. Writing one-time scripts in Crystal may be less fun. However, if you have a clear idea of what you want to do in your mind, have already written code in Ruby, and need to run them over and over, try creating a command line tool in Crystal. The Crystal language is as fast as the Rust and C languages. It will give you incredible power to make tools.
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
- - [RubyDoc.info - HTSlib](https://rdoc.info/gems/htslib)
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
- [GNU Autotools](https://en.wikipedia.org/wiki/GNU_Autotools) is required to compile htslib.
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
- - Use the new version of Ruby to take full advantage of Ruby's potential.
155
- - This is possible because we have a small number of users.
156
- - Remain compatible with [HTS.cr](https://github.com/bio-cr/hts.cr).
157
- - 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.
158
- - 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.
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
- Method naming generally follows the Rust-htslib API.
208
+ #### Support for bitfields of structures
161
209
 
162
- #### FFI Extensions
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) : Extension of Ruby-FFI to support bitfields.
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 Commitment Rights
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 Tbx~Hts~{
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
- +qname()
66
- +flag()
67
- +chorm()
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
- +mate_chrom()
71
- +isize()
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
- +qual()
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 |b|
198
- b.
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 |b|
249
- b.each do |r|
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. Eww!
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
- type = type ? type.to_s : aux.read_string(1)
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
@@ -87,6 +87,14 @@ module HTS
87
87
  LibHTS.sam_hdr_str(@sam_hdr)
88
88
  end
89
89
 
90
+ def name2tid(name)
91
+ LibHTS.sam_hdr_name2tid(@sam_hdr, name)
92
+ end
93
+
94
+ def tid2name(tid)
95
+ LibHTS.sam_hdr_tid2name(@sam_hdr, tid)
96
+ end
97
+
90
98
  private
91
99
 
92
100
  def initialize_copy(orig)
@@ -12,8 +12,8 @@ module HTS
12
12
 
13
13
  attr_reader :header
14
14
 
15
- def initialize(bam1_t, header)
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
- (@bam1[:core][:l_qseq]).times do |i|
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 += @bam1[:core][:l_qseq] if n < 0
199
- return "." if (n >= @bam1[:core][:l_qseq]) || (n < 0) # eg. base(-1000)
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(@bam1[:core][:l_qseq])
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 += @bam1[:core][:l_qseq] if n < 0
224
- return 0 if (n >= @bam1[:core][:l_qseq]) || (n < 0) # eg. base_qual(-1000)
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 auxillary fields as a hash.
263
+ # TODO: add a method to get the auxiliary fields as a hash.
260
264
 
261
- # TODO: add a method to set the auxillary fields.
265
+ # TODO: add a method to set the auxiliary fields.
262
266
 
263
- # TODO: add a method to remove the auxillary fields.
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 <<(aln)
123
- write(aln)
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
- private
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 query_reuse(region)
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
- bam1 = LibHTS.bam_init1
211
- record = Record.new(bam1, header)
212
- begin
213
- yield record while LibHTS.sam_itr_next(@hts_file, qiter, bam1) > 0
214
- ensure
215
- LibHTS.hts_itr_destroy(qiter)
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
- def query_copy(region)
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
- qiter = LibHTS.sam_itr_querys(@idx, header, region)
226
- raise "Failed to query region: #{region}" if qiter.null?
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
- begin
229
- loop do
230
- bam1 = LibHTS.bam_init1
231
- slen = LibHTS.sam_itr_next(@hts_file, qiter, bam1)
232
- break if slen == -1
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(bam1, header)
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(bam1, header)
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
@@ -94,6 +94,14 @@ module HTS
94
94
  kstr[:s]
95
95
  end
96
96
 
97
+ def name2id(name)
98
+ LibHTS.bcf_hdr_name2id(@bcf_hdr, name)
99
+ end
100
+
101
+ def id2name(id)
102
+ LibHTS.bcf_hdr_id2name(@bcf_hdr, id)
103
+ end
104
+
97
105
  private
98
106
 
99
107
  def bcf_hl_type_to_int(bcf_hl_type)
@@ -4,8 +4,8 @@ module HTS
4
4
  class Bcf < Hts
5
5
  # A class for working with VCF records.
6
6
  class Record
7
- def initialize(bcf_t, header)
8
- @bcf1 = bcf_t
7
+ def initialize(header, bcf_t = nil)
8
+ @bcf1 = bcf_t || LibHTS.bcf_init
9
9
  @header = header
10
10
  end
11
11
 
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 # sccessful
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.dup
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
- private
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 querys_reuse(region)
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(bcf1, header)
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 querys_copy(region)
262
- check_closed
282
+ def queryi_copy(tid, beg, end_, &block)
283
+ return to_enum(__method__, tid, beg, end_) unless block_given?
263
284
 
264
- raise "query is only available for BCF files" unless file_format == "bcf"
265
- raise "Index file is required to call the query method." unless index_loaded?
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
- begin
272
- loop do
273
- bcf1 = LibHTS.bcf_init
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
- yield Record.new(bcf1, header)
279
- end
280
- ensure
281
- LibHTS.bcf_itr_destroy(qiter)
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
- self
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(bcf1, header)
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(bcf1, header)
332
+ record = Record.new(header, bcf1)
304
333
  yield record
305
334
  end
306
335
  self
@@ -1,5 +1,3 @@
1
- require_relative "../faidx"
2
-
3
1
  module HTS
4
2
  class Faidx
5
3
  class Sequence
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 = if [".fq", ".fastq"].include? File.extname(@file_name)
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.fai_fetch(@fai, name, rlen)
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.faidx_fetch_seq(@fai, name, start, stop, rlen)
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.fai_fetchqual(@fai, name, rlen)
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.faidx_fetch_qual(@fai, name, start, stop, rlen)
143
+ result = LibHTS.faidx_fetch_qual64(@fai, name, start, stop, rlen)
136
144
  end
137
145
 
138
146
  case rlen.read_int
@@ -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 writen to each bgzip block.
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],
@@ -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], # FIXME
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 :bam_plp_callback_funcion, [:pointer, Bam1, BamPileupCd], :int
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 bam_plp_callback_funcion],
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 bam_plp_callback_funcion],
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 bam_plp_callback_funcion],
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 bam_plp_callback_funcion],
652
+ %i[bam_mplp bam_plp_callback_function],
641
653
  :void
642
654
 
643
655
  attach_function \
data/lib/hts/libhts.rb CHANGED
@@ -37,5 +37,5 @@ require_relative "libhts/sam"
37
37
  require_relative "libhts/cram"
38
38
  require_relative "libhts/vcf"
39
39
  require_relative "libhts/tbx"
40
- require_relative "libhts/faidx"
40
+ require_relative "libhts/fai"
41
41
  require_relative "libhts/thread_pool"
@@ -5,7 +5,7 @@ require_relative "../htslib"
5
5
  require_relative "hts"
6
6
 
7
7
  module HTS
8
- class Tbx < Hts
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, mode = "r", index: nil, threads: nil, build_index: false)
25
+ def initialize(file_name, index: nil, threads: nil, build_index: false)
26
26
  if block_given?
27
- message = "HTS::Tbx.new() dose not take block; Please use HTS::Tbx.open() instead"
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 = mode
35
+ @mode = "r"
36
36
  @nthreads = threads
37
- @hts_file = LibHTS.hts_open(@file_name, @mode)
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 tid(name)
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(tid(region), start, end_, &block)
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
- r = LibHTS::KString.new
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTS
4
- VERSION = "0.2.6"
4
+ VERSION = "0.2.8"
5
5
  end
data/lib/htslib.rb CHANGED
@@ -55,6 +55,6 @@ module HTS
55
55
  autoload :Hts, "hts/hts"
56
56
  autoload :Bam, "hts/bam"
57
57
  autoload :Bcf, "hts/bcf"
58
- autoload :Tbx, "hts/tbx"
59
58
  autoload :Faidx, "hts/faidx"
59
+ autoload :Tabix, "hts/tabix"
60
60
  end
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.6
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-01-09 00:00:00.000000000 Z
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/faidx.rb
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/tbx.rb
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.1
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