split prep_ngen_data into steps - #112
Conversation
|
This is awesome and much more readable! Glad the global variables are gone. I really like the usage of the dataclasses to store our variables, maybe the config one can be used as an argument in the writers.py module to reduce the number of arguments passed around? I tried to have three separate entry points for each |
|
I'm happy with any idea that reduces inputs args! An idea I have for this in relation to the community contribution docs I'm working on, is it would be nifty to be able to link conceptually relevant portions of the code base in those docs. For instance, the core processing function for forcings is |
|
We could also auto-generate API docs with links to source code if that would help with community contribution. Something like https://numpy.org/doc/stable/reference/generated/numpy.isdtype.html So if we do break up big functions into little functions with good docstrings, those could accomplish the goal of exposing relevant sections through autogenerated API docs. This could also be a chance for us to "privatize" our internal functions that may never change/get reused. |
|
@quinnylee I think that's a great idea. I can focus on breaking up I have the initial community contribution docs PR up here. I'm thinking the section "Alternative catchment averaging and weight generation" in CONTRIBUTING.md would contain the links we are talking about here. |
There was a problem hiding this comment.
Pull request overview
Refactors the main prep_ngen_data pipeline by splitting configuration, geometry loading, extraction, writing, plotting, metadata collection, and tar packaging into named steps and new helper modules, aiming to preserve existing behavior while making the flow easier to follow and maintain.
Changes:
- Introduces
config.py,writers.py, andmetadata.pyto encapsulate config parsing/output layout, output writing, and run-statistics generation. - Reworks
processor.pyinto a step-based orchestration using newGeometry/Extracted/WriteResultdataclasses. - Stabilizes tests by restoring shared module-level configuration state between test cases via an autouse fixture.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_forcingprocessor.py | Adds autouse fixture to reset mutated shared conf between tests. |
| tests/test_channelrouting.py | Adds autouse fixture to reset mutated shared conf between tests. |
| src/forcingprocessor/writers.py | New module for dataframe/netcdf/tar writing and multiprocessing orchestration. |
| src/forcingprocessor/weights_hf2ds.py | Import cleanup, typing tweaks, and small runtime hardening (timeouts, cpu_count guard). |
| src/forcingprocessor/utils.py | Adds shared helpers (phase timing, JSON/dataset readers, work distribution/load balancing). |
| src/forcingprocessor/troute_restart_tools.py | Adds typing ignore for boto3 client creation. |
| src/forcingprocessor/subset_conus_vpus.py | Import cleanup and minor refactors/formatting. |
| src/forcingprocessor/processor.py | Major refactor: step-based pipeline + new dataclasses + delegates to config/writers/metadata. |
| src/forcingprocessor/plot_forcings.py | Typing improvements, safer defaults, and minor refactors to plotting helpers/CLI. |
| src/forcingprocessor/nwm_filenames_generator.py | Improves file loading hygiene (encoding, variable naming). |
| src/forcingprocessor/metadata.py | New module for metadata/statistics frame generation and output writing. |
| src/forcingprocessor/medium_range_time_ax_mod.py | Docstring/header cleanup, constant naming, and typing adjustments. |
| src/forcingprocessor/config.py | New module for config parsing/validation, output layout, and run manifest writing. |
| src/forcingprocessor/channel_routing_tools.py | Minor cleanup and typing ignore for boto3 client creation. |
Suppressed comments (1)
src/forcingprocessor/processor.py:613
- Spelling: the status message says "processs" (extra 's'), which looks unintentional and makes logs harder to scan.
print(
f"\n\nWrite processs: {cfg.nprocs}\nWrite time: {write_time:.2f}" +
f"\nWrite rate {geom.ncatchments / write_time:.2f} files/second\n",
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Sorry this has ballooned into an absolute monster of a branch. Let me know what you all think of the changes. Will be more than happy to revert (or you can go ahead and do it yourself since i'll be at conferences for like two weeks straight) if you think any of them are not useful!! |
WIP — opening this to get feedback on a refactor idea before taking it further.
prep_ngen_datainprocessor.pyhad grown to ~700 lines and was hard to follow. This is particularly a problem for anyone looking to work on/contribute to this code base.This PR splits
prep_ngen_datainto an init step followed by named sequential steps, so the top-level function has much of the details abstracted out. This PR should not change functionality and is a pure refactor (besides maybe addressing a few bugs along the way).Additions
config.pywriters.pymetadata.pyutils.pyGeometry/Extracted/WriteResultdataclasses to carry state between stepsRemovals
prep_ngen_dataused to setforcings/channel_routingmetadata dicts (identical keys, differed only innvars_intput/nvars_output)Changes
prep_ngen_datais now:read_config→build_output_layout→parse_nwm_filenames→load_geometry→write_run_manifest→extract→write_outputs→ plot →collect_metadata→ tardata_sourcebranching pushed down into named per-mode functions instead of ~20 inlineif data_source ==checksprocessor.py: 1686 → 748 linesTesting
All pytests pass besides unmerged fix for
test_restart, pre-existing upstream off-by-one, unrelated to this PR)Screenshots
Notes
Todos
data_source, since thetroute_restartspath shares almost nothing withforcingsChecklist
Testing checklist
Target Environment support
Accessibility
Other