Class: HTS::Bcf::Format

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

Defined Under Namespace

Classes: BufferState, GenotypeView, NumericVectorView

Constant Summary collapse

GT_MISSING =
0
GT_VECTOR_END =
Native::BCF_INT32_VECTOR_END

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(record) ⇒ Format

Returns a new instance of Format.



101
102
103
104
# File 'lib/hts/bcf/format.rb', line 101

def initialize(record)
  @record = record
  @buffers = {}
end

Class Method Details

.gt_allele(value) ⇒ Object



12
# File 'lib/hts/bcf/format.rb', line 12

def gt_allele(value) = (Integer(value) >> 1) - 1

.gt_missing?(value) ⇒ Boolean

Returns:

  • (Boolean)


13
# File 'lib/hts/bcf/format.rb', line 13

def gt_missing?(value) = (Integer(value) >> 1).zero?

.gt_phased(allele) ⇒ Object



11
# File 'lib/hts/bcf/format.rb', line 11

def gt_phased(allele) = ((Integer(allele) + 1) << 1) | 1

.gt_phased?(value) ⇒ Boolean

Returns:

  • (Boolean)


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

def gt_phased?(value) = (Integer(value) & 1) == 1

.gt_unphased(allele) ⇒ Object



10
# File 'lib/hts/bcf/format.rb', line 10

def gt_unphased(allele) = (Integer(allele) + 1) << 1

.gt_vector_end?(value) ⇒ Boolean

Returns:

  • (Boolean)


15
# File 'lib/hts/bcf/format.rb', line 15

def gt_vector_end?(value) = Integer(value) == GT_VECTOR_END

Instance Method Details

#[](key) ⇒ Object



154
# File 'lib/hts/bcf/format.rb', line 154

def [](key) = get(key)

#delete(key) ⇒ Object



249
250
251
252
253
254
255
# File 'lib/hts/bcf/format.rb', line 249

def delete(key)
  schema = format_schema(key)
  return false unless schema && !get_raw(key).nil?

  result = native.format_delete(header_native, key.to_s, type_code(schema.first))
  result >= 0
end

#each_f32_vector(key, &block) ⇒ Object



203
# File 'lib/hts/bcf/format.rb', line 203

def each_f32_vector(key, &block) = each_vector(key, :float, &block)

#each_genotype(key = "GT") ⇒ Object

Raises:

  • (ArgumentError)


156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/hts/bcf/format.rb', line 156

def each_genotype(key = "GT")
  return enum_for(__method__, key) unless block_given?
  raise ArgumentError, "genotype FORMAT key must be GT" unless key.to_s == "GT"

  values = get_raw(key, :int)
  return nil unless values

  count, width = sample_layout(values.length)
  buffer, generation = advance_buffer(key, :genotype)
  view = GenotypeView.new
  count.times do |sample|
    yield sample, view.reset(values.slice(sample * width, width), buffer, generation)
  end
  self
end

#each_i32(key) ⇒ Object



191
192
193
194
195
196
197
198
199
200
# File 'lib/hts/bcf/format.rb', line 191

def each_i32(key)
  return enum_for(__method__, key) unless block_given?

  ensure_scalar!(key, :int)
  values = get_raw(key, :int)
  return self unless values

  values.each_with_index { |value, index| yield index, missing_int(value) }
  self
end

#each_i32_vector(key, &block) ⇒ Object



202
# File 'lib/hts/bcf/format.rb', line 202

def each_i32_vector(key, &block) = each_vector(key, :int, &block)

#fieldsObject



257
# File 'lib/hts/bcf/format.rb', line 257

def fields = native.format_fields(header_native)

#genotype_at(key, sample_index) ⇒ Object

Raises:



172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/hts/bcf/format.rb', line 172

def genotype_at(key, sample_index)
  values = get_raw(key, :int)
  return nil unless values

  count, width = sample_layout(values.length)
  sample_index = Integer(sample_index)
  sample_index += count if sample_index.negative?
  raise IndexError, "sample index #{sample_index} outside of FORMAT" unless sample_index.between?(0, count - 1)

  buffer, generation = advance_buffer(key, :genotype)
  GenotypeView.new.reset(values.slice(sample_index * width, width), buffer, generation)
end

#genotype_strings(key = "GT") ⇒ Object



185
186
187
188
189
# File 'lib/hts/bcf/format.rb', line 185

def genotype_strings(key = "GT")
  strings = []
  found = each_genotype(key) { |_, genotype| strings << genotype.to_s }
  found ? strings : nil
