htslib 0.0.8 → 0.0.10

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.
data/lib/hts/hts.rb ADDED
@@ -0,0 +1,56 @@
1
+ require_relative "../htslib"
2
+
3
+ module HTS
4
+ class Hts
5
+ def struct
6
+ @hts_file
7
+ end
8
+
9
+ def to_ptr
10
+ @hts_file.to_ptr
11
+ end
12
+
13
+ def format
14
+ LibHTS.hts_get_format(@hts_file)[:format].to_s
15
+ end
16
+
17
+ def format_version
18
+ v = LibHTS.hts_get_format(@hts_file)[:version]
19
+ major = v[:major]
20
+ minor = v[:minor]
21
+ if minor == -1
22
+ major.to_s
23
+ else
24
+ "#{major}.#{minor}"
25
+ end
26
+ end
27
+
28
+ def seek(offset)
29
+ if @hts_file[:is_cram] == 1
30
+ LibHTS.cram_seek(@hts_file[:fp][:cram], offset, IO::SEEK_SET)
31
+ elsif @hts_file[:is_bgzf] == 1
32
+ LibHTS.bgzf_seek(@hts_file[:fp][:bgzf], offset, IO::SEEK_SET)
33
+ else
34
+ LibHTS.hseek(@hts_file[:fp][:hfile], offset, IO::SEEK_SET)
35
+ end
36
+ end
37
+
38
+ def tell
39
+ if @hts_file[:is_cram] == 1
40
+ # LibHTS.cram_tell(@hts_file[:fp][:cram])
41
+ # warn 'cram_tell is not implemented in c htslib'
42
+ nil
43
+ elsif @hts_file[:is_bgzf] == 1
44
+ LibHTS.bgzf_tell(@hts_file[:fp][:bgzf])
45
+ else
46
+ LibHTS.htell(@hts_file[:fp][:hfile])
47
+ end
48
+ end
49
+
50
+ def rewind
51
+ r = seek(@start_position) if @start_position
52
+ raise "Failed to rewind: #{r}" if r < 0
53
+ r
54
+ end
55
+ end
56
+ end
@@ -18,19 +18,19 @@ module HTS
18
18
  # Open an existing hFILE stream for reading or writing.
19
19
  attach_function \
20
20
  :bgzf_hopen,
21
- %i[HFILE string],
21
+ [HFILE, :string],
22
22
  BGZF.by_ref
23
23
 
24
24
  # Close the BGZF and free all associated resources.
25
25
  attach_function \
26
26
  :bgzf_close,
27
- [:HFILE],
27
+ [HFILE],
28
28
  :int
29
29
 
30
30
  # Read up to _length_ bytes from the file storing into _data_.
31
31
  attach_function \
32
32
  :bgzf_read,
33
- %i[HFILE pointer size_t],
33
+ [HFILE, :pointer, :size_t],
34
34
  :ssize_t
35
35
 
36
36
  # Write _length_ bytes from _data_ to the file. If no I/O errors occur,
@@ -75,6 +75,11 @@ module HTS
75
75
  [BGZF],
76
76
  :int
77
77
 
78
+ # Return a virtual file pointer to the current location in the file.
79
+ def self.bgzf_tell(fp)
80
+ (fp[:block_address] << 16) | (fp[:block_offset] & 0xFFFF)
81
+ end
82
+
78
83
  # Set the file to read from the location specified by _pos_.
79
84
  attach_function \
80
85
  :bgzf_seek,
@@ -176,7 +181,7 @@ module HTS
176
181
  # Load BGZF index from an hFILE
177
182
  attach_function \
178
183
  :bgzf_index_load_hfile,
179
- [BGZF, :HFILE, :string],
184
+ [BGZF, HFILE, :string],
180
185
  :int
181
186
 
182
187
  # Save BGZF index
@@ -188,7 +193,7 @@ module HTS
188
193
  # Write a BGZF index to an hFILE
189
194
  attach_function \
190
195
  :bgzf_index_dump_hfile,
191
- [BGZF, :HFILE, :string],
196
+ [BGZF, HFILE, :string],
192
197
  :int
193
198
  end
194
199
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  module HTS
4
4
  module LibHTS
5
- typedef :pointer, :HFILE
6
5
  typedef :int64, :hts_pos_t
7
6
  typedef :pointer, :bam_plp_auto_f
8
7
 
