Skip to content

Commit e3dd516

Browse files
authored
Merge pull request #511 from jacob1299/fix/rrfs-s3-urls
Fix RRFS template to match current S3 bucket structure
2 parents 05785ac + 0ef2d2e commit e3dd516

1 file changed

Lines changed: 37 additions & 49 deletions

File tree

src/herbie/models/rrfs.py

Lines changed: 37 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -7,78 +7,66 @@
77
88
fxx : int
99
product : {"prs", "nat", "testbed", "ififip"}
10-
member : {"control", int}
11-
domain : {"conus", "alaska", "hawaii", "puerto rico", None}
10+
member : {None, int}
11+
None for deterministic run, int (1-5) for ensemble members
12+
domain : {"conus", "alaska", "hawaii", "puerto rico", "na"}
1213
13-
If product="natlev', then domain must be None
14+
If product="natlev", then domain should be "na"
1415
"""
1516

1617

1718
class rrfs:
1819
def template(self):
19-
self.DESCRIPTION = "Rapid Refresh Forecast System (RRFS) Ensemble"
20+
self.DESCRIPTION = "Rapid Refresh Forecast System (RRFS)"
2021
self.DETAILS = {
2122
"aws product description": "https://registry.opendata.aws/noaa-rrfs/",
2223
}
2324
self.HELP = HELP
2425

2526
self.PRODUCTS = {
26-
# Below are ensemble products found in ensprod/
27-
"prslev": "",
28-
"natlev": "",
29-
"testbed": "",
30-
"ififip": "",
27+
"prslev": "pressure level fields",
28+
"natlev": "native level fields",
29+
"testbed": "testbed fields",
30+
"ififip": "icing/freezing fields",
3131
}
3232

33-
# Format the member argument
34-
# member can be one of {'control', 'mem000#'}
35-
if isinstance(self.member, int):
36-
self.member = f"mem{self.member:04d}"
37-
3833
# Format the product parameter
3934
if self.product == "prs":
4035
self.product = "prslev"
4136
elif self.product == "nat":
4237
self.product = "natlev"
4338

44-
# Format the domain parameter
45-
if self.domain == "conus":
46-
self.domain = "conus" # We'll handle the "_3km" part in the URL generation
47-
elif self.domain == "alaska":
48-
self.domain = "ak"
49-
elif self.domain == "hawaii":
50-
self.domain = "hi"
51-
elif self.domain == "puerto rico":
52-
self.domain = "pr"
53-
elif self.domain is None:
54-
self.domain = ""
55-
56-
def generate_url(domain_suffix, member_prefix=""):
57-
url = f"https://noaa-rrfs-pds.s3.amazonaws.com/rrfs_a/rrfs_a.{self.date:%Y%m%d/%H}/{self.member}/rrfs.t{self.date:%H}z{member_prefix}.{self.product}.f{self.fxx:03d}.{domain_suffix}.grib2"
58-
return url.replace("..", ".")
39+
# Format the domain parameter (default to conus)
40+
domain_map = {"alaska": "ak", "hawaii": "hi", "puerto rico": "pr"}
41+
self.domain = getattr(self, "domain", None) or "conus"
42+
self.domain = domain_map.get(self.domain, self.domain)
5943

60-
urls = []
44+
# Resolution depends on the domain
45+
resolution = "2p5km" if self.domain in ("hi", "pr") else "3km"
6146

62-
# Handle different domain formats
63-
domain_suffixes = [self.domain]
64-
if self.domain == "conus":
65-
domain_suffixes = ["conus", "conus_3km"] # Prioritize newer format
47+
# Ensemble member (int) vs deterministic (None/other)
48+
self.member = getattr(self, "member", None)
6649

67-
# Handle different member formats
68-
member_prefixes = [""]
69-
if self.member.startswith("mem"):
70-
member_num = int(self.member[3:])
71-
member_prefixes = [f".m{member_num:02d}", ""] # Prioritize newer format
72-
73-
# Generate all possible URL combinations
74-
for member_prefix in member_prefixes:
75-
for domain_suffix in domain_suffixes:
76-
urls.append(generate_url(domain_suffix, member_prefix))
77-
78-
# Create separate sources for each URL
79-
self.SOURCES = {f"aws_{i}": url for i, url in enumerate(urls)}
80-
81-
self.LOCALFILE = f"{self.member}/{self.get_remoteFileName}"
50+
if isinstance(self.member, int):
51+
member_str = f"m{self.member:03d}"
52+
# Ensemble members are only available for the "na" domain
53+
self.SOURCES = {
54+
"aws": (
55+
f"https://noaa-rrfs-pds.s3.amazonaws.com/"
56+
f"rrfs_a/rrfsens.{self.date:%Y%m%d/%H}/{member_str}/"
57+
f"rrfs.t{self.date:%H}z.{member_str}.nbmfld.{resolution}.f{self.fxx:03d}.na.grib2"
58+
),
59+
}
60+
else:
61+
self.SOURCES = {
62+
"aws": (
63+
f"https://noaa-rrfs-pds.s3.amazonaws.com/"
64+
f"rrfs_a/rrfs.{self.date:%Y%m%d/%H}/"
65+
f"rrfs.t{self.date:%H}z.{self.product}.{resolution}.f{self.fxx:03d}.{self.domain}.grib2"
66+
),
67+
}
68+
69+
self.LOCALFILE = f"{self.get_remoteFileName}"
8270

8371

8472
class rrfs_old:

0 commit comments

Comments
 (0)