@@ -202,3 +202,129 @@ def template(self):
202202 }
203203 self .IDX_SUFFIX = [".idx" ]
204204 self .LOCALFILE = f"{ self .get_remoteFileName } "
205+
206+
207+ class aigefs :
208+ """AI Global Ensemble Forecast System (AIGEFS).
209+ """
210+
211+ def template (self ):
212+ self .DESCRIPTION = "AI Global Ensemble Forecast System (AIGEFS)"
213+ self .DETAILS = {
214+ "NOMADS" : "https://www.nco.ncep.noaa.gov/pmb/products/aigefs/" ,
215+ }
216+
217+ self .PRODUCTS = {
218+ "pres" : "pressure fields, 0.25 degree resolution" ,
219+ "sfc" : "surface fields, 0.25 degree resolution" ,
220+ }
221+
222+ if self .product is None :
223+ # Just select the first PRODUCT as default
224+ self .product = list (self .PRODUCTS )[0 ]
225+
226+ if self .member == 0 :
227+ self .member = "mem000"
228+ elif self .member == "control" :
229+ self .member = "mem000"
230+ elif isinstance (self .member , int ):
231+ self .member = f"mem{ self .member :02d} "
232+
233+ filedir = f"aigefs.{ self .date :%Y%m%d/%H} "
234+ if self .member in ["spr" , "avg" ]:
235+ filepaths = {
236+ "sfc" : f"{ filedir } /ensstat/products/atmos/grib2/aigefs.t{ self .date :%H} z.sfc.{ self .member } .f{ self .fxx :03d} " ,
237+ "pres" : f"{ filedir } /ensstat/products/atmos/grib2/aigefs.t{ self .date :%H} z.pres.{ self .member } .f{ self .fxx :03d} " ,
238+ }
239+ else :
240+ filepaths = {
241+ "sfc" : f"{ filedir } /{ self .member } /model/atmos/grib2/aigefs.t{ self .date :%H} z.sfc.f{ self .fxx :03d} " ,
242+ "pres" : f"{ filedir } /{ self .member } /model/atmos/grib2/aigefs.t{ self .date :%H} z.pres.f{ self .fxx :03d} " ,
243+ }
244+
245+ valid_members = {
246+ "pres" : [f"mem{ i :03d} " for i in range (0 , 31 )] + ["control" , "spr" , "avg" ],
247+ "sfc" : [f"mem{ i :03d} " for i in range (0 , 31 )] + ["control" , "spr" , "avg" ],
248+ }
249+
250+ filepath = filepaths .get (self .product )
251+ if filepath is None :
252+ raise ValueError (
253+ f"product={ self .product } not recognized. Must be one of { self .PRODUCTS .keys ()} "
254+ )
255+
256+ _member = valid_members .get (self .product )
257+ if _member is not None and self .member not in _member :
258+ raise ValueError (
259+ f"For AIGEFS product { self .product } , member must be one of { _member } "
260+ )
261+
262+ self .SOURCES = {
263+ "nomads" : f"https://nomads.ncep.noaa.gov/pub/data/nccf/com/aigefs/prod/{ filepath } .grib2"
264+ }
265+
266+ self .IDX_SUFFIX = [".grib2.idx" ]
267+ self .LOCALFILE = f"aigefs.t{ self .date :%H} z.{ self .product } .{ self .member } .f{ self .fxx :03d} "
268+
269+
270+ class hgefs :
271+ """Hybrid Ensemble Forecast System (HGEFS).
272+ """
273+
274+ def template (self ):
275+ self .DESCRIPTION = "Hybrid Global Ensemble Forecast System (HGEFS)"
276+ self .DETAILS = {
277+ "NOMADS" : "https://www.nco.ncep.noaa.gov/pmb/products/hgefs/" ,
278+ }
279+
280+ self .PRODUCTS = {
281+ "pres" : "pressure fields, 0.25 degree resolution" ,
282+ "sfc" : "surface fields, 0.25 degree resolution" ,
283+ }
284+
285+ if self .product is None :
286+ # Just select the first PRODUCT as default
287+ self .product = list (self .PRODUCTS )[0 ]
288+
289+ if self .member == 0 :
290+ self .member = "mem000"
291+ elif self .member == "control" :
292+ self .member = "mem000"
293+ elif isinstance (self .member , int ):
294+ self .member = f"mem{ self .member :02d} "
295+
296+ filedir = f"hgefs.{ self .date :%Y%m%d/%H} "
297+ if self .member in ["spr" , "avg" ]:
298+ filepaths = {
299+ "sfc" : f"{ filedir } /ensstat/products/atmos/grib2/hgefs.t{ self .date :%H} z.sfc.{ self .member } .f{ self .fxx :03d} " ,
300+ "pres" : f"{ filedir } /ensstat/products/atmos/grib2/hgefs.t{ self .date :%H} z.pres.{ self .member } .f{ self .fxx :03d} " ,
301+ }
302+ else :
303+ filepaths = {
304+ "sfc" : f"{ filedir } /{ self .member } /model/atmos/grib2/hgefs.t{ self .date :%H} z.sfc.f{ self .fxx :03d} " ,
305+ "pres" : f"{ filedir } /{ self .member } /model/atmos/grib2/hgefs.t{ self .date :%H} z.pres.f{ self .fxx :03d} " ,
306+ }
307+
308+ valid_members = {
309+ "pres" : ["spr" , "avg" ],
310+ "sfc" : ["spr" , "avg" ],
311+ }
312+
313+ filepath = filepaths .get (self .product )
314+ if filepath is None :
315+ raise ValueError (
316+ f"product={ self .product } not recognized. Must be one of { self .PRODUCTS .keys ()} "
317+ )
318+
319+ _member = valid_members .get (self .product )
320+ if _member is not None and self .member not in _member :
321+ raise ValueError (
322+ f"For HGEFS product { self .product } , member must be one of { _member } "
323+ )
324+
325+ self .SOURCES = {
326+ "nomads" : f"https://nomads.ncep.noaa.gov/pub/data/nccf/com/hgefs/prod/{ filepath } .grib2"
327+ }
328+
329+ self .IDX_SUFFIX = [".grib2.idx" ]
330+ self .LOCALFILE = f"hgefs.t{ self .date :%H} z.{ self .product } .{ self .member } .f{ self .fxx :03d} "
0 commit comments