mabuseif commited on
Commit
e4a440d
·
verified ·
1 Parent(s): 84b54a5

Update data/climate_data.py

Browse files
Files changed (1) hide show
  1. data/climate_data.py +11 -43
data/climate_data.py CHANGED
@@ -95,20 +95,10 @@ class ClimateData:
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)
@@ -117,7 +107,6 @@ class ClimateData:
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
 
@@ -151,7 +140,7 @@ class ClimateData:
151
  hdd = st.number_input("Heating Degree Days (base 18°C)", min_value=0.0, value=0.0, step=100.0)
152
  cdd = st.number_input("Cooling Degree Days (base 18°C)", min_value=0.0, value=0.0, step=100.0)
153
  winter_design_temp = st.number_input("Winter Design Temp (99.6%) (°C)", min_value=-50.0, max_value=20.0, value=0.0, step=0.5)
154
- summer_design_temp_db = st.number_input("Summer Design Temp EXPORTDB (0.4%) (°C)", min_value=0.0, max_value=50.0, value=35.0, step=0.5)
155
  summer_design_temp_wb = st.number_input("Summer Design Temp WB (0.4%) (°C)", min_value=0.0, max_value=40.0, value=25.0, step=0.5)
156
  summer_daily_range = st.number_input("Summer Daily Range (°C)", min_value=0.0, value=5.0, step=0.5)
157
 
@@ -162,7 +151,7 @@ class ClimateData:
162
  col1, col2 = st.columns(2)
163
  with col1:
164
  for month in month_names[:6]:
165
- monthly_temps[month] = st.number_input(f"{month} Temp (°C)", min_value=- diaspora50.0, max_value=50.0, value=20.0, step=0.5, key=f"temp_{month}")
166
  with col2:
167
  for month in month_names[6:]:
168
  monthly_temps[month] = st.number_input(f"{month} Temp (°C)", min_value=-50.0, max_value=50.0, value=20.0, step=0.5, key=f"temp_{month}")
@@ -211,43 +200,35 @@ class ClimateData:
211
  longitude = float(header_parts[7])
212
  elevation = float(header_parts[8])
213
 
214
- # Find data start after "DATA PERIODS"
215
  data_start_idx = next(i for i, line in enumerate(epw_lines) if line.startswith("DATA PERIODS")) + 1
216
  epw_data = pd.read_csv(StringIO("\n".join(epw_lines[data_start_idx:])), header=None, dtype=str)
217
  if len(epw_data) != 8760:
218
  raise ValueError(f"EPW file has {len(epw_data)} records, expected 8760.")
219
 
220
- # Convert to numeric, handling non-numeric values
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)
239
  hdd = round(np.nansum(np.maximum(18 - daily_temps, 0)))
240
  cdd = round(np.nansum(np.maximum(daily_temps - 18, 0)))
241
 
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)
249
 
250
- # Monthly averages
251
  monthly_temps = {}
252
  monthly_humidity = {}
253
  month_names = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
@@ -256,7 +237,6 @@ class ClimateData:
256
  monthly_temps[month_names[i-1]] = round(np.nanmean(dry_bulb[month_mask]), 1)
257
  monthly_humidity[month_names[i-1]] = round(np.nanmean(humidity[month_mask]), 1)
258
 
259
- # Assign climate zone
260
  avg_humidity = np.nanmean(humidity)
261
  climate_zone = self.assign_climate_zone(hdd, cdd, avg_humidity)
262
 
@@ -285,7 +265,6 @@ class ClimateData:
285
  except Exception as e:
286
  st.error(f"Error processing EPW file: {str(e)}. Ensure it has 8760 hourly records and correct format.")
287
 
288
- # Navigation buttons
289
  col1, col2 = st.columns(2)
290
  with col1:
291
  st.button("Back to Building Information", on_click=lambda: setattr(session_state, "page", "Building Information"))
@@ -299,7 +278,6 @@ class ClimateData:
299
  """Display a table of design conditions including additional parameters for HVAC calculations."""
300
  st.subheader("Design Conditions for HVAC Calculations")
301
 
302
- # Prepare the design data with additional parameters
303
  design_data = pd.DataFrame({
304
  "Parameter": [
305
  "Latitude",
@@ -327,23 +305,18 @@ class ClimateData:
327
  ]
328
  })
329
 
330
- # Add monthly temperatures
331
  month_names = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
332
  monthly_temp_data = pd.DataFrame({
333
  "Parameter": [f"{month} Avg Temp" for month in month_names],
334
  "Value": [f"{location.monthly_temps[month]} °C" for month in month_names]
335
  })
336
 
337
- # Add monthly humidity
338
  monthly_humidity_data = pd.DataFrame({
339
  "Parameter": [f"{month} Avg Humidity" for month in month_names],
340
  "Value": [f"{location.monthly_humidity[month]} %" for month in month_names]
341
  })
