Class: HTS::Bcf::Format

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

Instance Method Summary collapse

Constructor Details

#initialize(record) ⇒ Format

Returns a new instance of Format.



6
7
8
# File 'lib/hts/bcf/format.rb', line 6

def initialize(record)
  @record = record
end

Instance Method Details

#[](key) ⇒ Object



82
83
84
# File 'lib/hts/bcf/format.rb', line 82

def [](key)
  get(key)
end

#delete(key) ⇒ Object

Raises:



132
133
134
135
136
137
138
139
140
141
# File 'lib/hts/bcf/format.rb', line 132

def delete(key)
  return false if header_format_type(key).nil?
  return false unless format_present?(key)

  type = key == "GT" ? LibHTS::BCF_HT_INT : header_format_type_code(key)
  ret = LibHTS.bcf_update_format(@record.header.struct, @record.struct, key, FFI::Pointer::NULL, 0, type)
  raise FormatUpdateError, "Failed to delete FORMAT field '#{key}': #{ret}" if ret < 0

  true
end

#fieldsObject



143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/hts/bcf/format.rb', line 143

def fields
  ids.map do |id|
    name = LibHTS.bcf_hdr_int2id(@record.header.struct, LibHTS::BCF_DT_ID, id)
    num  = LibHTS.bcf_hdr_id2number(@record.header.struct, LibHTS::BCF_HL_FMT, id)
    type = LibHTS.bcf_hdr_id2type(@record.header.struct, LibHTS::BCF_HL_FMT, id)
    {
      name:,
      n: num,
      type: ht_type_to_sym(type),
      id:
    }
  end
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`.



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

def get(key, type = nil)
  return get_raw(key, type) unless type.nil?

  return decode_genotypes if key == "GT"

  case header_format_type(key)
  when :int
    decode_integer_values(key)
  when :float
    decode_float_values(key)
  when :flag
    raise_unsupported_format_flag(key)
  when :string
    get_string_values(key)
  end
end

#get_flag(key) ⇒ Object

For compatibility with HTS.cr.



68
69
70
# File 'lib/hts/bcf/format.rb', line 68

def get_flag(key)
  get_raw(key, :flag)
end

#get_float(key) ⇒ Object

For compatibility with HTS.cr.



63
64
65
# File 'lib/hts/bcf/format.rb', line 63

def get_float(key)
  get_raw(key, :float)
end

#get_genotypesObject

For compatibility with HTS.cr.



78
79
80
# File 'lib/hts/bcf/format.rb', line 78

def get_genotypes
  get_numeric_values("GT", LibHTS::BCF_HT_INT, "genotype") { |dst, len| dst.read_array_of_int32(len) }
end

#get_int(key) ⇒ Object

For compatibility with HTS.cr.



58
59
60
# File 'lib/hts/bcf/format.rb', line 58

def get_int(key)
  get_raw(key, :int)
end

#get_raw(key, type = nil) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/hts/bcf/format.rb', line 31

def get_raw(key, type = nil)
  # The GT FORMAT field is special in that it is marked as a string in the header,
  # but it is actually encoded as an integer.
  type = if type.nil?
           key == "GT" ? :int : header_format_type(key)
         else
           type.to_sym
         end

  case type
  when :int, :int32
    raise_unsupported_format_flag(key)
    get_numeric_values(key, LibHTS::BCF_HT_INT, "integer") { |dst, len| dst.read_array_of_int32(len) }
  when :float, :real
    raise_unsupported_format_flag(key)
    get_numeric_values(key, LibHTS::BCF_HT_REAL, "float") { |dst, len| dst.read_array_of_float(len) }
  when :flag
    raise_unsupported_format_flag(key)
  when :string, :str
    return decode_genotypes if key == "GT"

    raise_unsupported_format_flag(key)
    get_string_values(key)
  end
end

#get_string(key) ⇒ Object

For compatibility with HTS.cr.



73
74
75
# File 'lib/hts/bcf/format.rb', line 73

def get_string(key)
  get_raw(key, :string)
end

#lengthObject



157
158
159
# File 'lib/hts/bcf/format.rb', line 157

def length
  @record.struct[:n_fmt]
end

#sizeObject



161
162
163
# File 'lib/hts/bcf/format.rb', line 161

def size
  length
end

#to_hObject



165
166
167
168
169
170
171
172
# File 'lib/hts/bcf/format.rb', line 165

def to_h
  ret = {}
  ids.each do |id|
    name = LibHTS.bcf_hdr_int2id(@record.header.struct, LibHTS::BCF_DT_ID, id)
    ret[name] = get(name)
  end
  ret
end

#update_float(key, values) ⇒ Object



98
99
100
101
102
103
104
105
106
# File 'lib/hts/bcf/format.rb', line 98

def update_float(key, values)
  ensure_expected_format_type!(key, :float, "float")
  values = normalize_float_values(values)
  validate_numeric_sample_count!(key, values.size)

  ptr = FFI::MemoryPointer.new(:float, values.size)
  ptr.write_array_of_float(values)
  check_update_rc!(LibHTS.bcf_update_format_float(@record.header.struct, @record.struct, key, ptr, values.size), key)
end

#update_genotypes(values) ⇒ Object



121
122
123
124
125
126
127
128
129
130
# File 'lib/hts/bcf/format.rb', line 121

def update_genotypes(values)
  ensure_gt_defined!

  values = normalize_int_values(values)
  validate_numeric_sample_count!("GT", values.size)

  ptr = FFI::MemoryPointer.new(:int32, values.size)
  ptr.write_array_of_int32(values)
  check_update_rc!(LibHTS.bcf_update_genotypes(@record.header.struct, @record.struct, ptr, values.size), "GT")
end

#update_int(key, values) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/hts/bcf/format.rb', line 86

def update_int(key, values)
  raise UnsupportedFormatOperationError, "Use update_genotypes for GT" if key == "GT"

  ensure_expected_format_type!(key, :int, "integer")
  values = normalize_int_values(values)
  validate_numeric_sample_count!(key, values.size)

  ptr = FFI::MemoryPointer.new(:int32, values.size)
  ptr.write_array_of_int32(values)
  check_update_rc!(LibHTS.bcf_update_format_int32(@record.header.struct, @record.struct, key, ptr, values.size), key)
end

#update_string(key, values) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/hts/bcf/format.rb', line 108

def update_string(key, values)
  raise UnsupportedFormatOperationError, "Use update_genotypes for GT" if key == "GT"

  ensure_expected_format_type!(key, :string, "string")
  values = normalize_string_values(values)
  validate_string_sample_count!(key, values.size)

  strings = values.map { |value| FFI::MemoryPointer.from_string(value) }
  ptr = FFI::MemoryPointer.new(:pointer, strings.size)
  ptr.write_array_of_pointer(strings)
  check_update_rc!(LibHTS.bcf_update_format_string(@record.header.struct, @record.struct, key, ptr, values.size), key)
end