Skip to content

Conversation

@sunt05
Copy link

@sunt05 sunt05 commented Nov 14, 2025

Reintroduces observed soil moisture support by converting xsmd inputs before calling SUEWS. Adds soil observation metadata to the land-cover schema plus docs describing the required fields. Documents the change in the changelog and adds unit tests that exercise volumetric and gravimetric conversions. Testing: source .venv/bin/activate && PYTHONPATH=src pytest test/core/test_soil_obs_conversion.py

@sunt05 sunt05 temporarily deployed to github-pages-preview November 14, 2025 13:39 — with GitHub Actions Inactive
@github-actions
Copy link

🤖 I've automatically formatted the code in this PR using:

  • Python: ruff v0.8.6
  • Fortran: fprettify v0.3.7

Please pull the latest changes before making further edits.

@github-actions
Copy link

github-actions bot commented Nov 14, 2025

🔍 Schema Preview Deployed

Preview URLs:

Production URLs (unchanged):


⚠️ Important: Preview schemas are in a subdirectory and do not affect production. The preview pages include warning banners to prevent accidental use in production configs.

@sunt05 sunt05 temporarily deployed to github-pages-preview November 14, 2025 20:57 — with GitHub Actions Inactive
@sunt05 sunt05 temporarily deployed to github-pages-preview November 15, 2025 00:25 — with GitHub Actions Inactive
@github-actions
Copy link

🤖 I've automatically formatted the code in this PR using:

  • Python: ruff v0.8.6
  • Fortran: fprettify v0.3.7

Please pull the latest changes before making further edits.

@sunt05 sunt05 temporarily deployed to github-pages-preview November 15, 2025 23:43 — with GitHub Actions Inactive
@github-actions
Copy link

🤖 I've automatically formatted the code in this PR using:

  • Python: ruff v0.8.6
  • Fortran: fprettify v0.3.7

Please pull the latest changes before making further edits.

@sunt05 sunt05 force-pushed the sunt05/gh3-xsmd-input branch from 26d43ac to 81626bf Compare November 16, 2025 08:27
@sunt05 sunt05 temporarily deployed to github-pages-preview November 16, 2025 08:27 — with GitHub Actions Inactive
@sunt05 sunt05 marked this pull request as ready for review November 16, 2025 15:56
@sunt05 sunt05 marked this pull request as draft November 16, 2025 17:54
@sunt05 sunt05 temporarily deployed to github-pages-preview November 16, 2025 21:24 — with GitHub Actions Inactive
@sunt05 sunt05 temporarily deployed to github-pages-preview November 19, 2025 07:54 — with GitHub Actions Inactive
@sunt05 sunt05 force-pushed the sunt05/gh3-xsmd-input branch from cce8efe to 6b605ca Compare November 19, 2025 14:10
@sunt05 sunt05 temporarily deployed to github-pages-preview November 19, 2025 14:10 — with GitHub Actions Inactive
@sunt05 sunt05 force-pushed the sunt05/gh3-xsmd-input branch from 6b605ca to 95ea7ca Compare November 19, 2025 14:49
@sunt05 sunt05 temporarily deployed to github-pages-preview November 19, 2025 14:49 — with GitHub Actions Inactive
@sunt05 sunt05 force-pushed the sunt05/gh3-xsmd-input branch from 95ea7ca to 0ede9a4 Compare November 19, 2025 21:58
@sunt05 sunt05 temporarily deployed to github-pages-preview November 19, 2025 21:58 — with GitHub Actions Inactive
@sunt05 sunt05 temporarily deployed to github-pages-preview November 27, 2025 10:28 — with GitHub Actions Inactive
@sunt05 sunt05 force-pushed the sunt05/gh3-xsmd-input branch from fbba5b4 to 34a4d53 Compare November 27, 2025 11:38
@sunt05 sunt05 temporarily deployed to github-pages-preview November 27, 2025 11:38 — with GitHub Actions Inactive
@sunt05 sunt05 force-pushed the sunt05/gh3-xsmd-input branch from 34a4d53 to babe08e Compare November 27, 2025 12:50
@sunt05 sunt05 temporarily deployed to github-pages-preview November 27, 2025 12:50 — with GitHub Actions Inactive
@sunt05 sunt05 force-pushed the sunt05/gh3-xsmd-input branch from babe08e to 82129c1 Compare November 27, 2025 23:39
@sunt05 sunt05 temporarily deployed to github-pages-preview November 27, 2025 23:39 — with GitHub Actions Inactive
@sunt05 sunt05 temporarily deployed to github-pages-preview November 27, 2025 23:47 — with GitHub Actions Inactive
@sunt05 sunt05 force-pushed the sunt05/gh3-xsmd-input branch from c88cbac to d1e0980 Compare December 1, 2025 15:26
@sunt05 sunt05 temporarily deployed to github-pages-preview December 1, 2025 15:26 — with GitHub Actions Inactive
@sunt05 sunt05 force-pushed the sunt05/gh3-xsmd-input branch from 328226a to 559e8f8 Compare December 2, 2025 07:47
@sunt05 sunt05 temporarily deployed to github-pages-preview December 2, 2025 07:47 — with GitHub Actions Inactive
@github-actions
Copy link