@@ -25,6 +24,25 @@ module HTS
25
24
  :f, :pointer # kstream_t
26
25
  end
27
26
 
27
+ # HFILE
28
+
29
+ class HFILE < FFI::BitStruct
30
+ layout \
31
+ :buffer, :string,
32
+ :begin, :string,
33
+ :end, :string,
34
+ :limit, :string,
35
+ :backend, :pointer,
36
+ :offset, :size_t,
37
+ :_flags, :uint,
38
+ :has_errno, :int
39
+
40
+ bit_fields :_flags,
41
+ :at_eof, 1,
42
+ :mobile, 1,
43
+ :readonly, 1
44
+ end
45
+
28
46
  # BGZF
29
47
  class BGZF < FFI::BitStruct
30
48
  layout \
@@ -38,7 +56,7 @@ module HTS
38
56
  :uncompressed_block, :pointer,
39
57
  :compressed_block, :pointer,
40
58
  :cache, :pointer,
41
- :fp, :HFILE,
59
+ :fp, HFILE.ptr,
42
60
  :mt, :pointer,
43
61
  :idx, :pointer,
44
62
  :idx_build_otf, :int,
@@ -198,8 +216,8 @@ module HTS
198
216
  :fp,
199
217
  union_layout(
200
218
  :bgzf, BGZF.ptr,
201
- :cram, :pointer,
202
- :hfile, :pointer # HFILE
219
+ :cram, :pointer, # cram_fd
220
+ :hfile, HFILE.ptr
203
221
  ),
204
222
  :state, :pointer,
205
223
  :format, HtsFormat,
