|
7 | 7 |
|
8 | 8 | fxx : int |
9 | 9 | 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"} |
12 | 13 |
|
13 | | -If product="natlev', then domain must be None |
| 14 | +If product="natlev", then domain should be "na" |
14 | 15 | """ |
15 | 16 |
|
16 | 17 |
|
17 | 18 | class rrfs: |
18 | 19 | def template(self): |
19 | | - self.DESCRIPTION = "Rapid Refresh Forecast System (RRFS) Ensemble" |
| 20 | + self.DESCRIPTION = "Rapid Refresh Forecast System (RRFS)" |
20 | 21 | self.DETAILS = { |
21 | 22 | "aws product description": "https://registry.opendata.aws/noaa-rrfs/", |
22 | 23 | } |
23 | 24 | self.HELP = HELP |
24 | 25 |
|
25 | 26 | 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", |
31 | 31 | } |
32 | 32 |
|
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 | | - |
38 | 33 | # Format the product parameter |
39 | 34 | if self.product == "prs": |
40 | 35 | self.product = "prslev" |
41 | 36 | elif self.product == "nat": |
42 | 37 | self.product = "natlev" |
43 | 38 |
|
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) |
59 | 43 |
|
60 | | - urls = [] |
| 44 | + # Resolution depends on the domain |
| 45 | + resolution = "2p5km" if self.domain in ("hi", "pr") else "3km" |
61 | 46 |
|
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) |
66 | 49 |
|
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}" |
82 | 70 |
|
83 | 71 |
|
84 | 72 | class rrfs_old: |
|
0 commit comments