mabuseif commited on
Commit
e17a40a
·
verified ·
1 Parent(s): bdbcbd3

Update data/climate_data.py

Browse files
Files changed (1) hide show
  1. data/climate_data.py +50 -23
data/climate_data.py CHANGED
@@ -93,6 +93,36 @@ class ClimateData:
93
  self.countries = sorted(list(set(loc.country for loc in self.locations.values())))
94
  self.country_states = self._group_locations_by_country_state()
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  def display_climate_input(self, session_state: Dict[str, Any]):
97
  """Display form for manual input or EPW upload in Streamlit."""
98
  st.title("Climate Data")
@@ -191,15 +221,18 @@ class ClimateData:
191
  for col in epw_data.columns:
192
  epw_data[col] = pd.to_numeric(epw_data[col], errors='coerce')
193
 
194
- # Extract key columns (using specified indices: 7, 8, 9)
195
  months = epw_data[1].values # Month
196
- dry_bulb = epw_data[7].values # Dry-bulb temperature (°C)
197
- wet_bulb = epw_data[8].values # Wet-bulb temperature (°C)
198
- humidity = epw_data[9].values # Relative humidity (%)
 
 
 
199
 
200
  # Check for critical NaN issues
201
- if np.all(np.isnan(dry_bulb)) or np.all(np.isnan(humidity)):
202
- raise ValueError("Dry bulb temperature or humidity data is entirely NaN.")
203
 
204
  # Calculate HDD and CDD (base 18°C)
205
  daily_temps = np.nanmean(dry_bulb.reshape(-1, 24), axis=1)
@@ -209,8 +242,7 @@ class ClimateData:
209
  # Design conditions
210
  winter_design_temp = round(np.nanpercentile(dry_bulb, 0.4), 1) # 99.6% heating design
211
  summer_design_temp_db = round(np.nanpercentile(dry_bulb, 99.6), 1) # 0.4% cooling design DB
212
- summer_idx = np.argmax(dry_bulb >= summer_design_temp_db)
213
- summer_design_temp_wb = round(wet_bulb[summer_idx], 1) if not np.isnan(wet_bulb[summer_idx]) else 25.0
214
  summer_mask = (months >= 6) & (months <= 8)
215
  summer_temps = dry_bulb[summer_mask].reshape(-1, 24)
216
  summer_daily_range = round(np.nanmean(np.nanmax(summer_temps, axis=1) - np.nanmin(summer_temps, axis=1)), 1)
@@ -247,7 +279,7 @@ class ClimateData:
247
  monthly_humidity=monthly_humidity
248
  )
249
  self.add_location(location)
250
- st.success("Climate data extracted from EPW file!")
251
  self.display_design_conditions(location)
252
  self.visualize_data(location, epw_data=epw_data)
253
  except Exception as e:
@@ -333,7 +365,7 @@ class ClimateData:
333
 
334
  # Add min/max for EPW data only
335
  if epw_data is not None:
336
- dry_bulb = epw_data[7].values # Dry-bulb temperature (°C)
337
  month_col = epw_data[1].values
338
  temps_min = []
339
  temps_max = []
@@ -382,7 +414,8 @@ class ClimateData:
382
 
383
  # Add min/max for EPW data only
384
  if epw_data is not None:
385
- humidity = epw_data[9].values # Relative humidity (%)
 
386
  humidity_min = []
387
  humidity_max = []
388
  for i in range(1, 13):
@@ -425,23 +458,17 @@ class ClimateData:
425
 
426
  @classmethod
427
  def from_json(cls, file_path: str) -> 'ClimateData':
428
- """Create a ClimateData instance from a JSON file."""
429
  with open(file_path, 'r') as f:
430
  data = json.load(f)
431
  climate_data = cls()
432
- climate_data.locations = {}
433
  for loc_id, loc_dict in data.items():
434
- climate_data.locations[loc_id] = ClimateLocation(**loc_dict)
435
- climate_data.countries = sorted(list(set(loc.country for loc in climate_data.locations.values())))
436
- climate_data.country_states = climate_data._group_locations_by_country_state()
437
  return climate_data
438
 
439
-
440
  if __name__ == "__main__":
441
- if "building_info" not in st.session_state:
442
- st.session_state.building_info = {"country": "Iceland", "city": "Reykjavik"}
443
- if "page" not in st.session_state:
444
- st.session_state.page = "Climate Data"
445
-
446
  climate_data = ClimateData()
447
- climate_data.display_climate_input(st.session_state)
 
 
93
  self.countries = sorted(list(set(loc.country for loc in self.locations.values())))
94
  self.country_states = self._group_locations_by_country_state()
95
 
