Aliases: add module aliases for 9 nested module references Apply: replace apply/3 with direct module attribute calls Line length: break 1 long spec line Refactoring: extract helpers to reduce complexity and nesting in show.ex, radio.ex, weather workers, terrain, duct detection, backfill dashboard, contact map, and mix tasks
144 lines
4.5 KiB
Elixir
144 lines
4.5 KiB
Elixir
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
|