htslib 0.0.2 → 0.0.6

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: d4fe8c4a8f710ee3b35793e997f394ba8f80e0fe5b507768de2af2c5ab1297a0
4
- data.tar.gz: 1bb06ced745342f4de8665f046304364c9d419ae05eee355c3cd852d6b2b454a
3
+ metadata.gz: f05bc93a621f3d5fb8d06e44c20ac4a3a95c5f6e243df2aebc97e10125fcb779
4
+ data.tar.gz: 73e747aa0999e54b3c8f01b981b91c4e293167265276a24eac85ea0fd6b85c13
5
5
  SHA512:
6
- metadata.gz: 8c7fb677d2462a1ddf4cd146d9f9962b570f39762e98d893d77f89bbbf61c92329ed8391030f772bf4f98fb3dc874edc3c365dd2d85266e1e966b24effc1715c
7
- data.tar.gz: fee9ec647e3ef51e83a1aec1c62ac02c796dcfefe4d5fd6c901e4b04e4253619e7337cee651df1ece9ca58c74a7a50620befd5cd8ab823696d0f893a437bd562
6
+ metadata.gz: 8d0f3f8bb9f7a9c063222fd2dc6463f58bdfd784aff39757921dda1c8d417023b024ca9f6c92d7f0eecd30b8064adb1b94966cf962cf9e0e56d67303de0a903b
7
+ data.tar.gz: 8ef35b7aef04bf2f51ae0ba110d9ffc81c26d7a0c97a821aa1274c04b31ec29515b33c278391494f6a0d8efc5e2d965060ccd190ee0f92a2ec3562fb59c49169
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # HTSlib
1
+ # ruby-htslib
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/htslib.svg)](https://badge.fury.io/rb/htslib)
4
4
  ![CI](https://github.com/kojix2/ruby-htslib/workflows/CI/badge.svg)
@@ -6,17 +6,22 @@
6
6
  [![DOI](https://zenodo.org/badge/247078205.svg)](https://zenodo.org/badge/latestdoi/247078205)
7
7
  [![Docs Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://rubydoc.info/gems/htslib)
8
8
 
9
- :dna: [HTSlib](https://github.com/samtools/htslib) - high-throughput sequencing data manipulation - for Ruby
9
+ :dna: [HTSlib](https://github.com/samtools/htslib) - for Ruby
10
+
11
+ Ruby-htslib is the Ruby bindings to HTSlib, a C library for processing high throughput sequencing (HTS) data.
12
+ It will provide APIs to read and write file formats such as [SAM, BAM, VCF, and BCF](http://samtools.github.io/hts-specs/).
10
13
 
11
14
  :apple: Feel free to fork it out if you can develop it!
12
15
 
13
- :bowtie: Just a prototype. Pre-alpha stage.
16
+ :bowtie: alpha stage.
14
17
 
15
18
  ## Requirements
16
19
 
17
- * [htslib](https://github.com/samtools/htslib)
20
+ * [Ruby](https://github.com/ruby/ruby) 2.7 or above.
21
+ * [HTSlib](https://github.com/samtools/htslib)
18
22
  * Ubuntu : `apt install libhts-dev`
19
23
  * macOS : `brew install htslib`
24
+ * Build from source code (see Development section)
20
25
 
21
26
  ## Installation
22
27
 
@@ -24,43 +29,51 @@
24
29
  gem install htslib
25
30
  ```
26
31
 
27
- If you installed htslib with Ubuntu/apt or Mac/homebrew, pkg-config will automatically detect the location of the shared library.
28
-
29
- Or you can set the environment variable `HTSLIBDIR`.
32
+ If you have installed htslib with apt on Ubuntu or homebrew on Mac, [pkg-config](https://github.com/ruby-gnome/pkg-config)
33
+ will automatically detect the location of the shared library.
34
+ Alternatively, you can specify the directory of the shared library by setting the environment variable `HTSLIBDIR`.
30
35
 
31
36
  ```sh
32
37
  export HTSLIBDIR="/your/path/to/htslib" # libhts.so
33
38
  ```
34
39
 
35
- ## Usage
40
+ ## Overview
41
+
42
+ ### Low level API
36
43
 
37
- HTS::FFI - Low-level API
44
+ `HTS::LibHTS` provides native functions.
38
45
 
39
46
  ```ruby
40
47
  require 'htslib'
41
48
 
42
- a = HTS::FFI.hts_open("a.bam", "r")
43
- b = HTS::FFI.hts_get_format(a)
49
+ a = HTS::LibHTS.hts_open("a.bam", "r")
50
+ b = HTS::LibHTS.hts_get_format(a)
44
51
  p b[:category]
45
52
  p b[:format]
46
53
  ```
47
54
 
48
- A high-level API based on [hts-python](https://github.com/quinlan-lab/hts-python) is under development.
55
+ Note: Managed struct is not used in ruby-htslib. You may need to free the memory by yourself.
56
+
57
+ ### High level API (Plan)
58
+
59
+ `Cram` `Bam` `Bcf` `Faidx` `Tabix`
60
+
61
+ A high-level API is under development. We will change and improve the API to make it better.
49
62
 
50
63
  ```ruby
51
64
  require 'htslib'
52
65
 
53
66
  bam = HTS::Bam.new("a.bam")
54
67
 
55
- bam.each do |aln|
56
- p name: aln.qname,
57
- flag: aln.flag,
58
- start: aln.start + 1,
59
- mpos: aln.mate_pos + 1,
60
- mqual: aln.mapping_quality,
61
- seq: aln.sequence,
62
- cigar: aln.cigar.to_s,
63
- qual: aln.base_qualities.map { |i| (i + 33).chr }.join
68
+ bam.each do |r|
69
+ p name: r.qname,
70
+ flag: r.flag,
71
+ start: r.start + 1,
72
+ mpos: r.mate_pos + 1,
73
+ mqual: r.mapping_quality,
74
+ seq: r.sequence,
75
+ cigar: r.cigar.to_s,
76
+ qual: r.base_qualities.map { |i| (i + 33).chr }.join
64
77
  end
65
78
  ```
66
79
 
@@ -80,6 +93,17 @@ bundle exec rake htslib:build
80
93
  bundle exec rake test
81
94
  ```
82
95
 
96
+ * Actively use the advanced features of Ruby.
97
+ * Consider compatibility with [htslib.cr](https://github.com/bio-crystal/htslib.cr) to some extent.
98
+
99
+ #### FFI Extensions
100
+
101
+ * [ffi-bitfield](https://github.com/kojix2/ffi-bitfield) : Extension of Ruby-FFI to support bitfields.
102
+
103
+ #### Automatic generation or automatic validation (Future plan)
104
+
105
+ + [c2ffi](https://github.com/rpav/c2ffi) is a tool to create JSON format metadata from C header files. It is planned to use c2ffi to automatically generate bindings or tests.
106
+
83
107
  ## Contributing
84
108
 
85
109
  Ruby-htslib is a library under development, so even small improvements like typofix are welcome! Please feel free to send us your pull requests.
@@ -88,12 +112,16 @@ Ruby-htslib is a library under development, so even small improvements like typo
88
112
  * Fix bugs and [submit pull requests](https://github.com/kojix2/ruby-htslib/pulls)
89
113
  * Write, clarify, or fix documentation
90
114
  * Suggest or add new features
115
+ * [financial contributions](https://github.com/sponsors/kojix2)
91
116
 
92
117
  ## Links
93
118
 
94
119
  * [samtools/hts-spec](https://github.com/samtools/hts-specs)
95
- * [c2ffi](https://github.com/rpav/c2ffi)
120
+ * [bioruby](https://github.com/bioruby/bioruby)
121
+
122
+ ## Funding support
96
123
 
124
+ This work was supported partially by [Ruby Association Grant 2020](https://www.ruby.or.jp/en/news/20201022).
97
125
  ## License
98
126
 
99
127
  [MIT License](https://opensource.org/licenses/MIT).
data/lib/hts/bam/cigar.rb CHANGED
@@ -7,22 +7,27 @@ module HTS
7
7
  class Bam
8
8
  class Cigar
9
9
  include Enumerable
10
- OPS = 'MIDNSHP=XB'
11
10
 
12
- def initialize(cigar, n_cigar)
13
- @c = cigar
11
+ def initialize(pointer, n_cigar)
12
+ @pointer = pointer
14
13
  @n_cigar = n_cigar
15
14
  end
16
15
 
16
+ def to_ptr
17
+ @pointer
18
+ end
19
+
17
20
  def to_s
18
21
  to_a.flatten.join
19
22
  end
20
23
 
21
24
  def each
25
+ return to_enum(__method__) unless block_given?
26
+
22
27
  @n_cigar.times do |i|
23
- c = @c[i].read_uint32
24
- yield [FFI.bam_cigar_oplen(c),
25
- FFI.bam_cigar_opchr(c)]
28
+ c = @pointer[i].read_uint32
29
+ yield [LibHTS.bam_cigar_oplen(c),
30
+ LibHTS.bam_cigar_opchr(c)]
26
31
  end
27
32
  end
28
33
  end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Based on hts-nim
4
+ # https://github.com/brentp/hts-nim/blob/master/src/hts/bam/flag.nim
5
+
6
+ module HTS
7
+ class Bam
8
+ class Flag
9
+ def initialize(flag_value)
10
+ raise TypeError unless flag_value.is_a? Integer
11
+
12
+ @value = flag_value
13
+ end
14
+
15
+ attr_accessor :value
16
+
17
+ # BAM_FPAIRED = 1
18
+ # BAM_FPROPER_PAIR = 2
19
+ # BAM_FUNMAP = 4
20
+ # BAM_FMUNMAP = 8
21
+ # BAM_FREVERSE = 16
22
+ # BAM_FMREVERSE = 32
23
+ # BAM_FREAD1 = 64
24
+ # BAM_FREAD2 = 128
25
+ # BAM_FSECONDARY = 256
26
+ # BAM_FQCFAIL = 512
27
+ # BAM_FDUP = 1024
28
+ # BAM_FSUPPLEMENTARY = 2048
29
+
30
+ # TODO: Enabling bitwise operations
31
+ # hts-nim
32
+ # proc `and`*(f: Flag, o: uint16): uint16 {. borrow, inline .}
33
+ # proc `and`*(f: Flag, o: Flag): uint16 {. borrow, inline .}
34
+ # proc `or`*(f: Flag, o: uint16): uint16 {. borrow .}
35
+ # proc `or`*(o: uint16, f: Flag): uint16 {. borrow .}
36
+ # proc `==`*(f: Flag, o: Flag): bool {. borrow, inline .}
37
+ # proc `==`*(f: Flag, o: uint16): bool {. borrow, inline .}
38
+ # proc `==`*(o: uint16, f: Flag): bool {. borrow, inline .}
39
+
40
+ def paired?
41
+ has_flag? LibHTS::BAM_FPAIRED
42
+ end
43
+
44
+ def proper_pair?
45
+ has_flag? LibHTS::BAM_FPROPER_PAIR
46
+ end
47
+
48
+ def unmapped?
49
+ has_flag? LibHTS::BAM_FUNMAP
50
+ end
51
+
52
+ def mate_unmapped?
53
+ has_flag? LibHTS::BAM_FMUNMAP
54
+ end
55
+
56
+ def reverse?
57
+ has_flag? LibHTS::BAM_FREVERSE
58
+ end
59
+
60
+ def mate_reverse?
61
+ has_flag? LibHTS::BAM_FMREVERSE
62
+ end
63
+
64
+ def read1?
65
+ has_flag? LibHTS::BAM_FREAD1
66
+ end
67
+
68
+ def read2?
69
+ has_flag? LibHTS::BAM_FREAD2
70
+ end
71
+
72
+ def secondary?
73
+ has_flag? LibHTS::BAM_FSECONDARY
74
+ end
75
+
76
+ def qcfail?
77
+ has_flag? LibHTS::BAM_FQCFAIL
78
+ end
79
+
80
+ def dup?
81
+ has_flag? LibHTS::BAM_FDUP
82
+ end
83
+
84
+ def supplementary?
85
+ has_flag? LibHTS::BAM_FSUPPLEMENTARY
86
+ end
87
+
88
+ def has_flag?(m)
89
+ (@value & m) != 0
90
+ end
91
+
92
+ def to_s
93
+ "0x#{format('%x', @value)}\t#{@value}\t#{LibHTS.bam_flag2str(@value)}"
94
+ end
95
+ end
96
+ end
97
+ end
@@ -6,21 +6,31 @@
6
6
  module HTS
7
7
  class Bam
8
8
  class Header
9
- attr_reader :h
9
+ def initialize(pointer)
10
+ @sam_hdr = pointer
11
+ end
12
+
13
+ def struct
14
+ @sam_hdr
15
+ end
16
+
17
+ def to_ptr
18
+ @sam_hdr.to_ptr
19
+ end
10
20
 
11
- def initialize(h)
12
- @h = h
21
+ def target_count
22
+ @sam_hdr[:n_targets]
13
23
  end
14
24
 
15
25
  # FIXME: better name?
16
26
  def seqs
17
- Array.new(@h[:n_targets]) do |i|
18
- FFI.sam_hdr_tid2name(@h, i)
27
+ Array.new(@sam_hdr[:n_targets]) do |i|
28
+ LibHTS.sam_hdr_tid2name(@sam_hdr, i)
19
29
  end
20
30
  end
21
31
 
22
- def text
23
- FFI.sam_hdr_str(@h)
32
+ def to_s
33
+ LibHTS.sam_hdr_str(@sam_hdr)
24
34
  end
25
35
  end
26
36
  end
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Based on hts-python
4
+ # https://github.com/quinlan-lab/hts-python
5
+
6
+ module HTS
7
+ class Bam
8
+ class Record
9
+ SEQ_NT16_STR = "=ACMGRSVTWYHKDBN"
10
+
11
+ def initialize(bam1_t, header)
12
+ @bam1 = bam1_t
13
+ @header = header
14
+ end
15
+
16
+ def struct
17
+ @bam1
18
+ end
19
+
20
+ def to_ptr
21
+ @bam1.to_ptr
22
+ end
23
+
24
+ attr_reader :header
25
+
26
+ # def initialize_copy
27
+ # super
28
+ # end
29
+
30
+ def self.rom_sam_str; end
31
+
32
+ def tags; end
33
+
34
+ # returns the query name.
35
+ def qname
36
+ LibHTS.bam_get_qname(@bam1).read_string
37
+ end
38
+
39
+ # Set (query) name.
40
+ # def qname=(name)
41
+ # raise 'Not Implemented'
42
+ # end
43
+
44
+ # returns the tid of the record or -1 if not mapped.
45
+ def tid
46
+ @bam1[:core][:tid]
47
+ end
48
+
49
+ # returns the tid of the mate or -1 if not mapped.
50
+ def mate_tid
51
+ @bam1[:core][:mtid]
52
+ end
53
+
54
+ # returns 0-based start position.
55
+ def start
56
+ @bam1[:core][:pos]
57
+ end
58
+
59
+ # returns end position of the read.
60
+ def stop
61
+ LibHTS.bam_endpos @bam1
62
+ end
63
+
64
+ # returns 0-based mate position
65
+ def mate_start
66
+ @bam1[:core][:mpos]
67
+ end
68
+ alias mate_pos mate_start
69
+
70
+ # returns the chromosome or '' if not mapped.
71
+ def chrom
72
+ return "" if tid == -1
73
+
74
+ LibHTS.sam_hdr_tid2name(@header, tid)
75
+ end
76
+
77
+ # returns the chromosome of the mate or '' if not mapped.
78
+ def mate_chrom
79
+ mtid = mate_tid
80
+ return "" if mtid == -1
81
+
82
+ LibHTS.sam_hdr_tid2name(@header, mtid)
83
+ end
84
+
85
+ def strand
86
+ LibHTS.bam_is_rev(@bam1) ? "-" : "+"
87
+ end
88
+
89
+ # def start=(v)
90
+ # raise 'Not Implemented'
91
+ # end
92
+
93
+ # insert size
94
+ def isize
95
+ @bam1[:core][:isize]
96
+ end
97
+
98
+ # mapping quality
99
+ def mapping_quality
100
+ @bam1[:core][:qual]
101
+ end
102
+
103
+ # returns a `Cigar` object.
104
+ def cigar
105
+ Cigar.new(LibHTS.bam_get_cigar(@bam1), @bam1[:core][:n_cigar])
106
+ end
107
+
108
+ def qlen
109
+ LibHTS.bam_cigar2qlen(
110
+ @bam1[:core][:n_cigar],
111
+ LibHTS.bam_get_cigar(@bam1)
112
+ )
113
+ end
114
+
115
+ def rlen
116
+ LibHTS.bam_cigar2rlen(
117
+ @bam1[:core][:n_cigar],
118
+ LibHTS.bam_get_cigar(@bam1)
119
+ )
120
+ end
121
+
122
+ # return the read sequence
123
+ def sequence
124
+ r = LibHTS.bam_get_seq(@bam1)
125
+ seq = String.new
126
+ (@bam1[:core][:l_qseq]).times do |i|
127
+ seq << SEQ_NT16_STR[LibHTS.bam_seqi(r, i)]
128
+ end
129
+ seq
130
+ end
131
+
132
+ # return only the base of the requested index "i" of the query sequence.
133
+ def base_at(n)
134
+ n += @bam1[:core][:l_qseq] if n < 0
135
+ return "." if (n >= @bam1[:core][:l_qseq]) || (n < 0) # eg. base_at(-1000)
136
+
137
+ r = LibHTS.bam_get_seq(@bam1)
138
+ SEQ_NT16_STR[LibHTS.bam_seqi(r, n)]
139
+ end
140
+
141
+ # return the base qualities
142
+ def base_qualities
143
+ q_ptr = LibHTS.bam_get_qual(@bam1)
144
+ q_ptr.read_array_of_uint8(@bam1[:core][:l_qseq])
145
+ end
146
+
147
+ # return only the base quality of the requested index "i" of the query sequence.
148
+ def base_quality_at(n)
149
+ n += @bam1[:core][:l_qseq] if n < 0
150
+ return 0 if (n >= @bam1[:core][:l_qseq]) || (n < 0) # eg. base_quality_at(-1000)
151
+
152
+ q_ptr = LibHTS.bam_get_qual(@bam1)
153
+ q_ptr.get_uint8(n)
154
+ end
155
+
156
+ def flag_str
157
+ LibHTS.bam_flag2str(@bam1[:core][:flag])
158
+ end
159
+
160
+ # returns a `Flag` object.
161
+ def flag
162
+ Flag.new(@bam1[:core][:flag])
163
+ end
164
+
165
+ def tag(str)
166
+ aux = LibHTS.bam_aux_get(@bam1, str)
167
+ return nil if aux.null?
168
+
169
+ t = aux.read_string(1)
170
+
171
+ # A (character), B (general array),
172
+ # f (real number), H (hexadecimal array),
173
+ # i (integer), or Z (string).
174
+
175
+ case t
176
+ when "i", "I", "c", "C", "s", "S"
177
+ LibHTS.bam_aux2i(aux)
178
+ when "f", "d"
179
+ LibHTS.bam_aux2f(aux)
180
+ when "Z", "H"
181
+ LibHTS.bam_aux2Z(aux)
182
+ when "A" # char
183
+ LibHTS.bam_aux2A(aux).chr
184
+ end
185
+ end
186
+
187
+ def to_s
188
+ kstr = LibHTS::KString.new
189
+ raise "Failed to format bam record" if LibHTS.sam_format1(@header.struct, @bam1, kstr) == -1
190
+
191
+ kstr[:s]
192
+ end
193
+
194
+ # TODO:
195
+ # def eql?
196
+ # def hash
197
+ end
198
+ end
199
+ end
data/lib/hts/bam.rb CHANGED
@@ -3,76 +3,111 @@
3
3
  # Based on hts-python
4
4
  # https://github.com/quinlan-lab/hts-python
5
5
 
6
- require_relative 'bam/header'
7
- require_relative 'bam/cigar'
8
- require_relative 'bam/alignment'
6
+ require_relative "bam/header"
7
+ require_relative "bam/cigar"
8
+ require_relative "bam/flag"
9
+ require_relative "bam/record"
9
10
 
10
11
  module HTS
11
12
  class Bam
12
13
  include Enumerable
13
- attr_reader :file_path, :mode, :header, :htf
14
14
 
15
- def initialize(file_path, mode = 'r', create_index: nil, header: nil, fasta: nil)
16
- @file_path = File.expand_path(file_path)
17
- File.exist?(@file_path) || raise("No such SAM/BAM file - #{@file_path}")
15
+ attr_reader :file_path, :mode, :header
16
+ # HtfFile is FFI::BitStruct
17
+ attr_reader :htf_file
18
18
 
19
- @mode = mode
20
- @htf = FFI.hts_open(@file_path, mode)
19
+ class << self
20
+ alias open new
21
+ end
21
22
 
22
- if mode[0] == 'r'
23
- @idx = FFI.sam_index_load(@htf, @file_path)
24
- if (@idx.null? && create_index.nil?) || create_index
25
- FFI.sam_index_build(file_path, -1)
26
- @idx = FFI.sam_index_load(@htf, @file_path)
27
- warn 'NO querying'
28
- end
29
- @header = Bam::Header.new(FFI.sam_hdr_read(@htf))
30
- @b = FFI.bam_init1
23
+ def initialize(file_path, mode = "r", create_index: nil)
24
+ file_path = File.expand_path(file_path)
25
+
26
+ unless File.exist?(file_path)
27
+ message = "No such SAM/BAM file - #{file_path}"
28
+ raise message
29
+ end
31
30
 
31
+ @file_path = file_path
32
+ @mode = mode
33
+ @htf_file = LibHTS.hts_open(file_path, mode)
34
+ @header = Bam::Header.new(LibHTS.sam_hdr_read(htf_file))
35
+
36
+ # read
37
+ if mode[0] == "r"
38
+ # load index
39
+ @idx = LibHTS.sam_index_load(htf_file, file_path)
40
+ # create index
41
+ if create_index || (@idx.null? && create_index.nil?)
42
+ warn "Create index for #{file_path}"
43
+ LibHTS.sam_index_build(file_path, -1)
44
+ @idx = LibHTS.sam_index_load(htf_file, file_path)
45
+ end
32
46
  else
33
- # FIXME
34
- raise 'not implemented yet.'
47
+ # FIXME: implement
48
+ raise "not implemented yet."
49
+ end
35
50
 
51
+ # IO like API
52
+ if block_given?
53
+ begin
54
+ yield self
55
+ ensure
56
+ close
57
+ end
36
58
  end
37
59
  end
38
60
 
39
- def self.header_from_fasta; end
61
+ def struct
62
+ htf_file
63
+ end
64
+
65
+ def to_ptr
66
+ htf_file.to_ptr
67
+ end
40
68
 
41
69
  def write(alns)
42
70
  alns.each do
43
- FFI.sam_write1(@htf, @header, alns.b) > 0 || raise
71
+ LibHTS.sam_write1(htf_file, header, alns.b) > 0 || raise
44
72
  end
45
73
  end
46
74
 
47
75
  # Close the current file.
48
76
  def close
49
- FFI.hts_close(@htf)
77
+ LibHTS.hts_close(htf_file)
50
78
  end
51
79
 
52
80
  # Flush the current file.
53
81
  def flush
54
- raise
55
- # FFI.bgzf_flush(@htf.fp.bgzf)
82
+ # LibHTS.bgzf_flush(@htf_file.fp.bgzf)
56
83
  end
57
84
 
58
- def each(&block)
85
+ def each
59
86
  # Each does not always start at the beginning of the file.
60
87
  # This is the common behavior of IO objects in Ruby.
61
88
  # This may change in the future.
62
- block.call(Alignment.new(@b, @header.h)) while FFI.sam_read1(@htf, @header.h, @b) > 0
89
+ return to_enum(__method__) unless block_given?
90
+
91
+ while LibHTS.sam_read1(htf_file, header, bam1 = LibHTS.bam_init1) > 0
92
+ record = Record.new(bam1, header)
93
+ yield record
94
+ end
95
+ self
63
96
  end
64
97
 
65
98
  # query [WIP]
66
99
  def query(region)
67
- qiter = FFI.sam_itr_querys(@idx, @header.h, region)
100
+ qiter = LibHTS.sam_itr_querys(@idx, header, region)
68
101
  begin
69
- slen = FFI.sam_itr_next(@htf, qiter, @b)
102
+ bam1 = LibHTS.bam_init1
103
+ slen = LibHTS.sam_itr_next(htf_file, qiter, bam1)
70
104
  while slen > 0
71
- yield Alignment.new(@b, @header.h)
72
- slen = FFI.sam_itr_next(@htf, qiter, @b)
105
+ yield Record.new(bam1, header)
106
+ bam1 = LibHTS.bam_init1
107
+ slen = LibHTS.sam_itr_next(htf_file, qiter, bam1)
73
108
  end
74
109
  ensure
75
- FFI.hts_itr_destroy(qiter)
110
+ LibHTS.hts_itr_destroy(qiter)
76
111
  end
77
112
  end
78
113
  end