Skip to content

Commit dfb1d3e

Browse files
committed
Rename UnifiedModelSetup to UnifiedCalibrator and add ET output support
1 parent da4863e commit dfb1d3e

File tree

8 files changed

+217
-33
lines changed

8 files changed

+217
-33
lines changed

configs/example_config.yaml

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,37 @@
33

44
data:
55
# Data source configuration
6-
dataset: "camels_us" # Dataset type: camels_us, selfmadehydrodataset, etc.
6+
dataset: "camels" # Dataset type: camels_us, selfmadehydrodataset, etc.
77
path: null # Data path (null = auto-detect from hydro_setting.yml or use ~/hydromodel_data/)
88
# If specified, provide the datasets-origin directory only
99
# Example: "D:/project/data" (NOT "D:/project/data/CAMELS_US")
1010
# aqua_fetch will automatically append "CAMELS_US" directory name
11-
basin_ids: ["01013500","01022500","11532500"] # List of basin IDs to calibrate
11+
basin_ids: ["12025000"] # List of basin IDs to calibrate
1212
warmup_length: 365 # Warmup period in days
13-
variables: ["precipitation", "potential_evapotranspiration", "streamflow"] # Input variables
13+
variables: ["prcp", "PET", "dayl", "srad", "tmax", "tmin", "vp", "streamflow"] # Input variables
1414

1515
# Time periods
16-
train_period: ["1985-10-01", "1995-09-30"] # Training period
17-
valid_period: ["1995-10-01", "2005-09-30"] # Validation period
18-
test_period: ["2005-10-01", "2014-09-30"] # Testing period
16+
train_period: ["1981-01-01", "2004-12-31"] # Training period
17+
valid_period: ["2005-01-01", "2009-12-31"] # Validation period
18+
test_period: ["2010-01-01", "2014-12-31"] # Testing period
1919

2020
# Output configuration
21-
output_dir: "results" # Output directory for results
21+
output_dir: "results/12025000" # Output directory for results
2222

2323
model:
2424
# Model configuration
25-
name: "xaj" # Model type: xaj, xaj_mz, gr4j
25+
name: "xaj" # Model type: xaj, xaj_mz, gr4j, gr5j, gr6j, etc.
2626
params: # Model parameters
2727
source_type: "sources" # XAJ source type
2828
source_book: "HF" # HF (Hydrological Forecast) computation method
2929
kernel_size: 15 # Kernel size for Muskingum routing
3030

31+
# Output variable: "qsim" (streamflow), "es" (ET for XAJ), "et" (ET for GR)
32+
output_variable: "qsim"
33+
3134
training:
3235
# Training configuration
3336
algorithm: "SCE_UA" # Calibration algorithm: SCE_UA (or sceua), GA (or genetic_algorithm), scipy (or scipy_minimize)
34-
3537
# Algorithm-specific parameters (uncomment the section for your chosen algorithm)
3638

3739
# SCE-UA (Shuffled Complex Evolution) parameters

docs/changelog.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
- **Fixed Data Access Issues in Calibration**:
1616
- Fixed `AttributeError` when calibrating multi-basin flood event data
17-
- Previous behavior: `UnifiedModelSetup` tried to access `p_and_e.shape[1]` when `p_and_e=None` for separate basin data
18-
- Added proper detection of `basin_data_separate` mode in `UnifiedModelSetup.__init__()`
17+
- Previous behavior: `UnifiedCalibrator` tried to access `p_and_e.shape[1]` when `p_and_e=None` for separate basin data
18+
- Added proper detection of `basin_data_separate` mode in `UnifiedCalibrator.__init__()`
1919
- Modified `set_basin_index()` to extract basin-specific data from `basin_data_separate` when available
2020
- Each basin now uses its own time series without padding during calibration
2121
- Modified `unified_calibrate.py` (lines 116-253, 377-386)

docs/usage.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ calibrate()
225225
226226
2. UnifiedDataLoader.load_data()
227227
228-
3. Create UnifiedModelSetup (wraps MODEL_DICT)
228+
3. Create UnifiedCalibrator (wraps MODEL_DICT)
229229
230230
4. Select algorithm (SCE_UA, GA, scipy)
231231

