From e9ba9f71a0d4a949466741b6271825559b7b986e Mon Sep 17 00:00:00 2001 From: wpbonelli Date: Tue, 11 Mar 2025 08:35:59 -0400 Subject: [PATCH] feat(models): add example scenario mapping --- autotest/test_models.py | 7 + modflow_devtools/make_registry.py | 31 +- modflow_devtools/models.py | 20 +- modflow_devtools/registry/examples.toml | 377 ++++++++++++++++++++++++ 4 files changed, 421 insertions(+), 14 deletions(-) create mode 100644 modflow_devtools/registry/examples.toml diff --git a/autotest/test_models.py b/autotest/test_models.py index 9cb36b1b..5c7b56f5 100644 --- a/autotest/test_models.py +++ b/autotest/test_models.py @@ -35,6 +35,13 @@ def test_models(model_name, files): assert any(Path(f).name == "mfsim.nam" for f in files) +@pytest.mark.parametrize("example_name, model_names", models.get_examples().items()) +def test_get_examples(example_name, model_names): + assert example_name in models.EXAMPLES + for model_name in model_names: + assert model_name in models.MODELMAP + + @pytest.mark.parametrize("model_name, files", list(islice(MODELMAP.items(), TAKE))) def test_copy_to(model_name, files, tmp_path): workspace = models.copy_to(tmp_path, model_name) diff --git a/modflow_devtools/make_registry.py b/modflow_devtools/make_registry.py index 9b852b77..befe3140 100644 --- a/modflow_devtools/make_registry.py +++ b/modflow_devtools/make_registry.py @@ -9,7 +9,10 @@ from modflow_devtools.misc import get_model_paths from modflow_devtools.models import BASE_URL -REGISTRY_PATH = Path(__file__).parent / "registry" / "registry.toml" +REGISTRY_DIR = Path(__file__).parent / "registry" +REGISTRY_PATH = REGISTRY_DIR / "registry.toml" +MODELMAP_PATH = REGISTRY_DIR / "models.toml" +EXAMPLES_PATH = REGISTRY_DIR / "examples.toml" def _sha256(path: Path) -> str: @@ -28,21 +31,16 @@ def _sha256(path: Path) -> str: def write_registry( path: str | PathLike, - registry_path: str | PathLike, url: str, append: bool = False, ): path = Path(path).expanduser().absolute() - registry_path = Path(registry_path).expanduser().absolute() - modelmap_path = registry_path.parent / "models.toml" - if not path.is_dir(): raise NotADirectoryError(f"Path {path} is not a directory.") - if not registry_path.exists(): - registry_path.parent.mkdir(parents=True, exist_ok=True) registry: dict[str, dict[str, str | None]] = {} modelmap: dict[str, list[str]] = {} + examples: dict[str, list[str]] = {} exclude = [".DS_Store", "compare"] if is_zip := url.endswith((".zip", ".tar")): registry[url.rpartition("/")[2]] = {"hash": None, "url": url} @@ -60,10 +58,13 @@ def _find_examples_dir(p): # then the model names could correspond directly to directory names. model_path = model_path.expanduser().absolute() base_path = _find_examples_dir(model_path) if is_zip else path - model_name = ( - str(model_path.relative_to(base_path)).replace("/", "_").replace("-", "_") - ) + rel_path = model_path.relative_to(base_path) + model_name = str(rel_path).replace("/", "_").replace("-", "_") modelmap[model_name] = [] + if is_zip: + if rel_path.parts[0] not in examples: + examples[rel_path.parts[0]] = [] + examples[rel_path.parts[0]].append(model_name) for p in model_path.glob("*"): if not p.is_file() or any(e in p.name for e in exclude): continue @@ -85,15 +86,19 @@ def drop_none_or_empty(path, key, value): return False return True - with registry_path.open("ab+" if append else "wb") as registry_file: + REGISTRY_DIR.mkdir(parents=True, exist_ok=True) + with REGISTRY_PATH.open("ab+" if append else "wb") as registry_file: tomli.dump( remap(dict(sorted(registry.items())), visit=drop_none_or_empty), registry_file, ) - with modelmap_path.open("ab+" if append else "wb") as modelmap_file: + with MODELMAP_PATH.open("ab+" if append else "wb") as modelmap_file: tomli.dump(dict(sorted(modelmap.items())), modelmap_file) + with EXAMPLES_PATH.open("ab+" if append else "wb") as examples_file: + tomli.dump(dict(sorted(examples.items())), examples_file) + if __name__ == "__main__": parser = argparse.ArgumentParser(description="Make a registry of example models.") @@ -113,4 +118,4 @@ def drop_none_or_empty(path, key, value): args = parser.parse_args() path = Path(args.path) url = args.url if args.url else BASE_URL - write_registry(path=path, registry_path=REGISTRY_PATH, url=url, append=args.append) + write_registry(path=path, url=url, append=args.append) diff --git a/modflow_devtools/models.py b/modflow_devtools/models.py index 6cdd0c4a..05842cdd 100644 --- a/modflow_devtools/models.py +++ b/modflow_devtools/models.py @@ -18,6 +18,7 @@ REGISTRY_ANCHOR = f"{modflow_devtools.__name__}.registry" REGISTRY_FILE_NAME = "registry.toml" MODELMAP_FILE_NAME = "models.toml" +EXAMPLES_FILE_NAME = "examples.toml" # the mf6 examples release is our base url BASE_URL = "https://github.com/MODFLOW-ORG/modflow6-examples/releases/download/current" @@ -26,7 +27,8 @@ # set up the pooch FETCHERS = {} REGISTRY: dict[str, str] = {} -MODELMAP: dict[str, list[Path]] = {} +MODELMAP: dict[str, list[str]] = {} +EXAMPLES: dict[str, list[str]] = {} POOCH = pooch.create( path=pooch.os_cache(modflow_devtools.__name__.replace("_", "-")), base_url=BASE_URL, @@ -86,6 +88,22 @@ def _fetch_zip(zip_name): ) +try: + with pkg_resources.open_binary( + REGISTRY_ANCHOR, EXAMPLES_FILE_NAME + ) as examples_file: + EXAMPLES = tomli.load(examples_file) +except: # noqa: E722 + warn( + f"No examples file '{EXAMPLES_FILE_NAME}' " + f"in module '{REGISTRY_ANCHOR}' resources" + ) + + +def get_examples() -> dict[str, list[str]]: + return EXAMPLES + + def get_registry() -> dict[str, str]: return POOCH.registry diff --git a/modflow_devtools/registry/examples.toml b/modflow_devtools/registry/examples.toml new file mode 100644 index 00000000..5bfed6d1 --- /dev/null +++ b/modflow_devtools/registry/examples.toml @@ -0,0 +1,377 @@ +ex-gwe-ates = [ + "ex_gwe_ates", +] +ex-gwe-barends = [ + "ex_gwe_barends_mf6gwf", + "ex_gwe_barends_mf6gwe", +] +ex-gwe-danckwerts = [ + "ex_gwe_danckwerts", +] +ex-gwe-geotherm = [ + "ex_gwe_geotherm_mf6gwf", + "ex_gwe_geotherm_mf6gwe", +] +ex-gwe-prt = [ + "ex_gwe_prt_gwf", + "ex_gwe_prt_gwe", + "ex_gwe_prt_prt", +] +ex-gwe-radial-slow = [ + "ex_gwe_radial_slow_mf6gwf", + "ex_gwe_radial_slow_mf6gwe_b", +] +ex-gwe-vsc = [ + "ex_gwe_vsc", +] +ex-gwf-advtidal = [ + "ex_gwf_advtidal", +] +ex-gwf-bcf2ss-p01a = [ + "ex_gwf_bcf2ss_p01a", +] +ex-gwf-bcf2ss-p02a = [ + "ex_gwf_bcf2ss_p02a", +] +ex-gwf-bump-p01a = [ + "ex_gwf_bump_p01a", +] +ex-gwf-bump-p01b = [ + "ex_gwf_bump_p01b", +] +ex-gwf-bump-p01c = [ + "ex_gwf_bump_p01c", +] +ex-gwf-capture = [ + "ex_gwf_capture", +] +ex-gwf-csub-p01 = [ + "ex_gwf_csub_p01", +] +ex-gwf-csub-p02a = [ + "ex_gwf_csub_p02a", +] +ex-gwf-csub-p02b = [ + "ex_gwf_csub_p02b", +] +ex-gwf-csub-p02c = [ + "ex_gwf_csub_p02c_hb_100", + "ex_gwf_csub_p02c_hb_050", + "ex_gwf_csub_p02c_es_002", + "ex_gwf_csub_p02c_es_001", + "ex_gwf_csub_p02c_es_050", + "ex_gwf_csub_p02c_es_020", + "ex_gwf_csub_p02c_es_010", + "ex_gwf_csub_p02c_hb_001", + "ex_gwf_csub_p02c_hb_020", + "ex_gwf_csub_p02c_hb_010", + "ex_gwf_csub_p02c_es_005", + "ex_gwf_csub_p02c_hb_005", + "ex_gwf_csub_p02c_es_100", + "ex_gwf_csub_p02c_hb_002", +] +ex-gwf-csub-p03a = [ + "ex_gwf_csub_p03a", +] +ex-gwf-csub-p03b = [ + "ex_gwf_csub_p03b", +] +ex-gwf-csub-p04 = [ + "ex_gwf_csub_p04", +] +ex-gwf-curve-90 = [ + "ex_gwf_curve_90", +] +ex-gwf-curvilin = [ + "ex_gwf_curvilin", +] +ex-gwf-disvmesh = [ + "ex_gwf_disvmesh", +] +ex-gwf-drn-p01a = [ + "ex_gwf_drn_p01a", +] +ex-gwf-drn-p01b = [ + "ex_gwf_drn_p01b", +] +ex-gwf-fhb = [ + "ex_gwf_fhb", +] +ex-gwf-hanic = [ + "ex_gwf_hanic", +] +ex-gwf-hanir = [ + "ex_gwf_hanir", +] +ex-gwf-hanix = [ + "ex_gwf_hanix", +] +ex-gwf-lak-p01 = [ + "ex_gwf_lak_p01", +] +ex-gwf-lak-p02 = [ + "ex_gwf_lak_p02", +] +ex-gwf-lgr = [ + "ex_gwf_lgr", +] +ex-gwf-lgrv-gc = [ + "ex_gwf_lgrv_gc", +] +ex-gwf-lgrv-gr = [ + "ex_gwf_lgrv_gr", +] +ex-gwf-lgrv-lgr = [ + "ex_gwf_lgrv_lgr", +] +ex-gwf-maw-p01a = [ + "ex_gwf_maw_p01a", +] +ex-gwf-maw-p01b = [ + "ex_gwf_maw_p01b", +] +ex-gwf-maw-p02 = [ + "ex_gwf_maw_p02", +] +ex-gwf-maw-p03a = [ + "ex_gwf_maw_p03a", +] +ex-gwf-maw-p03b = [ + "ex_gwf_maw_p03b", +] +ex-gwf-maw-p03c = [ + "ex_gwf_maw_p03c", +] +ex-gwf-nwt-p02a = [ + "ex_gwf_nwt_p02a", +] +ex-gwf-nwt-p02b = [ + "ex_gwf_nwt_p02b", +] +ex-gwf-nwt-p03a = [ + "ex_gwf_nwt_p03a", +] +ex-gwf-nwt-p03b = [ + "ex_gwf_nwt_p03b", +] +ex-gwf-rad-disu = [ + "ex_gwf_rad_disu", +] +ex-gwf-sagehen = [ + "ex_gwf_sagehen", +] +ex-gwf-sfr-p01 = [ + "ex_gwf_sfr_p01", +] +ex-gwf-sfr-p01b = [ + "ex_gwf_sfr_p01b", +] +ex-gwf-sfr-pindersauera = [ + "ex_gwf_sfr_pindersauera", +] +ex-gwf-sfr-pindersauerb = [ + "ex_gwf_sfr_pindersauerb", +] +ex-gwf-spbc = [ + "ex_gwf_spbc", +] +ex-gwf-toth = [ + "ex_gwf_toth", +] +ex-gwf-twri01 = [ + "ex_gwf_twri01", +] +ex-gwf-u1disv = [ + "ex_gwf_u1disv", +] +ex-gwf-u1disv-x = [ + "ex_gwf_u1disv_x", +] +ex-gwf-u1gwfgwf-s1 = [ + "ex_gwf_u1gwfgwf_s1", +] +ex-gwf-u1gwfgwf-s2 = [ + "ex_gwf_u1gwfgwf_s2", +] +ex-gwf-u1gwfgwf-s3 = [ + "ex_gwf_u1gwfgwf_s3", +] +ex-gwf-u1gwfgwf-s4 = [ + "ex_gwf_u1gwfgwf_s4", +] +ex-gwf-whirl = [ + "ex_gwf_whirl", +] +ex-gwf-zaidel = [ + "ex_gwf_zaidel", +] +ex-gwt-gwtgwt-p10 = [ + "ex_gwt_gwtgwt_p10", +] +ex-gwt-hecht-mendez-b = [ + "ex_gwt_hecht_mendez_b_mf6gwf", + "ex_gwt_hecht_mendez_b_mf6gwt", +] +ex-gwt-hecht-mendez-c = [ + "ex_gwt_hecht_mendez_c_mf6gwf", + "ex_gwt_hecht_mendez_c_mf6gwt", +] +ex-gwt-henry-a = [ + "ex_gwt_henry_a", +] +ex-gwt-henry-b = [ + "ex_gwt_henry_b", +] +ex-gwt-keating = [ + "ex_gwt_keating_mf6gwf", + "ex_gwt_keating_mf6gwt", +] +ex-gwt-moc3d-p01a = [ + "ex_gwt_moc3d_p01a_mf6gwf", + "ex_gwt_moc3d_p01a_mf6gwt", +] +ex-gwt-moc3d-p01b = [ + "ex_gwt_moc3d_p01b_mf6gwf", + "ex_gwt_moc3d_p01b_mf6gwt", +] +ex-gwt-moc3d-p01c = [ + "ex_gwt_moc3d_p01c_mf6gwf", + "ex_gwt_moc3d_p01c_mf6gwt", +] +ex-gwt-moc3d-p01d = [ + "ex_gwt_moc3d_p01d_mf6gwf", + "ex_gwt_moc3d_p01d_mf6gwt", +] +ex-gwt-moc3d-p02 = [ + "ex_gwt_moc3d_p02_mf6gwf", + "ex_gwt_moc3d_p02_mf6gwt", +] +ex-gwt-moc3d-p02tg = [ + "ex_gwt_moc3d_p02tg_mf6gwf", + "ex_gwt_moc3d_p02tg_mf6gwt", +] +ex-gwt-mt3dms-p01a = [ + "ex_gwt_mt3dms_p01a", +] +ex-gwt-mt3dms-p01b = [ + "ex_gwt_mt3dms_p01b", +] +ex-gwt-mt3dms-p01c = [ + "ex_gwt_mt3dms_p01c", +] +ex-gwt-mt3dms-p01d = [ + "ex_gwt_mt3dms_p01d", +] +ex-gwt-mt3dms-p02a = [ + "ex_gwt_mt3dms_p02a_mf6gwf", + "ex_gwt_mt3dms_p02a_mf6gwt", +] +ex-gwt-mt3dms-p02b = [ + "ex_gwt_mt3dms_p02b_mf6gwf", + "ex_gwt_mt3dms_p02b_mf6gwt", +] +ex-gwt-mt3dms-p02c = [ + "ex_gwt_mt3dms_p02c_mf6gwf", + "ex_gwt_mt3dms_p02c_mf6gwt", +] +ex-gwt-mt3dms-p02d = [ + "ex_gwt_mt3dms_p02d_mf6gwf", + "ex_gwt_mt3dms_p02d_mf6gwt", +] +ex-gwt-mt3dms-p02e = [ + "ex_gwt_mt3dms_p02e_mf6gwf", + "ex_gwt_mt3dms_p02e_mf6gwt", +] +ex-gwt-mt3dms-p02f = [ + "ex_gwt_mt3dms_p02f_mf6gwf", + "ex_gwt_mt3dms_p02f_mf6gwt", +] +ex-gwt-mt3dms-p03 = [ + "ex_gwt_mt3dms_p03", +] +ex-gwt-mt3dms-p04a = [ + "ex_gwt_mt3dms_p04a", +] +ex-gwt-mt3dms-p04b = [ + "ex_gwt_mt3dms_p04b", +] +ex-gwt-mt3dms-p04c = [ + "ex_gwt_mt3dms_p04c", +] +ex-gwt-mt3dms-p05 = [ + "ex_gwt_mt3dms_p05", +] +ex-gwt-mt3dms-p06 = [ + "ex_gwt_mt3dms_p06", +] +ex-gwt-mt3dms-p07 = [ + "ex_gwt_mt3dms_p07", +] +ex-gwt-mt3dms-p08 = [ + "ex_gwt_mt3dms_p08", +] +ex-gwt-mt3dms-p09 = [ + "ex_gwt_mt3dms_p09", +] +ex-gwt-mt3dms-p10 = [ + "ex_gwt_mt3dms_p10", +] +ex-gwt-mt3dsupp631 = [ + "ex_gwt_mt3dsupp631_mf6gwf", + "ex_gwt_mt3dsupp631_mf6gwt", +] +ex-gwt-mt3dsupp632a = [ + "ex_gwt_mt3dsupp632a_mf6gwf", + "ex_gwt_mt3dsupp632a_mf6gwt", +] +ex-gwt-mt3dsupp632b = [ + "ex_gwt_mt3dsupp632b_mf6gwf", + "ex_gwt_mt3dsupp632b_mf6gwt", +] +ex-gwt-mt3dsupp632c = [ + "ex_gwt_mt3dsupp632c_mf6gwf", + "ex_gwt_mt3dsupp632c_mf6gwt", +] +ex-gwt-mt3dsupp82 = [ + "ex_gwt_mt3dsupp82_mf6gwf", + "ex_gwt_mt3dsupp82_mf6gwt", +] +ex-gwt-prudic2004t2 = [ + "ex_gwt_prudic2004t2_mf6gwf", + "ex_gwt_prudic2004t2_mf6gwt", +] +ex-gwt-rotate = [ + "ex_gwt_rotate", +] +ex-gwt-saltlake = [ + "ex_gwt_saltlake", +] +ex-gwt-stallman = [ + "ex_gwt_stallman", +] +ex-gwt-synthetic-valley = [ + "ex_gwt_synthetic_valley_mf6gwf", + "ex_gwt_synthetic_valley_mf6gwt", +] +ex-gwt-uzt-2d-a = [ + "ex_gwt_uzt_2d_a", +] +ex-gwt-uzt-2d-b = [ + "ex_gwt_uzt_2d_b", +] +ex-prt-mp7-p01 = [ + "ex_prt_mp7_p01_gwf", + "ex_prt_mp7_p01_prt", +] +ex-prt-mp7-p02 = [ + "ex_prt_mp7_p02_gwf", + "ex_prt_mp7_p02_prt", +] +ex-prt-mp7-p03 = [ + "ex_prt_mp7_p03_gwf", + "ex_prt_mp7_p03_prt", +] +ex-prt-mp7-p04 = [ + "ex_prt_mp7_p04_gwf", + "ex_prt_mp7_p04_prt", +]