Skip to content

Feat: pixml loader for rfc forecasts - #254

Open
msweier wants to merge 13 commits into
mainfrom
feat/pixml
Open

Feat: pixml loader for rfc forecasts#254
msweier wants to merge 13 commits into
mainfrom
feat/pixml

Conversation

@msweier

@msweier msweier commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Use cwms-cli nws pixml to load an NWS/RFC Delft-FEWS PI-XML forecast product into a CWMS database. Parameter mapping, timeseries group overrides, versioning, and issued-time tracking is driven by a JSON config file or a config blob stored in CDA.

nws pixml supports:

  • loading a single PI-XML file or URL (.gz/.zip auto-unzipped)
  • config-driven NWS to CWMS parameter mapping
  • TSID resolution via timeseries group alias override with optional built fallback
  • run selection by filename pattern (e.g. base / auto / CRF)
  • per-run versioning control (versioned or unversioned)
  • issued-time tracking via a consolidated JSON blob

This was based on MVP and MVM's needs and tested on the MVP and MVM RFC products with the hope that it may be configurable for other district's needs.

Developed with Claude Opus.

@msweier
msweier marked this pull request as draft August 7, 2026 20:08

@krowvin krowvin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of acronyms. I'm not familiar with pixml. Might consider spelling the first ones out or linking to external docs more too.

Commenting for now, give Eric some time to peak this if he can.

Comment thread docs/cli/nws_pixml.rst
The loader resolves its JSON config from the first source that matches:

1. ``--config`` — a local JSON file path
2. ``--config-blob`` — a blob ID to fetch from CDA

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
2. ``--config-blob`` — a blob ID to fetch from CDA
2. ``--config-blob-id`` — a blob ID to fetch from CDA

Without ID or the description one might think it's the actual blob data

Comment thread docs/cli/nws_pixml.rst
----------------

The config is a JSON object. See the example configs shipped in
``docs/nws/mvp.example.json`` and ``docs/nws/mvm.example.json``.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this link to these? Might see if you can

Comment thread docs/cli/nws_pixml.rst
The config is a JSON object. See the example configs shipped in
``docs/nws/mvp.example.json`` and ``docs/nws/mvm.example.json``.

Top-level keys:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a reference for external docs we can give for these as well?

Comment thread docs/cli/nws_pixml.rst
warned and skipped. If ``build_missing_timeseries`` is false or omitted,
unmatched series are skipped instead of being built from the config.

If two series in one product resolve to the same TSID, only the first is

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make sure to toss a warning log when this happens too. We can hope people do read this though.

Comment thread docs/cli/nws_pixml.rst
- ``CDA_API_ROOT`` — default value for ``-a/--api-root``
- ``CDA_API_KEY`` — default value for ``-k/--api-key``

Example: MVP setup

@krowvin krowvin Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Example: MVP setup
Example: MVP (St. Paul District) setup

@msweier
msweier marked this pull request as ready for review August 26, 2026 17:56
@msweier
msweier requested review from krowvin August 26, 2026 19:07

@krowvin krowvin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only thing I really want to confirm before approval is our use of options, flags, and sub commands.

Typically something like
-i is a short option
--input is a long option
cwms-cli nws is a sub command of cwms-cli

In the source it is reading like
cwms-cli nws input ...etc is a valid option/arg.

I'd say the rest is largely up to you to decide if you wish to make changes, just let me know your thoughts in the replies.

That and if Mike has any opinions on that massively negative number. To me that looks like it's a 128bit signed number. Suggesting if you go to the bottom max of a 128bit signed value that's pretty much zero?

Comment thread cwmscli/nws/load_pixml.py
logger = logging.getLogger(__name__)

# CWMS sentinel for a missing value and its quality code.
CWMS_MISSING_VALUE = -340282346638528859811704183484516925440

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread cwmscli/nws/load_pixml.py

# Regular CWMS interval names keyed by their length in seconds. Used to derive the
# interval segment of a built timeseries id from a PI-XML <timeStep> multiplier.
_SECONDS_TO_INTERVAL = {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should expose this via a util/global. Could get reused.

Comment thread cwmscli/nws/load_pixml.py
# --------------------------------------------------------------------------- #
# Parse
# --------------------------------------------------------------------------- #
def _document_timezone(root, ns) -> timezone:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding tests for all these private methods?

Comment thread cwmscli/nws/__init__.py
@click.option(
"-i",
"--input",
"input_",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless we have a reason for this option I would take it out, I typically don't see somearg_ with a trailing slash and the other two should cover it

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trailing _ was one thing, but then I realized this ends up reading like new commands.

If we do want to go this route we'll have to document it because not every command does this

Comment thread cwmscli/nws/__init__.py
"input_",
required=True,
type=str,
help="Path or URL to the PI-XML product. URLs ending in .gz or .zip are unzipped automatically.",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have set options for this input? You might consider a method that reads the ending formats and throws an error if it's not one of those formats, normalized?

Options may be able to support extensions for files directly as well. We use Path in other places but there very well maybe a Url too.

While this isn't a blocker it could help with the user experience!

Comment thread docs/cli/nws_pixml.rst
Comment on lines +191 to +193
- ``OFFICE`` — default value for ``-o/--office``
- ``CDA_API_ROOT`` — default value for ``-a/--api-root``
- ``CDA_API_KEY`` — default value for ``-k/--api-key``

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly link to and/or have it display these from the global doc location on this?

Comment thread docs/nws/mvm.example.json
Comment on lines +4 to +10
"location_alias_groups": [
{
"group_id": "NWS Handbook 5 ID",
"category_id": "Agency Aliases",
"group_office_id": "CWMS",
"category_office_id": "CWMS"
},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the location group object ever changes we might have to come back in here and change this.

The way it was handled in GWW was to refrence what we need and then point to the generic cwmsjs/etc page that would define this.

In our case with this being python, the type doc pages do not exist... yet

Comment thread docs/nws/mvm.example.json

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible can we rendered this config file somewhere? Part of the reason i chose RST was so we could dynamically render existing files into the docs themselves.

And that way you only have one place to change it, see above comment linking to config doc

Comment thread docs/nws/mvp.example.json
@@ -0,0 +1,100 @@
{
"office": "MVP",
"pi_namespace": "http://www.wldelft.nl/fews/PI",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should pixml also default to this if this namespace is not provided?

I also notice this is http? Do they not have an SSL varient/HTTPS?

Comment thread docs/nws/mvp.example.json
Comment on lines +44 to +50
"SQIN": "Flow-Sim",
"QINE": "Flow",
"PELV": "Elev",
"SPEL": "Elev",
"RAIM": "Precip-RainAndMelt",
"MAP": "Precip-Rain",
"SSTG": "Stage"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these params and other items are documented on their site lets be sure to add links to that. It also helps show that we are not responsible if these change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants