Class: HTS::Bam::Aux

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/hts/bam/auxi.rb

Overview

Auxiliary record data

The result of the alignment is assigned to the bam1 structure. Ruby’s Aux class references a part of it. There is no one-to-one correspondence between C structures and Ruby’s Aux class.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(record) ⇒ Aux

Returns a new instance of Aux.



24
25
26
# File 'lib/hts/bam/auxi.rb', line 24

def initialize(record)
  @record = record
end

Instance Attribute Details

#recordObject (readonly)

Returns the value of attribute record.



22
23
24
# File 'lib/hts/bam/auxi.rb', line 22

def record
  @record
end

Instance Method Details

#[](key) ⇒ Object



54
55
56
# File 'lib/hts/bam/auxi.rb', line 54

def [](key)
  get(key)
end

#[]=(key, value) ⇒ Object

Set auxiliary tag value (auto-detects type from value) For compatibility with HTS.cr.

Parameters:

  • key (String)

    tag name (2 characters)

  • value (Integer, Float, String, Array)

    tag value



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/hts/bam/auxi.rb', line 62

def []=(key, value)
  case value
  when Integer
    update_int(key, value)
  when Float
    update_float(key, value)
  when String
    update_string(key, value)
  when Array
    update_array(key, value)
  else
    raise ArgumentError, "Unsupported type: #{value.class}"
  end
end

#delete(key) ⇒ Boolean

Delete an auxiliary tag For compatibility with HTS.cr.

Parameters:

  • key (String)

    tag name (2 characters)

Returns:

  • (Boolean)

    true if tag was deleted, false if tag was not found



209
210
211
212
213
214
215
216
217
# File 'lib/hts/bam/auxi.rb', line 209

def delete(key)
  aux_ptr = LibHTS.bam_aux_get(@record.struct, key)
  return false if aux_ptr.null?

  ret = LibHTS.bam_aux_del(@record.struct, aux_ptr)
  raise "Failed to delete tag '#{key}': errno #{FFI.errno}" if ret < 0

  true
end

#eachObject



237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/hts/bam/auxi.rb', line 237

def each
  return enum_for(__method__) unless block_given?

  aux_ptr = first_pointer
  return nil if aux_ptr.null?

  loop do
    yield get_ruby_aux(aux_ptr)
    aux_ptr = LibHTS.bam_aux_next(@record.struct, aux_ptr)
    break if aux_ptr.null?
  end
end

#firstObject



230
231
232
233
234
235
# File 'lib/hts/bam/auxi.rb', line 230

def first
  aux_ptr = first_pointer
  return nil if aux_ptr.null?

  get_ruby_aux(aux_ptr)
end

#get(key, type = nil) ⇒ Object

Note:

Why is this method named “get” instead of “fetch”?

This is for compatibility with the Crystal language which provides methods like ‘get_int`, `get_float`, etc. I think they are better than `fetch_int“ and `fetch_float`.



32
33
34
35
36
37
# File 'lib/hts/bam/auxi.rb', line 32

def get(key, type = nil)
  aux_ptr = LibHTS.bam_aux_get(@record.struct, key)
  return nil if aux_ptr.null?

  get_ruby_aux(aux_ptr, type)
end

#get_float(key) ⇒ Object

For compatibility with HTS.cr.



45
46
47
# File 'lib/hts/bam/auxi.rb', line 45

def get_float(key)
  get(key, "f")
end

#get_int(key) ⇒ Object

For compatibility with HTS.cr.



40
41
42
# File 'lib/hts/bam/auxi.rb', line 40

def get_int(key)
  get(key, "i")
end

#get_string(key) ⇒ Object

For compatibility with HTS.cr.



50
51
52
# File 'lib/hts/bam/auxi.rb', line 50

def get_string(key)
  get(key, "Z")
end

#key?(key) ⇒ Boolean Also known as: include?

Check if a tag exists For compatibility with HTS.cr.

Parameters:

  • key (String)

    tag name (2 characters)

Returns:

  • (Boolean)

    true if tag exists



223
224
225
226
# File 'lib/hts/bam/auxi.rb', line 223

def key?(key)
  aux_ptr = LibHTS.bam_aux_get(@record.struct, key)
  !aux_ptr.null?
end

#to_hObject



250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/hts/bam/auxi.rb', line 250

def to_h
  h = {}
  aux_ptr = first_pointer
  return h if aux_ptr.null?

  loop do
    key = FFI::Pointer.new(aux_ptr.address - 2).read_string(2)
    h[key] = get_ruby_aux(aux_ptr)
    aux_ptr = LibHTS.bam_aux_next(@record.struct, aux_ptr)
    break if aux_ptr.null?
  end
  h
end

#update_array(key, value, type: nil) ⇒ Object

Update or add an array tag For compatibility with HTS.cr.

Parameters:

  • key (String)

    tag name (2 characters)

  • value (Array)

    array of integers or floats

  • type (String, nil) (defaults to: nil)

    element type (‘c’, ‘C’, ‘s’, ‘S’, ‘i’, ‘I’, ‘f’). Auto-detected if nil.

Raises:

  • (ArgumentError)


179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/hts/bam/auxi.rb', line 179

