NCEP obs refactor#966
Conversation
Greptile SummaryThis PR refactors
|
| Filename | Overview |
|---|---|
| earth2studio/data/ncep_obs.py | New module introducing _NCEPObsStore Protocol and _NCEPObsSourceBase; clean separation of concerns, well-structured with appropriate abstract hooks and schema resolution logic |
| earth2studio/data/nnja.py | Decomposes _NNJAObsBase into _NNJAObsStore (transport) and _NNJAObsSourceBase (lifecycle wiring); NNJAObsConv public API and behavior preserved with correct MRO delegation and warn-only missing-file handler |
| test/data/test_nnja.py | Patch targets updated to ncep_obs module; new asyncio test validates store contract and lifecycle, covering fetch delegation, URI dedup, and attrs propagation |
Reviews (1): Last reviewed commit: "rename to ncep_obs" | Re-trigger Greptile
|
Note: this retains the original time request semantics of NNJAObsConv. Can patch in future PR: #967 |
Exercise the three-operation store seam through the synchronous __call__ path so cleanup delegation is verified, including that cleanup still runs when the request fails mid-flight.
| from earth2studio.utils.type import TimeArray, TimeTolerance, VariableArray | ||
|
|
||
|
|
||
| class _NCEPObsStore(Protocol): |
There was a problem hiding this comment.
lets not create other interfaces... the interfaces are in base.py
focus on mixins, not protocals and base classes.
Replace the _NCEPObsStore protocol and the _NCEPObsSourceBase / _NNJAObsSourceBase / _NNJAObsStore hierarchy with mixins: NCEPObsRequestMixin (shared request lifecycle) and NNJAObsArchiveMixin (NNJA S3 transport, cache, six-hour validation). NNJAObsConv composes both. Fold the request mixin into utils_ncep and delete the ncep_obs module so shared NCEP code lives in one util file rather than a module that is not itself a data source.
|
|
||
| result = pd.concat(frames, ignore_index=True) | ||
| return result[[name for name in schema.names if name in result.columns]] | ||
| class _NNJAObsSourceBase(_NCEPObsSourceBase): |
There was a problem hiding this comment.
Too many base classes.
Try to make just one. Avoiding some crazy inheritance stack is good. Because hard to look where code is at
Some repeat code is okay, this doesnt look like its adding much?
There was a problem hiding this comment.
I can switch to mixin. The thing is it’s literally duplicate functionality across gdas and nnja (and gfs if we add that). We were also seeing divergence in functionality because of separation.
…k + shared conv planner
…dex/e2s-ncep-obs-foundation # Conflicts: # earth2studio/data/nnja.py
|
@NickGeneva Reworked this per your feedback. Quick rundown of what changed and where it's headed. Addressing your notes
New shape (2 files)
So a source = compose {a transport mixin} + {the request-lifecycle mixin} Why it's shaped this wayThe next stacked PRs drop in additively:
|
Earth2Studio Pull Request
Description
NNJAObsConvcombined three concerns in one class: request assembly, NNJAS3/cache transport, and conventional/GPSRO product decoding. That made the
request lifecycle impossible to reuse for other NCEP observation products or
archives without copying it.
This PR is a behavior-preserving refactor that separates those concerns behind
a private seam:
_NCEPObsSourceBasefor the shared DataFrame request lifecycle (inputnormalization, field projection, cycle-window construction, URI dedup,
ordered decode/concat, source attrs, sync wrapping, cleanup);
_NCEPObsStoreprotocol (fetch_files,local_path,cleanup);_NNJAObsStore;_NNJAObsSourceBasefor NNJA store wiring, six-hour validation,availability, and cache access;
routing, and PrepBUFR/GPSRO decoding on
NNJAObsConv.No public API, schema, variable, dtype, or runtime behavior changes.
Why This Boundary
NCEP observation sources vary along two independent axes:
cached;
decoding, and missing-file policy.
This PR separates those axes without introducing a broad public framework:
The private seam is intended to support this follow-up shape (not included
here):
The goal is only to establish and validate the minimal reusable ownership
boundary so those sources do not copy the request/download/assembly lifecycle
again.
Compatibility
NNJAObsConvconstructor and call signatures are unchanged.are unchanged.
cleanup, and missing-file behavior are unchanged.
Validation
Origin/main and this branch independently decoded the same bounded real
PrepBUFR bytes. Exact positional DataFrame equality passed for 173,152 rows
across
t,q,u,v, andpres, including row order, every value,dtypes, null masks, column order, and attrs. The ordered row SHA-256 is
7becb34bc3bcec2211e046ca5f01ac9b2be389111914c4046c115ff10d80a31d.Focused NNJA tests (19 passed, 2 slow deselected), Ruff, Black, mypy, and
git diff --checkpass on the changed files.Follow-ups
NNJAObsSatas a second_NNJAObsSourceBaseconsumer._NomadsObsStore+NomadsGDASObsConvmigration deleting its duplicatelifecycle.
Checklist
Dependencies