Skip to content

Conversation

@bouweandela
Copy link
Member

@bouweandela bouweandela commented Jan 16, 2026

Description

Added features

  • A new way of configuring the CMOR tables, with separate extensions for CMIP6, CMIP5, and CMIP3 tables to avoid confusion because of differing coordinate definitions.
  • The possibility to use data that has not been CMORized, as long as it is compliant enough with the CMOR standards for the preprocessor functions and/or diagnostics to be able to function. For preprocessor functions compliance with the CF conventions will typically be enough, while diagnostics will likely expect full CMOR compliance.
  • Updated the function esmvalcore.preprocessor.align_metadata so it works with branded variables

Closes #2918
Closes #2746
Closes #2364

Links to documentation:

Deprecated features


Before you get started

Checklist

It is the responsibility of the author to make sure the pull request is ready to review. The icons indicate whether the item will be subject to the 🛠 Technical or 🧪 Scientific review.


To help with the number pull requests:

@bouweandela bouweandela force-pushed the new-config-cmor branch 2 times, most recently from 2b7ae33 to f7e0982 Compare January 19, 2026 12:41
@bouweandela bouweandela added the enhancement New feature or request label Jan 19, 2026
@bouweandela bouweandela added this to the v2.14.0 milestone Jan 19, 2026
@bouweandela bouweandela force-pushed the new-config-cmor branch 4 times, most recently from 2403e51 to c2bd443 Compare January 19, 2026 15:44
@codecov
Copy link

codecov bot commented Jan 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.68%. Comparing base (dee1bcb) to head (b43a466).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2946      +/-   ##
==========================================
+ Coverage   95.61%   95.68%   +0.06%     
==========================================
  Files         266      266              
  Lines       15584    15718     +134     
==========================================
+ Hits        14901    15040     +139     
+ Misses        683      678       -5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@schlunma
Copy link
Contributor

Hello, this pull request has been marked with the v2.14.0 milestone. The release of version 2.14.0 is currently scheduled for February 2026. To get this into the new release, it would be great to get this merged by the end of January.

If you won't be able to finish this in time, don't worry - just unassign the milestone v2.14.0. If you need any support, ping myself (@schlunma; the release manager for v2.14.0) or the @ESMValGroup/technical-lead-development-team. Please note that I won't be available until the beginning of February, though.

@valeriupredoi
Copy link
Contributor

@bouweandela shout if you need a helping hand here, with the missing tests - I can help. Apart from that, it looks great - and a lot of bookkeeping work too, which is not pleasant 🍻

@bouweandela
Copy link
Member Author

Thanks for offering V! The tests shouldn't be too much effort, it's mostly the docs that still need to be updated and I want to think about if I can avoid making #2954 worse. I was actually having a go at fixing that, but realized that it's probably best to leave that for another PR. If you could help out with reviewing and testing that would be great. Hopefully I'll have this ready for review by the end of the week.

@valeriupredoi
Copy link
Contributor

sure thing, can do! 🍺

@valeriupredoi
Copy link
Contributor

OK @bouweandela - tests as promised:

  • basic help functionality OK
  • basic run with an existing cmorizer (one!) OK
  • create new cmorizer with no data OK
  • add data, and run with a standard OBS table OK
  • run with OBS6 table OK
  • run with new custom variable (without edit of custom table) OK
  • add custom variable to custom table and run OK

I am rather happy with the funtionality here, and well done! 🍻 Off to pub now 🍻

@bouweandela
Copy link
Member Author

Thanks a lot V, enjoy 🍻 🍻

Copy link
Contributor

@valeriupredoi valeriupredoi left a comment

Choose a reason for hiding this comment

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

last approval after testing 😀 @schlunma can merge this for 2.14 - you can hold me accountable for any serious issues from it 😆

@schlunma
Copy link
Contributor

schlunma commented Feb 9, 2026

@bouweandela Could you please fix the merge conflict? I'll try to play around with this today, and hopefully merge it very soon. This is the last feature PR that we will include for the release candidate.

@bouweandela
Copy link
Member Author

Thanks @schlunma, I've addressed the merge conflict.

