Class: HTS::Bcf::Info
- Inherits:
-
Object
- Object
- HTS::Bcf::Info
- Defined in:
- lib/hts/bcf/info.rb
Overview
Info field
Instance Method Summary collapse
- #[](key) ⇒ Object
-
#[]=(key, value) ⇒ Object
Set INFO field value with automatic type detection.
-
#delete(key) ⇒ Boolean
Delete an INFO field.
-
#fields ⇒ Object
FIXME: naming? room for improvement.
-
#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.
-
#get_flag(key) ⇒ Object
For compatibility with HTS.cr.
-
#get_float(key) ⇒ Object
For compatibility with HTS.cr.
-
#get_int(key) ⇒ Object
For compatibility with HTS.cr.
-
#get_string(key) ⇒ Object
For compatibility with HTS.cr.
-
#initialize(record) ⇒ Info
constructor
A new instance of Info.
-
#key?(key) ⇒ Boolean
(also: #include?)
Check if an INFO field exists.
- #length ⇒ Object
- #size ⇒ Object
- #to_h ⇒ Object
-
#update_flag(key, present = true) ⇒ Object
Update INFO flag field.
-
#update_float(key, values) ⇒ Object
Update INFO field with float value(s).
-
#update_int(key, values) ⇒ Object
Update INFO field with integer value(s).
-
#update_string(key, value) ⇒ Object
Update INFO field with string value.
Constructor Details
#initialize(record) ⇒ Info
Returns a new instance of Info.
7 8 9 10 |
# File 'lib/hts/bcf/info.rb', line 7 def initialize(record) @record = record @p1 = FFI::MemoryPointer.new(:pointer) # FIXME: naming end |
Instance Method Details
#[](key) ⇒ Object
73 74 75 |
# File 'lib/hts/bcf/info.rb', line 73 def [](key) get(key) end |
#[]=(key, value) ⇒ Object
Set INFO field value with automatic type detection.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/hts/bcf/info.rb', line 85 def []=(key, value) case value when nil delete(key) when true, false update_flag(key, value) when Integer update_int(key, [value]) when Float update_float(key, [value]) when String update_string(key, value) when Array if value.empty? raise ArgumentError, "Cannot set INFO field to empty array. Use nil to delete." elsif value.all? { |v| v.is_a?(Integer) } update_int(key, value) elsif value.all? { |v| v.is_a?(Numeric) } update_float(key, value) else raise ArgumentError, "INFO array must contain only integers or floats, got: #{value.map(&:class).uniq}" end else raise ArgumentError, "Unsupported INFO value type: #{value.class}" end end |
#delete(key) ⇒ Boolean
Delete an INFO field.
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/hts/bcf/info.rb', line 205 def delete(key) # Try to get current type to check existence type = get_info_type(key) return false if type.nil? # Delete by setting n=0 ret = LibHTS.bcf_update_info( @record.header.struct, @record.struct, key, FFI::Pointer::NULL, 0, type ) return false if ret < 0 true end |
#fields ⇒ Object
FIXME: naming? room for improvement.
236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/hts/bcf/info.rb', line 236 def fields keys.map do |key| name = LibHTS.bcf_hdr_int2id(@record.header.struct, LibHTS::BCF_DT_ID, key) num = LibHTS.bcf_hdr_id2number(@record.header.struct, LibHTS::BCF_HL_INFO, key) type = LibHTS.bcf_hdr_id2type(@record.header.struct, LibHTS::BCF_HL_INFO, key) { name:, n: num, type: ht_type_to_sym(type), key: } end end |
#get(key, type = nil) ⇒ Object
Specify the type. If you don’t specify a type, it will still work, but it will be slower.
@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`.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/hts/bcf/info.rb', line 17 def get(key, type = nil) n = FFI::MemoryPointer.new(:int) p1 = @p1 h = @record.header.struct r = @record.struct info_values = proc do |typ| ret = LibHTS.bcf_get_info_values(h, r, key, p1, n, typ) return nil if ret < 0 # return from method. p1.read_pointer end type ||= ht_type_to_sym(get_info_type(key)) case type&.to_sym when :int, :int32 info_values.call(LibHTS::BCF_HT_INT) .read_array_of_int32(n.read_int) when :float, :real info_values.call(LibHTS::BCF_HT_REAL) .read_array_of_float(n.read_int) when :flag, :bool case ret = LibHTS.bcf_get_info_flag(h, r, key, p1, n) when 1 then true when 0 then false when -1 then nil else raise "Unknown return value from bcf_get_info_flag: #{ret}" end when :string, :str info_values.call(LibHTS::BCF_HT_STR) .read_string end end |
#get_flag(key) ⇒ Object
For compatibility with HTS.cr.
69 70 71 |
# File 'lib/hts/bcf/info.rb', line 69 def get_flag(key) get(key, :flag) end |
#get_float(key) ⇒ Object
For compatibility with HTS.cr.
59 60 61 |
# File 'lib/hts/bcf/info.rb', line 59 def get_float(key) get(key, :float) end |
#get_int(key) ⇒ Object
For compatibility with HTS.cr.
54 55 56 |
# File 'lib/hts/bcf/info.rb', line 54 def get_int(key) get(key, :int) end |
#get_string(key) ⇒ Object
For compatibility with HTS.cr.
64 65 66 |
# File 'lib/hts/bcf/info.rb', line 64 def get_string(key) get(key, :string) end |
#key?(key) ⇒ Boolean Also known as: include?
Check if an INFO field exists.
227 228 229 230 231 |
# File 'lib/hts/bcf/info.rb', line 227 def key?(key) # Use get() to check if value is actually present # (get_info_type only checks header, not actual value) !get(key).nil? end |
#length ⇒ Object
250 251 252 |
# File 'lib/hts/bcf/info.rb', line 250 def length @record.struct[:n_info] end |
#size ⇒ Object
254 255 256 |
# File 'lib/hts/bcf/info.rb', line 254 def size length end |
#to_h ⇒ Object
258 259 260 261 262 263 264 265 |
# File 'lib/hts/bcf/info.rb', line 258 def to_h ret = {} keys.each do |key| name = LibHTS.bcf_hdr_int2id(@record.header.struct, LibHTS::BCF_DT_ID, key) ret[name] = get(name) end ret end |
#update_flag(key, present = true) ⇒ Object
Update INFO flag field. For compatibility with HTS.cr.
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/hts/bcf/info.rb', line 176 def update_flag(key, present = true) ret = if present LibHTS.bcf_update_info( @record.header.struct, @record.struct, key, FFI::Pointer::NULL, 1, LibHTS::BCF_HT_FLAG ) else # Remove flag by setting n=0 LibHTS.bcf_update_info( @record.header.struct, @record.struct, key, FFI::Pointer::NULL, 0, LibHTS::BCF_HT_FLAG ) end raise "Failed to update INFO flag field '#{key}': #{ret}" if ret < 0 ret end |
#update_float(key, values) ⇒ Object
Update INFO field with float value(s). For compatibility with HTS.cr.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/hts/bcf/info.rb', line 137 def update_float(key, values) values = Array(values).map(&:to_f) ptr = FFI::MemoryPointer.new(:float, values.size) ptr.write_array_of_float(values) ret = LibHTS.bcf_update_info( @record.header.struct, @record.struct, key, ptr, values.size, LibHTS::BCF_HT_REAL ) raise "Failed to update INFO float field '#{key}': #{ret}" if ret < 0 ret end |
#update_int(key, values) ⇒ Object
Update INFO field with integer value(s). For compatibility with HTS.cr.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/hts/bcf/info.rb', line 116 def update_int(key, values) values = Array(values) ptr = FFI::MemoryPointer.new(:int32, values.size) ptr.write_array_of_int32(values) ret = LibHTS.bcf_update_info( @record.header.struct, @record.struct, key, ptr, values.size, LibHTS::BCF_HT_INT ) raise "Failed to update INFO int field '#{key}': #{ret}" if ret < 0 ret end |
#update_string(key, value) ⇒ Object
Update INFO field with string value. For compatibility with HTS.cr.
158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/hts/bcf/info.rb', line 158 def update_string(key, value) ret = LibHTS.bcf_update_info( @record.header.struct, @record.struct, key, value.to_s, 1, LibHTS::BCF_HT_STR ) raise "Failed to update INFO string field '#{key}': #{ret}" if ret < 0 ret end |