htslib 0.2.6 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +78 -30
- data/TUTORIAL.md +61 -15
- data/lib/hts/bam/auxi.rb +82 -21
- data/lib/hts/bam/flag.rb +8 -6
- data/lib/hts/bam/header.rb +50 -8
- data/lib/hts/bam/record.rb +81 -11
- data/lib/hts/bam.rb +98 -54
- data/lib/hts/bcf/header.rb +10 -0
- data/lib/hts/bcf/record.rb +2 -2
- data/lib/hts/bcf.rb +83 -54
- data/lib/hts/faidx/sequence.rb +0 -2
- data/lib/hts/faidx.rb +13 -5
- data/lib/hts/libhts/bgzf.rb +1 -1
- data/lib/hts/libhts/constants.rb +13 -0
- data/lib/hts/libhts/cram.rb +113 -1
- data/lib/hts/libhts/hts.rb +1 -1
- data/lib/hts/libhts/sam.rb +38 -8
- data/lib/hts/libhts/tbx.rb +7 -0
- data/lib/hts/libhts/tbx_funcs.rb +7 -2
- data/lib/hts/libhts/vcf.rb +6 -0
- data/lib/hts/libhts/vcf_funcs.rb +2 -2
- data/lib/hts/libhts.rb +1 -1
- data/lib/hts/{tbx.rb → tabix.rb} +15 -21
- data/lib/hts/version.rb +1 -1
- data/lib/htslib.rb +1 -1
- metadata +9 -79
- /data/lib/hts/libhts/{faidx.rb → fai.rb} +0 -0
data/lib/hts/bam/record.rb
CHANGED
@@ -12,9 +12,64 @@ module HTS
|
|
12
12
|
|
13
13
|
attr_reader :header
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
# Initialization API is experimental.
|
16
|
+
|
17
|
+
def initialize(
|
18
|
+
header,
|
19
|
+
bam1 = nil,
|
20
|
+
qname: nil,
|
21
|
+
flag: nil,
|
22
|
+
tid: nil,
|
23
|
+
pos: nil,
|
24
|
+
mapq: nil,
|
25
|
+
cigar: nil,
|
26
|
+
mtid: nil,
|
27
|
+
mpos: nil,
|
28
|
+
isize: nil,
|
29
|
+
seq: nil,
|
30
|
+
qual: nil,
|
31
|
+
l_aux: nil
|
32
|
+
)
|
33
|
+
@bam1 = bam1 || LibHTS.bam_init1
|
17
34
|
@header = header
|
35
|
+
|
36
|
+
params = [qname, flag, tid, pos, mapq, cigar, mtid, mpos, isize, seq, qual, l_aux]
|
37
|
+
return if params.all? { |x| x.nil? }
|
38
|
+
|
39
|
+
if params.all?
|
40
|
+
c = FFI::MemoryPointer.new(:pointer)
|
41
|
+
m = FFI::MemoryPointer.new(:size_t)
|
42
|
+
LibHTS.sam_parse_cigar(cigar, FFI::Pointer::NULL, c, m)
|
43
|
+
cigar_array = c.read_pointer.read_array_of_uint32(m.read(:size_t))
|
44
|
+
cigar_pointer = FFI::MemoryPointer.new(:uint32, cigar_array.length)
|
45
|
+
cigar_pointer.write_array_of_uint32(cigar_array)
|
46
|
+
if qual.is_a?(Array)
|
47
|
+
qual = qual.pack("C*")
|
48
|
+
elsif qual.is_a?(String)
|
49
|
+
raise "Which implementation is better? +33 or not? Please tell me."
|
50
|
+
end
|
51
|
+
r = LibHTS.bam_set1(
|
52
|
+
@bam1,
|
53
|
+
qname.length,
|
54
|
+
qname,
|
55
|
+
flag,
|
56
|
+
tid,
|
57
|
+
pos,
|
58
|
+
mapq,
|
59
|
+
cigar_array.length,
|
60
|
+
cigar_pointer,
|
61
|
+
mtid,
|
62
|
+
mpos,
|
63
|
+
isize,
|
64
|
+
seq.length,
|
65
|
+
seq,
|
66
|
+
qual,
|
67
|
+
l_aux
|
68
|
+
)
|
69
|
+
raise "bam_set1 failed: #{r}" if r < 0
|
70
|
+
else
|
71
|
+
warn "Ignore bam_set1 because some arguments are missing."
|
72
|
+
end
|
18
73
|
end
|
19
74
|
|
20
75
|
# Return the FFI::Struct object.
|
@@ -32,6 +87,10 @@ module HTS
|
|
32
87
|
LibHTS.bam_get_qname(@bam1).read_string
|
33
88
|
end
|
34
89
|
|
90
|
+
def qname=(name)
|
91
|
+
LibHTS.bam_set_qname(@bam1, name)
|
92
|
+
end
|
93
|
+
|
35
94
|
# Get the chromosome ID of the alignment. -1 if not mapped.
|
36
95
|
# @return [Integer] chromosome ID
|
37
96
|
def tid
|
@@ -154,6 +213,17 @@ module HTS
|
|
154
213
|
Cigar.new(self)
|
155
214
|
end
|
156
215
|
|
216
|
+
def cigar=(str)
|
217
|
+
if cigar.is_a? Cigar
|
218
|
+
raise "Not implemented yet."
|
219
|
+
elsif cigar.is_a? String
|
220
|
+
r = LibHTS.bam_parse_cigar(str, FFI::Pointer::NULL, @bam1)
|
221
|
+
raise "bam_parse_cigar failed: #{r}" if r != 0
|
222
|
+
else
|
223
|
+
raise ArgumentError, "cigar must be a String or Bam::Cigar"
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
157
227
|
# Calculate query length from CIGAR.
|
158
228
|
# @return [Integer] query length
|
159
229
|
def qlen
|
@@ -178,7 +248,7 @@ module HTS
|
|
178
248
|
def seq
|
179
249
|
r = LibHTS.bam_get_seq(@bam1)
|
180
250
|
seq = String.new
|
181
|
-
|
251
|
+
len.times do |i|
|
182
252
|
seq << SEQ_NT16_STR[LibHTS.bam_seqi(r, i)]
|
183
253
|
end
|
184
254
|
seq
|
@@ -195,8 +265,8 @@ module HTS
|
|
195
265
|
# @param [Integer] i index
|
196
266
|
# @return [String] base
|
197
267
|
def base(n)
|
198
|
-
n +=
|
199
|
-
return "." if (n >=
|
268
|
+
n += len if n < 0
|
269
|
+
return "." if (n >= len) || (n < 0) # eg. base(-1000)
|
200
270
|
|
201
271
|
r = LibHTS.bam_get_seq(@bam1)
|
202
272
|
SEQ_NT16_STR[LibHTS.bam_seqi(r, n)]
|
@@ -206,7 +276,7 @@ module HTS
|
|
206
276
|
# @return [Array] base qualities
|
207
277
|
def qual
|
208
278
|
q_ptr = LibHTS.bam_get_qual(@bam1)
|
209
|
-
q_ptr.read_array_of_uint8(
|
279
|
+
q_ptr.read_array_of_uint8(len)
|
210
280
|
end
|
211
281
|
|
212
282
|
# Get the base qualities as a string. (a.k.a QUAL)
|
@@ -220,8 +290,8 @@ module HTS
|
|
220
290
|
# @param [Integer] i index
|
221
291
|
# @return [Integer] base quality
|
222
292
|
def base_qual(n)
|
223
|
-
n +=
|
224
|
-
return 0 if (n >=
|
293
|
+
n += len if n < 0
|
294
|
+
return 0 if (n >= len) || (n < 0) # eg. base_qual(-1000)
|
225
295
|
|
226
296
|
q_ptr = LibHTS.bam_get_qual(@bam1)
|
227
297
|
q_ptr.get_uint8(n)
|
@@ -256,11 +326,11 @@ module HTS
|
|
256
326
|
end
|
257
327
|
end
|
258
328
|
|
259
|
-
# TODO: add a method to get the
|
329
|
+
# TODO: add a method to get the auxiliary fields as a hash.
|
260
330
|
|
261
|
-
# TODO: add a method to set the
|
331
|
+
# TODO: add a method to set the auxiliary fields.
|
262
332
|
|
263
|
-
# TODO: add a method to remove the
|
333
|
+
# TODO: add a method to remove the auxiliary fields.
|
264
334
|
|
265
335
|
# TODO: add a method to set variable length data (qname, cigar, seq, qual).
|
266
336
|
|
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.get_tid(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
@@ -19,6 +19,8 @@ module HTS
|
|
19
19
|
else
|
20
20
|
raise TypeError, "Invalid argument"
|
21
21
|
end
|
22
|
+
|
23
|
+
yield self if block_given?
|
22
24
|
end
|
23
25
|
|
24
26
|
def struct
|
@@ -94,6 +96,14 @@ module HTS
|
|
94
96
|
kstr[:s]
|
95
97
|
end
|
96
98
|
|
99
|
+
def name2id(name)
|
100
|
+
LibHTS.bcf_hdr_name2id(@bcf_hdr, name)
|
101
|
+
end
|
102
|
+
|
103
|
+
def id2name(id)
|
104
|
+
LibHTS.bcf_hdr_id2name(@bcf_hdr, id)
|
105
|
+
end
|
106
|
+
|
97
107
|
private
|
98
108
|
|
99
109
|
def bcf_hl_type_to_int(bcf_hl_type)
|
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
|
@@ -214,7 +185,7 @@ module HTS
|
|
214
185
|
|
215
186
|
def each_info(key)
|
216
187
|
check_closed
|
217
|
-
return to_enum(__method__, key) unless
|
188
|
+
return to_enum(__method__, key) unless block_given?
|
218
189
|
|
219
190
|
each do |r|
|
220
191
|
yield r.info(key)
|
@@ -223,27 +194,78 @@ module HTS
|
|
223
194
|
|
224
195
|
def each_format(key)
|
225
196
|
check_closed
|
226
|
-
return to_enum(__method__, key) unless
|
197
|
+
return to_enum(__method__, key) unless block_given?
|
227
198
|
|
228
199
|
each do |r|
|
229
200
|
yield r.format(key)
|
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],
|