Copy link
Contributor

@schlunma schlunma left a comment

Choose a reason for hiding this comment

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

A couple of questions/comments on the docs, will continue with testing later.

@schlunma
Copy link
Contributor

schlunma commented Feb 10, 2026

Removing an entry from the custom CMIP6 tables, e.g. the entry for clhmtisccp and running esmvaltool run ~/ESMValTool/esmvaltool/recipes/examples/recipe_preprocessor_derive_test.yml

with the following user config file

projects:
  CMIP5:
    cmor_table:
      paths:
        - cmip5/Tables
        - cmip5-custom
        - ~/tmp/cmor  # <-- this is the problematic line

fails with

Traceback (most recent call last):
  File "/home/b/b309141/micromamba/envs/esm/bin/esmvaltool", line 3, in <module>
    from esmvalcore._main import run
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/_main.py", line 43, in <module>
    from esmvalcore.config._config import warn_if_old_extra_facets_exist
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/config/__init__.py", line 20, in <module>
    from esmvalcore.config._config_object import CFG, Config, Session
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/config/_config_object.py", line 406, in <module>
    CFG = _get_global_config()
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/config/_config_object.py", line 401, in _get_global_config
    config_obj.reload()
    ~~~~~~~~~~~~~~~~~^^
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/config/_config_object.py", line 157, in reload
    self.load_from_dirs([USER_CONFIG_DIR])
    ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/config/_config_object.py", line 130, in load_from_dirs
    self.update(new_config_dict)
    ~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/config/_validated_config.py", line 105, in update
    self[key] = other[key]
    ~~~~^^^^^
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/config/_validated_config.py", line 74, in __setitem__
    cval = self._validate[key](val)
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/config/_config_validators.py", line 424, in validate_projects
    validate_cmor_tables(mapping)
    ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/config/_config_validators.py", line 391, in validate_cmor_tables
    project: esmvalcore.cmor.table.get_tables(
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        session={"projects": value},  # type: ignore[arg-type]
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        project=project,
        ^^^^^^^^^^^^^^^^
    )
    ^
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/cmor/table.py", line 389, in get_tables
    tables = cls(**kwargs)
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/cmor/table.py", line 1281, in __init__
    self._load_table(table_file)
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/cmor/table.py", line 1299, in _load_table
    table = self._read_table_file(table_file)
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/cmor/table.py", line 1308, in _read_table_file
    self._read_line()
    ~~~~~~~~~~~~~~~^^
  File "/home/b/b309141/repos/ESMValCore/esmvalcore/cmor/table.py", line 1346, in _read_line
    index = line.index(":")
ValueError: substring not found

Somehow the CMIP5 and CMIP6 projects get mixed up.

@bouweandela
Copy link
Member Author

bouweandela commented Feb 11, 2026

Trying to reproduce your issue, I followed these steps:

  1. create a file ~/.config/esmvaltool/cmor_tables.yml with the content
projects:
  CMIP5:
    cmor_table:
      paths:
        - cmip5/Tables
        - cmip5-custom
        - ~/tmp/cmor  # <-- this is the problematic line
  1. create an empty directory ~/tmp/cmor
  2. remove the variable clhmtisccp from the file esmvalcore/cmor/tables/cmip6-custom/CMIP6_custom.json
  3. run the command esmvaltool run examples/recipe_preprocessor_derive_test.yml --diagnostics '*/clhmtisccp'

Does that describe what you did? Or is there some content in your ~/tmp/cmor directory? The stack trace above indicates that there is an issue with reading one of the files of your CMIP5 CMOR configuration. I would expect a message saying in which file the error occurs in, could you share that?

If I follow the 4 steps above, the run ends with the message:

2026-02-11 09:46:40,123 UTC [647747] ERROR   Unable to load CMOR table (project) 'CMIP6' for variable 'clhmtisccp' with mip 'CFmon'

as expected, because I removed the variable from the table file in step 3 above.

@valeriupredoi
Copy link
Contributor

Trying to reproduce your issue, I followed these steps:

  1. create a file ~/.config/esmvaltool/cmor_tables.yml with the content
