htslib 0.2.8 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: caaf2dd527c9570e2e4c72b22e5252a1ef69adbf983fbfe3e815c3a9bc1b91c0
4
- data.tar.gz: b7e0b6ecf736142ea9b43e4ed7f80513b1c0d002ea40b2565e218be3a40d2fac
3
+ metadata.gz: ea68a4c331c9a404cfce2bf86fea386985e96ee3b76ae25e9d9b701593294880
4
+ data.tar.gz: d826e59f66e20bc40bc47c2033295abe2b3aceab8cb9d5af3d4d41309e448732
5
5
  SHA512:
6
- metadata.gz: 6fe725489c93915fc5afa5d58dd2a5a0030b82546f473b6cae4245898b01f60919494d64b31f3442c3ea316a25fb31c0b46cfdd447230c253c21818ca3da9fb8
7
- data.tar.gz: f5bed585f7bded73022ea0ad9a1dc2eb6a10c13e63772cac267a3c23497b521d82d5ab82763e512b452d47f59be8c47dcf5ff2046c96dcc492604931799cf2b2
6
+ metadata.gz: 646dca4eb44c96a67020f57a090c26715b003521c9c6afffad1becf031576c334ea03c99b61f795a35932935535c53a1899a960ab986480cb3f5eef5b9913b96
7
+ data.tar.gz: e1cc5d9357932e04cebae1aaa5a8dc7024e0755584ea21999b18004dba76726c10b23276ee6d98fc1580ffb5aad45aeb12fd3e1bf94cfc45fdee70aefda87f91
data/README.md CHANGED
@@ -1,11 +1,14 @@
1
1
  # ruby-htslib
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/htslib.svg)](https://badge.fury.io/rb/htslib)
4
- ![CI](https://github.com/kojix2/ruby-htslib/workflows/CI/badge.svg)
4
+ [![test](https://github.com/kojix2/ruby-htslib/actions/workflows/ci.yml/badge.svg)](https://github.com/kojix2/ruby-htslib/actions/workflows/ci.yml)
5
5
  [![The MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.txt)
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
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/kojix2/ruby-htslib)
10
+ [![Lines of Code](https://img.shields.io/endpoint?url=https%3A%2F%2Ftokei.kojix2.net%2Fbadge%2Fgithub%2Fkojix2%2Fruby-htslib%2Flines)](https://tokei.kojix2.net/github/kojix2/ruby-htslib)
11
+
9
12
  Ruby-htslib is the [Ruby](https://www.ruby-lang.org) bindings to [HTSlib](https://github.com/samtools/htslib), a C library for high-throughput sequencing data formats. It allows you to read and write file formats commonly used in genomics, such as [SAM, BAM, VCF, and BCF](http://samtools.github.io/hts-specs/), in the Ruby language.
10
13
 
11
14
  :apple: Feel free to fork it!
@@ -162,6 +165,8 @@ Try Crystal. [HTS.cr](https://github.com/bio-cr/hts.cr) is implemented in Crysta
162
165
 
163
166
  ## Development
164
167
 
168
+ ![Diagram](diagram.svg)
169
+
165
170
  #### Compile from source code
166
171
 
167
172
  [GNU Autotools](https://en.wikipedia.org/wiki/GNU_Autotools) is required to compile htslib.
data/lib/hts/bam/auxi.rb CHANGED
@@ -30,10 +30,10 @@ module HTS
30
30
  # which provides methods like `get_int`, `get_float`, etc.
31
31
  # I think they are better than `fetch_int`` and `fetch_float`.
32
32
  def get(key, type = nil)
33
- aux = LibHTS.bam_aux_get(@record.struct, key)
34
- return nil if aux.null?
33
+ aux_ptr = LibHTS.bam_aux_get(@record.struct, key)
34
+ return nil if aux_ptr.null?
35
35
 
36
- get_ruby_aux(aux, type)
36
+ get_ruby_aux(aux_ptr, type)
37
37
  end
38
38
 
39
39
  # For compatibility with HTS.cr.
@@ -56,43 +56,47 @@ module HTS
56
56
  end
57
57
 
58
58
  def first
59
- aux = LibHTS.bam_aux_first(@record.struct)
60
- return nil if aux.null?
59
+ aux_ptr = first_pointer
60
+ return nil if aux_ptr.null?
61
61
 
62
- get_ruby_aux(aux)
62
+ get_ruby_aux(aux_ptr)
63
63
  end
64
64
 
65
65
  def each
66
66
  return enum_for(__method__) unless block_given?
67
67
 
68
- aux = LibHTS.bam_aux_first(@record.struct)
69
- return nil if aux.null?
68
+ aux_ptr = first_pointer
69
+ return nil if aux_ptr.null?
70
70
 
71
71
  loop do
72
- yield get_ruby_aux(aux)
73
- aux = LibHTS.bam_aux_next(@record.struct, aux)
74
- break if aux.null?
72
+ yield get_ruby_aux(aux_ptr)
73
+ aux_ptr = LibHTS.bam_aux_next(@record.struct, aux_ptr)
74
+ break if aux_ptr.null?
75
75
  end
76
76
  end
77
77
 
78
78
  def to_h
79
79
  h = {}
80
- aux = LibHTS.bam_aux_first(@record.struct)
81
- return h if aux.null?
80
+ aux_ptr = first_pointer
81
+ return h if aux_ptr.null?
82
82
 
83
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?
84
+ key = FFI::Pointer.new(aux_ptr.address - 2).read_string(2)
85
+ h[key] = get_ruby_aux(aux_ptr)
86
+ aux_ptr = LibHTS.bam_aux_next(@record.struct, aux_ptr)
87
+ break if aux_ptr.null?
88
88
  end
89
89
  h
90
90
  end
91
91
 
92
92
  private
93
93
 
94
- def get_ruby_aux(aux, type = nil)
95
- type = type ? type.to_s : aux.read_string(1)
94
+ def first_pointer
95
+ LibHTS.bam_aux_first(@record.struct)
96
+ end
97
+
98
+ def get_ruby_aux(aux_ptr, type = nil)
99
+ type = type ? type.to_s : aux_ptr.read_string(1)
96
100
 
97
101
  # A (character), B (general array),
98
102
  # f (real number), H (hexadecimal array),
@@ -100,23 +104,23 @@ module HTS
100
104
 
101
105
  case type
102
106
  when "i", "I", "c", "C", "s", "S"
103
- LibHTS.bam_aux2i(aux)
107
+ LibHTS.bam_aux2i(aux_ptr)
104
108
  when "f", "d"
105
- LibHTS.bam_aux2f(aux)
109
+ LibHTS.bam_aux2f(aux_ptr)
106
110
  when "Z", "H"
107
- LibHTS.bam_aux2Z(aux)
111
+ LibHTS.bam_aux2Z(aux_ptr)
108
112
  when "A" # char
109
- LibHTS.bam_aux2A(aux).chr
113
+ LibHTS.bam_aux2A(aux_ptr).chr
110
114
  when "B" # array
111
- t2 = aux.read_string(2)[1] # just a little less efficient
112
- l = LibHTS.bam_auxB_len(aux)
115
+ t2 = aux_ptr.read_string(2)[1] # just a little less efficient
116
+ l = LibHTS.bam_auxB_len(aux_ptr)
113
117
  case t2
114
118
  when "c", "C", "s", "S", "i", "I"
115
119
  # FIXME : Not efficient.
116
- Array.new(l) { |i| LibHTS.bam_auxB2i(aux, i) }
120
+ Array.new(l) { |i| LibHTS.bam_auxB2i(aux_ptr, i) }
117
121
  when "f", "d"
118
122
  # FIXME : Not efficient.
119
- Array.new(l) { |i| LibHTS.bam_auxB2f(aux, i) }
123
+ Array.new(l) { |i| LibHTS.bam_auxB2f(aux_ptr, i) }
120
124
  else
121
125
  raise NotImplementedError, "type: #{type} #{t2}"
122
126
  end
data/lib/hts/bam/flag.rb CHANGED
@@ -69,27 +69,29 @@ module HTS
69
69
  end
70
70
 
71
71
  def &(other)
72
- Flag.new(@value & other.to_i)
72
+ self.class.new(@value & other.to_i)
73
73
  end
74
74
 
75
75
  def |(other)
76
- Flag.new(@value | other.to_i)
76
+ self.class.new(@value | other.to_i)
77
77
  end
78
78
 
79
79
  def ^(other)
80
- Flag.new(@value ^ other.to_i)
80
+ self.class.new(@value ^ other.to_i)
81
81
  end
82
82
 
83
83
  def ~
84
- Flag.new(~@value)
84
+ # FIXME: Only 12bits are used for flags
85
+ # The result is different from the Crystal version.
86
+ self.class.new(~@value)
85
87
  end
86
88
 
87
89
  def <<(f)
88
- Flag.new(@value << f.to_i)
90
+ self.class.new(@value << f.to_i)
89
91
  end
90
92
 
91
93
  def >>(other)
92
- Flag.new(@value >> other.to_i)
94
+ self.class.new(@value >> other.to_i)
93
95
  end
94
96
 
95
97
  def to_i
@@ -6,8 +6,8 @@ module HTS
6
6
  class Bam < Hts
7
7
  # A class for working with alignment header.
8
8
  class Header
9
- def self.parse(str)
10
- new(LibHTS.sam_hdr_parse(str.size, str))
9
+ def self.parse(text)
10
+ new(LibHTS.sam_hdr_parse(text.size, text))
11
11
  end
12
12
 
13
13
  def initialize(arg = nil)
@@ -21,6 +21,8 @@ module HTS
21
21
  else
22
22
  raise TypeError, "Invalid argument"
23
23
  end
24
+
25
+ yield self if block_given?
24
26
  end
25
27
 
26
28
  def struct
@@ -31,11 +33,23 @@ module HTS
31
33
  @sam_hdr.to_ptr
32
34
  end
33
35
 
36
+ def targets
37
+ Array.new(target_count) do |i|
38
+ name = LibHTS.sam_hdr_tid2name(@sam_hdr, i)
39
+ len = LibHTS.sam_hdr_tid2len(@sam_hdr, i)
40
+ { name:, len: }
41
+ end
42
+ end
43
+
34
44
  def target_count
35
45
  # FIXME: sam_hdr_nref
36
46
  @sam_hdr[:n_targets]
37
47
  end
38
48
 
49
+ def target_name(tid)
50
+ tid2name(tid)
51
+ end
52
+
39
53
  def target_names
40
54
  Array.new(target_count) do |i|
41
55
  LibHTS.sam_hdr_tid2name(@sam_hdr, i)
@@ -48,15 +62,20 @@ module HTS
48
62
  end
49
63
  end
50
64
 
51
- # experimental
52
- def add_lines(str)
53
- LibHTS.sam_hdr_add_lines(@sam_hdr, str, 0)
65
+ def write(...)
66
+ add_lines(...)
54
67
  end
55
68
 
56
69
  # experimental
57
- def add_line(type, *args)
58
- args = args.flat_map { |arg| [:string, arg] }
59
- LibHTS.sam_hdr_add_line(@sam_hdr, type, *args, :pointer, FFI::Pointer::NULL)
70
+ def <<(obj)
71
+ case obj
72
+ when Array, Hash
73
+ args = obj.flatten(-1).map { |i| i.to_a if i.is_a?(Hash) }
74
+ add_line(*args)
75
+ else
76
+ add_lines(obj.to_s)
77
+ end
78
+ self
60
79
  end
61
80
 
62
81
  # experimental
@@ -87,6 +106,13 @@ module HTS
87
106
  LibHTS.sam_hdr_str(@sam_hdr)
88
107
  end
89
108
 
109
+ # experimental
110
+ def get_tid(name)
111
+ name2tid(name)
112
+ end
113
+
114
+ private
115
+
90
116
  def name2tid(name)
91
117
  LibHTS.sam_hdr_name2tid(@sam_hdr, name)
92
118
  end
@@ -95,7 +121,15 @@ module HTS
95
121
  LibHTS.sam_hdr_tid2name(@sam_hdr, tid)
96
122
  end
97
123
 
98
- private
124
+ def add_lines(str)
125
+ LibHTS.sam_hdr_add_lines(@sam_hdr, str, 0)
126
+ end
127
+
128
+ def add_line(*args)
129
+ type = args.shift
130
+ args = args.flat_map { |arg| [:string, arg] }
131
+ LibHTS.sam_hdr_add_line(@sam_hdr, type, *args, :pointer, FFI::Pointer::NULL)
132
+ end
99
133
 
100
134
  def initialize_copy(orig)
101
135
  @sam_hdr = LibHTS.sam_hdr_dup(orig.struct)
@@ -12,9 +12,64 @@ module HTS
12
12
 
13
13
  attr_reader :header
14
14
 
15
- def initialize(header, bam1_t = nil)
16
- @bam1 = bam1_t || LibHTS.bam_init1
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.
@@ -158,6 +213,17 @@ module HTS
158
213
  Cigar.new(self)
159
214
  end
160
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
+
161
227
  # Calculate query length from CIGAR.
162
228
  # @return [Integer] query length
163
229
  def qlen
data/lib/hts/bam.rb CHANGED
@@ -7,6 +7,8 @@ require_relative "bam/header"
7
7
  require_relative "bam/cigar"
8
8
  require_relative "bam/flag"
9
9
  require_relative "bam/record"
10
+ # require_relative "bam/pileup"
11
+ # require_relative "bam/pileup_entry"
10
12
 
11
13
  module HTS
12
14
  # A class for working with SAM, BAM, CRAM files.
@@ -30,7 +32,7 @@ module HTS
30
32
  def initialize(file_name, mode = "r", index: nil, fai: nil, threads: nil,
31
33
  build_index: false)
32
34
  if block_given?
33
- message = "HTS::Bam.new() dose not take block; Please use HTS::Bam.open() instead"
35
+ message = "HTS::Bam.new() does not take block; Please use HTS::Bam.open() instead"
34
36
  raise message
35
37
  end
36
38
 
@@ -44,6 +46,17 @@ module HTS
44
46
 
45
47
  raise Errno::ENOENT, "Failed to open #{@file_name}" if @hts_file.null?
46
48
 
49
+ # Auto-detect and set reference for CRAM files
50
+ if fai.nil? && @file_name.end_with?(".cram")
51
+ # Try to find reference file in the same directory
52
+ base_name = File.basename(@file_name, ".cram")
53
+ dir_name = File.dirname(@file_name)
54
+ potential_ref = File.join(dir_name, "#{base_name}.fa")
55
+
56
+ # For remote URLs, assume reference exists; for local files, check existence
57
+ fai = potential_ref if @file_name.start_with?("http") || File.exist?(potential_ref)
58
+ end
59
+
47
60
  if fai
48
61
  r = LibHTS.hts_set_fai_filename(@hts_file, fai)
49
62
  raise "Failed to load fasta index: #{fai}" if r < 0
@@ -67,7 +80,7 @@ module HTS
67
80
  else
68
81
  warn "Create index for #{@file_name}"
69
82
  end
70
- case LibHTS.sam_index_build3(@file_name, index_name, min_shift, (@nthreads || threads))
83
+ case LibHTS.sam_index_build3(@file_name, index_name, min_shift, @nthreads || threads)
71
84
  when 0 # successful
72
85
  when -1 then raise "indexing failed"
73
86
  when -2 then raise "opening #{@file_name} failed"
@@ -95,7 +108,7 @@ module HTS
95
108
  end
96
109
 
97
110
  def close
98
- LibHTS.hts_idx_destroy(@idx) if @idx&.null?
111
+ LibHTS.hts_idx_destroy(@idx) if @idx && !@idx.null?
99
112
  @idx = nil
100
113
  super
101
114
  end
@@ -141,7 +154,7 @@ module HTS
141
154
  alias isize insert_size
142
155
  alias mpos mate_pos
143
156
 
144
- # FXIME: experimental
157
+ # FIXME: experimental
145
158
  def aux(tag)
146
159
  check_closed
147
160
 
@@ -194,7 +207,7 @@ module HTS
194
207
  raise "Index file is required to call the query method." unless index_loaded?
195
208
 
196
209
  if beg && end_
197
- tid = header.name2tid(region)
210
+ tid = header.get_tid(region)
198
211
  queryi(tid, beg, end_, copy:, &block)
199
212
  elsif beg.nil? && end_.nil?
200
213
  querys(region, copy:, &block)
@@ -203,6 +216,10 @@ module HTS
203
216
  end
204
217
  end
205
218
 
219
+ # def pileup
220
+ # Pileup.new(self)
221
+ # end
222
+
206
223
  private
207
224
 
208
225
  def queryi(tid, beg, end_, copy: false, &block)
@@ -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
data/lib/hts/bcf.rb CHANGED
@@ -30,7 +30,7 @@ module HTS
30
30
  def initialize(file_name, mode = "r", index: nil, threads: nil,
31
31
  build_index: false)
32
32
  if block_given?
33
- message = "HTS::Bcf.new() dose not take block; Please use HTS::Bcf.open() instead"
33
+ message = "HTS::Bcf.new() does not take block; Please use HTS::Bcf.open() instead"
34
34
  raise message
35
35
  end
36
36
 
@@ -62,7 +62,7 @@ module HTS
62
62
  else
63
63
  warn "Create index for #{@file_name}"
64
64
  end
65
- case LibHTS.bcf_index_build3(@file_name, index_name, min_shift, (@nthreads || threads))
65
+ case LibHTS.bcf_index_build3(@file_name, index_name, min_shift, @nthreads || threads)
66
66
  when 0 # successful
67
67
  when -1 then raise "indexing failed"
68
68
  when -2 then raise "opening #{@file_name} failed"
@@ -90,7 +90,7 @@ module HTS
90
90
  end
91
91
 
92
92
  def close
93
- LibHTS.hts_idx_destroy(@idx) unless @idx&.null?
93
+ LibHTS.hts_idx_destroy(@idx) if @idx && !@idx.null?
94
94
  @idx = nil
95
95
  super
96
96
  end
@@ -185,7 +185,7 @@ module HTS
185
185
 
186
186
  def each_info(key)
187
187
  check_closed
188
- return to_enum(__method__, key) unless block
188
+ return to_enum(__method__, key) unless block_given?
189
189
 
190
190
  each do |r|
191
191
  yield r.info(key)
@@ -194,7 +194,7 @@ module HTS
194
194
 
195
195
  def each_format(key)
196
196
  check_closed
197
- return to_enum(__method__, key) unless block
197
+ return to_enum(__method__, key) unless block_given?
198
198
 
199
199
  each do |r|
200
200
  yield r.format(key)
data/lib/hts/faidx.rb CHANGED
@@ -21,7 +21,7 @@ module HTS
21
21
 
22
22
  def initialize(file_name)
23
23
  if block_given?
24
- message = "HTS::Faidx.new() dose not take block; Please use HTS::Faidx.open() instead"
24
+ message = "HTS::Faidx.new() does not take block; Please use HTS::Faidx.open() instead"
25
25
  raise message
26
26
  end
27
27
 
@@ -158,7 +158,7 @@ module HTS
158
158
  :specific, :pointer
159
159
  end
160
160
 
161
- class HtsIdx < FFI::Struct # FIXME: ManagedStruct
161
+ class HtsIdx < FFI::Struct
162
162
  layout \
163
163
  :fmt, :int,
164
164
  :min_shift, :int,
@@ -189,9 +189,9 @@ module HTS
189
189
  :n_unmapped, :uint64
190
190
  )
191
191
 
192
- def self.release(ptr)
193
- LibHTS.hts_idx_destroy(ptr) unless ptr.null?
194
- end
192
+ # def self.release(ptr)
193
+ # LibHTS.hts_idx_destroy(ptr) unless ptr.null?
194
+ # end
195
195
  end
196
196
 
197
197
  class HtsReglist < FFI::Struct
@@ -379,6 +379,10 @@ module HTS
379
379
  :is_refskip, 1,
380
380
  :_reserved, 1,
381
381
  :aux, 27
382
+
383
+ # def self.release(ptr)
384
+ # LibHTS.bam_plp_destroy(ptr) unless ptr.null?
385
+ # end
382
386
  end
383
387
 
384
388
  class TbxConf < FFI::Struct
@@ -570,5 +574,18 @@ module HTS
570
574
  :external, 4,
571
575
  :core, 5
572
576
  )
577
+
578
+ CramBlockMethod = enum(
579
+ :unknown, -1,
580
+ :raw, 0,
581
+ :gzip, 1,
582
+ :bzip2, 2,
583
+ :lzma, 3,
584
+ :rans4x8, 4,
585
+ :ransnx16, 5,
586
+ :arith, 6,
587
+ :fqz, 7,
588
+ :tok3, 8
589
+ )
573
590
  end
574
591
  end
@@ -79,12 +79,27 @@ module HTS
79
79
  %i[cram_container int32 pointer],
80
80
  :void
81
81
 
82
+ attach_function \
83
+ :cram_container_get_num_records,
84
+ [:cram_container],
85
+ :int32
86
+
87
+ attach_function \
88
+ :cram_container_get_num_bases,
89
+ [:cram_container],
90
+ :int32
91
+
92
+ # Returns true if the container is empty (EOF marker)
82
93
  attach_function \
83
94
  :cram_container_is_empty,
84
95
  [:cram_fd],
85
96
  :int
86
97
 
87
- # cram_block
98
+ # Returns chromosome and start/span from container struct
99
+ attach_function \
100
+ :cram_container_get_coords,
101
+ %i[cram_container pointer pointer],
102
+ :void
88
103
 
89
104
  attach_function \
90
105
  :cram_block_get_content_id,
@@ -116,6 +131,16 @@ module HTS
116
131
  [:cram_block],
117
132
  CramContentType
118
133
 
134
+ attach_function \
135
+ :cram_block_get_method,
136
+ [:cram_block],
137
+ CramBlockMethod
138
+
139
+ attach_function \
140
+ :cram_expand_method,
141
+ [:pointer, :int32, CramBlockMethod],
142
+ :pointer
143
+
119
144
  attach_function \
120
145
  :cram_block_set_content_id,
121
146
  %i[cram_block int32],
@@ -167,6 +192,18 @@ module HTS
167
192
  [:cram_block],
168
193
  :uint32
169
194
 
195
+ # Returns the Block Content ID values referred to by a cram_codec in ids[2].
196
+ attach_function \
197
+ :cram_codec_get_content_ids,
198
+ %i[pointer pointer],
199
+ :void
200
+
201
+ # Produces a human readable description of the codec parameters.
202
+ attach_function \
203
+ :cram_codec_describe,
204
+ [:pointer, KString.ptr],
205
+ :int
206
+
170
207
  # Renumbers RG numbers in a cram compression header.
171
208
  attach_function \
172
209
  :cram_transcode_rg,
@@ -180,6 +217,51 @@ module HTS
180
217
  %i[cram_fd cram_fd int32],
181
218
  :int
182
219
 
220
+ # Copies a container, but filtering it down to a specific region (as
221
+ # already specified in 'in'
222
+ attach_function \
223
+ :cram_filter_container,
224
+ %i[cram_fd cram_fd cram_container pointer],
225
+ :int
226
+
227
+ # Decodes a CRAM block compression header.
228
+ attach_function \
229
+ :cram_decode_compression_header,
230
+ %i[cram_fd cram_block],
231
+ :pointer # cram_block_compression_hdr
232
+
233
+ # Frees a cram_block_compression_hdr structure.
234
+ attach_function \
235
+ :cram_free_compression_header,
236
+ [:pointer],
237
+ :void
238
+
239
+ # Map cram block numbers to data-series.
240
+ attach_function \
241
+ :cram_update_cid2ds_map,
242
+ %i[pointer pointer],
243
+ :pointer
244
+
245
+ # Return a list of data series observed as belonging to a block with
246
+ # the specified content_id.
247
+ attach_function \
248
+ :cram_cid2ds_query,
249
+ %i[pointer int pointer],
250
+ :int
251
+
252
+ # Frees a cram_cid2ds_t allocated by cram_update_cid2ds_map
253
+ attach_function \
254
+ :cram_cid2ds_free,
255
+ [:pointer],
256
+ :void
257
+
258
+ # Produces a description of the record and tag encodings held within
259
+ # a compression header and appends to 'ks'.
260
+ attach_function \
261
+ :cram_describe_encodings,
262
+ [:pointer, KString.ptr],
263
+ :int
264
+
183
265
  # Returns the number of cram blocks within this slice.
184
266
  attach_function \
185
267
  :cram_slice_hdr_get_num_blocks,
@@ -360,5 +442,35 @@ module HTS
360
442
  :cram_get_refs,
361
443
  [HtsFile.by_ref],
362
444
  :pointer # refs_t
445
+
446
+ # Returns the file offsets of CRAM slices covering a specific region query.
447
+ attach_function \
448
+ :cram_index_extents,
449
+ %i[cram_fd int hts_pos_t hts_pos_t pointer pointer],
450
+ :int
451
+
452
+ # Returns the total number of containers in the CRAM index.
453
+ attach_function \
454
+ :cram_num_containers,
455
+ [:cram_fd],
456
+ :int64
457
+
458
+ # Returns the number of containers in the CRAM index within given offsets.
459
+ attach_function \
460
+ :cram_num_containers_between,
461
+ %i[cram_fd off_t off_t pointer pointer],
462
+ :int64
463
+
464
+ # Returns the byte offset for the start of the n^th container.
465
+ attach_function \
466
+ :cram_container_num2offset,
467
+ %i[cram_fd int64],
468
+ :off_t
469
+
470
+ # Returns the container number for the first container at offset >= pos.
471
+ attach_function \
472
+ :cram_container_offset2num,
473
+ %i[cram_fd off_t],
474
+ :int64
363
475
  end
364
476
  end
@@ -447,7 +447,7 @@ module HTS
447
447
  # Computes the final 128-bit MD5 hash from the given context
448
448
  attach_function \
449
449
  :hts_md5_final,
450
- %i[pointer pointer], # unsinged char
450
+ %i[pointer pointer], # unsigned char
451
451
  :void
452
452
 
453
453
  # Resets an md5_context to the initial state, as returned by hts_md5_init().
@@ -247,7 +247,7 @@ module HTS
247
247
  :hts_pos_t,
248
248
  :uint8,
249
249
  :size_t,
250
- :string,
250
+ :pointer,
251
251
  :int32,
252
252
  :hts_pos_t,
253
253
  :hts_pos_t,
@@ -512,6 +512,12 @@ module HTS
512
512
  [Bam1, :pointer],
513
513
  :int
514
514
 
515
+ # Delete an aux field from a BAM record. Identical to @c bam_aux_del() apart from the return value
516
+ attach_function \
517
+ :bam_aux_remove,
518
+ [Bam1, :pointer],
519
+ :pointer
520
+
515
521
  # Update or add a string-type tag
516
522
  attach_function \
517
523
  :bam_aux_update_str,
@@ -674,12 +680,18 @@ module HTS
674
680
  [:pointer], # hts_base_mod_state
675
681
  :void
676
682
 
677
- # Parses the Mm and Ml tags out of a bam record.
683
+ # Parses the MM and ML tags out of a bam record.
678
684
  attach_function \
679
685
  :bam_parse_basemod,
680
686
  [Bam1, :pointer],
681
687
  :int
682
688
 
689
+ # Parses the MM and ML tags out of a bam record.
690
+ attach_function \
691
+ :bam_parse_basemod2,
692
+ [Bam1, :pointer, :uint32],
693
+ :int
694
+
683
695
  # Returns modification status for the next base position in the query seq.
684
696
  attach_function \
685
697
  :bam_mods_at_next_pos,
@@ -704,6 +716,12 @@ module HTS
704
716
  %i[pointer int pointer pointer string],
705
717
  :int
706
718
 
719
+ # Returns data about the i^th modification type for the alignment record.
720
+ attach_function \
721
+ :bam_mods_queryi,
722
+ %i[pointer int pointer pointer string],
723
+ :int
724
+
707
725
  # Returns the list of base modification codes provided for this
708
726
  attach_function \
709
727
  :bam_mods_recorded,
@@ -105,7 +105,7 @@ module HTS
105
105
 
106
106
  # Modifies a single base in the bam structure.
107
107
  def bam_set_seqi(s, i, b)
108
- s[i >> 1] = (s[i >> 1] & (0xf0 >> ((~i & 1) << 2))) | ((b) << ((~i & 1) << 2))
108
+ s[i >> 1] = (s[i >> 1] & (0xf0 >> ((~i & 1) << 2))) | (b << ((~i & 1) << 2))
109
109
  end
110
110
 
111
111
  # Returns the SAM formatted text of the \@HD header line
@@ -2,6 +2,13 @@
2
2
 
3
3
  module HTS
4
4
  module LibHTS
5
+ attach_variable :tbx_conf_gff, TbxConf
6
+ attach_variable :tbx_conf_bed, TbxConf
7
+ attach_variable :tbx_conf_psltbl, TbxConf
8
+ attach_variable :tbx_conf_sam, TbxConf
9
+ attach_variable :tbx_conf_vcf, TbxConf
10
+ attach_variable :tbx_conf_gaf, TbxConf
11
+
5
12
  attach_function \
6
13
  :tbx_name2id,
7
14
  [Tbx, :string],
@@ -8,11 +8,16 @@ module HTS
8
8
  end
9
9
 
10
10
  def tbx_itr_queryi(tbx, tid, beg, end_)
11
- hts_itr_query(tbx[:idx], tid, beg, end_, @@tbx_readrec)
11
+ hts_itr_query(tbx[:idx], tid, beg, end_, @ffi_functions[:tbx_readrec])
12
+ end
13
+
14
+ @@tbx_name2id = proc do |tbx, ss|
15
+ LibHTS.tbx_name2id(tbx, ss)
12
16
  end
13
17
 
14
18
  def tbx_itr_querys(tbx, s)
15
- hts_itr_querys(tbx[:idx], s, @@tbx_name2id, tbx, @@hts_itr_query, @@tbx_readrec)
19
+ hts_itr_querys(tbx[:idx], s, @@tbx_name2id, tbx, @ffi_functions[:hts_itr_query],
20
+ @ffi_functions[:tbx_readrec])
16
21
  end
17
22
 
18
23
  def tbx_itr_next(htsfp, tbx, itr, r)
@@ -2,6 +2,12 @@
2
2
 
3
3
  module HTS
4
4
  module LibHTS
5
+ # Get error description for bcf error code
6
+ attach_function \
7
+ :bcf_strerror,
8
+ %i[int pointer size_t],
9
+ :string
10
+
5
11
  # Create an empty BCF header.
6
12
  attach_function \
7
13
  :bcf_hdr_init,
@@ -167,7 +167,7 @@ module HTS
167
167
 
168
168
  # Conversion between alleles indexes to Number=G genotype index (assuming diploid, all 0-based)
169
169
  def bcf_alleles2gt(a, b)
170
- ((a) > (b) ? (a * (a + 1) / 2 + b) : (b * (b + 1) / 2 + a))
170
+ (a > b ? (a * (a + 1) / 2 + b) : (b * (b + 1) / 2 + a))
171
171
  end
172
172
 
173
173
  # Get INFO values
@@ -272,7 +272,7 @@ module HTS
272
272
  alias bcf_itr_destroy hts_itr_destroy
273
273
 
274
274
  def bcf_itr_queryi(idx, tid, beg, _end)
275
- hts_itr_query(idx, tid, beg, _end, @@bcf_readrec)
275
+ hts_itr_query(idx, tid, beg, _end, @ffi_functions[:bcf_readrec])
276
276
  end
277
277
 
278
278
  @@bcf_hdr_name2id = proc do |hdr, id|
@@ -280,7 +280,7 @@ module HTS
280
280
  end
281
281
 
282
282
  def bcf_itr_querys(idx, hdr, s)
283
- hts_itr_querys(idx, s, @@bcf_hdr_name2id, hdr, @@hts_itr_query, @@bcf_readrec)
283
+ hts_itr_querys(idx, s, @@bcf_hdr_name2id, hdr, @ffi_functions[:hts_itr_query], @ffi_functions[:bcf_readrec])
284
284
  end
285
285
 
286
286
  # Load a BCF index
data/lib/hts/tabix.rb CHANGED
@@ -24,7 +24,7 @@ module HTS
24
24
 
25
25
  def initialize(file_name, index: nil, threads: nil, build_index: false)
26
26
  if block_given?
27
- message = "HTS::Tabix.new() dose not take block; Please use HTS::Tabix.open() instead"
27
+ message = "HTS::Tabix.new() does not take block; Please use HTS::Tabix.open() instead"
28
28
  raise message
29
29
  end
30
30
 
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.8"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: htslib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - kojix2
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-05-17 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: ffi
@@ -52,77 +51,6 @@ dependencies:
52
51
  - - ">="
53
52
  - !ruby/object:Gem::Version
54
53
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: bundler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: irb
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: minitest
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: rake
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: simplecov
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- description:
126
54
  email:
127
55
  - 2xijok@gmail.com
128
56
  executables: []
@@ -174,7 +102,6 @@ licenses:
174
102
  - MIT
175
103
  metadata:
176
104
  msys2_mingw_dependencies: htslib
177
- post_install_message:
178
105
  rdoc_options: []
179
106
  require_paths:
180
107
  - lib
@@ -189,8 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
116
  - !ruby/object:Gem::Version
190
117
  version: '0'
191
118
  requirements: []
192
- rubygems_version: 3.4.10
193
- signing_key:
119
+ rubygems_version: 3.7.1
194
120
  specification_version: 4
195
121
  summary: HTSlib bindings for Ruby
196
122
  test_files: []