Skip to content

Refactor data loading to modular data_utils structure#2

Merged
sandrohuni merged 39 commits into
mainfrom
refactor/modular-data-utils
Mar 11, 2026
Merged

Refactor data loading to modular data_utils structure#2
sandrohuni merged 39 commits into
mainfrom
refactor/modular-data-utils

Conversation

@sandrohuni

Copy link
Copy Markdown
Collaborator

Summary

Refactors ST_Forecast/get_data.py to use a cleaner, modular data_utils/ structure. Reduces code duplication and improves maintainability while preserving all functionality.

Closes #1

Changes

New Module Structure

ST_Forecast/
├── log_config.py          # Shared logging configuration
├── data_utils/
│   ├── __init__.py        # Public API exports
│   ├── loaders.py         # Data loading functions (275 lines)
│   ├── transformers.py    # Transformation utilities (389 lines)
│   └── scalers.py         # Scaling functions (265 lines)

Key Improvements

1. Code Reduction: Reduced get_data.py from 1200 → 631 lines (47% reduction)

2. Separation of Concerns:

  • loaders.py: Region-specific data loading (discharge, ERA5, static, snow)
  • transformers.py: Data transformations (SLA shifting, reindexing, moving averages)
  • scalers.py: Modular scaling functions (discharge, ERA5, static features)

3. Extracted Functions (16 total):

  • get_discharge_df(), get_era5_df(), get_static_df()
  • load_snow_data(), load_forcing_data()
  • time_shift_sla_data(), append_nir_to_sla(), load_sla_nir_data()
  • process_sla_data(), add_moving_avg()
  • compute_discharge_scalers(), apply_discharge_scalers()
  • compute_era5_scalers(), apply_era5_scalers()
  • scale_static_features(), save_scalers()

4. Preserved Functionality:

  • All region-specific handling (KGZ, TJK)
  • Legacy functions kept for backward compatibility
  • Same output format from load_data()

Testing

All import smoke tests pass (4/4)

pytest tests/test_imports.py -v
  • Verifies all data_utils imports work
  • No circular dependencies
  • Legacy functions still accessible

Technical Details

Import Structure

# get_data.py now imports from data_utils
from .data_utils import (
    get_discharge_df,
    get_era5_df,
    get_static_df,
    compute_discharge_scalers,
    apply_discharge_scalers,
    compute_era5_scalers,
    apply_era5_scalers,
    scale_static_features,
    save_scalers,
    add_moving_avg,
    process_sla_data,
)

Backward Compatibility

  • load_data() function signature unchanged
  • Returns same dict structure
  • Legacy functions (scale_discharge, scale_era5) kept temporarily

Code Quality

  • ✅ Formatted with ruff format
  • ✅ Proper docstrings with type hints
  • ✅ Logging configured consistently

Migration Impact

Zero breaking changes - existing code using load_data() will work without modification.

Related Files

  • Removed: ST_Forecast/data_loading_example.py (functionality now in data_utils)
  • Added: tests/test_imports.py (smoke tests)
  • Added: scratchpads/issues/refactor-data-loading-modular-structure-1.md (implementation plan)

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

sandrohuni and others added 30 commits October 21, 2025 13:19
- Import functions from data_utils.loaders, transformers, scalers
- Remove duplicate function definitions
- Reduced file size from 1200 to 631 lines (47% reduction)
- Keep legacy functions for backward compatibility
- All imports working correctly
- Add load_data_df to test assertions
- All tests passing (4/4)
Changed stack_era5() to use explicit code matching via dictionary instead
of assuming discharge and forcing TimeSeries lists are in the same order.

- Create forcing_map dictionary for O(1) code lookups
- Skip basins with missing forcing data (with warning)
- Return filtered result list instead of modifying in place
- Add comprehensive docstring explaining the matching logic

This fixes the "error 15025.0 15022.0" messages caused by TimeSeries
lists being in different orders.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add factory functions for creating training components with full configurability:
- RunConfig extended with scheduler, likelihood, callbacks, and checkpoint settings
- New training_components.py with create_likelihood, create_scheduler_config, etc.
- Unified initialize_model() using factory functions for all 6 model types
- Configurable checkpoint_strategy (best/last) in training
- Quantiles flow from config through model init

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add TP, FP, TN, FN counts to flood_metrics.csv output
- Add horizontal threshold lines (2, 5, 10-year) to forecast plots
- Add confusion matrix visualization by return period with lead time subplots
- Extend compute_classification_metrics, compute_basin_flood_metrics,
  and compute_all_basins_flood_metrics to include confusion matrix counts
- Add load_flood_thresholds helper and RETURN_PERIOD_* constants
- Add plot_confusion_matrices_by_return_period function
- Update generate_visualizations to wire new features

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@sandrohuni
sandrohuni merged commit 74ad9e0 into main Mar 11, 2026
1 check passed
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.

Refactor data loading to use modular data_utils structure

1 participant