@@ -0,0 +1,297 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTS
4
+ module LibHTS
5
+
6
+ =begin
7
+
8
+ attach_function \
9
+ :cram_fd_get_header,
10
+ [CramFd],
11
+ SamHdr.by_ref
12
+
13
+ attach_function \
14
+ :cram_fd_set_header,
15
+ [CramFd, SamHdr.by_ref],
16
+ :void
17
+
18
+ attach_function \
19
+ :cram_fd_get_version,
20
+ [CramFd],
21
+ :int
22
+
23
+ attach_function \
24
+ :cram_fd_set_version,
25
+ [CramFd, :int],
26
+ :void
27
+
28
+ attach_function \
29
+ :cram_major_vers,
30
+ [CramFd],
31
+ :int
32
+
33
+ attach_function \
34
+ :cram_minor_vers,
35
+ [CramFd],
36
+ :int
37
+
38
+ attach_function \
39
+ :cram_fd_get_fp,
40
+ [CramFd],
41
+ HFile.by_ref
42
+
43
+ attach_function \
44
+ :cram_fd_set_fp,
45
+ [CramFd, HFile],
46
+ :void
47
+
48
+ attach_function \
49
+ :cram_container_get_length,
50
+ [CramContainer],
51
+ :int32
52
+
53
+ attach_function \
54
+ :cram_container_set_length,
55
+ [CramContainer, :int32],
56
+ :void
57
+
58
+ attach_function \
59
+ :cram_container_get_num_blocks,
60
+ [CramContainer],
61
+ :int32
62
+
63
+ attach_function \
64
+ :cram_container_set_num_blocks,
65
+ [CramContainer, :int32],
66
+ :void
67
+
68
+ attach_function \
69
+ :cram_container_get_landmarks,
70
+ [CramContainer, :int32],
71
+ :pointer
72
+
73
+ attach_function \
74
+ :cram_container_set_landmarks,
75
+ [CramContainer, :Int32, :pointer],
76
+ :void
77
+
78
+ attach_function \
79
+ :cram_container_is_empty,
80
+ [CramFd],
81
+ :int
82
+
83
+ attach_function \
84
+ :cram_block_get_content_id,
85
+ [CramBlock],
86
+ :int32
87
+
88
+ attach_function \
89
+ :cram_block_get_comp_size,
90
+ [CramBlock],
91
+ :int32
92
+
93
+ attach_function \
94
+ :cram_block_get_uncomp_size,
95
+ [CramBlock],
96
+ :int32
97
+
98
+ attach_function \
99
+ :cram_block_get_crc32,
100
+ [CramBlock],
101
+ :int32
102
+
103
+ attach_function \
104
+ :cram_block_get_data,
105
+ [CramBlock],
106
+ :pointer
107
+
108
+ attach_function \
109
+ :cram_block_get_content_type,
110
+ [CramBlock],
111
+ CramContentType # ?
112
+
113
+ attach_function \
114
+ :cram_block_set_content_id,
115
+ [CramBlock, :int32],
116
+ :void
117
+
118
+ attach_function \
119
+ :cram_block_set_comp_size,
120
+ [CramBlock, :int32],
121
+ :void
122
+
123
+ attach_function \
124
+ :cram_block_set_uncomp_size,
125
+ [CramBlock, :int32],
126
+ :void
127
+
128
+ attach_function \
129
+ :cram_block_set_crc32,
130
+ [CramBlock, :int32],
131
+ :void
132
+
133
+ attach_function \
134
+ :cram_block_set_data,
135
+ [CramBlock, :pointer],
136
+ :void
137
+
138
+ attach_function \
139
+ :cram_block_append,
140
+ [CramBlock, :pointer, :int],
141
+ :int
142
+
143
+ attach_function \
144
+ :cram_block_update_size,
145
+ [CramBlock],
146
+ :void
147
+
148
+ attach_function \
149
+ :cram_block_get_offset,
150
+ [CramBlock],
151
+ :size_t
152
+
153
+ attach_function \
154
+ :cram_block_set_offset,
155
+ [CramBlock, :size_t],
156
+ :void
157
+
158
+ attach_function \
159
+ :cram_block_size,
160
+ [CramBlock],
161
+ :uint32
162
+
163
+ attach_function \
164
+ :cram_transcode_rg,
165
+ [CramFd, CramFd, CramContainer, :int, :pointer, :pointer],
166
+ :int
167
+
168
+ attach_function \
169
+ :cram_copy_slice,
170
+ [CramFd, CramFd, :int32],
171
+ :int
172
+
173
+ attach_function \
174
+ :cram_new_block,
175
+ [CramContentType, :int],
176
+ CramBlock
177
+
178
+ attach_function \
179
+ :cram_read_block,
180
+ [CramFd],
181
+ CramBlock
182
+
183
+ attach_function \
184
+ :cram_write_block,
185
+ [CramFd, CramBlock],
186
+ :int
187
+
188
+ attach_function \
189
+ :cram_free_block,
190
+ [CramBlock],
191
+ :void
192
+
193
+ attach_function \
194
+ :cram_uncompress_block,
195
+ [CramBlock],
196
+ :int
197
+
198
+ attach_function \
199
+ :cram_compress_block,
200
+ [CramFd, CramBlock, CramMetrics, :int, :int],
201
+ :int
202
+
203
+ attach_function \
204
+ :cram_compress_block2,
205
+ [CramFd, CramSlice, CramBlock, CramMetrics, :int, :int],
206
+ :int
207
+
208
+ attach_function \
209
+ :cram_new_container,
210
+ [:int, :int],
211
+ CramContainer
212
+
213
+ attach_function \
214
+ :cram_free_container,
215
+ [CramContainer],
216
+ :void
217
+
218
+ attach_function \
219
+ :cram_read_container,
220
+ [CramFd],
221
+ CramContainer
222
+
223
+ attach_function \
224
+ :cram_write_container,
225
+ [CramFd, CramContainer],
226
+ :int
227
+
228
+ attach_function \
229
+ :cram_store_container,
230
+ [CramFd, CramContainer, :string, :pointer],
231
+ :int
232
+
233
+ attach_function \
234
+ :cram_container_size,
235
+ [CramContainer],
236
+ :int
237
+
238
+ attach_function \
239
+ :cram_open,
240
+ [:string, :string],
241
+ CramFd
242
+
243
+ attach_function \
244
+ :cram_dopen,
245
+ [:pointer, :string, :string],
246
+ CramFd
247
+
248
+ attach_function \
249
+ :cram_close,
250
+ [CramFd],
251
+ :int
252
+
253
+ =end
254
+
255
+ attach_function \
256
+ :cram_seek,
257
+ [:pointer, :off_t, :int], :int # FIXME pointer should be CramFd
258
+
259
+ =begin
260
+
261
+ attach_function \
262
+ :cram_flush,
263
+ [CramFd],
264
+ :int
265
+
266
+ attach_function \
267
+ :cram_eof,
268
+ [CramFd],
269
+ :int
270
+
271
+ attach_function \
272
+ :cram_set_option,
273
+ [CramFd, HtsFmtOption, ...], # vararg!
274
+ :int
275
+
276
+ attach_function \
277
+ :cram_set_voption,
278
+ [CramFd, HtsFmtOption, VaList],
279
+ :int
280
+
281
+ attach_function \
282
+ :cram_set_header,
283
+ [CramFd, SamHdr.by_ref],
284
+ :int
285
+
286
+ attach_function \
287
+ :cram_check_eof = :cram_check_EOF,
288
+ [CramFd], :int
289
+
290
+ attach_function \
291
+ :cram_get_refs,
292
+ [HtsFile],
293
+ RefsT # what is RefsT
294
+
295
+ =end
296
+ end
297
+ end
@@ -6,13 +6,13 @@ module HTS
6
6
  attach_function \