96
+ @staticmethod
97
+ def calculate_wet_bulb(dry_bulb: np.ndarray, relative_humidity: np.ndarray) -> np.ndarray:
98
+ """Calculate Wet Bulb Temperature using Stull (2011) approximation.
99
+
100
+ Args:
101
+ dry_bulb (np.ndarray): Dry Bulb Temperature (°C)
102
+ relative_humidity (np.ndarray): Relative Humidity (%)
103
+
104
+ Returns:
105
+ np.ndarray: Wet Bulb Temperature (°C)
106
+ """
107
+ # Ensure inputs are numpy arrays and handle NaN values
108
+ db = np.array(dry_bulb, dtype=float)
109
+ rh = np.array(relative_humidity, dtype=float)
110
+
111
+ # Stull formula
112
+ term1 = db * np.arctan(0.151977 * (rh + 8.313659)**0.5)
113
+ term2 = np.arctan(db + rh)
114
+ term3 = np.arctan(rh - 1.676331)
115
+ term4 = 0.00391838 * rh**1.5 * np.arctan(0.023101 * rh)
116
+ term5 = -4.686035
117
+
118
+ wet_bulb = term1 + term2 - term3 + term4 + term5
119
+
120
+ # Mask invalid values (e.g., RH < 5% or > 99%, or extreme DBT)
121
+ invalid_mask = (rh < 5) | (rh > 99) | (db < -20) | (db > 50) | np.isnan(db) | np.isnan(rh)
122
+ wet_bulb[invalid_mask] = np.nan
123
+
124
+ return wet_bulb
125
+
126
  def display_climate_input(self, session_state: Dict[str, Any]):
127
  """Display form for manual input or EPW upload in Streamlit."""
128
  st.title("Climate Data")
 
221
  for col in epw_data.columns:
222
  epw_data[col] = pd.to_numeric(epw_data[col], errors='coerce')
223
 
224
+ # Extract key columns (adjusted for your file)
225
  months = epw_data[1].values # Month
226
+ dry_bulb = epw_data[6].values # Dry-bulb temperature (°C) - 7th in Excel
227
+ humidity = epw_data[8].values # Relative humidity (%) - 9th in Excel
228
+ pressure = epw_data[9].values # Atmospheric pressure (Pa) - 10th in Excel
229
+
230
+ # Calculate Wet Bulb Temperature
231
+ wet_bulb = self.calculate_wet_bulb(dry_bulb, humidity)
232
 
233
  # Check for critical NaN issues
234
+ if np.all(np.isnan(dry_bulb)) or np.all(np.isnan(humidity)) or np.all(np.isnan(wet_bulb)):
235
+ raise ValueError("Dry bulb, humidity, or calculated wet bulb data is entirely NaN.")
236
 
237
  # Calculate HDD and CDD (base 18°C)
238
  daily_temps = np.nanmean(dry_bulb.reshape(-1, 24), axis=1)
 
242
  # Design conditions
243
  winter_design_temp = round(np.nanpercentile(dry_bulb, 0.4), 1) # 99.6% heating design
244
  summer_design_temp_db = round(np.nanpercentile(dry_bulb, 99.6), 1) # 0.4% cooling design DB
245
+ summer_design_temp_wb = round(np.nanpercentile(wet_bulb, 99.6), 1) # 0.4% cooling design WB
 
246
  summer_mask = (months >= 6) & (months <= 8)
247
  summer_temps = dry_bulb[summer_mask].reshape(-1, 24)
248
  summer_daily_range = round(np.nanmean(np.nanmax(summer_temps, axis=1) - np.nanmin(summer_temps, axis=1)), 1)
 
279
  monthly_humidity=monthly_humidity
280
  )
281
  self.add_location(location)
282
+ st.success("Climate data extracted from EPW file with calculated Wet Bulb Temperature!")
283
  self.display_design_conditions(location)
284
  self.visualize_data(location, epw_data=epw_data)
285
  except Exception as e:
 
365
 
366
  # Add min/max for EPW data only
367
  if epw_data is not None:
368
+ dry_bulb = epw_data[6].values # Dry-bulb temperature (°C)
369
  month_col = epw_data[1].values
370
  temps_min = []
371
  temps_max = []
 
414
 
415
  # Add min/max for EPW data only
416
  if epw_data is not None:
417
+ humidity = epw_data[8].values # Relative humidity (%) - adjusted to 9th column
418
+ month_col = epw_data[1].values
419
  humidity_min = []
420
  humidity_max = []
421
  for i in range(1, 13):
 
458
 
459
  @classmethod
460
  def from_json(cls, file_path: str) -> 'ClimateData':
461
+ """Load climate data from a JSON file."""
462
  with open(file_path, 'r') as f:
463
  data = json.load(f)
464
  climate_data = cls()
 
465
  for loc_id, loc_dict in data.items():
466
+ location = ClimateLocation(**loc_dict)
467
+ climate_data.add_location(location)
 
468
  return climate_data
469
 
470
+ # Example usage
471
  if __name__ == "__main__":
 
 
 
 
 
472
  climate_data = ClimateData()
473
+ session_state = {"building_info": {"country": "Iceland", "city": "Reykjavik"}, "page": "Climate Data"}
474
+ climate_data.display_climate_input(session_state)