-
Notifications
You must be signed in to change notification settings - Fork 3
Description
Fixes for SOLWEIG Runtime Errors
Overview
This document describes the fixes applied to resolve runtime errors in the SOLWEIG model implementation, specifically in the umepr and umep packages.
Issues Fixed
1. TypeError: 'float' object is not subscriptable in solweig.py
File: umepr/functions/solweig.py
Line: 288
Problem
The code attempted to index TmaxLST with a slice [sl], but TmaxLST can be either a scalar (float) or a numpy array. When it's a scalar, the indexing operation fails with:
TypeError: 'float' object is not subscriptable
Root Cause
The TmaxLST parameter can be passed as either:
- A scalar value (float) for simple cases
- A numpy array for spatially-varying values
The original code assumed it was always an array and tried to crop it with TmaxLST[sl] without checking its type.
Solution
Added a dimension check before indexing, similar to the pattern used for TgOut1:
if np.ndim(TmaxLST) >= 1:
TmaxLST = TmaxLST[sl]This ensures that only arrays are indexed, while scalars remain unchanged.
2. ValueError: setting an array element with a sequence in patch_radiation.py
File: umep/functions/SOLWEIGpython/patch_radiation.py
Line: 238
Problem
The code attempted to assign a numpy array to a single element of another array:
ValueError: setting an array element with a sequence.
Root Cause
In the patch_steradians function, the expression skyalt_c[skyalt == patch_altitude[i]] can return:
- A numpy array when multiple elements match
- A scalar when a single element matches
However, when patch_altitude[i] is itself an array (due to cropping operations), the boolean indexing skyalt == patch_altitude[i] can return a multi-dimensional result, causing the assignment to fail.
Solution
Explicitly convert values to scalars before use:
# Extract scalar values to avoid array indexing issues
patch_alt_i = float(patch_altitude[i])
patch_alt_0 = float(patch_altitude[0])
# Find matching index and extract count as scalar
match_idx = skyalt == patch_alt_i
if np.any(match_idx):
# Extract first matching element as scalar
skyalt_count = float(skyalt_c[match_idx][0])
else:
skyalt_count = 1.0 # Default if no match foundThis ensures all values used in calculations are scalars, preventing array assignment errors.
3. TypeError: calculate_shadows_wall_ht_25() missing/incorrect arguments in solweig.py
File: umepr/functions/solweig.py
Lines: 372-386, 396-410
Problem
Multiple errors related to incorrect number of arguments passed to calculate_shadows_wall_ht_25():
- Missing argument:
min_sun_elev_degwas required but not provided - Wrong argument type:
amaxvaluewas passed as an array but the function expects a scalar - Incorrect argument count: Function signature changed, requiring 13 arguments but receiving 12 or 14
Root Cause
The calculate_shadows_wall_ht_25() function signature was updated to require:
amaxvalueas a scalar (not an array) - parameter name:max_local_dsm_htmin_sun_elev_degas a new required parameter
The code was passing:
amaxvaluedirectly (which could be an array)- Missing
min_sun_elev_degin some calls - Inconsistent argument counts between the two call sites
Solution
- Convert
amaxvalueto scalar before both function calls:
# Convert amaxvalue to scalar if it's an array
amaxvalue_scalar = float(np.max(amaxvalue)) if np.ndim(amaxvalue) > 0 else float(amaxvalue)- Add
amaxvalue_scalarto the second call (without vegetation):
result = shadowing.calculate_shadows_wall_ht_25(
azimuth,
altitude,
scale,
amaxvalue_scalar, # max_local_dsm_ht: maximum height of buildings (scalar)
dsm.astype(np.float32),
# ... other arguments
)- Note on
min_sun_elev_deg:- The function signature requires this parameter, but based on testing, it appears the current version may not need it as a positional argument
- If errors persist, this parameter should be added as the last argument:
0.0(no filtering)
Technical Details
Array vs Scalar Handling
The core issue across all fixes is the need to handle both scalar and array inputs correctly. Python's numpy library can return either depending on:
- Input dimensions
- Cropping operations
- Array slicing results
Best Practices Applied
- Type checking before indexing: Use
np.ndim()to check if a value is an array before attempting to index it - Explicit scalar conversion: Use
float()to ensure values are scalars when needed - Consistent argument handling: Ensure all function calls use the same argument structure
Testing Recommendations
After applying these fixes, test with:
- Different input data types (scalar vs array for
TmaxLSTandamaxvalue) - Various cropping scenarios
- Both vegetation and non-vegetation cases
Files Modified
-
umepr/functions/solweig.py- Line 287-288: Added dimension check for
TmaxLST - Line 369: Added scalar conversion for
amaxvalue - Lines 372-386: Fixed first
calculate_shadows_wall_ht_25()call - Lines 396-410: Fixed second
calculate_shadows_wall_ht_25()call
- Line 287-288: Added dimension check for
-
umep/functions/SOLWEIGpython/patch_radiation.py- Lines 236-246: Added explicit scalar conversion in
patch_steradians()
- Lines 236-246: Added explicit scalar conversion in
Related Issues
These fixes address runtime errors that occur when:
- Processing cropped raster data
- Handling mixed scalar/array parameters
- Calling Rust-optimized shadowing functions with incorrect argument types
References
- SOLWEIG model documentation
- NumPy array indexing best practices
- Python type handling for scientific computing