mabuseif commited on
Commit
65de910
·
verified ·
1 Parent(s): 4b44d5f

Update app/climate_data.py

Browse files
Files changed (1) hide show
  1. app/climate_data.py +78 -63
app/climate_data.py CHANGED
@@ -199,8 +199,8 @@ class ClimateDataManager:
199
  if line.strip(): # Skip empty lines
200
  data.append(line.split(','))
201
 
202
- # Create DataFrame
203
- columns = [
204
  "year", "month", "day", "hour", "minute", "data_source", "dry_bulb_temp",
205
  "dew_point_temp", "relative_humidity", "atmospheric_pressure", "extraterrestrial_radiation",
206
  "extraterrestrial_radiation_normal", "horizontal_infrared_radiation", "global_horizontal_radiation",
@@ -208,11 +208,22 @@ class ClimateDataManager:
208
  "direct_normal_illuminance", "diffuse_horizontal_illuminance", "zenith_luminance",
209
  "wind_direction", "wind_speed", "total_sky_cover", "opaque_sky_cover", "visibility",
210
  "ceiling_height", "present_weather_observation", "present_weather_codes",
211
- "precipitable_water", "aerosol_optical_depth", "snow_depth", "days_since_last_snowfall",
212
- "albedo", "liquid_precipitation_depth", "liquid_precipitation_quantity"
213
  ]
214
 
215
- df = pd.DataFrame(data, columns=columns)
 
 
 
 
 
 
 
 
 
 
 
 
216
 
217
  # Convert numeric columns
218
  numeric_columns = [
@@ -222,7 +233,8 @@ class ClimateDataManager:
222
  ]
223
 
224
  for col in numeric_columns:
225
- df[col] = pd.to_numeric(df[col], errors='coerce')
 
226
 
227
  # Calculate design conditions
228
  design_conditions = self._calculate_design_conditions(df)
@@ -359,14 +371,15 @@ class ClimateDataManager:
359
 
360
  try:
361
  # Ensure numeric columns
362
- df["dry_bulb_temp"] = pd.to_numeric(df["dry_bulb_temp"], errors='coerce')
363
- df["relative_humidity"] = pd.to_numeric(df["relative_humidity"], errors='coerce')
364
- df["atmospheric_pressure"] = pd.to_numeric(df["atmospheric_pressure"], errors='coerce')
365
- df["global_horizontal_radiation"] = pd.to_numeric(df["global_horizontal_radiation"], errors='coerce')
366
- df["direct_normal_radiation"] = pd.to_numeric(df["direct_normal_radiation"], errors='coerce')
367
- df["diffuse_horizontal_radiation"] = pd.to_numeric(df["diffuse_horizontal_radiation"], errors='coerce')
368
- df["wind_speed"] = pd.to_numeric(df["wind_speed"], errors='coerce')
369
- df["wind_direction"] = pd.to_numeric(df["wind_direction"], errors='coerce')
 
370
 
371
  # Convert to integers for month, day, hour
372
  df["month"] = pd.to_numeric(df["month"], errors='coerce').astype('Int64')
@@ -642,17 +655,29 @@ def display_climate_summary(climate_data: Dict[str, Any]):
642
  design = climate_data["design_conditions"]
643
  location = climate_data["location"]
644
 
645
- # Location Details
646
- st.markdown(f"""
647
- ### Location Details
648
- - **Country:** {location['country']}
649
- - **City:** {location['city']}
650
- - **State/Province:** {location['state_province']}
651
- - **Latitude:** {location['latitude']}°
652
- - **Longitude:** {location['longitude']}°
653
- - **Elevation:** {location['elevation']} m
654
- - **Time Zone:** {location['timezone']} hours (UTC)
655
- """)
 
 
 
 
 
 
 
 
 
 
 
 
656
 
657
  # Climate Zone
658
  st.markdown(f"### ASHRAE Climate Zone: {climate_data['climate_zone']}")
@@ -674,34 +699,6 @@ def display_climate_summary(climate_data: Dict[str, Any]):
674
  st.write(f"**Average Wind Speed:** {design['wind_speed']} m/s")
675
  st.write(f"**Average Atmospheric Pressure:** {design['pressure']} Pa")
676
 