7
7
  :hopen,
8
8
  %i[string string varargs],
9
- :HFILE
9
+ HFILE.by_ref
10
10
 
11
11
  # Associate a stream with an existing open file descriptor
12
12
  attach_function \
13
13
  :hdopen,
14
14
  %i[int string],
15
- :HFILE
15
+ HFILE.by_ref
16
16
 
17
17
  # Report whether the file name or URL denotes remote storage
18
18
  attach_function \
@@ -29,55 +29,63 @@ module HTS
29
29
  # Flush (for output streams) and close the stream
30
30
  attach_function \
31
31
  :hclose,
32
- [:HFILE],
32
+ [HFILE],
33
33
  :int
34
34
 
35
35
  # Close the stream, without flushing or propagating errors
36
36
  attach_function \
37
37
  :hclose_abruptly,
38
- [:HFILE],
38
+ [HFILE],
39
39
  :void
40
40
 
41
41
  # Reposition the read/write stream offset
42
42
  attach_function \
43
43
  :hseek,
44
- %i[HFILE off_t int],
44
+ [HFILE, :off_t, :int],
45
45
  :off_t
46
46
 
47
+ # Report the current stream offset
48
+ def self.htell(fp)
49
+ # TODO: This is a hack. Is this OK?
50
+ bg = FFI::Pointer.new(:int, fp.pointer.address + fp.offset_of(:begin)).read_int
51
+ bf = FFI::Pointer.new(:int, fp.pointer.address + fp.offset_of(:buffer)).read_int
52
+ fp[:offset] + (bg - bf)
53
+ end
54
+
47
55
  # Read from the stream until the delimiter, up to a maximum length
48
56
  attach_function \
49
57
  :hgetdelim,
50
- %i[string size_t int HFILE],
58
+ [:string, :size_t, :int, HFILE],
51
59
  :ssize_t
52
60
 
53
61
  # Read a line from the stream, up to a maximum length
54
62
  attach_function \
55
63
  :hgets,
56
- %i[string int HFILE],
64
+ [:string, :int, HFILE],
57
65
  :string
58
66
 
59
67
  # Peek at characters to be read without removing them from buffers
60
68
  attach_function \
61
69
  :hpeek,
62
- %i[HFILE pointer size_t],
70
+ [HFILE, :pointer, :size_t],
63
71
  :ssize_t
64
72
 
65
73
  # For writing streams, flush buffered output to the underlying stream
66
74
  attach_function \
67
75
  :hflush,
68
- [:HFILE],
76
+ [HFILE],
69
77
  :int
70
78
 
71
79
  # For hfile_mem: get the internal buffer and it's size from a hfile
72
80
  attach_function \
73
81
  :hfile_mem_get_buffer,
74
- %i[HFILE pointer],
82
+ [HFILE, :pointer],
75
83
  :string
76
84
 
77
85
  # For hfile_mem: get the internal buffer and it's size from a hfile.
78
86
  attach_function \
79
87
  :hfile_mem_steal_buffer,
80
- %i[HFILE pointer],
88
+ [HFILE, :pointer],
81
89
  :string
82
90
  end
83
91
  end
@@ -61,7 +61,7 @@ module HTS
61
61
  # Determine format by peeking at the start of a file
62
62
  attach_function \
63
63
  :hts_detect_format,
64
- [:HFILE, HtsFormat],
64
+ [HFILE, HtsFormat],
65
65
  :int
66
66
 
67
67
  # Get a human-readable description of the file format
@@ -86,7 +86,7 @@ module HTS
86
86
  # Open an existing stream as a SAM/BAM/CRAM/VCF/BCF/etc file
87
87
  attach_function \