342
 
343
- # Combine all data into one table
344
  full_design_data = pd.concat([design_data, monthly_temp_data, monthly_humidity_data], ignore_index=True)
345
-
346
- # Display the table in Streamlit
347
  st.table(full_design_data)
348
 
349
  @staticmethod
@@ -378,7 +351,6 @@ class ClimateData:
378
  temps_avg = [location.monthly_temps[m] for m in month_names]
379
  humidity_avg = [location.monthly_humidity[m] for m in month_names]
380
 
381
- # Temperature Plot
382
  fig_temp = go.Figure()
383
  fig_temp.add_trace(go.Scatter(
384
  x=months,
@@ -389,9 +361,8 @@ class ClimateData:
389
  marker=dict(size=8)
390
  ))
391
 
392
- # Add min/max for EPW data only
393
  if epw_data is not None:
394
- dry_bulb = epw_data[6].values # Dry-bulb temperature (°C)
395
  month_col = epw_data[1].values
396
  temps_min = []
397
  temps_max = []
@@ -427,7 +398,6 @@ class ClimateData:
427
  )
428
  st.plotly_chart(fig_temp, use_container_width=True)
429
 
430
- # Humidity Plot
431
  fig_hum = go.Figure()
432
  fig_hum.add_trace(go.Scatter(
433
  x=months,
@@ -438,9 +408,8 @@ class ClimateData:
438
  marker=dict(size=8)
439
  ))
440
 
441
- # Add min/max for EPW data only
442
  if epw_data is not None:
443
- humidity = epw_data[8].values # Relative humidity (%) - adjusted to 9th column
444
  month_col = epw_data[1].values
445
  humidity_min = []
446
  humidity_max = []
@@ -493,7 +462,6 @@ class ClimateData:
493
  climate_data.add_location(location)
494
  return climate_data
495
 
496
- # Example usage
497
  if __name__ == "__main__":
498
  climate_data = ClimateData()
499
  session_state = {"building_info": {"country": "Iceland", "city": "Reykjavik"}, "page": "Climate Data"}
 
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
  db = np.array(dry_bulb, dtype=float)
100
  rh = np.array(relative_humidity, dtype=float)
101
 
 
102
  term1 = db * np.arctan(0.151977 * (rh + 8.313659)**0.5)
103
  term2 = np.arctan(db + rh)
104
  term3 = np.arctan(rh - 1.676331)
 
107
 
108
  wet_bulb = term1 + term2 - term3 + term4 + term5
109
 
 
110
  invalid_mask = (rh < 5) | (rh > 99) | (db < -20) | (db > 50) | np.isnan(db) | np.isnan(rh)
111
  wet_bulb[invalid_mask] = np.nan
112
 
 
140
  hdd = st.number_input("Heating Degree Days (base 18°C)", min_value=0.0, value=0.0, step=100.0)
141
  cdd = st.number_input("Cooling Degree Days (base 18°C)", min_value=0.0, value=0.0, step=100.0)
142
  winter_design_temp = st.number_input("Winter Design Temp (99.6%) (°C)", min_value=-50.0, max_value=20.0, value=0.0, step=0.5)
143
+ summer_design_temp_db = st.number_input("Summer Design Temp DB (0.4%) (°C)", min_value=0.0, max_value=50.0, value=35.0, step=0.5)
144
  summer_design_temp_wb = st.number_input("Summer Design Temp WB (0.4%) (°C)", min_value=0.0, max_value=40.0, value=25.0, step=0.5)
145
  summer_daily_range = st.number_input("Summer Daily Range (°C)", min_value=0.0, value=5.0, step=0.5)
146
 
 
151
  col1, col2 = st.columns(2)
152
  with col1:
153
  for month in month_names[:6]:
154
+ monthly_temps[month] = st.number_input(f"{month} Temp (°C)", min_value=-50.0, max_value=50.0, value=20.0, step=0.5, key=f"temp_{month}")
155
  with col2:
156
  for month in month_names[6:]:
157
  monthly_temps[month] = st.number_input(f"{month} Temp (°C)", min_value=-50.0, max_value=50.0, value=20.0, step=0.5, key=f"temp_{month}")
 
200
  longitude = float(header_parts[7])
201
  elevation = float(header_parts[8])
202
 
 
203
  data_start_idx = next(i for i, line in enumerate(epw_lines) if line.startswith("DATA PERIODS")) + 1
204
  epw_data = pd.read_csv(StringIO("\n".join(epw_lines[data_start_idx:])), header=None, dtype=str)
205
  if len(epw_data) != 8760:
206
  raise ValueError(f"EPW file has {len(epw_data)} records, expected 8760.")
207
 
 
208
  for col in epw_data.columns:
