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



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.



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.



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

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



183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/hts/bam/auxi.rb', line 183

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



176
177
178
179
180
181
# File 'lib/hts/bam/auxi.rb', line 176

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.



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

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

#to_hObject



196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/hts/bam/auxi.rb', line 196

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.

Raises:

  • (ArgumentError)


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/hts/bam/auxi.rb', line 115

def update_array(key, value, type: nil)
  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

  # Convert array to appropriate C type
  case type
  when "c", "C", "s", "S", "i", "I"
    # Integer types
    ptr = FFI::MemoryPointer.new(:int32, value.size)
    ptr.write_array_of_int32(value.map(&:to_i))
    ret = LibHTS.bam_aux_update_array(@record.struct, key, type.ord, value.size, ptr)
  when "f"
    # Float type
    ptr = FFI::MemoryPointer.new(:float, value.size)
    ptr.write_array_of_float(value.map(&:to_f))
    ret = LibHTS.bam_aux_update_array(@record.struct, key, type.ord, value.size, ptr)
  else
    raise ArgumentError, "Invalid array type: #{type}"
  end

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

  value
end

#update_float(key, value) ⇒ Object

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



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

def update_float(key, value)
  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_int(key, value) ⇒ Object

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



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

def update_int(key, value)
  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_string(key, value) ⇒ Object

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



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

def update_string(key, value)
  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