htslib 0.0.8 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
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