88
88
  :hts_hopen,
89
- %i[HFILE string string],
89
+ [HFILE, :string, :string],
90
90
  HtsFile.by_ref
91
91
 
92
92
  # For output streams, flush any buffered data
@@ -345,7 +345,8 @@ module HTS
345
345
  # Get the next read from a SAM/BAM/CRAM iterator
346
346
  def self.sam_itr_next(htsfp, itr, r)
347
347
  # FIXME: check if htsfp is compressed BGZF
348
- hts_log_error("Null iterator") if itr.null?
348
+ raise("Null iterator") if itr.null?
349
+
349
350
  # FIXME: check multi
350
351
  hts_itr_next(htsfp[:fp][:bgzf], itr, r, htsfp)
351
352
  end
data/lib/hts/libhts.rb CHANGED
@@ -23,12 +23,13 @@ end
23
23
  require_relative "libhts/constants"
24
24
 
25
25
  # This is alphabetical order.
26
+ require_relative "libhts/kfunc"
26
27
  require_relative "libhts/bgzf"
27
- require_relative "libhts/faidx"
28
28
  require_relative "libhts/hfile"
29
29
  require_relative "libhts/hts"
30
30
  require_relative "libhts/sam"
31
- require_relative "libhts/kfunc"
32
- require_relative "libhts/tbx"
31
+ require_relative "libhts/cram"
33
32
  require_relative "libhts/vcf"
33
+ require_relative "libhts/tbx"
34
+ require_relative "libhts/faidx"
34
35
  require_relative "libhts/thread_pool"
data/lib/hts/tabix.rb CHANGED
@@ -1,28 +1,53 @@
1
- # frozen_string_literal: true
1
+ require_relative "../htslib"
2
2
 
3
- # Based on hts-python
4
- # https://github.com/quinlan-lab/hts-python
3
+ require_relative "hts"
5
4
 
6
5
  module HTS
7
- class Tabix
8
- class << self
9
- alias open new
6
+ class Tabix < Hts
7
+ include Enumerable
8
+
9
+ attr_reader :file_name
10
+
11
+ def self.open(*args, **kw)
12
+ file = new(*args, **kw) # do not yield
13
+ return file unless block_given?
14
+
15
+ begin
16
+ yield file
17
+ ensure
18
+ file.close
19
+ end
20
+ file
10
21
  end
11
- def initialize
12
- # IO like API
22
+
23
+ def initialize(file_name, threads: nil)
13
24
  if block_given?
14
- begin
15
- yield self
16
- ensure
17
- close
18
- end
25
+ message = "HTS::Tabix.new() dose not take block; Please use HTS::Tabix.open() instead"
26
+ raise message
19
27
  end
20
- end
21
28
 
22
- def build; end
29
+ @file_name = file_name
30
+
31
+ # NOTE: Do not check for the existence of local files, since file_names may be remote URIs.
23
32
 
24
- def sequences; end
33
+ @mode = "r"
34
+ @hts_file = LibHTS.hts_open(@file_name, @mode)
25
35
 
26
- # def __call__\
36
+ raise Errno::ENOENT, "Failed to open #{@file_name}" if @hts_file.null?
37
+
38
+ if threads&.> 0
39
+ r = LibHTS.hts_set_threads(@hts_file, threads)
40
+ raise "Failed to set number of threads: #{threads}" if r < 0
41
+ end
42
+ end
43
+
44
+ def close
45
+ LibHTS.hts_close(@hts_file)
46
+ @hts_file = nil
47
+ end
48
+
49
+ def closed?
50
+ @hts_file.nil?
51
+ end
27
52
  end
28
53
  end
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.0.8"
4
+ VERSION = "0.0.10"
5
5
  end
data/lib/htslib.rb CHANGED
@@ -37,9 +37,9 @@ module HTS
37
37
  # You can change the path of the shared library with `HTS.lib_path=`
38
38
  # before calling the LibHTS module.
39
39
  autoload :LibHTS, "hts/libhts"
40
- end
41
40
 
42
- require_relative "hts/bam"
43
- require_relative "hts/faidx"
44
- require_relative "hts/tabix"
45
- require_relative "hts/bcf"
41
+ autoload :Bam, "hts/bam"
42
+ autoload :Bcf, "hts/bcf"
43
+ autoload :Tabix, "hts/tabix"
44
+ autoload :Faidx, "hts/faidx"
45
+ end