| from __future__ import annotations |
|
|
| import os |
| from copy import deepcopy |
| from pathlib import Path |
| from typing import Any |
|
|
| import yaml |
|
|
| from utils.dataset_cache import apply_io_defaults, resolve_effective_dataset_root |
|
|
|
|
| ROOT = Path(__file__).resolve().parents[1] |
| DEFAULT_DATA_ROOT = ROOT.parent / "Datasets" |
| FALLBACK_DATA_ROOTS = (ROOT.parent / "mamba-cd" / "datasets",) |
|
|
|
|
| def _read_yaml(path: Path) -> dict[str, Any]: |
| if not path.exists(): |
| raise FileNotFoundError(f"Config file not found: {path}") |
| with path.open("r", encoding="utf-8") as f: |
| return yaml.safe_load(f) or {} |
|
|
|
|
| def _expand_data_root(value: str) -> str: |
| unresolved = value |
| if "${DATA_ROOT}" in value: |
| data_root = os.environ.get("DATA_ROOT") |
| if not data_root and DEFAULT_DATA_ROOT.is_dir(): |
| data_root = str(DEFAULT_DATA_ROOT) |
| if not data_root: |
| raise EnvironmentError( |
| "DATA_ROOT is not set. Set DATA_ROOT to the parent directory containing " |
| "LEVIR-CD-plus-256, WHU-CD, WildFireS2, and other dataset folders." |
| ) |
| value = value.replace("${DATA_ROOT}", data_root) |
| expanded = Path(value).expanduser().resolve() |
| if expanded.exists() or "${DATA_ROOT}" not in unresolved: |
| return str(expanded) |
|
|
| suffix = unresolved.split("${DATA_ROOT}", 1)[1].lstrip("/\\") |
| for root in FALLBACK_DATA_ROOTS: |
| candidate = (root / suffix).expanduser().resolve() |
| if candidate.exists(): |
| return str(candidate) |
| return str(expanded) |
|
|
|
|
| def list_available_datasets() -> list[str]: |
| configs_dir = ROOT / "configs" / "datasets" |
| return sorted(path.stem for path in configs_dir.glob("*.yaml")) |
|
|
|
|
| def load_dataset_config(dataset_name: str) -> dict[str, Any]: |
| path = Path(dataset_name) |
| if not path.suffix: |
| path = ROOT / "configs" / "datasets" / f"{dataset_name}.yaml" |
| elif not path.is_absolute(): |
| path = ROOT / path |
| cfg = _read_yaml(path) |
| if "data_root" not in cfg: |
| raise KeyError(f"{path} must define data_root") |
| cfg["data_root"] = _expand_data_root(str(cfg["data_root"])) |
| cfg["_config_path"] = str(path) |
| cfg["_dataset_name"] = path.stem |
| effective = resolve_effective_dataset_root(path.stem, cfg) |
| cfg.update(effective) |
| apply_io_defaults(cfg) |
| return cfg |
|
|
|
|
| def load_model_config(model_name: str) -> dict[str, Any]: |
| path = Path(model_name) |
| if not path.suffix: |
| path = ROOT / "configs" / "models" / f"{model_name}.yaml" |
| elif not path.is_absolute(): |
| path = ROOT / path |
| return _read_yaml(path) |
|
|
|
|
| def merge_configs(model_cfg: dict[str, Any], dataset_cfg: dict[str, Any]) -> dict[str, Any]: |
| merged = deepcopy(model_cfg) |
| merged["dataset"] = deepcopy(dataset_cfg) |
| for key in ("batch_size", "num_workers", "img_size", "channels", "num_classes", "ignore_index"): |
| if key in dataset_cfg: |
| merged[key] = deepcopy(dataset_cfg[key]) |
| return merged |
|
|