209
  epw_data[col] = pd.to_numeric(epw_data[col], errors='coerce')
210
 
 
211
  months = epw_data[1].values # Month
212
+ dry_bulb = epw_data[6].values # Dry-bulb temperature (°C)
213
+ humidity = epw_data[8].values # Relative humidity (%)
214
+ pressure = epw_data[9].values # Atmospheric pressure (Pa)
215
 
 
216
  wet_bulb = self.calculate_wet_bulb(dry_bulb, humidity)
217
 
 
218
  if np.all(np.isnan(dry_bulb)) or np.all(np.isnan(humidity)) or np.all(np.isnan(wet_bulb)):
219
  raise ValueError("Dry bulb, humidity, or calculated wet bulb data is entirely NaN.")
220
 
 
221
  daily_temps = np.nanmean(dry_bulb.reshape(-1, 24), axis=1)
222
  hdd = round(np.nansum(np.maximum(18 - daily_temps, 0)))
223
  cdd = round(np.nansum(np.maximum(daily_temps - 18, 0)))
224
 
225
+ winter_design_temp = round(np.nanpercentile(dry_bulb, 0.4), 1)
226
+ summer_design_temp_db = round(np.nanpercentile(dry_bulb, 99.6), 1)
227
+ summer_design_temp_wb = round(np.nanpercentile(wet_bulb, 99.6), 1)
 
228
  summer_mask = (months >= 6) & (months <= 8)
229
  summer_temps = dry_bulb[summer_mask].reshape(-1, 24)
230
  summer_daily_range = round(np.nanmean(np.nanmax(summer_temps, axis=1) - np.nanmin(summer_temps, axis=1)), 1)
231
 
 
232
  monthly_temps = {}
233
  monthly_humidity = {}
234
  month_names = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
 
237
  monthly_temps[month_names[i-1]] = round(np.nanmean(dry_bulb[month_mask]), 1)
238
  monthly_humidity[month_names[i-1]] = round(np.nanmean(humidity[month_mask]), 1)
239
 
 
240
  avg_humidity = np.nanmean(humidity)
241
  climate_zone = self.assign_climate_zone(hdd, cdd, avg_humidity)
242
 
 
265
  except Exception as e:
266
  st.error(f"Error processing EPW file: {str(e)}. Ensure it has 8760 hourly records and correct format.")
267
 
 
268
  col1, col2 = st.columns(2)
269
  with col1:
270
  st.button("Back to Building Information", on_click=lambda: setattr(session_state, "page", "Building Information"))
 
278
  """Display a table of design conditions including additional parameters for HVAC calculations."""
279
  st.subheader("Design Conditions for HVAC Calculations")
280
 
 
281
  design_data = pd.DataFrame({
282
  "Parameter": [
283
  "Latitude",
 
305
  ]
306
  })
307
 
 
308
  month_names = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
309
  monthly_temp_data = pd.DataFrame({
310
  "Parameter": [f"{month} Avg Temp" for month in month_names],
311
  "Value": [f"{location.monthly_temps[month]} °C" for month in month_names]
312
  })
313
 
 
314
  monthly_humidity_data = pd.DataFrame({
315
  "Parameter": [f"{month} Avg Humidity" for month in month_names],
316
  "Value": [f"{location.monthly_humidity[month]} %" for month in month_names]
317
  })
318
 
 
319
  full_design_data = pd.concat([design_data, monthly_temp_data, monthly_humidity_data], ignore_index=True)
 
 
320
  st.table(full_design_data)
321
 
322
  @staticmethod
 
351
  temps_avg = [location.monthly_temps[m] for m in month_names]
352
  humidity_avg = [location.monthly_humidity[m] for m in month_names]
353
 
 
354
  fig_temp = go.Figure()
355
  fig_temp.add_trace(go.Scatter(
356
  x=months,
 
361
  marker=dict(size=8)
362
  ))
363
 
 
364
  if epw_data is not None:
365
+ dry_bulb = epw_data[6].values
366
  month_col = epw_data[1].values
367
  temps_min = []
368
  temps_max = []
 
398
  )
399
  st.plotly_chart(fig_temp, use_container_width=True)
400
 
 
401
  fig_hum = go.Figure()
402
  fig_hum.add_trace(go.Scatter(
403
  x=months,
 
408
  marker=dict(size=8)
409
  ))
410
 
 
411
  if epw_data is not None:
412
+ humidity = epw_data[8].values
413
  month_col = epw_data[1].values
414
  humidity_min = []
415
  humidity_max = []
 
462
  climate_data.add_location(location)
463
  return climate_data
464
 
 
465
  if __name__ == "__main__":
466
  climate_data = ClimateData()
467
  session_state = {"building_info": {"country": "Iceland", "city": "Reykjavik"}, "page": "Climate Data"}