hydromodel/configs/config_manager.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,8 @@ def load_simplified_config(
448448
"model_cfgs": {
449449
"model_name": model_cfg["name"],
450450
**model_cfg.get("params", {}),
451+
# Add output_variable configuration if specified
452+
**({"output_variable": model_cfg["output_variable"]} if "output_variable" in model_cfg else {}),
451453
},
452454
"training_cfgs": {
453455
"algorithm_name": training_cfg["algorithm"],
@@ -462,6 +464,8 @@ def load_simplified_config(
462464
"experiment_name": f"{model_cfg['name']}_{training_cfg['algorithm']}",
463465
"random_seed": training_cfg.get("random_seed", 1234),
464466
"save_config": training_cfg.get("save_config", True),
467+
# Add output_variable configuration if specified in training (highest priority)
468+
**({"output_variable": training_cfg["output_variable"]} if "output_variable" in training_cfg else {}),
465469
},
466470
"evaluation_cfgs": {
467471
"metrics": eval_cfg["metrics"],

hydromodel/trainers/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from .unified_calibrate import (
1717
calibrate,
1818
ModelSetupBase,
19-
UnifiedModelSetup,
19+
UnifiedCalibrator,
2020
DEAP_AVAILABLE,
2121
)
2222

@@ -31,7 +31,7 @@
3131
"calibrate",
3232
"evaluate",
3333
"ModelSetupBase",
34-
"UnifiedModelSetup",
34+
"UnifiedCalibrator",
3535
"UnifiedEvaluator",
3636
"DEAP_AVAILABLE",
3737
]

hydromodel/trainers/unified_calibrate.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def calculate_objective(
7575
pass
7676

7777

78-
class UnifiedModelSetup(ModelSetupBase):
78+
class UnifiedCalibrator(ModelSetupBase):
7979
"""
8080
Completely unified setup for all hydrological models using the MODEL_DICT interface.
8181
@@ -109,6 +109,20 @@ def __init__(
109109
self.training_config = training_config or {}
110110
self.warmup_length = warmup_length
111111

112+
# Get output variable configuration (default: qsim for streamflow)
113+
# Priority: training_config > model_config > default
114+
self.output_variable = (
115+
self.training_config.get("output_variable") or
116+
model_config.get("output_variable") or
117+
"qsim"
118+
)
119+
120+
# Validate output variable
121+
valid_outputs = ["qsim", "es", "et", "ets"]
122+
if self.output_variable not in valid_outputs:
123+
print(f"Warning: output_variable '{self.output_variable}' not recognized. Using 'qsim'.")
124+
self.output_variable = "qsim"
125+
112126
# Load data using unified data loader
113127
self.data_loader = UnifiedDataLoader(data_config)
114128
self.p_and_e_full, qobs_full = self.data_loader.load_data()
@@ -275,14 +289,24 @@ def simulate(self, params: np.ndarray) -> np.ndarray:
275289
is_event_data=self.is_event_data,
276290
)
277291

278-
# Extract simulation output (qsim) - most calibration only needs this
279-
# This avoids returning the full results dict every time
280-
if isinstance(results, dict) and "qsim" in results:
281-
return results["qsim"]
292+
# Extract simulation output based on configured variable
293+
# self.output_variable can be "qsim" (streamflow), "es"/"et"/"ets" (evapotranspiration)
294+
if isinstance(results, dict):
295+
# First try the configured output variable
296+
if self.output_variable in results:
297+
return results[self.output_variable]
298+
# Fallback to qsim if configured variable not available
299+
elif "qsim" in results:
300+
if self.output_variable != "qsim":
301+
print(f"Warning: '{self.output_variable}' not in results, using 'qsim' instead")
302+
return results["qsim"]
303+
# Last resort: return first available result
304+
else:
305+
return list(results.values())[0]
282306
elif isinstance(results, np.ndarray):
283307
return results
284308
else:
285-
# Fallback: return first available result
309+
# Fallback for unexpected result types
286310
return (
287311
list(results.values())[0]
288312
if isinstance(results, dict)
@@ -368,7 +392,7 @@ def calibrate(config, **kwargs) -> Dict[str, Any]:
368392
os.makedirs(output_dir, exist_ok=True)
369393

370394
# Create unified model setup
371-
model_setup = UnifiedModelSetup(
395+
model_setup = UnifiedCalibrator(
372396
data_config=data_config,
373397
model_config=model_config,
374398
loss_config=loss_config,
@@ -506,7 +530,7 @@ def _save_calibration_config(
506530

507531

508532
def _calibrate_model(
509-
model_setup: UnifiedModelSetup,
533+
model_setup: UnifiedCalibrator,
510534
algorithm_config: Dict,
511535
output_dir: str,
512536
basin_id: str,
@@ -799,7 +823,7 @@ class UnifiedSpotSetup(SpotSetup):
799823
def __init__(self, model_setup, total_iterations):
800824
# Do not call super().__init__ to avoid reloading or storing redundant data
801825
self.model_setup = model_setup
802-
# Reuse parameter definitions created by UnifiedModelSetup
826+
# Reuse parameter definitions created by UnifiedCalibrator
803827
self.params = model_setup.params
804828
self.parameter_names = model_setup.parameter_names
805829
# Progress tracking

0 commit comments

Comments
 (0)