Spaces:
Sleeping
Sleeping
Update data/climate_data.py
Browse files- data/climate_data.py +86 -86
data/climate_data.py
CHANGED
|
@@ -223,103 +223,103 @@ class ClimateData:
|
|
| 223 |
return None
|
| 224 |
|
| 225 |
@staticmethod
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
return False
|
| 239 |
-
|
| 240 |
-
if not (-90 <= data["latitude"] <= 90 and -180 <= data["longitude"] <= 180):
|
| 241 |
-
st.error("Validation failed: Invalid latitude or longitude")
|
| 242 |
-
return False
|
| 243 |
-
if data["elevation"] < 0:
|
| 244 |
-
st.error("Validation failed: Negative elevation")
|
| 245 |
return False
|
| 246 |
-
|
| 247 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 248 |
return False
|
| 249 |
-
if
|
| 250 |
-
st.error(f"Validation failed: Invalid
|
| 251 |
return False
|
| 252 |
-
if not (
|
| 253 |
-
st.error("Validation failed:
|
| 254 |
return False
|
| 255 |
-
if not (-50 <=
|
| 256 |
-
st.error(f"Validation failed:
|
| 257 |
return False
|
| 258 |
-
if not (0 <=
|
| 259 |
-
st.error("Validation failed:
|
| 260 |
return False
|
| 261 |
-
if
|
| 262 |
-
st.error("Validation failed:
|
| 263 |
return False
|
| 264 |
-
if not (0 <=
|
| 265 |
-
st.error(f"Validation failed:
|
| 266 |
return False
|
| 267 |
-
if not (
|
| 268 |
-
st.error(f"Validation failed:
|
| 269 |
return False
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
st.error(f"Validation failed: Hourly data has {len(data['hourly_data'])} records, expected ~8760")
|
| 273 |
return False
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
st.error(f"Validation failed: Dry bulb {record['dry_bulb']} outside range")
|
| 286 |
-
return False
|
| 287 |
-
if not (0 <= record["relative_humidity"] <= 100):
|
| 288 |
-
st.error(f"Validation failed: Relative humidity {record['relative_humidity']} outside range")
|
| 289 |
-
return False
|
| 290 |
-
if not (80000 <= record["atmospheric_pressure"] <= 110000):
|
| 291 |
-
st.error(f"Validation failed: Atmospheric pressure {record['atmospheric_pressure']} outside range")
|
| 292 |
-
return False
|
| 293 |
-
if not (0 <= record["global_horizontal_radiation"] <= 1200):
|
| 294 |
-
st.error(f"Validation failed: Global radiation {record['global_horizontal_radiation']} outside range")
|
| 295 |
-
return False
|
| 296 |
-
if not (0 <= record["wind_speed"] <= 30):
|
| 297 |
-
st.error(f"Validation failed: Wind speed {record['wind_speed']} outside range")
|
| 298 |
-
return False
|
| 299 |
-
if not (0 <= record["wind_direction"] <= 360):
|
| 300 |
-
st.error(f"Validation failed: Wind direction {record['wind_direction']} outside range")
|
| 301 |
-
return False
|
| 302 |
-
|
| 303 |
-
# Validate typical/extreme periods (optional)
|
| 304 |
-
if "typical_extreme_periods" in data and data["typical_extreme_periods"]:
|
| 305 |
-
expected_periods = ["summer_extreme", "summer_typical", "winter_extreme", "winter_typical"]
|
| 306 |
-
missing_periods = [p for p in expected_periods if p not in data["typical_extreme_periods"]]
|
| 307 |
-
if missing_periods:
|
| 308 |
-
st.warning(f"Validation warning: Missing typical/extreme periods: {', '.join(missing_periods)}")
|
| 309 |
-
for period in data["typical_extreme_periods"].values():
|
| 310 |
-
for date in ["start", "end"]:
|
| 311 |
-
if not (1 <= period[date]["month"] <= 12 and 1 <= period[date]["day"] <= 31):
|
| 312 |
-
st.error(f"Validation failed: Invalid date in typical/extreme periods: {period[date]}")
|
| 313 |
-
return False
|
| 314 |
-
|
| 315 |
-
# Validate ground temperatures (optional)
|
| 316 |
-
if "ground_temperatures" in data and data["ground_temperatures"]:
|
| 317 |
-
for depth, temps in data["ground_temperatures"].items():
|
| 318 |
-
if len(temps) != 12 or not all(0 <= t <= 50 for t in temps):
|
| 319 |
-
st.error(f"Validation failed: Invalid ground temperatures for depth {depth}")
|
| 320 |
return False
|
| 321 |
-
|
| 322 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 323 |
|
| 324 |
@staticmethod
|
| 325 |
def calculate_wet_bulb(dry_bulb: np.ndarray, relative_humidity: np.ndarray) -> np.ndarray:
|
|
|
|
| 223 |
return None
|
| 224 |
|
| 225 |
@staticmethod
|
| 226 |
+
def validate_climate_data(data: Dict[str, Any]) -> bool:
|
| 227 |
+
"""Validate climate data for required fields and ranges."""
|
| 228 |
+
required_fields = [
|
| 229 |
+
"id", "country", "city", "latitude", "longitude", "elevation", "time_zone",
|
| 230 |
+
"climate_zone", "heating_degree_days", "cooling_degree_days",
|
| 231 |
+
"winter_design_temp", "summer_design_temp_db", "summer_design_temp_wb",
|
| 232 |
+
"summer_daily_range", "wind_speed", "pressure", "hourly_data"
|
| 233 |
+
]
|
| 234 |
+
|
| 235 |
+
for field in required_fields:
|
| 236 |
+
if field not in data:
|
| 237 |
+
st.error(f"Validation failed: Missing required field '{field}'")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 238 |
return False
|
| 239 |
+
|
| 240 |
+
if not (-90 <= data["latitude"] <= 90 and -180 <= data["longitude"] <= 180):
|
| 241 |
+
st.error("Validation failed: Invalid latitude or longitude")
|
| 242 |
+
return False
|
| 243 |
+
if data["elevation"] < 0:
|
| 244 |
+
st.error("Validation failed: Negative elevation")
|
| 245 |
+
return False
|
| 246 |
+
if not (-12 <= data["time_zone"] <= 14):
|
| 247 |
+
st.error(f"Validation failed: Time zone {data['time_zone']} outside range (-12 to +14)")
|
| 248 |
+
return False
|
| 249 |
+
if data["climate_zone"] not in ["0A", "0B", "1A", "1B", "2A", "2B", "3A", "3B", "3C", "4A", "4B", "4C", "5A", "5B", "5C", "6A", "6B", "7", "8"]:
|
| 250 |
+
st.error(f"Validation failed: Invalid climate zone '{data['climate_zone']}'")
|
| 251 |
+
return False
|
| 252 |
+
if not (data["heating_degree_days"] >= 0 and data["cooling_degree_days"] >= 0):
|
| 253 |
+
st.error("Validation failed: Negative degree days")
|
| 254 |
+
return False
|
| 255 |
+
if not (-50 <= data["winter_design_temp"] <= 20):
|
| 256 |
+
st.error(f"Validation failed: Winter design temp {data['winter_design_temp']} outside range")
|
| 257 |
+
return False
|
| 258 |
+
if not (0 <= data["summer_design_temp_db"] <= 50 and 0 <= data["summer_design_temp_wb"] <= 40):
|
| 259 |
+
st.error("Validation failed: Invalid summer design temperatures")
|
| 260 |
+
return False
|
| 261 |
+
if data["summer_daily_range"] < 0:
|
| 262 |
+
st.error("Validation failed: Negative summer daily range")
|
| 263 |
+
return False
|
| 264 |
+
if not (0 <= data["wind_speed"] <= 30):
|
| 265 |
+
st.error(f"Validation failed: Wind speed {data['wind_speed']} outside range")
|
| 266 |
+
return False
|
| 267 |
+
if not (80000 <= data["pressure"] <= 110000):
|
| 268 |
+
st.error(f"Validation failed: Pressure {data['pressure']} outside range")
|
| 269 |
+
return False
|
| 270 |
+
|
| 271 |
+
if not data["hourly_data"] or len(data["hourly_data"]) < 8700:
|
| 272 |
+
st.error(f"Validation failed: Hourly data has {len(data['hourly_data'])} records, expected ~8760")
|
| 273 |
+
return False
|
| 274 |
+
for record in data["hourly_data"]:
|
| 275 |
+
if not (1 <= record["month"] <= 12):
|
| 276 |
+
st.error(f"Validation failed: Invalid month {record['month']}")
|
| 277 |
return False
|
| 278 |
+
if not (1 <= record["day"] <= 31):
|
| 279 |
+
st.error(f"Validation failed: Invalid day {record['day']}")
|
| 280 |
return False
|
| 281 |
+
if not (1 <= record["hour"] <= 24):
|
| 282 |
+
st.error(f"Validation failed: Invalid hour {record['hour']}")
|
| 283 |
return False
|
| 284 |
+
if not (-50 <= record["dry_bulb"] <= 50):
|
| 285 |
+
st.error(f"Validation failed: Dry bulb {record['dry_bulb']} outside range")
|
| 286 |
return False
|
| 287 |
+
if not (0 <= record["relative_humidity"] <= 100):
|
| 288 |
+
st.error(f"Validation failed: Relative humidity {record['relative_humidity']} outside range")
|
| 289 |
return False
|
| 290 |
+
if not (80000 <= record["atmospheric_pressure"] <= 110000):
|
| 291 |
+
st.error(f"Validation failed: Atmospheric pressure {record['atmospheric_pressure']} outside range")
|
| 292 |
return False
|
| 293 |
+
if not (0 <= record["global_horizontal_radiation"] <= 1200):
|
| 294 |
+
st.error(f"Validation failed: Global radiation {record['global_horizontal_radiation']} outside range")
|
| 295 |
return False
|
| 296 |
+
if not (0 <= record["wind_speed"] <= 30):
|
| 297 |
+
st.error(f"Validation failed: Wind speed {record['wind_speed']} outside range")
|
| 298 |
return False
|
| 299 |
+
if not (0 <= record["wind_direction"] <= 360):
|
| 300 |
+
st.error(f"Validation failed: Wind direction {record['wind_direction']} outside range")
|
|
|
|
| 301 |
return False
|
| 302 |
+
|
| 303 |
+
# Validate typical/extreme periods (optional)
|
| 304 |
+
if "typical_extreme_periods" in data and data["typical_extreme_periods"]:
|
| 305 |
+
expected_periods = ["summer_extreme", "summer_typical", "winter_extreme", "winter_typical"]
|
| 306 |
+
missing_periods = [p for p in expected_periods if p not in data["typical_extreme_periods"]]
|
| 307 |
+
if missing_periods:
|
| 308 |
+
st.warning(f"Validation warning: Missing typical/extreme periods: {', '.join(missing_periods)}")
|
| 309 |
+
for period in data["typical_extreme_periods"].values():
|
| 310 |
+
for date in ["start", "end"]:
|
| 311 |
+
if not (1 <= period[date]["month"] <= 12 and 1 <= period[date]["day"] <= 31):
|
| 312 |
+
st.error(f"Validation failed: Invalid date in typical/extreme periods: {period[date]}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 313 |
return False
|
| 314 |
+
|
| 315 |
+
# Validate ground temperatures (optional)
|
| 316 |
+
if "ground_temperatures" in data and data["ground_temperatures"]:
|
| 317 |
+
for depth, temps in data["ground_temperatures"].items():
|
| 318 |
+
if len(temps) != 12 or not all(0 <= t <= 50 for t in temps):
|
| 319 |
+
st.error(f"Validation failed: Invalid ground temperatures for depth {depth}")
|
| 320 |
+
return False
|
| 321 |
+
|
| 322 |
+
return True
|
| 323 |
|
| 324 |
@staticmethod
|
| 325 |
def calculate_wet_bulb(dry_bulb: np.ndarray, relative_humidity: np.ndarray) -> np.ndarray:
|