677
- # Typical/Extreme Periods
678
- if climate_data.get("typical_extreme_periods"):
679
- st.subheader("Typical/Extreme Periods")
680
- period_items = [
681
- f"- **{key.replace('_', ' ').title()}:** {period['start']['month']}/{period['start']['day']} to {period['end']['month']}/{period['end']['day']}"
682
- for key, period in climate_data["typical_extreme_periods"].items()
683
- ]
684
- st.markdown("\n".join(period_items))
685
-
686
- # Ground Temperatures
687
- if climate_data.get("ground_temperatures"):
688
- st.subheader("Ground Temperatures")
689
- table_data = []
690
- for depth, temps in climate_data["ground_temperatures"].items():
691
- row = {"Depth (m)": float(depth)}
692
- row.update({month: f"{temp:.2f}" for month, temp in zip(MONTHS, temps)})
693
- table_data.append(row)
694
- df = pd.DataFrame(table_data)
695
- st.dataframe(df, use_container_width=True)
696
- csv = df.to_csv(index=False)
697
- st.download_button(
698
- label="Download Ground Temperatures as CSV",
699
- data=csv,
700
- file_name=f"ground_temperatures_{location['city']}_{location['country']}.csv",
701
- mime="text/csv",
702
- key=f"download_ground_temperatures_{climate_data['id']}"
703
- )
704
-
705
  # Monthly Temperature Chart
706
  st.subheader("Monthly Average Temperatures")
707
 
@@ -744,18 +741,28 @@ def display_climate_summary(climate_data: Dict[str, Any]):
744
 
745
  st.plotly_chart(fig_rad, use_container_width=True)
746
 
747
- # Hourly Data Statistics
748
- st.subheader("Hourly Data Statistics")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
749
 
 
 
750
  if "hourly_data" in climate_data and climate_data["hourly_data"]:
