htslib 0.4.2 → 0.6.0
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 +83 -51
- data/TUTORIAL.md +11 -22
- data/ext/htslib_native/extconf.rb +41 -0
- data/ext/htslib_native/htslib_native.h +11 -0
- data/ext/htslib_native/htslib_native_ext.c +48 -0
- data/ext/htslib_native/native_bam.c +1167 -0
- data/ext/htslib_native/native_bcf.c +447 -0
- data/ext/htslib_native/native_faidx.c +164 -0
- data/ext/htslib_native/native_tabix.c +255 -0
- data/lib/hts/bam/auxi.rb +87 -342
- data/lib/hts/bam/base_mod.rb +38 -73
- data/lib/hts/bam/cigar.rb +9 -55
- data/lib/hts/bam/flag.rb +24 -30
- data/lib/hts/bam/header.rb +29 -56
- data/lib/hts/bam/mpileup.rb +158 -132
- data/lib/hts/bam/pileup.rb +120 -145
- data/lib/hts/bam/record.rb +233 -270
- data/lib/hts/bam.rb +154 -45
- data/lib/hts/bcf/errors.rb +4 -0
- data/lib/hts/bcf/format.rb +283 -377
- data/lib/hts/bcf/header.rb +40 -122
- data/lib/hts/bcf/header_record.rb +9 -35
- data/lib/hts/bcf/info.rb +73 -320
- data/lib/hts/bcf/record.rb +73 -101
- data/lib/hts/bcf.rb +178 -321
- data/lib/hts/faidx.rb +30 -87
- data/lib/hts/hts.rb +6 -94
- data/lib/hts/native.rb +13 -0
- data/lib/hts/tabix.rb +109 -51
- data/lib/hts/version.rb +1 -1
- data/lib/htslib.rb +6 -52
- metadata +13 -64
- data/lib/hts/ffi_ext/README.md +0 -8
- data/lib/hts/ffi_ext/pointer.rb +0 -18
- data/lib/hts/ffi_ext/struct.rb +0 -45
- data/lib/hts/libhts/bgzf.rb +0 -199
- data/lib/hts/libhts/constants.rb +0 -658
- data/lib/hts/libhts/cram.rb +0 -471
- data/lib/hts/libhts/fai.rb +0 -146
- data/lib/hts/libhts/hfile.rb +0 -121
- data/lib/hts/libhts/hts.rb +0 -477
- data/lib/hts/libhts/kfunc.rb +0 -38
- data/lib/hts/libhts/sam.rb +0 -760
- data/lib/hts/libhts/sam_funcs.rb +0 -155
- data/lib/hts/libhts/tbx.rb +0 -94
- data/lib/hts/libhts/tbx_funcs.rb +0 -36
- data/lib/hts/libhts/thread_pool.rb +0 -139
- data/lib/hts/libhts/vcf.rb +0 -567
- data/lib/hts/libhts/vcf_funcs.rb +0 -366
- data/lib/hts/libhts.rb +0 -47
data/lib/hts/bcf/header.rb
CHANGED
|
@@ -23,18 +23,17 @@ module HTS
|
|
|
23
23
|
|
|
24
24
|
def initialize(arg = nil)
|
|
25
25
|
case arg
|
|
26
|
-
when
|
|
27
|
-
@
|
|
28
|
-
when LibHTS::BcfHdr
|
|
29
|
-
@bcf_hdr = arg
|
|
26
|
+
when Native::BcfHeaderHandle
|
|
27
|
+
@native = arg
|
|
30
28
|
when nil
|
|
31
|
-
@
|
|
29
|
+
@native = Native::BcfHeaderHandle.create
|
|
32
30
|
else
|
|
33
31
|
raise TypeError, "Invalid argument"
|
|
34
32
|
end
|
|
35
33
|
|
|
36
34
|
@sync_depth = 0
|
|
37
35
|
@sync_needed = false
|
|
36
|
+
@schema_version = 0
|
|
38
37
|
@subset_samples = nil
|
|
39
38
|
@subset_imap = nil
|
|
40
39
|
@subset_imap_pointer = nil
|
|
@@ -42,29 +41,23 @@ module HTS
|
|
|
42
41
|
yield self if block_given?
|
|
43
42
|
end
|
|
44
43
|
|
|
45
|
-
def struct
|
|
46
|
-
@bcf_hdr
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def to_ptr
|
|
50
|
-
@bcf_hdr.to_ptr
|
|
51
|
-
end
|
|
52
|
-
|
|
53
44
|
def get_version
|
|
54
|
-
|
|
45
|
+
@native.version
|
|
55
46
|
end
|
|
47
|
+
alias version get_version
|
|
56
48
|
|
|
57
49
|
def set_version(version)
|
|
58
|
-
rc =
|
|
50
|
+
rc = @native.set_version(version)
|
|
59
51
|
raise "Failed to set VCF header version" if rc.negative?
|
|
60
52
|
|
|
61
53
|
mark_sync_needed!
|
|
62
54
|
sync_if_needed!
|
|
63
55
|
self
|
|
64
56
|
end
|
|
57
|
+
alias version= set_version
|
|
65
58
|
|
|
66
59
|
def nsamples
|
|
67
|
-
|
|
60
|
+
@native.nsamples
|
|
68
61
|
end
|
|
69
62
|
|
|
70
63
|
def target_count
|
|
@@ -84,13 +77,10 @@ module HTS
|
|
|
84
77
|
end
|
|
85
78
|
|
|
86
79
|
def samples
|
|
87
|
-
|
|
88
|
-
@bcf_hdr[:samples]
|
|
89
|
-
.read_array_of_pointer(nsamples)
|
|
90
|
-
.map(&:read_string)
|
|
80
|
+
@native.samples
|
|
91
81
|
end
|
|
92
82
|
|
|
93
|
-
attr_reader :subset_samples, :subset_imap_pointer
|
|
83
|
+
attr_reader :subset_samples, :subset_imap_pointer, :schema_version
|
|
94
84
|
|
|
95
85
|
def subset?
|
|
96
86
|
!@subset_imap.nil?
|
|
@@ -104,27 +94,18 @@ module HTS
|
|
|
104
94
|
subset_samples = normalize_subset_samples(samples)
|
|
105
95
|
validate_subset_samples!(subset_samples)
|
|
106
96
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
subset_hdr = LibHTS.bcf_hdr_subset(@bcf_hdr, 0, ::FFI::Pointer::NULL, ::FFI::Pointer::NULL)
|
|
110
|
-
else
|
|
111
|
-
encoded_samples = subset_samples.map { |name| FFI::MemoryPointer.from_string(name) }
|
|
112
|
-
sample_pointers = FFI::MemoryPointer.new(:pointer, subset_samples.length)
|
|
113
|
-
sample_pointers.write_array_of_pointer(encoded_samples)
|
|
114
|
-
imap_pointer = FFI::MemoryPointer.new(:int, subset_samples.length)
|
|
115
|
-
subset_hdr = LibHTS.bcf_hdr_subset(@bcf_hdr, subset_samples.length, sample_pointers, imap_pointer)
|
|
116
|
-
end
|
|
97
|
+
result = @native.subset(subset_samples)
|
|
98
|
+
raise SubsetError, "Failed to subset BCF header samples #{subset_samples.inspect}" unless result
|
|
117
99
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
self.class.new(subset_hdr).tap do |header|
|
|
100
|
+
subset_header, imap = result
|
|
101
|
+
composed_imap = compose_subset_imap(imap)
|
|
102
|
+
self.class.new(subset_header).tap do |header|
|
|
122
103
|
header.send(:set_subset_state, subset_samples, composed_imap)
|
|
123
104
|
end
|
|
124
105
|
end
|
|
125
106
|
|
|
126
107
|
def add_sample(sample, sync: true)
|
|
127
|
-
rc =
|
|
108
|
+
rc = @native.add_sample(sample)
|
|
128
109
|
raise "Failed to add sample #{sample}" if rc.negative?
|
|
129
110
|
|
|
130
111
|
mark_sync_needed!
|
|
@@ -133,17 +114,14 @@ module HTS
|
|
|
133
114
|
end
|
|
134
115
|
|
|
135
116
|
def merge(hdr)
|
|
136
|
-
|
|
137
|
-
raise "Failed to merge BCF headers" if merged.to_ptr.null?
|
|
138
|
-
|
|
139
|
-
@bcf_hdr = merged
|
|
117
|
+
@native.merge(hdr.__send__(:native_handle))
|
|
140
118
|
mark_sync_needed!
|
|
141
119
|
sync_if_needed!
|
|
142
120
|
self
|
|
143
121
|
end
|
|
144
122
|
|
|
145
123
|
def sync
|
|
146
|
-
rc =
|
|
124
|
+
rc = @native.sync
|
|
147
125
|
raise "Failed to sync BCF header" if rc.negative?
|
|
148
126
|
|
|
149
127
|
@sync_needed = false
|
|
@@ -151,11 +129,13 @@ module HTS
|
|
|
151
129
|
end
|
|
152
130
|
|
|
153
131
|
def read_bcf(fname)
|
|
154
|
-
|
|
132
|
+
result = @native.read_file(fname)
|
|
133
|
+
@schema_version += 1 unless result.negative?
|
|
134
|
+
result
|
|
155
135
|
end
|
|
156
136
|
|
|
157
137
|
def append(line)
|
|
158
|
-
rc =
|
|
138
|
+
rc = @native.append(line)
|
|
159
139
|
raise "Failed to append VCF header line" if rc.negative?
|
|
160
140
|
|
|
161
141
|
mark_sync_needed!
|
|
@@ -164,18 +144,14 @@ module HTS
|
|
|
164
144
|
|
|
165
145
|
def delete(bcf_hl_type, key = nil) # FIXME
|
|
166
146
|
existed = hrec_exists?(bcf_hl_type, key)
|
|
167
|
-
|
|
168
|
-
LibHTS.bcf_hdr_remove(@bcf_hdr, type, key)
|
|
147
|
+
@native.remove(bcf_hl_type.to_s, key)
|
|
169
148
|
mark_sync_needed! if existed
|
|
170
149
|
existed
|
|
171
150
|
end
|
|
172
151
|
|
|
173
152
|
def get_hrec(bcf_hl_type, key, value, str_class = nil)
|
|
174
|
-
|
|
175
|
-
hrec
|
|
176
|
-
return nil if hrec.to_ptr.null?
|
|
177
|
-
|
|
178
|
-
HeaderRecord.new(owned_hrec(hrec))
|
|
153
|
+
hrec = @native.get_hrec(bcf_hl_type.to_s, key, value, str_class)
|
|
154
|
+
hrec ? HeaderRecord.new(hrec) : nil
|
|
179
155
|
end
|
|
180
156
|
|
|
181
157
|
def edit
|
|
@@ -251,33 +227,19 @@ module HTS
|
|
|
251
227
|
end
|
|
252
228
|
|
|
253
229
|
def seqnames
|
|
254
|
-
|
|
255
|
-
names = LibHTS.bcf_hdr_seqnames(@bcf_hdr, n)
|
|
256
|
-
begin
|
|
257
|
-
names.read_array_of_pointer(n.read_int)
|
|
258
|
-
.map(&:read_string)
|
|
259
|
-
ensure
|
|
260
|
-
LibHTS.hts_free(names) unless names.null?
|
|
261
|
-
end
|
|
230
|
+
@native.seqnames
|
|
262
231
|
end
|
|
263
232
|
|
|
264
233
|
def to_s
|
|
265
|
-
|
|
266
|
-
begin
|
|
267
|
-
raise "Failed to get header string" if LibHTS.bcf_hdr_format(@bcf_hdr, 0, kstr).negative?
|
|
268
|
-
|
|
269
|
-
kstr.read_string_copy
|
|
270
|
-
ensure
|
|
271
|
-
kstr.free_buffer
|
|
272
|
-
end
|
|
234
|
+
@native.to_s
|
|
273
235
|
end
|
|
274
236
|
|
|
275
237
|
def name2id(name)
|
|
276
|
-
|
|
238
|
+
@native.name2id(name)
|
|
277
239
|
end
|
|
278
240
|
|
|
279
241
|
def id2name(id)
|
|
280
|
-
|
|
242
|
+
@native.id2name(id)
|
|
281
243
|
end
|
|
282
244
|
|
|
283
245
|
private
|
|
@@ -324,6 +286,7 @@ module HTS
|
|
|
324
286
|
|
|
325
287
|
def mark_sync_needed!
|
|
326
288
|
@sync_needed = true
|
|
289
|
+
@schema_version += 1
|
|
327
290
|
end
|
|
328
291
|
|
|
329
292
|
def sync_if_needed!
|
|
@@ -331,58 +294,26 @@ module HTS
|
|
|
331
294
|
end
|
|
332
295
|
|
|
333
296
|
def hrec_exists?(bcf_hl_type, key)
|
|
334
|
-
|
|
335
|
-
lookup_key, lookup_value, str_class
|
|
336
|
-
hrec = borrowed_hrec(type, lookup_key, lookup_value, str_class)
|
|
337
|
-
!hrec.to_ptr.null?
|
|
338
|
-
end
|
|
339
|
-
|
|
340
|
-
def borrowed_hrec(type, key, value, str_class)
|
|
341
|
-
LibHTS.bcf_hdr_get_hrec(@bcf_hdr, type, key, value, str_class)
|
|
342
|
-
end
|
|
343
|
-
|
|
344
|
-
def owned_hrec(hrec)
|
|
345
|
-
LibHTS.bcf_hrec_dup(hrec).tap do |owned|
|
|
346
|
-
raise "Failed to duplicate BCF header record" if owned.to_ptr.null?
|
|
347
|
-
end
|
|
297
|
+
lookup_key, lookup_value, str_class = hrec_lookup_args(bcf_hl_type, key)
|
|
298
|
+
!@native.get_hrec(bcf_hl_type.to_s, lookup_key, lookup_value, str_class).nil?
|
|
348
299
|
end
|
|
349
300
|
|
|
350
301
|
def hrec_lookup_args(type, key)
|
|
351
|
-
case type
|
|
352
|
-
when
|
|
302
|
+
case type.to_s.upcase
|
|
303
|
+
when "FILTER", "FIL", "INFO", "FORMAT", "FMT", "CONTIG", "CTG"
|
|
353
304
|
["ID", key, nil]
|
|
354
|
-
when
|
|
305
|
+
when "GENOTYPE", "GEN"
|
|
355
306
|
[key, nil, nil]
|
|
356
307
|
else
|
|
357
308
|
["ID", key, nil]
|
|
358
309
|
end
|
|
359
310
|
end
|
|
360
311
|
|
|
361
|
-
def bcf_hl_type_to_int(bcf_hl_type)
|
|
362
|
-
return bcf_hl_type if bcf_hl_type.is_a?(Integer)
|
|
363
|
-
|
|
364
|
-
case bcf_hl_type.to_s.upcase
|
|
365
|
-
when "FILTER", "FIL"
|
|
366
|
-
LibHTS::BCF_HL_FLT
|
|
367
|
-
when "INFO"
|
|
368
|
-
LibHTS::BCF_HL_INFO
|
|
369
|
-
when "FORMAT", "FMT"
|
|
370
|
-
LibHTS::BCF_HL_FMT
|
|
371
|
-
when "CONTIG", "CTG"
|
|
372
|
-
LibHTS::BCF_HL_CTG
|
|
373
|
-
when "STRUCTURED", "STR"
|
|
374
|
-
LibHTS::BCF_HL_STR
|
|
375
|
-
when "GENOTYPE", "GEN"
|
|
376
|
-
LibHTS::BCF_HL_GEN
|
|
377
|
-
else
|
|
378
|
-
raise TypeError, "Invalid argument"
|
|
379
|
-
end
|
|
380
|
-
end
|
|
381
|
-
|
|
382
312
|
def initialize_copy(orig)
|
|
383
|
-
@
|
|
313
|
+
@native = orig.__send__(:native_handle).duplicate
|
|
384
314
|
@sync_depth = 0
|
|
385
315
|
@sync_needed = false
|
|
316
|
+
@schema_version = orig.schema_version
|
|
386
317
|
set_subset_state(orig.subset_samples, orig.send(:subset_imap))
|
|
387
318
|
end
|
|
388
319
|
|
|
@@ -393,7 +324,7 @@ module HTS
|
|
|
393
324
|
def set_subset_state(samples, imap)
|
|
394
325
|
@subset_samples = samples&.dup
|
|
395
326
|
@subset_imap = imap&.dup
|
|
396
|
-
@subset_imap_pointer =
|
|
327
|
+
@subset_imap_pointer = nil
|
|
397
328
|
end
|
|
398
329
|
|
|
399
330
|
private
|
|
@@ -417,25 +348,12 @@ module HTS
|
|
|
417
348
|
raise UnknownSampleError, "Unknown sample names: #{missing.join(', ')}" unless missing.empty?
|
|
418
349
|
end
|
|
419
350
|
|
|
420
|
-
def read_subset_imap(pointer, length)
|
|
421
|
-
return [] if length.zero?
|
|
422
|
-
|
|
423
|
-
pointer.read_array_of_int(length)
|
|
424
|
-
end
|
|
425
|
-
|
|
426
351
|
def compose_subset_imap(imap)
|
|
427
352
|
base_imap = @subset_imap || Array.new(samples.length, &:itself)
|
|
428
353
|
imap.map { |index| base_imap.fetch(index) }
|
|
429
354
|
end
|
|
430
355
|
|
|
431
|
-
def
|
|
432
|
-
return nil unless imap
|
|
433
|
-
return nil if imap.empty?
|
|
434
|
-
|
|
435
|
-
FFI::MemoryPointer.new(:int, imap.length).tap do |pointer|
|
|
436
|
-
pointer.write_array_of_int(imap)
|
|
437
|
-
end
|
|
438
|
-
end
|
|
356
|
+
def native_handle = @native
|
|
439
357
|
end
|
|
440
358
|
end
|
|
441
359
|
end
|
|
@@ -3,47 +3,21 @@
|
|
|
3
3
|
module HTS
|
|
4
4
|
class Bcf < Hts
|
|
5
5
|
class HeaderRecord
|
|
6
|
-
def initialize(
|
|
7
|
-
|
|
8
|
-
when LibHTS::BcfHrec
|
|
9
|
-
@bcf_hrec = arg
|
|
10
|
-
else
|
|
11
|
-
raise TypeError, "Invalid argument"
|
|
12
|
-
end
|
|
13
|
-
end
|
|
6
|
+
def initialize(native)
|
|
7
|
+
raise TypeError, "Invalid argument" unless native.is_a?(Native::BcfHeaderRecordHandle)
|
|
14
8
|
|
|
15
|
-
|
|
16
|
-
@bcf_hrec
|
|
9
|
+
@native = native
|
|
17
10
|
end
|
|
18
11
|
|
|
19
|
-
def add_key(key)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def set_value(i, val, quote: true)
|
|
24
|
-
is_quoted = quote ? 1 : 0
|
|
25
|
-
LibHTS.bcf_hrec_set_val(@bcf_hrec, i, val, val.length, is_quoted)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def find_key(key)
|
|
29
|
-
LibHTS.bcf_hrec_find_key(@bcf_hrec, key)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def to_s
|
|
33
|
-
kstr = LibHTS::KString.new
|
|
34
|
-
begin
|
|
35
|
-
LibHTS.bcf_hrec_format(@bcf_hrec, kstr)
|
|
36
|
-
kstr.read_string_copy
|
|
37
|
-
ensure
|
|
38
|
-
kstr.free_buffer
|
|
39
|
-
end
|
|
40
|
-
end
|
|
12
|
+
def add_key(key) = @native.add_key(key)
|
|
13
|
+
def set_value(index, value, quote: true) = @native.set_value(index, value, quote)
|
|
14
|
+
def find_key(key) = @native.find_key(key)
|
|
15
|
+
def to_s = @native.to_s
|
|
41
16
|
|
|
42
17
|
private
|
|
43
18
|
|
|
44
|
-
def
|
|
45
|
-
|
|
46
|
-
end
|
|
19
|
+
def native_handle = @native
|
|
20
|
+
def initialize_copy(original) = (@native = original.__send__(:native_handle).duplicate)
|
|
47
21
|
end
|
|
48
22
|
end
|
|
49
23
|
end
|