github-actions bot commented Dec 2, 2025

🤖 I've automatically formatted the code in this PR using:

  • Python: ruff v0.8.6
  • Fortran: fprettify v0.3.7

Please pull the latest changes before making further edits.

@sunt05 sunt05 force-pushed the sunt05/gh3-xsmd-input branch from 1d41366 to d285282 Compare December 2, 2025 10:05
@sunt05 sunt05 temporarily deployed to github-pages-preview December 2, 2025 10:05 — with GitHub Actions Inactive
@sunt05 sunt05 temporarily deployed to github-pages-preview December 2, 2025 10:43 — with GitHub Actions Inactive
@github-actions
Copy link

github-actions bot commented Dec 2, 2025

🤖 I've automatically formatted the code in this PR using:

  • Python: ruff v0.8.6
  • Fortran: fprettify v0.3.7

Please pull the latest changes before making further edits.

@sunt05 sunt05 temporarily deployed to github-pages-preview December 2, 2025 11:25 — with GitHub Actions Inactive
@sunt05 sunt05 temporarily deployed to github-pages-preview December 2, 2025 15:26 — with GitHub Actions Inactive
sunt05 and others added 17 commits December 3, 2025 12:01
Co-authored-by: sunt05 <1802656+sunt05@users.noreply.github.com>
Code review fixes addressing Python compatibility, documentation clarity, and test coverage:

- Fix type hints: Use Optional[float] instead of float | None for Python 3.9+ compatibility
- Document surface type indices: Add comprehensive comment explaining SUEWS surface types 0-5
- Document missing value tolerance: Explain +1.0 offset for -999 missing value detection
- Add dimensional analysis: Document unit conversions for volumetric and gravimetric methods
- Add debug logging: Log conversion statistics (min/max/mean deficit, valid count) at DEBUG level
- Improve error messages: Make metadata mismatch error more actionable with specific solutions
- Add edge case tests: NaN handling, clipping validation, negative values, all-missing scenario
- Fix build configuration: Add _soil_obs.py to meson.build for proper module installation

All tests pass (7/7):
- test_convert_observed_soil_moisture_volumetric
- test_convert_observed_soil_moisture_gravimetric
- test_missing_metadata_raises_error
- test_xsmd_with_nan_values
- test_xsmd_exceeding_smcap
- test_xsmd_negative_values
- test_xsmd_all_missing
Co-authored-by: sunt05 <1802656+sunt05@users.noreply.github.com>
Fixes table conversion and CLI tests by handling optional soil observation fields gracefully:

**Problem**: Old SUEWS tables don't have the new soil observation metadata fields
(soildensity, obs_sm_depth, obs_sm_cap, obs_soil_not_rocks), causing conversion failures.

**Solution**:
1. `SurfaceProperties.from_df_state()`: Check if column exists before accessing; set to None
   for optional fields that are missing (backwards compatible with old tables)
2. `SurfaceProperties.to_df_state()`: Use -999 (missing value) for soil observation fields
   when None, instead of 0.0 which would fail validation
3. `test_df_state_conversion.py`: Update expected column count from 1423 to 1451
   (28 new columns = 4 fields × 7 surface types)

**Tests fixed** (8/8 passing):
- test_convert_old_csv
- test_single_layer_end_to_end
- test_multi_layer_end_to_end
- test_legacy_version_auto_detection[2020a]
- test_legacy_version_auto_detection[2019a]
- test_legacy_version_auto_detection[2018a]
- (2 additional CLI conversion tests)

**Behaviour**: New optional fields default to -999 (missing) when loading old tables,
which is correct since soil observations are only needed when SMDMethod > 0.
Co-authored-by: sunt05 <1802656+sunt05@users.noreply.github.com>
Reorganises soil observation conversion logic following SuPy's established pattern where specialized utilities live in the `util/` subdirectory.