751
- hourly_count = len(climate_data["hourly_data"])
752
- st.write(f"**Number of Hourly Records:** {hourly_count}")
753
-
754
- if hourly_count < 8760:
755
- st.warning(f"Expected 8760 hourly records for a full year, but found {hourly_count}. Some data may be missing.")
756
-
757
- # Hourly Climate Data Table
758
- st.subheader("Hourly Climate Data")
759
  hourly_table_data = [
760
  {
761
  "Month": record["month"],
@@ -782,6 +789,14 @@ def display_climate_summary(climate_data: Dict[str, Any]):
782
  mime="text/csv",
783
  key=f"download_hourly_climate_{climate_data['id']}"
784
  )
 
 
 
 
 
 
 
 
785
  else:
786
  st.warning("No hourly data available.")
787
 
 
199
  if line.strip(): # Skip empty lines
200
  data.append(line.split(','))
201
 
202
+ # Define core columns (common to both 32 and 35 column formats)
203
+ core_columns = [
204
  "year", "month", "day", "hour", "minute", "data_source", "dry_bulb_temp",
205
  "dew_point_temp", "relative_humidity", "atmospheric_pressure", "extraterrestrial_radiation",
206
  "extraterrestrial_radiation_normal", "horizontal_infrared_radiation", "global_horizontal_radiation",
 
208
  "direct_normal_illuminance", "diffuse_horizontal_illuminance", "zenith_luminance",
209
  "wind_direction", "wind_speed", "total_sky_cover", "opaque_sky_cover", "visibility",
210
  "ceiling_height", "present_weather_observation", "present_weather_codes",
211
+ "precipitable_water", "aerosol_optical_depth", "snow_depth", "days_since_last_snowfall"
 
212
  ]
213
 
214
+ # Additional columns for 35-column format
215
+ additional_columns = ["albedo", "liquid_precipitation_depth", "liquid_precipitation_quantity"]
216
+
217
+ # Determine number of columns in data
218
+ num_columns = len(data[0]) if data else 0
219
+ if num_columns not in [32, 35]:
220
+ raise ValueError(f"Invalid number of columns in EPW file: {num_columns}. Expected 32 or 35 columns.")
221
+
222
+ # Select appropriate columns based on file format
223
+ columns = core_columns if num_columns == 32 else core_columns + additional_columns
224
+
225
+ # Create DataFrame
226
+ df = pd.DataFrame(data, columns=columns[:num_columns])
227
 
228
  # Convert numeric columns
229
  numeric_columns = [
 
233
  ]
234
 
235
  for col in numeric_columns:
236
+ if col in df.columns:
237
+ df[col] = pd.to_numeric(df[col], errors='coerce')
238
 
239
  # Calculate design conditions
240
  design_conditions = self._calculate_design_conditions(df)
 
371
 
372
  try:
373
  # Ensure numeric columns
374
+ numeric_columns = [
375
+ "dry_bulb_temp", "relative_humidity", "atmospheric_pressure",
376
+ "global_horizontal_radiation", "direct_normal_radiation",
377
+ "diffuse_horizontal_radiation", "wind_speed", "wind_direction"
378
+ ]
379
+
380
+ for col in numeric_columns:
381
+ if col in df.columns:
382
+ df[col] = pd.to_numeric(df[col], errors='coerce')
383
 
384
  # Convert to integers for month, day, hour
385
  df["month"] = pd.to_numeric(df["month"], errors='coerce').astype('Int64')
 
655
  design = climate_data["design_conditions"]
656
  location = climate_data["location"]
657
 
658
+ # Location Details and Typical/Extreme Periods side by side
659
+ col1, col2 = st.columns(2)
660
+
661
+ with col1:
662
+ st.markdown("### Location Details")
663
+ st.markdown(f"""
664
+ - **Country:** {location['country']}
665
+ - **City:** {location['city']}
666
+ - **State/Province:** {location['state_province']}
667
+ - **Latitude:** {location['latitude']}°
668
+ - **Longitude:** {location['longitude']}°
669
+ - **Elevation:** {location['elevation']} m
670
+ - **Time Zone:** {location['timezone']} hours (UTC)
671
+ """)
672
+
673
+ with col2:
674
+ if climate_data.get("typical_extreme_periods"):
675
+ st.markdown("### Typical/Extreme Periods")
676
+ period_items = [
677
+ f"- **{key.replace('_', ' ').title()}:** {period['start']['month']}/{period['start']['day']} to {period['end']['month']}/{period['end']['day']}"
678
+ for key, period in climate_data["typical_extreme_periods"].items()
679
+ ]
680
+ st.markdown("\n".join(period_items))
681
 
682
  # Climate Zone
683
  st.markdown(f"### ASHRAE Climate Zone: {climate_data['climate_zone']}")
 
699
  st.write(f"**Average Wind Speed:** {design['wind_speed']} m/s")
700
  st.write(f"**Average Atmospheric Pressure:** {design['pressure']} Pa")
701
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
702
  # Monthly Temperature Chart
703
  st.subheader("Monthly Average Temperatures")
704
 
 
741
 
742
  st.plotly_chart(fig_rad, use_container_width=True)
743
 
744
+ # Ground Temperatures
745
+ if climate_data.get("ground_temperatures"):
746
+ st.subheader("Ground Temperatures")
747
+ table_data = []
748
+ for depth, temps in climate_data["ground_temperatures"].items():
749
+ row = {"Depth (m)": float(depth)}
750
+ row.update({month: f"{temp:.2f}" for month, temp in zip(MONTHS, temps)})
751
+ table_data.append(row)
752
+ df = pd.DataFrame(table_data)
753
+ st.dataframe(df, use_container_width=True)
754
+ csv = df.to_csv(index=False)
755
+ st.download_button(
756
+ label="Download Ground Temperatures as CSV",
757
+ data=csv,
758
+ file_name=f"ground_temperatures_{location['city']}_{location['country']}.csv",
759
+ mime="text/csv",
760
+ key=f"download_ground_temperatures_{climate_data['id']}"
761
+ )
762
 
763
+ # Hourly Climate Data Table
764
+ st.subheader("Hourly Climate Data")
765
  if "hourly_data" in climate_data and climate_data["hourly_data"]:
 
 
 
 
 
 
 
 
766
  hourly_table_data = [
767
  {
768
  "Month": record["month"],
 
789
  mime="text/csv",
790
  key=f"download_hourly_climate_{climate_data['id']}"
791
  )
792
+
793
+ # Hourly Data Statistics
794
+ st.subheader("Hourly Data Statistics")
795
+ hourly_count = len(climate_data["hourly_data"])
796
+ st.write(f"**Number of Hourly Records:** {hourly_count}")
797
+
798
+ if hourly_count < 8760:
799
+ st.warning(f"Expected 8760 hourly records for a full year, but found {hourly_count}. Some data may be missing.")
800
  else:
801
  st.warning("No hourly data available.")
802