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.
44 lines
1.2 KiB
Elixir
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
|