Skip to content

Add qartod and config#48

Open
madrichardson wants to merge 7 commits into
SWFSC:mainfrom
madrichardson:quarto-module
Open

Add qartod and config#48
madrichardson wants to merge 7 commits into
SWFSC:mainfrom
madrichardson:quarto-module

Conversation

@madrichardson

Copy link
Copy Markdown

No description provided.

@madrichardson

Copy link
Copy Markdown
Author

I added qartod.py inside the esdglider folder, and I added qartod-config.yml in esdglider/data. Also, I messed up my branch name because I've been working with Quarto a lot, so the branch should've been qartod-module, but instead I accidentally named it quarto-module.

Comment thread esdglider/.DS_Store Outdated

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.

Please remove this file from the pr

Comment thread esdglider/qartod.py
Comment thread esdglider/qartod.py Outdated
# to prevent file-locking issues during
# subsequent processing and output writing.

ds = xr.open_dataset(input_file)

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.

I use xr.load_dataset(input_file) rather than these three lines

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Ya that's a better approach, I'll update it.

@smwoodman

Copy link
Copy Markdown
Collaborator

Hi Madi - thanks for this! I've put some comments inline. A couple general ones, happy to discuss any of these:

For log messages, please use the syntax _log.info("QCing %s", var), rather than f-strings. I haven't run it in a while, but this comes from the pre-commit hooks that I (intermittently) use. I definitely need to pick a specific style guide, and have CoPilot go through and make this consistent :)

For me, having extra blank lines, eg between function calls makes the code less easily readable (example below). For esdglider, I'd like to stick to the principles of a) generally keeping code on one line is the line length is <80, and b) not having extra blank lines between lines in the same function.

# Please change 
final_flags = np.maximum.reduce(

    test_results

).astype("int8")

# to either:
final_flags = np.maximum.reduce(test_results).astype("int8")

# or:
final_flags = np.maximum.reduce(
    test_results
).astype("int8")

@madrichardson

madrichardson commented Jul 8, 2026

Copy link
Copy Markdown
Author

Hi Sam,

I'll make sure to fix all of these!

@madrichardson

Copy link
Copy Markdown
Author

Hi Madi - thanks for this! I've put some comments inline. A couple general ones, happy to discuss any of these:

For log messages, please use the syntax _log.info("QCing %s", var), rather than f-strings. I haven't run it in a while, but this comes from the pre-commit hooks that I (intermittently) use. I definitely need to pick a specific style guide, and have CoPilot go through and make this consistent :)

For me, having extra blank lines, eg between function calls makes the code less easily readable (example below). For esdglider, I'd like to stick to the principles of a) generally keeping code on one line is the line length is <80, and b) not having extra blank lines between lines in the same function.

# Please change 
final_flags = np.maximum.reduce(

    test_results

).astype("int8")

# to either:
final_flags = np.maximum.reduce(test_results).astype("int8")

# or:
final_flags = np.maximum.reduce(
    test_results
).astype("int8")

Do you want me to remove the comments in the code (example below)?

EVALUATE ALL DATA VARIABLES

for var in ds.data_vars:
    # REQUIRE TIME DIMENSION
    if "time" not in ds[var].dims:
        continue
    # SKIP EXISTING QC VARIABLES
    if var.endswith("_qc"):
        continue
    # SKIP EXCLUDED VARIABLES
    #
    # Exclude metadata variables and redundant
    # coordinate variables that should not
    # receive QARTOD testing.
    if var in skip_variables:
        continue
    time_variables.append(var)
# LOG SUMMARY
_log.info(
    "Found %d time variables for QC",
    len(time_variables)
)
return time_variables

@smwoodman

smwoodman commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

No, I think the comments are overall good, although I typically don't like them over logs because (unless it's really complicated) I think the log should be self-explanatory. I would format that block something like:

for var in ds.data_vars:
    # REQUIRE TIME DIMENSION
    if "time" not in ds[var].dims:
        continue

    # SKIP EXISTING QC VARIABLES AND EXCLUDED VARIABLES
    # {SMW note: I think fine to add more context here, if you feel it's necessary}
    if var.endswith("_qc") or var in skip_variables:
        continue

    time_variables.append(var)

_log.info(
    "Found %d time variables for QC",
    len(time_variables)
)

return time_variables

Thanks!

@madrichardson

Copy link
Copy Markdown
Author

I updated everything based on your comments. If there's anything else, please let me know!

@smwoodman

Copy link
Copy Markdown
Collaborator

Thank you! This is looking good. I'll try out the fork tomorrow.

One other ask - could you add a notebook (to the 'notebooks' folder) that shows a representative example or two of using this functionality?

@madrichardson

Copy link
Copy Markdown
Author

Yes! Sorry to get back late, I have been traveling. I'll make sure to add a notebook today.

@smwoodman

Copy link
Copy Markdown
Collaborator

Thanks, this is looking good. The outputs make sense

A couple more requests to complete the pr are below; sorry I didn't think to include these initially.

  • Add 'ioos_qc' to the pyproject.toml and environment.yml files; it can go into the pyproject file as a normal dependency.
  • Add yourself as an author in the pyproject.toml file
  • Add a blurb to the CHANGLOG file. For instance, under the 'Module and function restructuring' heading: "Added a qartod module, for generating qartod flags using the ioos_qc package for the science dataset". Note: to make this change, you'll need to update your branch with the updates that I've pushed to esdglider:main. If that is a hassle, no worries, and I can add this line after merging in the PR.
  • In the paths module, can you add a function (maybe get_path_qartod_config) for getting the path to the qartod-config.yml file? A la get_path_yaml. Sidebar, I need to rename the get_path_yaml function to differentiate it, probably to get_path_yaml_deployment_var. I'll do that in the main branch shortly.
  • It would be quite useful to have a way of visualizing/summarizing the generated QC flags, that could be easy to run for every deployment. I'm thinking of timeseries plots of each QC variable, which could be added to the plots folder. Another options could be a numerical summary printed to the logs, eg of the number of suspect/fail flags per variable. But maybe you/Dale/Cara have a better idea for this?

@madrichardson

Copy link
Copy Markdown
Author

I updated the requests you gave, but for visualizing/logging of the qc flags, what would be most helpful for you? Are you interested in seeing exactly when the bad flags occur or just generally how many flags (of each kind) there are?

@smwoodman

Copy link
Copy Markdown
Collaborator

Thanks @madrichardson! Updates look great. For visualizing/summarizing, I'm thinking both a histogram (or logged summary counts) of the number of each flag per variable, and then a timeseries of the flags. For the timeseries, either using color-coding to mark 'bad' flags, or have the plot only be of the 'bad' flags.

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