prop/test/microwaveprop/weather/grib2/complex_packing_test.exs
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

95 lines
3 KiB
Elixir

defmodule Microwaveprop.Weather.Grib2.ComplexPackingTest do
use ExUnit.Case, async: true
alias Microwaveprop.Weather.Grib2.ComplexPacking
alias Microwaveprop.Weather.Grib2.Section
@fixture_path "test/fixtures/grib2/hrrr_tmp_2m.grib2"
describe "extract_value/3 with real HRRR fixture" do
@tag :fixture
test "extracts a temperature value within meteorological range" do
if File.exists?(@fixture_path) do
fixture = File.read!(@fixture_path)
{:ok, parsed} = Section.parse_message(fixture)
# First grid point (index 0)
{:ok, value} =
ComplexPacking.extract_value(parsed.packing_params, parsed.data, 0)
# Should be a temperature in Kelvin (roughly 200-340K)
assert value > 200.0 and value < 340.0,
"Expected temperature 200-340K, got #{value}"
else
IO.puts("Skipping fixture test — #{@fixture_path} not found")
:ok
end
end
@tag :fixture
test "extracts values at multiple indices" do
if File.exists?(@fixture_path) do
fixture = File.read!(@fixture_path)
{:ok, parsed} = Section.parse_message(fixture)
# Check several indices across the grid
for idx <- [0, 1000, 100_000, 500_000, 1_000_000, 1_905_140] do
{:ok, value} =
ComplexPacking.extract_value(parsed.packing_params, parsed.data, idx)
assert value > 200.0 and value < 340.0,
"Index #{idx}: expected 200-340K, got #{value}"
end
else
:ok
end
end
@tag :fixture
test "Dallas area temperature is reasonable for a US city" do
if File.exists?(@fixture_path) do
fixture = File.read!(@fixture_path)
{:ok, parsed} = Section.parse_message(fixture)
grid = parsed.grid_params
{:ok, {i, j}} = Microwaveprop.Weather.Grib2.LambertConformal.to_grid_index(grid, 32.78, -96.8)
index = j * grid.nx + i
{:ok, value} =
ComplexPacking.extract_value(parsed.packing_params, parsed.data, index)
# Dallas in March — Kelvin should be roughly 270-310K (roughly -3C to 37C)
temp_c = value - 273.15
assert temp_c > -10.0 and temp_c < 45.0,
"Dallas temp #{Float.round(temp_c, 1)}C seems unreasonable"
else
:ok
end
end
end
describe "decode_all/2" do
@tag :fixture
test "decodes all values from fixture" do
if File.exists?(@fixture_path) do
fixture = File.read!(@fixture_path)
{:ok, parsed} = Section.parse_message(fixture)
{:ok, values_arr} = ComplexPacking.decode_all(parsed.packing_params, parsed.data)
assert :array.size(values_arr) == parsed.packing_params.num_data_points
# Check a sample of values are in reasonable temperature range
for idx <- [0, 100_000, 500_000, 1_000_000, 1_905_140] do
val = :array.get(idx, values_arr)
assert val > 200.0 and val < 340.0,
"Index #{idx}: expected 200-340K, got #{val}"
end
else
:ok
end
end
end
end