Table of Contents

Class WeatherRequests

Namespace
EncDotNet.S100.Collections.Weather
Assembly
EncDotNet.S100.Collections.dll

Builds the requests the weather services in the Library answer (#1075; design note weather-sources.md §6.3): GRIB filter URLs, GRIB2 file and .idx URLs, api.weather.gov alert queries and ERDDAP griddap subsets. Pure functions, so every URL can be checked without a network.

public static class WeatherRequests
Inheritance
WeatherRequests
Inherited Members

Fields

ErddapMaxAxisPoints

The most points a griddap subset asks for along latitude or longitude: 1500. A finer axis is strided (ErddapGriddapUri(Uri, WeatherServiceDataset, IReadOnlyList<ErddapAxis>, GeoBounds?, DateTimeOffset, DateTimeOffset)), so a 0.01° analysis over a wide area stays a few megabytes a day.

public const int ErddapMaxAxisPoints = 1500

Field Value

int

MaxZonesPerRequest

The most zone codes one alerts request names; more are asked for by marine area.

public const int MaxZonesPerRequest = 50

Field Value

int

Methods

CandidateRuns(DateTimeOffset, int, int)

The runs to try, newest first: the last cadenceHours cycle at or before now, then each earlier cycle, count in all.

public static IReadOnlyList<DateTimeOffset> CandidateRuns(DateTimeOffset now, int cadenceHours, int count)

Parameters

now DateTimeOffset
cadenceHours int
count int

Returns

IReadOnlyList<DateTimeOffset>

ErddapGriddapUri(Uri, WeatherServiceDataset, IReadOnlyList<ErddapAxis>, GeoBounds?, DateTimeOffset, DateTimeOffset)

A griddap subset of an ERDDAP dataset as NetCDF (griddap/<id>.nc?…): each variable over start to end, the area, and the first index of any other axis (a depth or height of one value). Latitude and longitude are strided when the area would take more than ErddapMaxAxisPoints points along them at the axis's spacing (Spacing).

public static Uri ErddapGriddapUri(Uri erddapUri, WeatherServiceDataset dataset, IReadOnlyList<ErddapAxis> axes, GeoBounds? area, DateTimeOffset start, DateTimeOffset end)

Parameters

erddapUri Uri

The ERDDAP root (…/erddap/).

dataset WeatherServiceDataset

The dataset.

axes IReadOnlyList<ErddapAxis>

The dataset's axes, in order, as its metadata lists them.

area GeoBounds?

The area, or null for all of it.

start DateTimeOffset

The first time (UTC).

end DateTimeOffset

The last time (UTC).

Returns

Uri

ErddapInfoUri(Uri, string)

The info/<id>/index.json metadata of an ERDDAP dataset.

public static Uri ErddapInfoUri(Uri erddapUri, string datasetId)

Parameters

erddapUri Uri

The ERDDAP root (…/erddap/).

datasetId string

The dataset id.

Returns

Uri

FilePath(WeatherService, DateTimeOffset, int)

The path of one forecast hour's file below the service's data root, from its File template.

public static string FilePath(WeatherService service, DateTimeOffset run, int hour)

Parameters

service WeatherService

A GRIB2 service.

run DateTimeOffset

The run (UTC).

hour int

The forecast hour.

Returns

string

FileUri(WeatherService, DateTimeOffset, int)

The URL of one forecast hour's whole GRIB2 file under the service's data root.

public static Uri FileUri(WeatherService service, DateTimeOffset run, int hour)

Parameters

service WeatherService
run DateTimeOffset
hour int

Returns

Uri

FormatRun(DateTimeOffset)

A run as files and the Library name it: 2026-10-28 00Z.

public static string FormatRun(DateTimeOffset run)

Parameters

run DateTimeOffset

Returns

string

GribFilterUri(Uri, WeatherService, IReadOnlyList<WeatherServiceParameter>, GeoBounds?, DateTimeOffset, int)

A NOMADS GRIB filter request for one forecast hour (filter_gfswave.pl?dir=…&file=…): var_X=on for each parameter, lev_Y=on for each of their levels (spaces as underscores, as the filter's form names them), and the area as a subregion. The filter returns the cross product of the variables and levels, so an extra field can come back; the GRIB2 reader lists it.

public static Uri GribFilterUri(Uri filterUri, WeatherService service, IReadOnlyList<WeatherServiceParameter> parameters, GeoBounds? area, DateTimeOffset run, int hour)

Parameters

filterUri Uri

The filter script.

service WeatherService

The GRIB2 service.

parameters IReadOnlyList<WeatherServiceParameter>

The parameters.

area GeoBounds?

The area, or null for the whole grid.

run DateTimeOffset

The run (UTC).

hour int

The forecast hour.

Returns

Uri

Remarks

Checked against the live filters (#1075): they take −180 to 180 or 0 to 360 longitudes alike, and an area across the antimeridian only as a west edge with an east edge past 180° (170° to 190°; 170° to −170° returns nothing, as does a box wider than 360°). The edges are inclusive except the east one on the GFS-Wave grid, whose longitudes sit a few millionths of a degree east of the grid (292.000007°), so rightlon is asked for half a cell further east, but not past 180° (the reader takes a column at 180.000007° as crossing it) or a turn past the west edge.

IndexUri(WeatherService, DateTimeOffset, int)

The URL of the .idx inventory beside FileUri(WeatherService, DateTimeOffset, int).

public static Uri IndexUri(WeatherService service, DateTimeOffset run, int hour)

Parameters

service WeatherService
run DateTimeOffset
hour int

Returns

Uri

IndexUriOf(Uri)

The .idx inventory URL beside a GRIB2 file URL.

public static Uri IndexUriOf(Uri gribFile)

Parameters

gribFile Uri

Returns

Uri

NwsAlertsUri(Uri, IReadOnlyList<string>)

The active alerts of api.weather.gov (alertsUri, …/alerts/active) for marine zones: ?zone= with up to MaxZonesPerRequest codes, else ?area= with their marine areas (the first two letters of a zone code, AN for ANZ535), else, with no zones, every marine alert (?region_type=marine).

public static Uri NwsAlertsUri(Uri alertsUri, IReadOnlyList<string> zones)

Parameters

alertsUri Uri
zones IReadOnlyList<string>

Returns

Uri

OneSideOfAntimeridian(GeoBounds, out bool)

The part of area one grid download can hold: the area itself, or, for an area across the antimeridian, its wider side of 180° (the west side on a tie). The weather readers can't open a regional grid that crosses 180° (WeatherGridLayout), though the GRIB filter and ERDDAP would serve one.

public static GeoBounds OneSideOfAntimeridian(GeoBounds area, out bool clipped)

Parameters

area GeoBounds

The chosen area.

clipped bool

True when the area crossed the antimeridian and was cut to one side.

Returns

GeoBounds

Rounded(GeoBounds, double)

The area rounded out to whole grid cells (gridDegrees, 0 for none), clamped to ±90° latitude. Longitudes are −180 to 180, and an area across the antimeridian keeps its west edge and gets an east edge past 180° (170° to 190°), as the GRIB filter takes it.

public static (double South, double West, double North, double East) Rounded(GeoBounds area, double gridDegrees)

Parameters

area GeoBounds
gridDegrees double

Returns

(double South, double West, double North, double East)