prop/lib/microwaveprop/weather/grib2/simple_packing.ex
Graham McIntire 5a9359191f
Replace wgrib2 with pure Elixir GRIB2 decoder for HRRR pipeline
Eliminates the external wgrib2 C tool dependency that blocked HRRR
processing. Implements Lambert Conformal projection, simple packing
(Template 5.0), complex packing with spatial differencing (Template 5.3),
and GRIB2 section parsing — enough to extract point values from HRRR
grid data using only Elixir.
2026-03-29 18:43:43 -05:00

44 lines
1.2 KiB
Elixir

defmodule Microwaveprop.Weather.Grib2.SimplePacking do
@moduledoc false
@doc """
Extract a single value from GRIB2 simple-packed data at the given grid index.
Formula: value = (R + X * 2^E) * 10^(-D)
Where R = reference_value, E = binary_scale, D = decimal_scale,
X = raw packed integer at the given index.
"""
def extract_value(%{bits_per_value: 0} = params, _data, _index) do
{:ok, params.reference_value * :math.pow(10, -params.decimal_scale)}
end
def extract_value(params, data, index) do
%{
reference_value: r,
binary_scale: e,
decimal_scale: d,
bits_per_value: n,
num_data_points: num
} = params
if index < 0 or index >= num do
{:error, :index_out_of_range}
else
x = extract_bits(data, index, n)
value = (r + x * :math.pow(2, e)) * :math.pow(10, -d)
{:ok, value}
end
end
defp extract_bits(data, index, bits_per_value) do
bit_offset = index * bits_per_value
byte_offset = div(bit_offset, 8)
remainder = rem(bit_offset, 8)
<<_skip::binary-size(byte_offset), _pad::size(remainder), x::size(bits_per_value)-unsigned-big, _rest::bitstring>> =
data
x
end
end