**Changes**:
- Moved `_soil_obs.py` → `util/_forcing.py`
- Updated import in `_run.py`: `from ._soil_obs` → `from .util._forcing`
- Updated `meson.build` to reflect new file location
- Updated test imports to load from new location
- No functional changes; purely organisational refactoring

**Rationale**:
- Removes module from top-level namespace
- Follows established pattern (util/_atm.py, util/_ohm.py, etc.)
- Improves code organisation whilst maintaining testability

**Testing**:
- Direct module loading confirms functionality (Python tests pass)
- Note: Full test suite blocked by unrelated Fortran build issue
- Replace convoluted importlib mechanics with standard import in
  test_soil_obs_conversion.py (reduces 14 lines to 3)
- Clarify df_state column count comment to explain the 28 soil
  observation fields (4 fields × 7 surfaces)
- Note that Water/Bldgs surfaces don't need soil obs but get
  columns anyway due to flat df_state structure

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

Co-Authored-By: Claude <noreply@anthropic.com>
Observed soil moisture is a point measurement, so per-surface weighted
averaging was over-engineered. Now reads metadata from surface 0 only.

Changes:
- Remove _surface_weights() and _weighted_average() functions
- Add SOIL_OBS_SURFACE_INDEX constant (=0) for single-surface read
- Fix NaN handling: use fillna(0) before astype(int) for smdmethod
- Update tests to use single-surface helper
- Update docs to specify Paved surface only
- Correct CHANGELOG date (13 Nov -> 14 Nov)

Code reduction: ~35 net lines removed

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

Co-Authored-By: Claude <noreply@anthropic.com>
The formula is numerically correct but the dimensional analysis comment
was misleading. Clarified that division by ρ_water (1 g/cm³) is implicit.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Previously, metadata was hardcoded to surface 0 (Paved), which doesn't
make sense if Paved has zero coverage. Now searches surfaces 0-5 and
uses the first one with complete metadata, allowing users to set
observation parameters on grass, bare soil, or any other surface.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Soil observation metadata is now correctly modelled as a site-level
property rather than being awkwardly stored per-surface. This reflects
the physical reality that observed soil moisture is a point measurement.

Changes:
- Add SoilObservationConfig class to site.py with depth, smcap,
  soil_not_rocks, and bulk_density fields
- Add soil_observation field to SiteProperties
- Update _forcing.py to check site-level config first, fall back
  to per-surface for backwards compatibility
- Add 4 new tests for site-level config and precedence behaviour
- Update documentation with preferred YAML approach

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

Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: sunt05 <1802656+sunt05@users.noreply.github.com>
Simplify soil observation configuration to only support the site-level
YAML approach via `site.properties.soil_observation`. This removes:

- Per-surface fallback in _extract_soil_obs_metadata()
- Per-surface soil observation fields from SurfaceProperties
- Legacy per-surface tests from test_soil_obs_conversion.py
- Legacy documentation from SUEWS_Soil.rst

The per-surface approach via SUEWS_Soil.txt columns is now fully
deprecated in favour of the YAML-only configuration.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: sunt05 <1802656+sunt05@users.noreply.github.com>
The soil observation configuration is now documented exclusively in
the auto-generated YAML config reference (from SoilObservationConfig
Pydantic model in site.py).

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

Co-Authored-By: Claude <noreply@anthropic.com>
These per-surface soil observation columns are no longer supported.
Soil observation configuration is now site-level only via YAML.

Removed from:
- Input_Options.rst: OBS_SMCap, OBS_SMDepth, OBS_SoilNotRocks entries
- csv-table/: OBS_SM*.csv files deleted
- SUEWS_Soil.csv: columns 7-9 removed
- sample-table/SUEWS_Soil.txt: columns 7-9 removed
- typical-general.csv: OBS_SM* rows removed

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

Co-Authored-By: Claude <noreply@anthropic.com>
@sunt05 sunt05 force-pushed the sunt05/gh3-xsmd-input branch from ec1cf2b to 7e9b915 Compare December 3, 2025 12:02
@sunt05 sunt05 temporarily deployed to github-pages-preview December 3, 2025 12:02 — with GitHub Actions Inactive
@sunt05 sunt05 temporarily deployed to github-pages-preview December 3, 2025 12:02 — with GitHub Actions Inactive
@github-actions
Copy link

github-actions bot commented Dec 3, 2025

Documentation Preview

Preview URL: https://umep-dev.github.io/SUEWS/preview/pr-859/docs/

This is a PR preview. Production docs remain at https://suews.readthedocs.io

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.

2 participants