Class: HTS::Bcf::Info

Inherits:
Object
  • Object
show all
Defined in:
lib/hts/bcf/info.rb

Constant Summary collapse

TYPE_CODES =
{
  flag: Native::BCF_HT_FLAG, bool: Native::BCF_HT_FLAG,
  int: Native::BCF_HT_INT, int32: Native::BCF_HT_INT,
  int64: Native::BCF_HT_LONG, long: Native::BCF_HT_LONG,
  float: Native::BCF_HT_REAL, real: Native::BCF_HT_REAL,
  string: Native::BCF_HT_STR, str: Native::BCF_HT_STR
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(record) ⇒ Info

Returns a new instance of Info.



14
# File 'lib/hts/bcf/info.rb', line 14

def initialize(record) = @record = record

Instance Method Details

#[](key) ⇒ Object



36
# File 'lib/hts/bcf/info.rb', line 36

def [](key) = get(key)

#[]=(key, value) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/hts/bcf/info.rb', line 38

def []=(key, value)
  case value
  when nil then delete(key)
  when true, false then update_flag(key, value)
  when Integer
    unless int32?(value)
      raise RangeError,
            "Integer out of int32 range for []=. Current htslib backend does not support int64 INFO update."
    end

    update_int(key, [value])
  when Float then update_float(key, [value])
  when String then update_string(key, value)
  when Array
    raise ArgumentError, "Cannot set INFO field to empty array. Use nil to delete." if value.empty?

    if value.all? { |item| item.is_a?(Integer) }
      unless value.all? do |item|
        int32?(item)
      end
        raise RangeError,
              "Integer array contains out-of-int32 values for []=. Current htslib backend does not support int64 INFO update."
      end

      update_int(key, value)
    elsif value.all? { |item| item.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) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/hts/bcf/info.rb', line 82

def delete(key)
  schema = header.schema("INFO", key.to_s)
  return false unless schema && key?(key)

  native.info_update(header_native, key.to_s, TYPE_CODES.fetch(schema.first), false)
  true
end

#fieldsObject



96
# File 'lib/hts/bcf/info.rb', line 96

def fields = native.info_fields(header_native)

#get(key, type = nil) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/hts/bcf/info.rb', line 16

def get(key, type = nil)
  schema = header.schema("INFO", key.to_s)
  raise InfoDefinitionError, "INFO tag #{key} not defined in header" unless schema

  actual_type = schema.first
  requested = type&.to_sym
  if requested && !type_compatible?(actual_type, requested)
    raise InfoTypeError, "Tag #{key} is not #{type_label(requested)} INFO field"
  end

  code = TYPE_CODES.fetch(requested || actual_type)
  value = native.info_get(header_native, key.to_s, code)
  code == Native::BCF_HT_FLAG && value.nil? ? false : value
end

#get_flag(key) ⇒ Object



35
# File 'lib/hts/bcf/info.rb', line 35

def get_flag(key) = get(key, :flag)

#get_float(key) ⇒ Object



32
# File 'lib/hts/bcf/info.rb', line 32

def get_float(key) = get(key, :float)

#get_int(key) ⇒ Object



31
# File 'lib/hts/bcf/info.rb', line 31

def get_int(key) = get(key, :int)

#get_int64(key) ⇒ Object



33
# File 'lib/hts/bcf/info.rb', line 33

def get_int64(key) = get(key, :int64)

#get_string(key) ⇒ Object



34
# File 'lib/hts/bcf/info.rb', line 34

def get_string(key) = get(key, :string)

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

Returns:

  • (Boolean)


90
91
92
93
# File 'lib/hts/bcf/info.rb', line 90

def key?(key)
  schema = header.schema("INFO", key.to_s)
  schema ? native.info_present?(header_native, key.to_s, TYPE_CODES.fetch(schema.first)) : false
end

#keysObject



97
# File 'lib/hts/bcf/info.rb', line 97

def keys = fields.map { |field| field[:key] }

#lengthObject Also known as: size



98
# File 'lib/hts/bcf/info.rb', line 98

def length = fields.length

#to_hObject



100
# File 'lib/hts/bcf/info.rb', line 100

def to_h = fields.to_h { |field| [field[:name], get(field[:name])] }

#update_flag(key, present = true) ⇒ Object



80
# File 'lib/hts/bcf/info.rb', line 80

def update_flag(key, present = true) = update(key, Native::BCF_HT_FLAG, !!present, "flag")

#update_float(key, values) ⇒ Object



73
# File 'lib/hts/bcf/info.rb', line 73

def update_float(key, values) = update(key, Native::BCF_HT_REAL, Array(values).map(&:to_f), "float")

#update_int(key, values) ⇒ Object



72
# File 'lib/hts/bcf/info.rb', line 72

def update_int(key, values) = update(key, Native::BCF_HT_INT, Array(values).map { |value| Integer(value) }, "int")

#update_int64(_key, _values) ⇒ Object



76
77
78
# File 'lib/hts/bcf/info.rb', line 76

def update_int64(_key,
                       _values) = raise(UnsupportedInfoOperationError,
"htslib backend does not implement int64 INFO update (BCF_HT_LONG)")

#update_string(key, value) ⇒ Object



74
# File 'lib/hts/bcf/info.rb', line 74

def update_string(key, value) = update(key, Native::BCF_HT_STR, value.to_s, "string")