def update_array(key, value, type: nil)
  validate_tag!(key)
  raise ArgumentError, "Array cannot be empty" if value.empty?

  # Auto-detect type if not specified
  if type.nil?
    if value.all? { |v| v.is_a?(Integer) }
      # Use 'i' for signed 32-bit integers by default
      type = "i"
    elsif value.all? { |v| v.is_a?(Float) || v.is_a?(Integer) }
      type = "f"
    else
      raise ArgumentError, "Array must contain only integers or floats"
    end
  end

  payload = pack_array_payload(value, type)
  ptr = FFI::MemoryPointer.new(:uint8, payload.bytesize)
  ptr.put_bytes(0, payload)
  ret = LibHTS.bam_aux_update_array(@record.struct, key, type.ord, value.size, ptr)

  raise "Failed to update array tag '#{key}': errno #{FFI.errno}" if ret < 0

  value
end

#update_char(key, value) ⇒ Object

Update or add a character tag.

Raises:

  • (ArgumentError)


144
145
146
147
148
149
150
151
152
# File 'lib/hts/bam/auxi.rb', line 144

def update_char(key, value)
  validate_tag!(key)

  string = value.to_s
  raise ArgumentError, "Character AUX tags must be a single character" unless string.length == 1

  replace_with_append(key, "A", string.b)
  string
end

#update_double(key, value) ⇒ Object

Update or add a double-precision floating-point tag.



167
168
169
170
171
172
# File 'lib/hts/bam/auxi.rb', line 167

def update_double(key, value)
  validate_tag!(key)

  replace_with_append(key, "d", [Float(value)].pack("E"))
  value.to_f
end

#update_float(key, value) ⇒ Object

Update or add a floating-point tag For compatibility with HTS.cr.

Parameters:

  • key (String)

    tag name (2 characters)

  • value (Float)

    floating-point value



123
124
125
126
127
128
129
# File 'lib/hts/bam/auxi.rb', line 123

def update_float(key, value)
  validate_tag!(key)
  ret = LibHTS.bam_aux_update_float(@record.struct, key, value.to_f)
  raise "Failed to update float tag '#{key}': errno #{FFI.errno}" if ret < 0

  value
end

#update_hex(key, value) ⇒ Object

Update or add a hexadecimal string tag.

Raises:

  • (ArgumentError)


155
156
157
158
159
160
161
162
163
164
# File 'lib/hts/bam/auxi.rb', line 155

def update_hex(key, value)
  validate_tag!(key)

  string = value.to_s
  raise ArgumentError, "Hex AUX tags must contain an even number of characters" if string.length.odd?
  raise ArgumentError, "Hex AUX tags must contain only hexadecimal characters" unless /\A[0-9A-Fa-f]*\z/.match?(string)

  replace_with_append(key, "H", string.b + "\0")
  string
end

#update_int(key, value) ⇒ Object

Update or add an integer tag For compatibility with HTS.cr.

Parameters:

  • key (String)

    tag name (2 characters)

  • value (Integer)

    integer value



81
82
83
84
85
86
87
# File 'lib/hts/bam/auxi.rb', line 81

def update_int(key, value)
  validate_tag!(key)
  ret = LibHTS.bam_aux_update_int(@record.struct, key, value.to_i)
  raise "Failed to update integer tag '#{key}': errno #{FFI.errno}" if ret < 0

  value
end

#update_int16(key, value) ⇒ Object

Update or add a signed 16-bit integer tag.



100
101
102
# File 'lib/hts/bam/auxi.rb', line 100

def update_int16(key, value)
  update_exact_integer(key, value, "s", -32_768, 32_767)
end

#update_int32(key, value) ⇒ Object

Update or add a signed 32-bit integer tag.



110
111
112
# File 'lib/hts/bam/auxi.rb', line 110

def update_int32(key, value)
  update_exact_integer(key, value, "i", -2_147_483_648, 2_147_483_647)
end

#update_int8(key, value) ⇒ Object

Update or add a signed 8-bit integer tag.



90
91
92
# File 'lib/hts/bam/auxi.rb', line 90

def update_int8(key, value)
  update_exact_integer(key, value, "c", -128, 127)
end

#update_string(key, value) ⇒ Object

Update or add a string tag For compatibility with HTS.cr.

Parameters:

  • key (String)

    tag name (2 characters)

  • value (String)

    string value



135
136
137
138
139
140
141
# File 'lib/hts/bam/auxi.rb', line 135

def update_string(key, value)
  validate_tag!(key)
  ret = LibHTS.bam_aux_update_str(@record.struct, key, -1, value.to_s)
  raise "Failed to update string tag '#{key}': errno #{FFI.errno}" if ret < 0

  value
end

#update_uint16(key, value) ⇒ Object

Update or add an unsigned 16-bit integer tag.



105
106
107
# File 'lib/hts/bam/auxi.rb', line 105

def update_uint16(key, value)
  update_exact_integer(key, value, "S", 0, 65_535)
end

#update_uint32(key, value) ⇒ Object

Update or add an unsigned 32-bit integer tag.



115
116
117
# File 'lib/hts/bam/auxi.rb', line 115

def update_uint32(key, value)
  update_exact_integer(key, value, "I", 0, 4_294_967_295)
end

#update_uint8(key, value) ⇒ Object

Update or add an unsigned 8-bit integer tag.



95
96
97
# File 'lib/hts/bam/auxi.rb', line 95

def update_uint8(key, value)
  update_exact_integer(key, value, "C", 0, 255)
end