end

#get(key, type = nil) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/hts/bcf/format.rb', line 106

def get(key, type = nil)
  key = key.to_s
  schema = format_schema(key)
  return nil unless schema

  raise_unsupported_flag(key) if schema.first == :flag

  requested = type&.to_sym
  if requested && !type_compatible?(schema.first, requested, key)
    raise FormatTypeError, "Tag #{key} is not #{type_label(requested)} FORMAT field"
  end
  return genotype_strings(key) if key == "GT" && (!requested || %i[string str].include?(requested))

  return get_float(key) if %i[float real].include?(requested)

  raw = get_raw(key, requested)
  return raw if requested
  return raw if schema.first == :string

  shape_values(raw, key, schema)
end

#get_flag(key) ⇒ Object



151
# File 'lib/hts/bcf/format.rb', line 151

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

#get_float(key) ⇒ Object



146
147
148
149
# File 'lib/hts/bcf/format.rb', line 146

def get_float(key)
  words = get_raw(key, :float)
  words&.map { |word| decode_float_word(word) }
end

#get_float_words(key) ⇒ Object



259
# File 'lib/hts/bcf/format.rb', line 259

def get_float_words(key) = get_raw(key, :float)

#get_genotypesObject



153
# File 'lib/hts/bcf/format.rb', line 153

def get_genotypes = get_raw("GT", :int)

#get_int(key) ⇒ Object



144
# File 'lib/hts/bcf/format.rb', line 144

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

#get_raw(key, type = nil) ⇒ Object



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

def get_raw(key, type = nil)
  key = key.to_s
  schema = format_schema(key)
  return nil unless schema

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

  code = key == "GT" ? Native::BCF_HT_INT : type_code(requested || schema.first)
  raw_float = code == Native::BCF_HT_REAL
  invalidate_views!(key)
  native.format_get(header_native, key, code, raw_float)
end

#get_string(key) ⇒ Object



152
# File 'lib/hts/bcf/format.rb', line 152

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

#idsObject



258
# File 'lib/hts/bcf/format.rb', line 258

def ids = fields.map { |field| field[:id] }

#lengthObject Also known as: size



260
# File 'lib/hts/bcf/format.rb', line 260

def length = fields.length

#to_hObject



262
# File 'lib/hts/bcf/format.rb', line 262

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

#update_float(key, values) ⇒ Object



213
214
215
216
217
# File 'lib/hts/bcf/format.rb', line 213

def update_float(key, values)
  values = normalize_values(values, &:to_f)
  validate_sample_divisibility!(key, values.length)
  update_format(key, Native::BCF_HT_REAL, values)
end

#update_float_words(key, values) ⇒ Object



219
220
221
222
223
224
225
226
227
228
# File 'lib/hts/bcf/format.rb', line 219

def update_float_words(key, values)
  values = normalize_values(values) { |value| Integer(value) }
  validate_sample_divisibility!(key, values.length)
  raise FormatDefinitionError, "FORMAT tag #{key} not defined in header" unless format_schema(key)

  result = native.format_update_float_words(header_native, key.to_s, values)
  raise FormatUpdateError, "Failed to update FORMAT field '#{key}': #{result}" if result.negative?

  result
end

#update_genotypes(values) ⇒ Object

Raises:



240
241
242
243
244
245
246
247
# File 'lib/hts/bcf/format.rb', line 240

def update_genotypes(values)
  values = normalize_values(values) { |value| Integer(value) }
  validate_sample_divisibility!("GT", values.length)
  result = native.genotype_update(header_native, values)
  raise FormatUpdateError, "Failed to update FORMAT field 'GT': #{result}" if result.negative?

  result
end

#update_int(key, values) ⇒ Object



205
206
207
208
209
210
211
# File 'lib/hts/bcf/format.rb', line 205

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

  values = normalize_values(values) { |value| Integer(value) }
  validate_sample_divisibility!(key, values.length)
  update_format(key, Native::BCF_HT_INT, values)
end

#update_string(key, values) ⇒ Object



230
231
232
233
234
235
236
237
238
# File 'lib/hts/bcf/format.rb', line 230

def update_string(key, values)
  values = Array(values).map(&:to_s)
  expected = sample_count
  unless values.length == expected
    raise ArgumentError, "FORMAT string values for #{key} must provide one entry per sample (#{expected})"
  end

  update_format(key, Native::BCF_HT_STR, values)
end