Documentation
¶
Index ¶
- Constants
- Variables
- func AtmosIntervals(times []time.Time) []util.TimeInterval
- func BuildObjectPath(prefix, identifier string, t time.Time) string
- func CheckAtmosConversion(at AtmosByPoint, soa AtmosByPointSOA) error
- func FetchRadarImage(center math.Point2LL, radius float32, resolution int) (image.Image, math.Extent2D, error)
- func FullDataDays(metar, precip, atmos []time.Time) []util.TimeInterval
- func IdFromLevelIndex(i int) string
- func LevelIndexFromId(b []byte) int
- func METARIntervals(times []time.Time) []util.TimeInterval
- func ManifestPath(prefix string) string
- func MergeAndAlignToMidnight(intervals ...[]util.TimeInterval) []util.TimeInterval
- func MonthlyManifestPath(prefix, month string) string
- func MonthlyManifestPrefix(prefix string) string
- func ParseWeatherObjectPath(relativePath string) (identifier string, timestamp int64, err error)
- func PrecipIntervals(times []time.Time) []util.TimeInterval
- func PressureFromLevelIndex(i int) float32
- func RadarImageToDBZ(img image.Image) []byte
- type AtmosByPoint
- type AtmosByPointSOA
- type AtmosByTime
- type AtmosByTimeSOA
- type AtmosGrid
- type AtmosLevelsSOA
- type AtmosResult
- type AtmosSample
- type AtmosSampleStack
- type CompressedMETAR
- func (cm CompressedMETAR) Airports() iter.Seq[string]
- func (cm CompressedMETAR) GetAirportMETAR(icao string) ([]METAR, error)
- func (cm CompressedMETAR) GetAirportMETARSOA(icao string) (METARSOA, error)
- func (cm CompressedMETAR) Len() int
- func (cm CompressedMETAR) MarshalMsgpack() ([]byte, error)
- func (cm CompressedMETAR) Save(w io.Writer) error
- func (cm CompressedMETAR) SetAirportMETAR(icao string, metar []METAR) error
- func (cm *CompressedMETAR) UnmarshalMsgpack(b []byte) error
- type METAR
- func METARForTime(metar []METAR, t time.Time) METAR
- func SampleMETAR(metar []METAR, intervals []util.TimeInterval, avgHdg float32) *METAR
- func SampleMETARWithSpec(metar []METAR, intervals []util.TimeInterval, spec *WindSpecifier, ...) *METAR
- func SampleMatchingMETAR(metar []METAR, intervals []util.TimeInterval, match func(METAR) bool) *METAR
- type METARSOA
- type Manifest
- func GenerateManifest(paths map[string]int64, pathParser func(string) (string, int64, error)) (*Manifest, error)
- func GenerateManifestWithPrefix(paths map[string]int64, prefix string) (*Manifest, error)
- func LoadManifest(r io.Reader) (*Manifest, error)
- func MakeManifest(data RawManifest) *Manifest
- func MakeManifestFromMap(m map[string][]time.Time) (*Manifest, error)
- func NewManifest() *Manifest
- func (m *Manifest) Count() int
- func (m *Manifest) GetAllTimestamps() []time.Time
- func (m *Manifest) GetTimestamps(identifier string) ([]time.Time, bool)
- func (m *Manifest) RawManifest() RawManifest
- func (m *Manifest) Save(w io.Writer) error
- func (m *Manifest) SetTRACONTimestamps(tracon string, times []time.Time) error
- func (m *Manifest) TRACONs() []string
- func (m *Manifest) TotalEntries() int
- type Model
- type Precip
- type Provider
- type RawManifest
- type Sample
- type WindSample
- type WindSpecifier
Constants ¶
const METARFilename = "METAR-flate.msgpack.zst"
METARFilename is the standard filename for the consolidated METAR file
const ManifestFilename = "manifest-int64time.msgpack.zst"
ManifestFilename is the standard filename for int64-based compressed manifests
const NumSampleLevels = 40
This is fairly specialized to our needs we ingest from: at each lat-long, we store a vertical stack of 40 levels with samples from the source HRRR files (wind direction, speed, temperature, dewpoint, height). The vertical indexing of is low to high where LevelIndexFromId and IdFromLevelIndex perform the indexing and its inverse.
Variables ¶
var AtmosARTCCs = []string{
"ZBW", "ZJX", "ZLA", "ZNY",
}
var AtmosTRACONs = []string{
"A11", "A80", "A90", "AAC", "ABE", "ABQ", "AGS", "ALB", "ASE", "AUS", "AVL", "BGR", "BHM", "BIL", "BNA", "BOI",
"BTV", "BUF", "C90", "CHS", "CID", "CLE", "CLT", "COS", "CPR", "D01", "D10", "D21", "DAB", "EWR", "F11", "GSO",
"GSP", "GTF", "I90", "IND", "JAX", "L30", "M98", "MCI", "MDT", "MIA", "MKE", "N90", "NCT", "OKC", "P31", "P50",
"P80", "PCT", "PHL", "PIT", "PVD", "PWM", "R90", "RDU", "S46", "S56", "SAT", "SAV", "SBA", "SBN", "SCT", "SDF",
"SGF", "SYR", "TPA", "Y90",
"FAI",
}
vice -listscenarios 2>/dev/null | cut -d / -f 1 | uniq
Functions ¶
func AtmosIntervals ¶ added in v0.13.2
func AtmosIntervals(times []time.Time) []util.TimeInterval
AtmosIntervals converts atmosphere timestamps to time intervals suitable for weather data.
func BuildObjectPath ¶ added in v0.13.2
BuildObjectPath constructs a weather data object path from a prefix, identifier, and timestamp. Returns a path in the format: "prefix/identifier/{RFC3339 time}.msgpack.zst"
func CheckAtmosConversion ¶ added in v0.13.0
func CheckAtmosConversion(at AtmosByPoint, soa AtmosByPointSOA) error
func FetchRadarImage ¶
func FullDataDays ¶ added in v0.13.0
func FullDataDays(metar, precip, atmos []time.Time) []util.TimeInterval
FullDataDays computes time intervals where all three data sources (METAR, precip, atmos) have continuous coverage, aligned to full 24-hour periods at midnight UTC.
func IdFromLevelIndex ¶ added in v0.13.0
func LevelIndexFromId ¶ added in v0.13.0
func METARIntervals ¶ added in v0.13.2
func METARIntervals(times []time.Time) []util.TimeInterval
METARIntervals converts METAR timestamps to time intervals suitable for weather data.
func ManifestPath ¶ added in v0.13.2
ManifestPath returns the full path to a manifest file for a given prefix
func MergeAndAlignToMidnight ¶ added in v0.13.2
func MergeAndAlignToMidnight(intervals ...[]util.TimeInterval) []util.TimeInterval
MergeAndAlignToMidnight merges multiple sets of time intervals and aligns them to full 24-hour periods starting and ending at midnight UTC (0000Z).
func MonthlyManifestPath ¶ added in v0.13.2
MonthlyManifestPath returns the full path to a monthly manifest file. The month parameter should be in "YYYY-MM" format (e.g., "2025-08"). Returns a path like "prefix/manifest-int64time-YYYY-MM.msgpack.zst"
func MonthlyManifestPrefix ¶ added in v0.13.2
MonthlyManifestPrefix returns the prefix used for listing monthly manifest files. Returns a prefix like "prefix/manifest-int64time-"
func ParseWeatherObjectPath ¶ added in v0.13.2
ParseWeatherObjectPath extracts the TRACON/airport identifier and timestamp from a weather data object path. Expected format: "TRACON/2025-08-06T03:00:00Z.msgpack.zst"
func PrecipIntervals ¶ added in v0.13.2
func PrecipIntervals(times []time.Time) []util.TimeInterval
PrecipIntervals converts precipitation timestamps to time intervals suitable for weather data.
func PressureFromLevelIndex ¶ added in v0.13.0
PressureFromLevelIndex returns pressure in millibars at the level.
func RadarImageToDBZ ¶
Types ¶
type AtmosByPoint ¶ added in v0.13.0
type AtmosByPoint struct {
// Lat-longs to stack of levels
SampleStacks map[math.Point2LL]*AtmosSampleStack
}
func MakeAtmosByPoint ¶ added in v0.13.0
func MakeAtmosByPoint() AtmosByPoint
func (*AtmosByPoint) Average ¶ added in v0.13.0
func (ap *AtmosByPoint) Average() (math.Point2LL, *AtmosSampleStack)
Average returns the averaged location and atmospheric data across all sample stacks
func (AtmosByPoint) GetGrid ¶ added in v0.13.0
func (ap AtmosByPoint) GetGrid() *AtmosGrid
func (AtmosByPoint) ToSOA ¶ added in v0.13.0
func (ap AtmosByPoint) ToSOA() (AtmosByPointSOA, error)
type AtmosByPointSOA ¶ added in v0.13.0
type AtmosByPointSOA struct {
Lat, Long []float32
Levels [NumSampleLevels]AtmosLevelsSOA
}
For storage, this information is encoded in structure-of-arrays format, which makes it more compressible.
func MakeFallbackAtmosFromMETAR ¶ added in v0.13.2
func MakeFallbackAtmosFromMETAR(metar METAR, location math.Point2LL) (*AtmosByPointSOA, error)
MakeFallbackAtmosFromMETAR creates a simple AtmosByPointSOA from METAR wind data. This is used as a fallback when actual atmospheric data is not available for a TRACON. The resulting grid has a single point at the specified location with uniform wind at all altitude levels based on the METAR surface wind.
func (AtmosByPointSOA) ToAOS ¶ added in v0.13.0
func (atsoa AtmosByPointSOA) ToAOS() AtmosByPoint
type AtmosByTime ¶ added in v0.13.0
type AtmosByTime struct {
SampleStacks map[time.Time]*AtmosSampleStack
}
func (AtmosByTime) ToSOA ¶ added in v0.13.0
func (at AtmosByTime) ToSOA() (AtmosByTimeSOA, error)
type AtmosByTimeSOA ¶ added in v0.13.0
type AtmosByTimeSOA struct {
Times []int64 // Delta-encoded Unix timestamps
Levels [NumSampleLevels]AtmosLevelsSOA
}
AtmosByTimeSOA stores atmospheric data for multiple time points at a single location (used for offline weather packaging)
func (AtmosByTimeSOA) ToAOS ¶ added in v0.13.0
func (atsoa AtmosByTimeSOA) ToAOS() AtmosByTime
type AtmosGrid ¶ added in v0.13.0
func MakeAtmosGrid ¶ added in v0.13.0
func MakeAtmosGrid(sampleStacks map[math.Point2LL]*AtmosSampleStack) *AtmosGrid
func (*AtmosGrid) AltitudeForIndex ¶ added in v0.13.0
type AtmosLevelsSOA ¶ added in v0.13.0
type AtmosResult ¶ added in v0.13.0
type AtmosSample ¶ added in v0.13.0
type AtmosSample struct {
UComponent float32 // eastward velocity m/s
VComponent float32 // northward velocity m/s
Temperature float32 // Kelvin
Dewpoint float32 // Kelvin
Height float32 // geopotential height (meters)
}
AtmosSample stores wind as velocity vectors (direction the air mass is moving). UComponent is the eastward wind velocity in m/s (positive = moving east). VComponent is the northward wind velocity in m/s (positive = moving north). These match the standard GRIB2 UGRD/VGRD convention.
type AtmosSampleStack ¶ added in v0.13.0
type AtmosSampleStack struct {
Levels [NumSampleLevels]AtmosSample
}
type CompressedMETAR ¶ added in v0.13.2
type CompressedMETAR struct {
// contains filtered or unexported fields
}
CompressedMETAR is a collection of compressed METAR data indexed by ICAO code.
func LoadCompressedMETAR ¶ added in v0.13.2
func LoadCompressedMETAR(r io.Reader) (CompressedMETAR, error)
LoadCompressedMETAR reads a complete compressed METAR file The reader should be the zstd-compressed msgpack file.
func NewCompressedMETAR ¶ added in v0.13.2
func NewCompressedMETAR() CompressedMETAR
NewCompressedMETAR creates a new empty CompressedMETAR collection.
func (CompressedMETAR) Airports ¶ added in v0.13.2
func (cm CompressedMETAR) Airports() iter.Seq[string]
func (CompressedMETAR) GetAirportMETAR ¶ added in v0.13.2
func (cm CompressedMETAR) GetAirportMETAR(icao string) ([]METAR, error)
GetAirportMETAR retrieves and decodes METAR data for a specific ICAO airport code.
func (CompressedMETAR) GetAirportMETARSOA ¶ added in v0.13.2
func (cm CompressedMETAR) GetAirportMETARSOA(icao string) (METARSOA, error)
func (CompressedMETAR) Len ¶ added in v0.13.2
func (cm CompressedMETAR) Len() int
func (CompressedMETAR) MarshalMsgpack ¶ added in v0.13.2
func (cm CompressedMETAR) MarshalMsgpack() ([]byte, error)
MarshalMsgpack implements custom msgpack encoding for CompressedMETAR. This allows the unexported field 'm' to be properly serialized.
func (CompressedMETAR) Save ¶ added in v0.13.2
func (cm CompressedMETAR) Save(w io.Writer) error
SaveMETAR writes a complete METAR file (METARFilename format). The data should be a map of airport ICAO codes to compressed METARSOA data. The writer will receive zstd-compressed msgpack data.
func (CompressedMETAR) SetAirportMETAR ¶ added in v0.13.2
func (cm CompressedMETAR) SetAirportMETAR(icao string, metar []METAR) error
func (*CompressedMETAR) UnmarshalMsgpack ¶ added in v0.13.2
func (cm *CompressedMETAR) UnmarshalMsgpack(b []byte) error
UnmarshalMsgpack implements custom msgpack decoding for CompressedMETAR. This allows the unexported field 'm' to be properly deserialized.
type METAR ¶
type METAR struct {
ICAO string `json:"icaoId"`
Time time.Time
Temperature float32 `json:"temp"`
Dewpoint float32 `json:"dewp"`
Altimeter float32 `json:"altim"`
WindDir *int `json:"-"` // nil for variable winds, otherwise heading 0-360
WindSpeed int `json:"wspd"`
WindGust *int `json:"wgst"`
Raw string `json:"rawOb"`
// WindDirRaw and ReportTime are used for JSON unmarshaling only
WindDirRaw any `json:"wdir"` // nil or string "VRB" for variable, else number for heading
ReportTime string `json:"reportTime"`
}
This is as much of the METAR as we need at runtime.
func SampleMETAR ¶ added in v0.13.0
func SampleMETAR(metar []METAR, intervals []util.TimeInterval, avgHdg float32) *METAR
Given an average headings (e.g. runway directions) and a slice of valid time intervals, randomly sample a METAR entry with wind that is compatible with the headings.
func SampleMETARWithSpec ¶ added in v0.13.0
func SampleMETARWithSpec(metar []METAR, intervals []util.TimeInterval, spec *WindSpecifier, magVar float32) *METAR
SampleMETARWithSpec randomly samples a METAR that matches the wind specifier
func SampleMatchingMETAR ¶ added in v0.13.0
func SampleMatchingMETAR(metar []METAR, intervals []util.TimeInterval, match func(METAR) bool) *METAR
SampleMatchingMETAR randomly samples from METARs that match a predicate using reservoir sampling
func (METAR) Altimeter_inHg ¶
func (METAR) IsVMC ¶ added in v0.13.0
IsVMC returns true if Visual Meteorological Conditions apply VMC requires >= 3 miles visibility and >= 1000' ceiling AGL
func (*METAR) UnmarshalJSON ¶ added in v0.13.0
UnmarshalJSON handles converting WindDirRaw to WindDir
func (METAR) Visibility ¶ added in v0.13.0
Visibility extracts visibility in statute miles from the raw METAR
type METARSOA ¶ added in v0.13.0
type METARSOA struct {
// These are all delta coded
ReportTime [][]byte
Temperature []int16 // fixed point, one decimal digit
Dewpoint []int16 // fixed point, one decimal digit
Altimeter []int16 // fixed point, one decimal digit
WindDir []int16
WindSpeed []int16
WindGust []int16
// This is not; it's not worth delta encoding the raw METAR reports
// since there's generally not much character alignment between
// successive reports.
Raw []string
}
Structure-of-arrays representation of an array of METAR objects for better compressability.
func MakeMETARSOA ¶ added in v0.13.0
type Manifest ¶ added in v0.13.2
type Manifest struct {
// contains filtered or unexported fields
}
Manifest represents a weather data manifest that maps TRACONs/airports to compressed timestamps. The manifest provides efficient access to available data timestamps for each location.
func GenerateManifest ¶ added in v0.13.2
func GenerateManifest(paths map[string]int64, pathParser func(string) (string, int64, error)) (*Manifest, error)
GenerateManifest creates a manifest from a map of object paths to their sizes/timestamps. The pathParser function extracts the identifier and timestamp from each path. Timestamps are sorted, delta-encoded, and compressed for each identifier.
func GenerateManifestWithPrefix ¶ added in v0.13.2
GenerateManifestWithPrefix is a convenience function that generates a manifest from paths that include a prefix. The prefix is stripped before parsing. This is commonly used with storage backends that return full paths.
func LoadManifest ¶ added in v0.13.2
LoadManifest reads a manifest from an io.Reader. The manifest format is msgpack-encoded RawManifest, compressed with zstd.
func MakeManifest ¶ added in v0.13.2
func MakeManifest(data RawManifest) *Manifest
MakeManifest creates a manifest from raw manifest data. This is useful when loading data from storage systems.
func MakeManifestFromMap ¶ added in v0.13.2
func NewManifest ¶ added in v0.13.2
func NewManifest() *Manifest
NewManifest creates an empty manifest with caching enabled
func (*Manifest) Count ¶ added in v0.13.2
Count returns the number of TRACONs/airports in the manifest
func (*Manifest) GetAllTimestamps ¶ added in v0.13.2
GetAllTimestamps returns all timestamps from all TRACONs/airports in the manifest. The timestamps are collected in an unspecified order.
func (*Manifest) GetTimestamps ¶ added in v0.13.2
GetTimestamps retrieves and decompresses the timestamps for a specific TRACON/airport. Results are cached to avoid repeated decompression. Returns nil, false if the TRACON/airport is not in the manifest.
func (*Manifest) RawManifest ¶ added in v0.13.2
func (m *Manifest) RawManifest() RawManifest
RawManifest returns the underlying RawManifest for compatibility with storage systems that need the raw format.
func (*Manifest) Save ¶ added in v0.13.2
Save writes the manifest to an io.Writer in the standard format (msgpack + zstd compression)
func (*Manifest) SetTRACONTimestamps ¶ added in v0.13.2
func (*Manifest) TRACONs ¶ added in v0.13.2
TRACONs returns a sorted list of all TRACON/airport identifiers in the manifest
func (*Manifest) TotalEntries ¶ added in v0.13.2
TotalEntries returns the total number of timestamp entries across all TRACONs/airports
type Model ¶ added in v0.13.0
type Model struct {
// contains filtered or unexported fields
}
func (*Model) GetAtmosGrid ¶ added in v0.13.0
type Precip ¶ added in v0.13.0
Precip is the object type that is stored in GCS after wx ingest for precipitation.
type Provider ¶ added in v0.13.0
type Provider interface {
// Returns a map from TRACON to available time intervals.
// For providers with precip data, intervals represent when both precip and atmos are available.
// For providers without precip data, intervals represent when atmos is available.
GetAvailableTimeIntervals() map[string][]util.TimeInterval
// Best effort, may not have it for all airports, but no error is returned for that.
GetMETAR(airports []string) (map[string]METARSOA, error)
// Returns the item at-or-before the given time
GetPrecipURL(tracon string, t time.Time) (string, time.Time, error)
// Returns atmos, its time, the time for the next one in the series.
// If primaryAirport is non-empty and no atmos data is available, creates
// a fallback grid from the primary airport's METAR wind data.
GetAtmosGrid(tracon string, t time.Time, primaryAirport string) (*AtmosByPointSOA, time.Time, time.Time, error)
}
type RawManifest ¶ added in v0.13.2
RawManifest is the underlying storage format for manifests. It maps TRACON/airport identifiers to compressed, delta-encoded int64 Unix timestamps.
type Sample ¶
type Sample struct {
WindSample
// contains filtered or unexported fields
}
func LerpSample ¶ added in v0.13.0
func MakeSample ¶ added in v0.13.2
MakeSample creates a Sample from float32 values, quantizing them appropriately. Values are clamped to prevent overflow.
func MakeStandardSampleForAltitude ¶ added in v0.13.0
func (Sample) RelativeHumidity ¶ added in v0.13.0
func (Sample) Temperature ¶
Temperature returns the temperature in Celsius
type WindSample ¶
type WindSample struct {
// contains filtered or unexported fields
}
func (WindSample) Component ¶ added in v0.13.0
func (s WindSample) Component(course float32) float32
Component calculates the wind component along a given course in knots. Positive values indicate tailwind, negative values indicate headwind.
func (WindSample) Deflection ¶ added in v0.13.0
func (s WindSample) Deflection(v [2]float32) float32
Deflection calculates the heading correction needed to compensate for wind. Given a velocity vector v, it returns the deflection angle that should be subtracted from the heading to fly into the wind.
func (WindSample) WindDirection ¶ added in v0.13.0
func (s WindSample) WindDirection() float32
func (WindSample) WindSpeed ¶ added in v0.13.0
func (s WindSample) WindSpeed() float32
func (WindSample) WindVec ¶ added in v0.13.0
func (s WindSample) WindVec() [2]float32
WindVec returns the dequantized wind velocity vector in nm/s
type WindSpecifier ¶ added in v0.13.0
type WindSpecifier struct {
Direction string `json:"direction,omitempty"` // e.g., "30-90", "270", empty for any
Speed string `json:"speed,omitempty"` // e.g., "5+", "5-", "5-15", empty for any
FlightRules string `json:"flight_rules,omitempty"` // "VMC" or "IMC", empty defaults to "VMC"
}
WindSpecifier defines constraints for sampling weather data
func (*WindSpecifier) Matches ¶ added in v0.13.0
func (ws *WindSpecifier) Matches(metar METAR, magVar float32) bool
Matches checks if a METAR matches this wind specifier
func (*WindSpecifier) Validate ¶ added in v0.13.0
func (ws *WindSpecifier) Validate() error
Validate checks if the wind specifier is valid