defmodule Microwaveprop.Weather.Grib2.ComplexPackingTest do use ExUnit.Case, async: true alias Microwaveprop.Weather.Grib2.ComplexPacking alias Microwaveprop.Weather.Grib2.LambertConformal alias Microwaveprop.Weather.Grib2.Section @fixture_path "test/fixtures/grib2/hrrr_tmp_2m.grib2" describe "extract_value/3 with real HRRR fixture" do @tag :slow 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 :slow 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 :slow 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}} = 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 :slow 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 describe "extract_values/3" do @tag :slow test "batch extracts multiple values matching individual calls" do if File.exists?(@fixture_path) do fixture = File.read!(@fixture_path) {:ok, parsed} = Section.parse_message(fixture) indices = [0, 1000, 100_000, 500_000, 1_000_000] {:ok, batch_result} = ComplexPacking.extract_values(parsed.packing_params, parsed.data, indices) assert map_size(batch_result) == length(indices) # Each batch value should match individual extraction for idx <- indices do {:ok, individual} = ComplexPacking.extract_value(parsed.packing_params, parsed.data, idx) assert_in_delta batch_result[idx], individual, 0.001, "Index #{idx}: batch #{batch_result[idx]} != individual #{individual}" end else :ok end end @tag :slow test "returns values in meteorological range" do if File.exists?(@fixture_path) do fixture = File.read!(@fixture_path) {:ok, parsed} = Section.parse_message(fixture) indices = [0, 500_000, 1_905_140] {:ok, result} = ComplexPacking.extract_values(parsed.packing_params, parsed.data, indices) for idx <- indices do assert result[idx] > 200.0 and result[idx] < 340.0, "Index #{idx}: expected 200-340K, got #{result[idx]}" end else :ok end end end end