projects:
  CMIP5:
    cmor_table:
      paths:
        - cmip5/Tables
        - cmip5-custom
        - ~/tmp/cmor  # <-- this is the problematic line
  1. create an empty directory ~/tmp/cmor
  2. remove the variable clhmtisccp from the file esmvalcore/cmor/tables/cmip6-custom/CMIP6_custom.json
  3. run the command esmvaltool run examples/recipe_preprocessor_derive_test.yml --diagnostics '*/clhmtisccp'

Does that describe what you did? Or is there some content in your ~/tmp/cmor directory? The stack trace above indicates that there is an issue with reading one of the files of your CMIP5 CMOR configuration. I would expect a message saying in which file the error occurs in, could you share that?

If I follow the 4 steps above, the run ends with the message:

2026-02-11 09:46:40,123 UTC [647747] ERROR   Unable to load CMOR table (project) 'CMIP6' for variable 'clhmtisccp' with mip 'CFmon'

as expected, because I removed the variable from the table file in step 3 above.

I ran this exact test when I ran tests last week - I am starting to get mildly miffed with the approach towards this PR's review - if we're trying to make any fairly/medium large development completely bulletproof, review will take ad infinitum! 🍺

@schlunma
Copy link
Contributor

@bouweandela you're right, the content of ~/tmp/cmor matters. I have a single file CMIP6_custom.json with the contents

{
    "Header": {
        "generic_levels": "olevel",
        "table_id": "Table custom"
    },
    "variable_entry": {
        "clhmtisccp": {
            "cell_measures": "area: areacella",
            "cell_methods": "time: mean",
            "comment": "at the top of the atmosphere (to be compared with satellite measurements)",
            "dimensions": "longitude latitude time",
            "long_name": "ISCCP High Level Medium-Thickness Cloud Area Fraction",
            "modeling_realm": "atmos",
            "out_name": "clhmtisccp",
            "standard_name": "",
            "type": "real",
            "units": "%"
        }
    }
}

I thought the CMIP5 table reader only looks for *.dat files. Does every reader type try to read every file in the custom directory? If yes, this should probably be documented (apologies if I missed that).

@schlunma
Copy link
Contributor

@valeriupredoi As release manager of the upcoming release,

  1. I want to make sure that there are no obvious problems with the current development version before running 150+ recipes. This will save me a lot of time.
  2. I also want to make sure that I understand the changes implemented in this PR before merging it.

Running some tests helps me with both. Apologies if this repeats some of your tests, but for large changes like this it's probably a good idea if more than one person actually runs some tests. I don't plan to perform any bigger (recipe) tests with this, so if @bouweandela clears up my reported issue, than I am happy to merge this asap.

@bouweandela
Copy link
Member Author

Does every reader type try to read every file in the custom directory?

The CMIP6 reader reads files with the .json extension only because these tables are json files, but for CMIP5 style tables there is no extension defined because they do not follow a file format that exists outside of CMOR: https://github.com/ESMValGroup/ESMValCore/tree/main/esmvalcore/cmor/tables/cmip5/Tables

@schlunma
Copy link
Contributor

Does every reader type try to read every file in the custom directory?

The CMIP6 reader reads files with the .json extension only because these tables are json files, but for CMIP5 style tables there is no extension defined because they do not follow a file format that exists outside of CMOR: https://github.com/ESMValGroup/ESMValCore/tree/main/esmvalcore/cmor/tables/cmip5/Tables

Would be great to add a note about that to the respective Info classes and/or here.

@bouweandela
Copy link
Member Author

Done in b43a466

@schlunma
Copy link
Contributor

Thanks!! My tests were successful, merging this now 🚀

@schlunma schlunma merged commit 2784aba into main Feb 11, 2026
4 checks passed
@schlunma schlunma deleted the new-config-cmor branch February 11, 2026 13:39
@valeriupredoi
Copy link
Contributor

Thanks!! My tests were successful, merging this now 🚀

brill, very many thanks, Manu 🍺

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

Labels

cmor Related to the CMOR standard deprecated feature enhancement New feature or request

Projects

None yet

3 participants