Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update variable names to v2.2 data model #211

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

JordanLaserGit
Copy link
Contributor

Updates ngen-cal to use the new v2.2 hydrofabric data model. Merging this PR will make ngen-cal incompatible with earlier data model versions. We can add checks to support backwards compatibility if desired. This addresses issue #210.

Additions

None

Removals

None

Changes

example:
"bexp_soil_layers_stag=1" -> "mode.bexp_soil_layers_stag=1"

Testing

  1. 3 tests are failing, but do not appear to be related to these changes

@hellkite500
Copy link
Member

Until 2.2 is more widely adopted, I think we should probably check/support both, marking 2.1 support for deprecation.

@JordanLaserGit
Copy link
Contributor Author

Checks have been added. User will get an exception if the neither variable option is found in the attributes.

@aaraney
Copy link
Member

aaraney commented Jan 8, 2025

Thanks for writing this up @JordanLaserGit! I envision that we will face similar issues when future versions of the HF are released. Likewise, this seems pretty crosscutting where I would expect many BMI config generation scripts need to be updated to accommodate the HF 2.2 model-attributes schema changes. For that reason, I prefer going with crosswalk or deferred mapping approach that ngen.config_gen could provide as a utility instead of just updating existing config generation scripts. Below is an example of kind of what I had in mind. Will you take a look at it and let me know what you think? If you can think of a simpler way to accomplish the same thing, i'm all ears!

# crosswalk between HF v2 model attribute names and HF v2.2 divide attributes
# names. 
from __future__ import annotations
import typing


_v2_to_v2_2_mapping = {
    "aspect_c_mean": "circ_mean.aspect",
    "bexp_soil_layers_stag=1": "mode.bexp_soil_layers_stag=1",
    "bexp_soil_layers_stag=2": "mode.bexp_soil_layers_stag=2",
    "bexp_soil_layers_stag=3": "mode.bexp_soil_layers_stag=3",
    "bexp_soil_layers_stag=4": "mode.bexp_soil_layers_stag=4",
    "cwpvt": "mean.cwpvt",
    "divide_id": "divide_id",
    "dksat_soil_layers_stag=1": "geom_mean.dksat_soil_layers_stag=1",
    "dksat_soil_layers_stag=2": "geom_mean.dksat_soil_layers_stag=2",
    "dksat_soil_layers_stag=3": "geom_mean.dksat_soil_layers_stag=3",
    "dksat_soil_layers_stag=4": "geom_mean.dksat_soil_layers_stag=4",
    "elevation_mean": "mean.elevation",
    "gw_Coeff": "mean.Coeff",
    "gw_Expon": "mode.Expon",
    "gw_Zmax": "mean.Zmax",
    "impervious_mean": "mean.impervious",
    "ISLTYP": "mode.ISLTYP",
    "IVGTYP": "mode.IVGTYP",
    "mfsno": "mean.mfsno",
    "mp": "mean.mp",
    "psisat_soil_layers_stag=1": "geom_mean.psisat_soil_layers_stag=1",
    "psisat_soil_layers_stag=2": "geom_mean.psisat_soil_layers_stag=2",
    "psisat_soil_layers_stag=3": "geom_mean.psisat_soil_layers_stag=3",
    "psisat_soil_layers_stag=4": "geom_mean.psisat_soil_layers_stag=4",
    # NOTE: aaraney: missing from 2.2?
    # "quartz_soil_layers_stag=1":
    # "quartz_soil_layers_stag=2":
    # "quartz_soil_layers_stag=3":
    # "quartz_soil_layers_stag=4":
    "refkdt": "mean.refkdt",
    "slope_mean": "mean.slope",
    "slope": "mean.slope_1km",
    "smcmax_soil_layers_stag=1": "mean.smcmax_soil_layers_stag=1",
    "smcmax_soil_layers_stag=2": "mean.smcmax_soil_layers_stag=2",
    "smcmax_soil_layers_stag=3": "mean.smcmax_soil_layers_stag=3",
    "smcmax_soil_layers_stag=4": "mean.smcmax_soil_layers_stag=4",
    "smcwlt_soil_layers_stag=1": "mean.smcwlt_soil_layers_stag=1",
    "smcwlt_soil_layers_stag=2": "mean.smcwlt_soil_layers_stag=2",
    "smcwlt_soil_layers_stag=3": "mean.smcwlt_soil_layers_stag=3",
    "smcwlt_soil_layers_stag=4": "mean.smcwlt_soil_layers_stag=4",
    "twi_dist_4": "dist_4.twi",
    "vcmx25": "mean.vcmx25",
    "X": "centroid_x",
    "Y": "centroid_y",
}


def divide_attributes_v2_to_v2_2_crosswalk(d: dict[str, typing.Any]):
    class Translate:
        def __contains__(self, name: str) -> bool:
            return name in _v2_to_v2_2_mapping or name in d

        def __getitem__(self, name: str) -> typing.Any:
            if name in _v2_to_v2_2_mapping:
                v2_2_name = _v2_to_v2_2_mapping[name]
                return d[v2_2_name]
            # fallback
            return d[name]

    return Translate()

To use this, you would pass the data parameter from hydrofabric_linked_data_hook to divide_attributes_v2_to_v2_2_crosswalk and it would return something you could treat like the data dictionary, but handle the remapping if necessary. This should let us and other users wrap the data dictionary at the top of their hydrofabric_linked_data_hook implementation and not need to modify any other existing code.

@JordanLaserGit
Copy link
Contributor Author

@aaraney Sure this looks like a fine solution. Will need to write new mappings if the variables change again, but shouldn't be too tough and would need to do that with my solution anyway. I went with the quick hack just to get ngen-cal to play nice with the new HF version, but the differed mapping solution will keep the code cleaner and serves as a reference for how the variables changed from one version to the next.

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.

3 participants