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/bam/base_mod.rb
CHANGED
|
@@ -12,6 +12,7 @@ module HTS
|
|
|
12
12
|
class BaseMod
|
|
13
13
|
include Enumerable
|
|
14
14
|
|
|
15
|
+
class Error < HTS::Error; end
|
|
15
16
|
class NotParsedError < StandardError; end
|
|
16
17
|
|
|
17
18
|
attr_reader :record
|
|
@@ -133,11 +134,10 @@ module HTS
|
|
|
133
134
|
# @param auto_parse [Boolean] If true, parse MM/ML lazily on first access
|
|
134
135
|
def initialize(record, auto_parse: true)
|
|
135
136
|
@record = record
|
|
136
|
-
@state =
|
|
137
|
+
@state = Native::BaseModHandle.open(record.__send__(:native_handle))
|
|
137
138
|
@closed = false
|
|
138
139
|
@auto_parse = !!auto_parse
|
|
139
140
|
@parsed = false
|
|
140
|
-
raise Error, "Failed to allocate hts_base_mod_state" if @state.null?
|
|
141
141
|
end
|
|
142
142
|
|
|
143
143
|
# Explicitly free the state
|
|
@@ -145,8 +145,7 @@ module HTS
|
|
|
145
145
|
def close
|
|
146
146
|
return if @closed
|
|
147
147
|
|
|
148
|
-
|
|
149
|
-
# is sufficient. Avoid manual free to prevent double-free.
|
|
148
|
+
@state.close
|
|
150
149
|
@state = nil
|
|
151
150
|
@closed = true
|
|
152
151
|
end
|
|
@@ -173,7 +172,7 @@ module HTS
|
|
|
173
172
|
# @return [Integer] Number of modification types found, or -1 on error
|
|
174
173
|
# @raise [Error] If parsing fails
|
|
175
174
|
def parse(flags = 0)
|
|
176
|
-
ret =
|
|
175
|
+
ret = @state.parse(flags)
|
|
177
176
|
raise Error, "Failed to parse base modifications" if ret < 0
|
|
178
177
|
|
|
179
178
|
@parsed = true
|
|
@@ -188,13 +187,10 @@ module HTS
|
|
|
188
187
|
# Reset state to ensure deterministic results even after prior iteration
|
|
189
188
|
parsed? ? parse : ensure_parsed!
|
|
190
189
|
|
|
191
|
-
|
|
190
|
+
values = @state.at(position, max_mods)
|
|
191
|
+
return nil unless values
|
|
192
192
|
|
|
193
|
-
|
|
194
|
-
mods_ptr, max_mods)
|
|
195
|
-
return nil if ret <= 0
|
|
196
|
-
|
|
197
|
-
build_position(position, mods_ptr, [ret, max_mods].min)
|
|
193
|
+
build_position(position, values)
|
|
198
194
|
end
|
|
199
195
|
|
|
200
196
|
# Array-style access to modifications at a position
|
|
@@ -211,36 +207,41 @@ module HTS
|
|
|
211
207
|
def each_position(max_mods: 10)
|
|
212
208
|
return enum_for(__method__, max_mods: max_mods) unless block_given?
|
|
213
209
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
yield build_position(position, mods_ptr, [ret, max_mods].min)
|
|
210
|
+
current_position = nil
|
|
211
|
+
modifications = []
|
|
212
|
+
each_raw(max_mods: max_mods) do |position, canonical, modified, strand, qual|
|
|
213
|
+
if current_position && position != current_position
|
|
214
|
+
yield Position.new(current_position, modifications)
|
|
215
|
+
modifications = []
|
|
216
|
+
end
|
|
217
|
+
current_position = position
|
|
218
|
+
modifications << Modification.new(
|
|
219
|
+
modified_base: modified, canonical_base: canonical,
|
|
220
|
+
strand: strand, qual: qual
|
|
221
|
+
)
|
|
227
222
|
end
|
|
223
|
+
yield Position.new(current_position, modifications) if current_position
|
|
224
|
+
self
|
|
228
225
|
end
|
|
229
226
|
|
|
230
227
|
alias each each_position
|
|
231
228
|
|
|
229
|
+
# Iterate primitive modification values without Position/Modification
|
|
230
|
+
# object allocation.
|
|
231
|
+
def each_raw(max_mods: 10)
|
|
232
|
+
return enum_for(__method__, max_mods: max_mods) unless block_given?
|
|
233
|
+
|
|
234
|
+
parsed? ? parse : ensure_parsed!
|
|
235
|
+
@state.each_raw(max_mods) { |*values| yield(*values) }
|
|
236
|
+
self
|
|
237
|
+
end
|
|
238
|
+
|
|
232
239
|
# Get list of modification types present in this record
|
|
233
240
|
# @return [Array<Integer>] Array of modification codes (char code or -ChEBI)
|
|
234
241
|
def modification_types
|
|
235
242
|
ensure_parsed!
|
|
236
243
|
|
|
237
|
-
|
|
238
|
-
codes_ptr = LibHTS.bam_mods_recorded(@state, ntype_ptr)
|
|
239
|
-
|
|
240
|
-
ntype = ntype_ptr.read_int
|
|
241
|
-
return [] if ntype <= 0 || codes_ptr.null?
|
|
242
|
-
|
|
243
|
-
codes_ptr.read_array_of_int(ntype)
|
|
244
|
+
@state.types
|
|
244
245
|
end
|
|
245
246
|
|
|
246
247
|
alias recorded_types modification_types
|
|
@@ -253,19 +254,7 @@ module HTS
|
|
|
253
254
|
|
|
254
255
|
code = code.ord if code.is_a?(String)
|
|
255
256
|
|
|
256
|
-
|
|
257
|
-
implicit_ptr = FFI::MemoryPointer.new(:int)
|
|
258
|
-
canonical_ptr = FFI::MemoryPointer.new(:char, 1)
|
|
259
|
-
|
|
260
|
-
ret = LibHTS.bam_mods_query_type(@state, code, strand_ptr,
|
|
261
|
-
implicit_ptr, canonical_ptr)
|
|
262
|
-
return nil if ret < 0
|
|
263
|
-
|
|
264
|
-
{
|
|
265
|
-
canonical: canonical_ptr.read_char.chr,
|
|
266
|
-
strand: strand_ptr.read_int,
|
|
267
|
-
implicit: implicit_ptr.read_int != 0
|
|
268
|
-
}
|
|
257
|
+
@state.query(code)
|
|
269
258
|
end
|
|
270
259
|
|
|
271
260
|
# Query information about i-th modification type
|
|
@@ -274,21 +263,7 @@ module HTS
|
|
|
274
263
|
def query_type_at(index)
|
|
275
264
|
ensure_parsed!
|
|
276
265
|
|
|
277
|
-
|
|
278
|
-
implicit_ptr = FFI::MemoryPointer.new(:int)
|
|
279
|
-
canonical_ptr = FFI::MemoryPointer.new(:char, 1)
|
|
280
|
-
|
|
281
|
-
ret = LibHTS.bam_mods_queryi(@state, index, strand_ptr,
|
|
282
|
-
implicit_ptr, canonical_ptr)
|
|
283
|
-
return nil if ret < 0
|
|
284
|
-
|
|
285
|
-
types = modification_types
|
|
286
|
-
{
|
|
287
|
-
code: types[index],
|
|
288
|
-
canonical: canonical_ptr.read_char.chr,
|
|
289
|
-
strand: strand_ptr.read_int,
|
|
290
|
-
implicit: implicit_ptr.read_int != 0
|
|
291
|
-
}
|
|
266
|
+
@state.query_at(index)
|
|
292
267
|
end
|
|
293
268
|
|
|
294
269
|
# Get all modifications as an array
|
|
@@ -319,21 +294,11 @@ module HTS
|
|
|
319
294
|
|
|
320
295
|
# Build Position object from hts_base_mod array
|
|
321
296
|
# @param position [Integer] Query position
|
|
322
|
-
# @param
|
|
323
|
-
# @param n_mods [Integer] Number of modifications
|
|
297
|
+
# @param values [Array<Array>] Native modification values
|
|
324
298
|
# @return [Position] Position object
|
|
325
|
-
def build_position(position,
|
|
326
|
-
modifications =
|
|
327
|
-
|
|
328
|
-
n_mods.times do |i|
|
|
329
|
-
mod_struct = LibHTS::HtsBaseMod.new(mods_ptr + i * LibHTS::HtsBaseMod.size)
|
|
330
|
-
|
|
331
|
-
modifications << Modification.new(
|
|
332
|
-
modified_base: mod_struct[:modified_base],
|
|
333
|
-
canonical_base: mod_struct[:canonical_base],
|
|
334
|
-
strand: mod_struct[:strand],
|
|
335
|
-
qual: mod_struct[:qual]
|
|
336
|
-
)
|
|
299
|
+
def build_position(position, values)
|
|
300
|
+
modifications = values.map do |canonical, modified, strand, qual|
|
|
301
|
+
Modification.new(modified_base: modified, canonical_base: canonical, strand:, qual:)
|
|
337
302
|
end
|
|
338
303
|
|
|
339
304
|
Position.new(position, modifications)
|
data/lib/hts/bam/cigar.rb
CHANGED
|
@@ -2,78 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
module HTS
|
|
4
4
|
class Bam < Hts
|
|
5
|
-
# CIGAR string
|
|
6
5
|
class Cigar
|
|
7
6
|
include Enumerable
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
OP_CHARS = "MIDNSHP=XB"
|
|
10
9
|
attr_accessor :array
|
|
11
10
|
|
|
12
|
-
# Create a new Cigar object from a string.
|
|
13
|
-
# @param [String] cigar_str
|
|
14
|
-
# The CIGAR string is converted to a uint32_t array in htslib.
|
|
15
11
|
def self.parse(str)
|
|
16
|
-
|
|
17
|
-
m = FFI::MemoryPointer.new(:size_t)
|
|
18
|
-
c.write_pointer(FFI::Pointer::NULL)
|
|
19
|
-
m.write(:size_t, 0)
|
|
20
|
-
ptr = nil
|
|
21
|
-
n_cigar = LibHTS.sam_parse_cigar(str, FFI::Pointer::NULL, c, m)
|
|
22
|
-
raise "sam_parse_cigar failed: #{n_cigar}" if n_cigar.negative?
|
|
23
|
-
|
|
24
|
-
ptr = c.read_pointer
|
|
25
|
-
cigar_array = ptr.null? ? [] : ptr.read_array_of_uint32(n_cigar)
|
|
26
|
-
obj = new
|
|
27
|
-
obj.array = cigar_array
|
|
28
|
-
obj
|
|
29
|
-
ensure
|
|
30
|
-
LibHTS.hts_free(ptr) if ptr && !ptr.null?
|
|
12
|
+
new.tap { |cigar| cigar.array = Native.cigar_parse(str.to_s) }
|
|
31
13
|
end
|
|
32
14
|
|
|
33
15
|
def initialize(record = nil)
|
|
34
|
-
|
|
35
|
-
# The record is used at initialization and is not retained after that.
|
|
36
|
-
bam1 = record.struct
|
|
37
|
-
n_cigar = bam1[:core][:n_cigar]
|
|
38
|
-
@array = LibHTS.bam_get_cigar(bam1).read_array_of_uint32(n_cigar)
|
|
39
|
-
else
|
|
40
|
-
@array = []
|
|
41
|
-
end
|
|
16
|
+
@array = record ? record.__send__(:native_handle).cigar_values : []
|
|
42
17
|
end
|
|
43
18
|
|
|
44
|
-
def to_s
|
|
45
|
-
map { |op, len| "#{len}#{op}" }.join
|
|
46
|
-
end
|
|
19
|
+
def to_s = map { |op, len| "#{len}#{op}" }.join
|
|
47
20
|
|
|
48
21
|
def each
|
|
49
22
|
return to_enum(__method__) unless block_given?
|
|
50
23
|
|
|
51
|
-
@array.each
|
|
52
|
-
op = LibHTS.bam_cigar_opchr(c)
|
|
53
|
-
len = LibHTS.bam_cigar_oplen(c)
|
|
54
|
-
yield [op, len]
|
|
55
|
-
end
|
|
24
|
+
@array.each { |encoded| yield OP_CHARS[encoded & 15], encoded >> 4 }
|
|
56
25
|
end
|
|
57
26
|
|
|
58
|
-
def qlen
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def rlen
|
|
65
|
-
a = FFI::MemoryPointer.new(:uint32, @array.size)
|
|
66
|
-
a.write_array_of_uint32(@array)
|
|
67
|
-
LibHTS.bam_cigar2rlen(@array.size, a)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def ==(other)
|
|
71
|
-
other.is_a?(Cigar) && (@array == other.array)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def eql?(other)
|
|
75
|
-
other.is_a?(Cigar) && @array.eql?(other.array)
|
|
76
|
-
end
|
|
27
|
+
def qlen = Native.cigar_qlen(@array)
|
|
28
|
+
def rlen = Native.cigar_rlen(@array)
|
|
29
|
+
def ==(other) = other.is_a?(Cigar) && @array == other.array
|
|
30
|
+
def eql?(other) = other.is_a?(Cigar) && @array.eql?(other.array)
|
|
77
31
|
end
|
|
78
32
|
end
|
|
79
33
|
end
|
data/lib/hts/bam/flag.rb
CHANGED
|
@@ -15,31 +15,28 @@ module HTS
|
|
|
15
15
|
|
|
16
16
|
attr_accessor :value
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
read1?:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
qcfail?: LibHTS::BAM_FQCFAIL,
|
|
41
|
-
duplicate?: LibHTS::BAM_FDUP,
|
|
42
|
-
supplementary?: LibHTS::BAM_FSUPPLEMENTARY }.freeze
|
|
18
|
+
PAIRED = 1
|
|
19
|
+
PROPER_PAIR = 2
|
|
20
|
+
UNMAPPED = 4
|
|
21
|
+
MATE_UNMAPPED = 8
|
|
22
|
+
REVERSE = 16
|
|
23
|
+
MATE_REVERSE = 32
|
|
24
|
+
READ1 = 64
|
|
25
|
+
READ2 = 128
|
|
26
|
+
SECONDARY = 256
|
|
27
|
+
QCFAIL = 512
|
|
28
|
+
DUPLICATE = 1024
|
|
29
|
+
SUPPLEMENTARY = 2048
|
|
30
|
+
|
|
31
|
+
UNMAP = UNMAPPED
|
|
32
|
+
MUNMAP = MATE_UNMAPPED
|
|
33
|
+
DUP = DUPLICATE
|
|
34
|
+
|
|
35
|
+
TABLE = { paired?: PAIRED, proper_pair?: PROPER_PAIR, unmapped?: UNMAPPED,
|
|
36
|
+
mate_unmapped?: MATE_UNMAPPED, reverse?: REVERSE,
|
|
37
|
+
mate_reverse?: MATE_REVERSE, read1?: READ1, read2?: READ2,
|
|
38
|
+
secondary?: SECONDARY, qcfail?: QCFAIL, duplicate?: DUPLICATE,
|
|
39
|
+
supplementary?: SUPPLEMENTARY }.freeze
|
|
43
40
|
|
|
44
41
|
# @!macro [attach] generate_flag_methods
|
|
45
42
|
# @!method $1
|
|
@@ -81,9 +78,7 @@ module HTS
|
|
|
81
78
|
end
|
|
82
79
|
|
|
83
80
|
def ~
|
|
84
|
-
|
|
85
|
-
# The result is different from the Crystal version.
|
|
86
|
-
self.class.new(~@value)
|
|
81
|
+
self.class.new((~@value) & 0x0fff)
|
|
87
82
|
end
|
|
88
83
|
|
|
89
84
|
def <<(f)
|
|
@@ -99,8 +94,7 @@ module HTS
|
|
|
99
94
|
end
|
|
100
95
|
|
|
101
96
|
def to_s
|
|
102
|
-
|
|
103
|
-
# "0x#{format('%x', @value)}\t#{@value}\t#{LibHTS.bam_flag2str(@value)}"
|
|
97
|
+
Native.bam_flag_string(@value)
|
|
104
98
|
end
|
|
105
99
|
end
|
|
106
100
|
end
|
data/lib/hts/bam/header.rb
CHANGED
|
@@ -40,17 +40,15 @@ module HTS
|
|
|
40
40
|
}.freeze
|
|
41
41
|
|
|
42
42
|
def self.parse(text)
|
|
43
|
-
new(
|
|
43
|
+
new(Native::SamHeaderHandle.parse(text))
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def initialize(arg = nil)
|
|
47
47
|
case arg
|
|
48
|
-
when
|
|
49
|
-
@
|
|
50
|
-
when LibHTS::SamHdr
|
|
51
|
-
@sam_hdr = arg
|
|
48
|
+
when Native::SamHeaderHandle
|
|
49
|
+
@native = arg
|
|
52
50
|
when nil
|
|
53
|
-
@
|
|
51
|
+
@native = Native::SamHeaderHandle.create
|
|
54
52
|
else
|
|
55
53
|
raise TypeError, "Invalid argument"
|
|
56
54
|
end
|
|
@@ -58,25 +56,16 @@ module HTS
|
|
|
58
56
|
yield self if block_given?
|
|
59
57
|
end
|
|
60
58
|
|
|
61
|
-
def struct
|
|
62
|
-
@sam_hdr
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def to_ptr
|
|
66
|
-
@sam_hdr.to_ptr
|
|
67
|
-
end
|
|
68
|
-
|
|
69
59
|
def targets
|
|
70
60
|
Array.new(target_count) do |i|
|
|
71
|
-
name =
|
|
72
|
-
len =
|
|
61
|
+
name = @native.target_name(i)
|
|
62
|
+
len = @native.target_length(i)
|
|
73
63
|
{ name:, len: }
|
|
74
64
|
end
|
|
75
65
|
end
|
|
76
66
|
|
|
77
67
|
def target_count
|
|
78
|
-
|
|
79
|
-
@sam_hdr[:n_targets]
|
|
68
|
+
@native.target_count
|
|
80
69
|
end
|
|
81
70
|
|
|
82
71
|
def target_name(tid)
|
|
@@ -85,13 +74,13 @@ module HTS
|
|
|
85
74
|
|
|
86
75
|
def target_names
|
|
87
76
|
Array.new(target_count) do |i|
|
|
88
|
-
|
|
77
|
+
@native.target_name(i)
|
|
89
78
|
end
|
|
90
79
|
end
|
|
91
80
|
|
|
92
81
|
def target_len
|
|
93
82
|
Array.new(target_count) do |i|
|
|
94
|
-
|
|
83
|
+
@native.target_length(i)
|
|
95
84
|
end
|
|
96
85
|
end
|
|
97
86
|
|
|
@@ -118,68 +107,50 @@ module HTS
|
|
|
118
107
|
|
|
119
108
|
# experimental
|
|
120
109
|
def find_line(type, key, value)
|
|
121
|
-
|
|
122
|
-
begin
|
|
123
|
-
r = LibHTS.sam_hdr_find_line_id(@sam_hdr, type, key, value, ks)
|
|
124
|
-
r == 0 ? ks.read_string_copy : nil
|
|
125
|
-
ensure
|
|
126
|
-
ks.free_buffer
|
|
127
|
-
end
|
|
110
|
+
@native.find_line(type, key, value)
|
|
128
111
|
end
|
|
129
112
|
|
|
130
113
|
def find_tag(type, id_key, id_value, key)
|
|
131
|
-
|
|
132
|
-
begin
|
|
133
|
-
r = LibHTS.sam_hdr_find_tag_id(@sam_hdr, type, id_key, id_value, key, ks)
|
|
134
|
-
r == 0 ? ks.read_string_copy : nil
|
|
135
|
-
ensure
|
|
136
|
-
ks.free_buffer
|
|
137
|
-
end
|
|
114
|
+
@native.find_tag(type, id_key, id_value, key)
|
|
138
115
|
end
|
|
139
116
|
|
|
140
117
|
# experimental
|
|
141
118
|
def find_line_at(type, pos)
|
|
142
|
-
|
|
143
|
-
begin
|
|
144
|
-
r = LibHTS.sam_hdr_find_line_pos(@sam_hdr, type, pos, ks)
|
|
145
|
-
r == 0 ? ks.read_string_copy : nil
|
|
146
|
-
ensure
|
|
147
|
-
ks.free_buffer
|
|
148
|
-
end
|
|
119
|
+
@native.find_line_at(type, pos)
|
|
149
120
|
end
|
|
150
121
|
|
|
151
122
|
# experimental
|
|
152
123
|
def remove_line(type, key, value)
|
|
153
|
-
|
|
124
|
+
@native.remove_line(type, key, value)
|
|
154
125
|
end
|
|
155
126
|
|
|
156
127
|
# experimental
|
|
157
128
|
def remove_line_at(type, pos)
|
|
158
|
-
|
|
129
|
+
@native.remove_line_at(type, pos)
|
|
159
130
|
end
|
|
160
131
|
|
|
161
132
|
def delete_line(type, key = nil, value = nil)
|
|
162
|
-
|
|
133
|
+
@native.remove_line(type, key, value).zero?
|
|
163
134
|
end
|
|
164
135
|
|
|
165
136
|
def delete_tag(type, id_key, id_value, key)
|
|
166
|
-
|
|
137
|
+
@native.remove_tag(type, id_key, id_value, key) == 1
|
|
167
138
|
end
|
|
168
139
|
|
|
169
140
|
def count_lines(type)
|
|
170
|
-
|
|
141
|
+
@native.count_lines(type)
|
|
171
142
|
end
|
|
172
143
|
|
|
173
144
|
def line_index(type, key)
|
|
174
|
-
|
|
145
|
+
@native.line_index(type, key)
|
|
175
146
|
end
|
|
176
147
|
|
|
177
148
|
def line_name(type, pos)
|
|
178
|
-
|
|
149
|
+
@native.line_name(type, pos)
|
|
179
150
|
end
|
|
180
151
|
|
|
181
152
|
def to_s
|
|
182
|
-
|
|
153
|
+
@native.to_s
|
|
183
154
|
end
|
|
184
155
|
|
|
185
156
|
# experimental
|
|
@@ -241,7 +212,7 @@ module HTS
|
|
|
241
212
|
# header.add_pg("samtools", VN: "1.15", PP: "bwa")
|
|
242
213
|
def add_pg(program_name, **options)
|
|
243
214
|
line = build_pg_line(program_name.to_s, options)
|
|
244
|
-
result =
|
|
215
|
+
result = @native.add_lines(line)
|
|
245
216
|
raise "Failed to add @PG line" if result < 0
|
|
246
217
|
|
|
247
218
|
self
|
|
@@ -418,26 +389,28 @@ module HTS
|
|
|
418
389
|
end
|
|
419
390
|
|
|
420
391
|
def name2tid(name)
|
|
421
|
-
|
|
392
|
+
@native.name2tid(name)
|
|
422
393
|
end
|
|
423
394
|
|
|
424
395
|
def tid2name(tid)
|
|
425
|
-
|
|
396
|
+
@native.target_name(tid)
|
|
426
397
|
end
|
|
427
398
|
|
|
428
399
|
def add_lines(str)
|
|
429
|
-
|
|
400
|
+
@native.add_lines(str)
|
|
430
401
|
end
|
|
431
402
|
|
|
432
403
|
def add_line(*args)
|
|
433
404
|
type = args.shift
|
|
434
|
-
|
|
435
|
-
|
|
405
|
+
pairs = args.each_slice(2).map { |key, value| "#{key}:#{value}" }
|
|
406
|
+
@native.add_lines("@#{type}\t#{pairs.join("\t")}\n")
|
|
436
407
|
end
|
|
437
408
|
|
|
438
409
|
def initialize_copy(orig)
|
|
439
|
-
@
|
|
410
|
+
@native = orig.__send__(:native_handle).duplicate
|
|
440
411
|
end
|
|
412
|
+
|
|
413
|
+
def native_handle = @native
|
|
441
414
|
end
|
|
442
415
|
end
|
|
443
416
|
end
|