forked from gsn/predictor
updated downloader
This commit is contained in:
parent
ca95e06ab7
commit
8e9f117799
30 changed files with 1209 additions and 698 deletions
|
|
@ -1,23 +1,130 @@
|
|||
package grib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.intra.yksa.space/gsn/predictor/internal/pkg/errcodes"
|
||||
env "github.com/caarlos0/env/v11"
|
||||
)
|
||||
|
||||
// DatasetConfig описывает параметры GFS-датасета: сетку, временные шаги,
|
||||
// уровни давления и URL для загрузки.
|
||||
type DatasetConfig struct {
|
||||
// Сетка
|
||||
Resolution float64 // шаг сетки в градусах (0.25 или 0.5)
|
||||
NLat int // точек по широте (721 для 0.25°, 361 для 0.5°)
|
||||
NLon int // точек по долготе (1440 для 0.25°, 720 для 0.5°)
|
||||
|
||||
// Время
|
||||
NT int // кол-во временных шагов (97 для 0–96 ч с шагом 1)
|
||||
MaxHour int // последний час прогноза (96)
|
||||
TimeStep int // интервал между шагами, часы (1 или 3)
|
||||
|
||||
// Вертикаль
|
||||
NP int // кол-во уровней давления
|
||||
Levels []float64 // уровни давления в гПа, по убыванию (1000 … 1)
|
||||
|
||||
// Переменные в кубе (порядок важен: индексы 0, 1, 2, …)
|
||||
NVar int // кол-во переменных
|
||||
Variables []string // GRIB-имена для фильтрации idx (HGT, UGRD, VGRD)
|
||||
|
||||
// URL загрузки (fmt-шаблоны: date, hour, hour, step)
|
||||
URLMask string // основной pgrb2
|
||||
URLMaskB string // дополнительный pgrb2b
|
||||
|
||||
// Имена файлов
|
||||
FileSuffix string // токен разрешения в именах файлов ("0p25", "0p50")
|
||||
}
|
||||
|
||||
// SizePerVar возвращает размер одной переменной в кубе, байт.
|
||||
func (dc *DatasetConfig) SizePerVar() int64 {
|
||||
return int64(dc.NT) * int64(dc.NP) * int64(dc.NLat) * int64(dc.NLon) * 4
|
||||
}
|
||||
|
||||
// CubeSize возвращает полный размер куба, байт.
|
||||
func (dc *DatasetConfig) CubeSize() int64 {
|
||||
return dc.SizePerVar() * int64(dc.NVar)
|
||||
}
|
||||
|
||||
// GridSize возвращает NLat * NLon.
|
||||
func (dc *DatasetConfig) GridSize() int {
|
||||
return dc.NLat * dc.NLon
|
||||
}
|
||||
|
||||
// InvResolution возвращает 1/Resolution — множитель для перевода координат в индексы.
|
||||
func (dc *DatasetConfig) InvResolution() float64 {
|
||||
return 1.0 / dc.Resolution
|
||||
}
|
||||
|
||||
// Steps возвращает список часов прогноза [0, TimeStep, 2*TimeStep, …, MaxHour].
|
||||
func (dc *DatasetConfig) Steps() []int {
|
||||
out := make([]int, 0, dc.NT)
|
||||
for h := 0; h <= dc.MaxHour; h += dc.TimeStep {
|
||||
out = append(out, h)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// FileName возвращает имя основного GRIB-файла (pgrb2).
|
||||
func (dc *DatasetConfig) FileName(run time.Time, step int) string {
|
||||
return fmt.Sprintf("gfs.t%02dz.pgrb2.%s.f%03d", run.Hour(), dc.FileSuffix, step)
|
||||
}
|
||||
|
||||
// FileNameB возвращает имя вторичного GRIB-файла (pgrb2b).
|
||||
func (dc *DatasetConfig) FileNameB(run time.Time, step int) string {
|
||||
return fmt.Sprintf("gfs.t%02dz.pgrb2b.%s.f%03d", run.Hour(), dc.FileSuffix, step)
|
||||
}
|
||||
|
||||
// GribURL возвращает URL основного GRIB-файла.
|
||||
func (dc *DatasetConfig) GribURL(run time.Time, step int) string {
|
||||
return fmt.Sprintf(dc.URLMask, run.Format("20060102"), run.Hour(), run.Hour(), step)
|
||||
}
|
||||
|
||||
// GribURLB возвращает URL вторичного GRIB-файла.
|
||||
func (dc *DatasetConfig) GribURLB(run time.Time, step int) string {
|
||||
return fmt.Sprintf(dc.URLMaskB, run.Format("20060102"), run.Hour(), run.Hour(), step)
|
||||
}
|
||||
|
||||
// DefaultDatasetConfig возвращает конфиг GFS 0.25° / 1 час / 47 уровней.
|
||||
func DefaultDatasetConfig() DatasetConfig {
|
||||
return DatasetConfig{
|
||||
Resolution: 0.25,
|
||||
NLat: 721,
|
||||
NLon: 1440,
|
||||
|
||||
NT: 97,
|
||||
MaxHour: 96,
|
||||
TimeStep: 1,
|
||||
|
||||
NP: 47,
|
||||
Levels: []float64{
|
||||
1000, 975, 950, 925, 900, 875, 850, 825, 800, 775,
|
||||
750, 725, 700, 675, 650, 625, 600, 575, 550, 525,
|
||||
500, 475, 450, 425, 400, 375, 350, 325, 300, 275,
|
||||
250, 225, 200, 175, 150, 125, 100, 70, 50, 30,
|
||||
20, 10, 7, 5, 3, 2, 1,
|
||||
},
|
||||
|
||||
NVar: 3,
|
||||
Variables: []string{"HGT", "UGRD", "VGRD"},
|
||||
|
||||
URLMask: "https://noaa-gfs-bdp-pds.s3.amazonaws.com/gfs.%s/%02d/atmos/gfs.t%02dz.pgrb2.0p25.f%03d",
|
||||
URLMaskB: "https://noaa-gfs-bdp-pds.s3.amazonaws.com/gfs.%s/%02d/atmos/gfs.t%02dz.pgrb2b.0p25.f%03d",
|
||||
|
||||
FileSuffix: "0p25",
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type Config struct {
|
||||
Dir string `env:"DIR" envDefault:"C:/tmp/grib"`
|
||||
TTL time.Duration `env:"TTL" envDefault:"48h"`
|
||||
CacheTTL time.Duration `env:"CACHE_TTL" envDefault:"1h"`
|
||||
Parallel int `env:"PARALLEL" envDefault:"8"`
|
||||
DatasetURL string `env:"DATASET_URL" envDefault:"https://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod"`
|
||||
// S3 configuration
|
||||
UseS3 bool `env:"USE_S3" envDefault:"true"`
|
||||
S3Bucket string `env:"S3_BUCKET" envDefault:"noaa-gfs-bdp-pds"`
|
||||
S3Region string `env:"S3_REGION" envDefault:"us-east-1"`
|
||||
S3Timeout time.Duration `env:"S3_TIMEOUT" envDefault:"300s"`
|
||||
Dir string `env:"DIR" envDefault:"C:/tmp/grib"`
|
||||
TTL time.Duration `env:"TTL" envDefault:"48h"`
|
||||
CacheTTL time.Duration `env:"CACHE_TTL" envDefault:"1h"`
|
||||
Parallel int `env:"PARALLEL" envDefault:"8"`
|
||||
|
||||
Dataset DatasetConfig
|
||||
}
|
||||
|
||||
func NewConfig() (*Config, error) {
|
||||
|
|
@ -27,6 +134,6 @@ func NewConfig() (*Config, error) {
|
|||
}); err != nil {
|
||||
return nil, errcodes.Wrap(err, "failed to parse GRIB config")
|
||||
}
|
||||
|
||||
cfg.Dataset = DefaultDatasetConfig()
|
||||
return cfg, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue