Add Wgrib2 module that shells out to wgrib2 binary for fast GRIB2 grid extraction using -lola (nearest-neighbor to regular lat-lon grid). Falls back to pure-Elixir decoder if wgrib2 is not installed. Also: parallel GRIB2 range downloads, merge adjacent byte ranges, skip corrupt messages instead of failing, pressure fetch is optional.
43 lines
1.2 KiB
Elixir
43 lines
1.2 KiB
Elixir
defmodule Microwaveprop.Propagation.Grid do
|
|
@moduledoc "CONUS grid definition for propagation scoring. 0.5 degree resolution (~55 km)."
|
|
|
|
@lat_min 25.0
|
|
@lat_max 50.0
|
|
@lon_min -125.0
|
|
@lon_max -66.0
|
|
@step 0.5
|
|
|
|
@doc "Returns all grid points as `{lat, lon}` tuples covering CONUS at 0.5 degree spacing."
|
|
def conus_points do
|
|
for lat <- float_range(@lat_min, @lat_max, @step),
|
|
lon <- float_range(@lon_min, @lon_max, @step) do
|
|
{Float.round(lat, 3), Float.round(lon, 3)}
|
|
end
|
|
end
|
|
|
|
@doc "Returns the grid step size in degrees."
|
|
def step, do: @step
|
|
|
|
@doc "Returns the CONUS bounding box as a map."
|
|
def bounds, do: %{lat_min: @lat_min, lat_max: @lat_max, lon_min: @lon_min, lon_max: @lon_max}
|
|
|
|
@doc "Returns the grid specification for wgrib2 -lola extraction."
|
|
def wgrib2_grid_spec do
|
|
lon_count = round((@lon_max - @lon_min) / @step) + 1
|
|
lat_count = round((@lat_max - @lat_min) / @step) + 1
|
|
|
|
%{
|
|
lon_start: @lon_min,
|
|
lon_count: lon_count,
|
|
lon_step: @step,
|
|
lat_start: @lat_min,
|
|
lat_count: lat_count,
|
|
lat_step: @step
|
|
}
|
|
end
|
|
|
|
defp float_range(start, stop, step) do
|
|
count = round((stop - start) / step) + 1
|
|
Enum.map(0..(count - 1), fn i -> start + i * step end)
|
|
end
|
|
end
|