Spaces:
Running
Running
""" | |
Data export module for HVAC Load Calculator. | |
This module provides functionality for exporting calculation results. | |
""" | |
import streamlit as st | |
import pandas as pd | |
import numpy as np | |
from typing import Dict, List, Any, Optional, Tuple | |
import json | |
import os | |
import base64 | |
import io | |
from datetime import datetime | |
import xlsxwriter | |
class DataExport: | |
"""Class for data export functionality.""" | |
def export_to_csv(data: Dict[str, Any], file_path: str = None) -> Optional[str]: | |
""" | |
Export data to CSV format. | |
Args: | |
data: Dictionary with data to export | |
file_path: Optional path to save the CSV file | |
Returns: | |
CSV string if file_path is None, otherwise None | |
""" | |
try: | |
# Create DataFrame from data | |
df = pd.DataFrame(data) | |
# Convert to CSV | |
csv_data = df.to_csv(index=False) | |
# Save to file if path provided | |
if file_path: | |
df.to_csv(file_path, index=False) | |
return None | |
# Return CSV string if no path provided | |
return csv_data | |
except Exception as e: | |
st.error(f"Error exporting to CSV: {e}") | |
return None | |
def export_to_excel(data_dict: Dict[str, pd.DataFrame], file_path: str = None) -> Optional[bytes]: | |
""" | |
Export data to Excel format. | |
Args: | |
data_dict: Dictionary with sheet names and DataFrames | |
file_path: Optional path to save the Excel file | |
Returns: | |
Excel bytes if file_path is None, otherwise None | |
""" | |
try: | |
# Create Excel file in memory or on disk | |
if file_path: | |
writer = pd.ExcelWriter(file_path, engine='xlsxwriter') | |
else: | |
output = io.BytesIO() | |
writer = pd.ExcelWriter(output, engine='xlsxwriter') | |
# Write each DataFrame to a different sheet | |
for sheet_name, df in data_dict.items(): | |
df.to_excel(writer, sheet_name=sheet_name, index=False) | |
# Auto-adjust column widths | |
worksheet = writer.sheets[sheet_name] | |
for i, col in enumerate(df.columns): | |
max_width = max( | |
df[col].astype(str).map(len).max(), | |
len(col) | |
) + 2 | |
worksheet.set_column(i, i, max_width) | |
# Save the Excel file | |
writer.close() | |
# Return Excel bytes if no path provided | |
if not file_path: | |
output.seek(0) | |
return output.getvalue() | |
return None | |
except Exception as e: | |
st.error(f"Error exporting to Excel: {e}") | |
return None | |
def export_scenario_to_json(scenario: Dict[str, Any], file_path: str = None) -> Optional[str]: | |
""" | |
Export scenario data to JSON format. | |
Args: | |
scenario: Dictionary with scenario data | |
file_path: Optional path to save the JSON file | |
Returns: | |
JSON string if file_path is None, otherwise None | |
""" | |
try: | |
# Convert to JSON | |
json_data = json.dumps(scenario, indent=4) | |
# Save to file if path provided | |
if file_path: | |
with open(file_path, "w") as f: | |
f.write(json_data) | |
return None | |
# Return JSON string if no path provided | |
return json_data | |
except Exception as e: | |
st.error(f"Error exporting scenario to JSON: {e}") | |
return None | |
def get_download_link(data: Any, filename: str, text: str, mime_type: str = "text/csv") -> str: | |
""" | |
Generate a download link for data. | |
Args: | |
data: Data to download | |
filename: Name of the file to download | |
text: Text to display for the download link | |
mime_type: MIME type of the file | |
Returns: | |
HTML string with download link | |
""" | |
if isinstance(data, str): | |
b64 = base64.b64encode(data.encode()).decode() | |
else: | |
b64 = base64.b64encode(data).decode() | |
href = f'<a href="data:{mime_type};base64,{b64}" download="{filename}">{text}</a>' | |
return href | |
def create_cooling_load_dataframes(results: Dict[str, Any]) -> Dict[str, pd.DataFrame]: | |
""" | |
Create DataFrames for cooling load results. | |
Args: | |
results: Dictionary with calculation results | |
Returns: | |
Dictionary with DataFrames for Excel export | |
""" | |
dataframes = {} | |
# Create summary DataFrame | |
summary_data = { | |
"Metric": [ | |
"Total Cooling Load", | |
"Sensible Cooling Load", | |
"Latent Cooling Load", | |
"Cooling Load per Area" | |
], | |
"Value": [ | |
results["cooling"]["total_load"], | |
results["cooling"]["sensible_load"], | |
results["cooling"]["latent_load"], | |
results["cooling"]["load_per_area"] | |
], | |
"Unit": [ | |
"kW", | |
"kW", | |
"kW", | |
"W/m²" | |
] | |
} | |
dataframes["Cooling Summary"] = pd.DataFrame(summary_data) | |
# Create component breakdown DataFrame | |
component_data = { | |
"Component": [ | |
"Walls", | |
"Roof", | |
"Windows", | |
"Doors", | |
"People", | |
"Lighting", | |
"Equipment", | |
"Infiltration", | |
"Ventilation" | |
], | |
"Load (kW)": [ | |
results["cooling"]["component_loads"]["walls"], | |
results["cooling"]["component_loads"]["roof"], | |
results["cooling"]["component_loads"]["windows"], | |
results["cooling"]["component_loads"]["doors"], | |
results["cooling"]["component_loads"]["people"], | |
results["cooling"]["component_loads"]["lighting"], | |
results["cooling"]["component_loads"]["equipment"], | |
results["cooling"]["component_loads"]["infiltration"], | |
results["cooling"]["component_loads"]["ventilation"] | |
], | |
"Percentage (%)": [ | |
results["cooling"]["component_loads"]["walls"] / results["cooling"]["total_load"] * 100, | |
results["cooling"]["component_loads"]["roof"] / results["cooling"]["total_load"] * 100, | |
results["cooling"]["component_loads"]["windows"] / results["cooling"]["total_load"] * 100, | |
results["cooling"]["component_loads"]["doors"] / results["cooling"]["total_load"] * 100, | |
results["cooling"]["component_loads"]["people"] / results["cooling"]["total_load"] * 100, | |
results["cooling"]["component_loads"]["lighting"] / results["cooling"]["total_load"] * 100, | |
results["cooling"]["component_loads"]["equipment"] / results["cooling"]["total_load"] * 100, | |
results["cooling"]["component_loads"]["infiltration"] / results["cooling"]["total_load"] * 100, | |
results["cooling"]["component_loads"]["ventilation"] / results["cooling"]["total_load"] * 100 | |
] | |
} | |
dataframes["Cooling Components"] = pd.DataFrame(component_data) | |
# Create detailed loads DataFrames | |
# Walls | |
wall_data = [] | |
for wall in results["cooling"]["detailed_loads"]["walls"]: | |
wall_data.append({ | |
"Name": wall["name"], | |
"Orientation": wall["orientation"], | |
"Area (m²)": wall["area"], | |
"U-Value (W/m²·K)": wall["u_value"], | |
"CLTD (°C)": wall["cltd"], | |
"Load (kW)": wall["load"] | |
}) | |
if wall_data: | |
dataframes["Cooling Walls"] = pd.DataFrame(wall_data) | |
# Roofs | |
roof_data = [] | |
for roof in results["cooling"]["detailed_loads"]["roofs"]: | |
roof_data.append({ | |
"Name": roof["name"], | |
"Orientation": roof["orientation"], | |
"Area (m²)": roof["area"], | |
"U-Value (W/m²·K)": roof["u_value"], | |
"CLTD (°C)": roof["cltd"], | |
"Load (kW)": roof["load"] | |
}) | |
if roof_data: | |
dataframes["Cooling Roofs"] = pd.DataFrame(roof_data) | |
# Windows | |
window_data = [] | |
for window in results["cooling"]["detailed_loads"]["windows"]: | |
window_data.append({ | |
"Name": window["name"], | |
"Orientation": window["orientation"], | |
"Area (m²)": window["area"], | |
"U-Value (W/m²·K)": window["u_value"], | |
"SHGC": window["shgc"], | |
"SCL (W/m²)": window["scl"], | |
"Load (kW)": window["load"] | |
}) | |
if window_data: | |
dataframes["Cooling Windows"] = pd.DataFrame(window_data) | |
# Doors | |
door_data = [] | |
for door in results["cooling"]["detailed_loads"]["doors"]: | |
door_data.append({ | |
"Name": door["name"], | |
"Orientation": door["orientation"], | |
"Area (m²)": door["area"], | |
"U-Value (W/m²·K)": door["u_value"], | |
"CLTD (°C)": door["cltd"], | |
"Load (kW)": door["load"] | |
}) | |
if door_data: | |
dataframes["Cooling Doors"] = pd.DataFrame(door_data) | |
# Internal loads | |
internal_data = [] | |
for internal_load in results["cooling"]["detailed_loads"]["internal"]: | |
internal_data.append({ | |
"Type": internal_load["type"], | |
"Name": internal_load["name"], | |
"Quantity": internal_load["quantity"], | |
"Heat Gain (W)": internal_load["heat_gain"], | |
"CLF": internal_load["clf"], | |
"Load (kW)": internal_load["load"] | |
}) | |
if internal_data: | |
dataframes["Cooling Internal Loads"] = pd.DataFrame(internal_data) | |
# Infiltration and ventilation | |
air_data = [ | |
{ | |
"Type": "Infiltration", | |
"Air Flow (m³/s)": results["cooling"]["detailed_loads"]["infiltration"]["air_flow"], | |
"Sensible Load (kW)": results["cooling"]["detailed_loads"]["infiltration"]["sensible_load"], | |
"Latent Load (kW)": results["cooling"]["detailed_loads"]["infiltration"]["latent_load"], | |
"Total Load (kW)": results["cooling"]["detailed_loads"]["infiltration"]["total_load"] | |
}, | |
{ | |
"Type": "Ventilation", | |
"Air Flow (m³/s)": results["cooling"]["detailed_loads"]["ventilation"]["air_flow"], | |
"Sensible Load (kW)": results["cooling"]["detailed_loads"]["ventilation"]["sensible_load"], | |
"Latent Load (kW)": results["cooling"]["detailed_loads"]["ventilation"]["latent_load"], | |
"Total Load (kW)": results["cooling"]["detailed_loads"]["ventilation"]["total_load"] | |
} | |
] | |
dataframes["Cooling Air Exchange"] = pd.DataFrame(air_data) | |
return dataframes | |
def create_heating_load_dataframes(results: Dict[str, Any]) -> Dict[str, pd.DataFrame]: | |
""" | |
Create DataFrames for heating load results. | |
Args: | |
results: Dictionary with calculation results | |
Returns: | |
Dictionary with DataFrames for Excel export | |
""" | |
dataframes = {} | |
# Create summary DataFrame | |
summary_data = { | |
"Metric": [ | |
"Total Heating Load", | |
"Heating Load per Area", | |
"Design Heat Loss", | |
"Safety Factor" | |
], | |
"Value": [ | |
results["heating"]["total_load"], | |
results["heating"]["load_per_area"], | |
results["heating"]["design_heat_loss"], | |
results["heating"]["safety_factor"] | |
], | |
"Unit": [ | |
"kW", | |
"W/m²", | |
"kW", | |
"%" | |
] | |
} | |
dataframes["Heating Summary"] = pd.DataFrame(summary_data) | |
# Create component breakdown DataFrame | |
component_data = { | |
"Component": [ | |
"Walls", | |
"Roof", | |
"Floor", | |
"Windows", | |
"Doors", | |
"Infiltration", | |
"Ventilation" | |
], | |
"Load (kW)": [ | |
results["heating"]["component_loads"]["walls"], | |
results["heating"]["component_loads"]["roof"], | |
results["heating"]["component_loads"]["floor"], | |
results["heating"]["component_loads"]["windows"], | |
results["heating"]["component_loads"]["doors"], | |
results["heating"]["component_loads"]["infiltration"], | |
results["heating"]["component_loads"]["ventilation"] | |
], | |
"Percentage (%)": [ | |
results["heating"]["component_loads"]["walls"] / results["heating"]["total_load"] * 100, | |
results["heating"]["component_loads"]["roof"] / results["heating"]["total_load"] * 100, | |
results["heating"]["component_loads"]["floor"] / results["heating"]["total_load"] * 100, | |
results["heating"]["component_loads"]["windows"] / results["heating"]["total_load"] * 100, | |
results["heating"]["component_loads"]["doors"] / results["heating"]["total_load"] * 100, | |
results["heating"]["component_loads"]["infiltration"] / results["heating"]["total_load"] * 100, | |
results["heating"]["component_loads"]["ventilation"] / results["heating"]["total_load"] * 100 | |
] | |
} | |
dataframes["Heating Components"] = pd.DataFrame(component_data) | |
# Create detailed loads DataFrames | |
# Walls | |
wall_data = [] | |
for wall in results["heating"]["detailed_loads"]["walls"]: | |
wall_data.append({ | |
"Name": wall["name"], | |
"Orientation": wall["orientation"], | |
"Area (m²)": wall["area"], | |
"U-Value (W/m²·K)": wall["u_value"], | |
"Temperature Difference (°C)": wall["delta_t"], | |
"Load (kW)": wall["load"] | |
}) | |
if wall_data: | |
dataframes["Heating Walls"] = pd.DataFrame(wall_data) | |
# Roofs | |
roof_data = [] | |
for roof in results["heating"]["detailed_loads"]["roofs"]: | |
roof_data.append({ | |
"Name": roof["name"], | |
"Orientation": roof["orientation"], | |
"Area (m²)": roof["area"], | |
"U-Value (W/m²·K)": roof["u_value"], | |
"Temperature Difference (°C)": roof["delta_t"], | |
"Load (kW)": roof["load"] | |
}) | |
if roof_data: | |
dataframes["Heating Roofs"] = pd.DataFrame(roof_data) | |
# Floors | |
floor_data = [] | |
for floor in results["heating"]["detailed_loads"]["floors"]: | |
floor_data.append({ | |
"Name": floor["name"], | |
"Area (m²)": floor["area"], | |
"U-Value (W/m²·K)": floor["u_value"], | |
"Temperature Difference (°C)": floor["delta_t"], | |
"Load (kW)": floor["load"] | |
}) | |
if floor_data: | |
dataframes["Heating Floors"] = pd.DataFrame(floor_data) | |
# Windows | |
window_data = [] | |
for window in results["heating"]["detailed_loads"]["windows"]: | |
window_data.append({ | |
"Name": window["name"], | |
"Orientation": window["orientation"], | |
"Area (m²)": window["area"], | |
"U-Value (W/m²·K)": window["u_value"], | |
"Temperature Difference (°C)": window["delta_t"], | |
"Load (kW)": window["load"] | |
}) | |
if window_data: | |
dataframes["Heating Windows"] = pd.DataFrame(window_data) | |
# Doors | |
door_data = [] | |
for door in results["heating"]["detailed_loads"]["doors"]: | |
door_data.append({ | |
"Name": door["name"], | |
"Orientation": door["orientation"], | |
"Area (m²)": door["area"], | |
"U-Value (W/m²·K)": door["u_value"], | |
"Temperature Difference (°C)": door["delta_t"], | |
"Load (kW)": door["load"] | |
}) | |
if door_data: | |
dataframes["Heating Doors"] = pd.DataFrame(door_data) | |
# Infiltration and ventilation | |
air_data = [ | |
{ | |
"Type": "Infiltration", | |
"Air Flow (m³/s)": results["heating"]["detailed_loads"]["infiltration"]["air_flow"], | |
"Temperature Difference (°C)": results["heating"]["detailed_loads"]["infiltration"]["delta_t"], | |
"Load (kW)": results["heating"]["detailed_loads"]["infiltration"]["load"] | |
}, | |
{ | |
"Type": "Ventilation", | |
"Air Flow (m³/s)": results["heating"]["detailed_loads"]["ventilation"]["air_flow"], | |
"Temperature Difference (°C)": results["heating"]["detailed_loads"]["ventilation"]["delta_t"], | |
"Load (kW)": results["heating"]["detailed_loads"]["ventilation"]["load"] | |
} | |
] | |
dataframes["Heating Air Exchange"] = pd.DataFrame(air_data) | |
return dataframes | |
def display_export_interface(session_state: Dict[str, Any]) -> None: | |
""" | |
Display export interface in Streamlit. | |
Args: | |
session_state: Streamlit session state containing calculation results | |
""" | |
st.header("Export Results") | |
# Check if calculations have been performed | |
if "calculation_results" not in session_state or not session_state["calculation_results"]: | |
st.warning("No calculation results available. Please run calculations first.") | |
return | |
# Create tabs for different export options | |
tab1, tab2, tab3 = st.tabs(["CSV Export", "Excel Export", "Scenario Export"]) | |
with tab1: | |
DataExport._display_csv_export(session_state) | |
with tab2: | |
DataExport._display_excel_export(session_state) | |
with tab3: | |
DataExport._display_scenario_export(session_state) | |
def _display_csv_export(session_state: Dict[str, Any]) -> None: | |
""" | |
Display CSV export interface. | |
Args: | |
session_state: Streamlit session state containing calculation results | |
""" | |
st.subheader("CSV Export") | |
# Get results | |
results = session_state["calculation_results"] | |
# Create tabs for cooling and heating loads | |
tab1, tab2 = st.tabs(["Cooling Load CSV", "Heating Load CSV"]) | |
with tab1: | |
# Create cooling load DataFrames | |
cooling_dfs = DataExport.create_cooling_load_dataframes(results) | |
# Display and export each DataFrame | |
for sheet_name, df in cooling_dfs.items(): | |
st.write(f"### {sheet_name}") | |
st.dataframe(df) | |
# Add download button | |
csv_data = DataExport.export_to_csv(df) | |
if csv_data: | |
filename = f"{sheet_name.replace(' ', '_').lower()}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv" | |
download_link = DataExport.get_download_link(csv_data, filename, f"Download {sheet_name} CSV") | |
st.markdown(download_link, unsafe_allow_html=True) | |
with tab2: | |
# Create heating load DataFrames | |
heating_dfs = DataExport.create_heating_load_dataframes(results) | |
# Display and export each DataFrame | |
for sheet_name, df in heating_dfs.items(): | |
st.write(f"### {sheet_name}") | |
st.dataframe(df) | |
# Add download button | |
csv_data = DataExport.export_to_csv(df) | |
if csv_data: | |
filename = f"{sheet_name.replace(' ', '_').lower()}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv" | |
download_link = DataExport.get_download_link(csv_data, filename, f"Download {sheet_name} CSV") | |
st.markdown(download_link, unsafe_allow_html=True) | |
def _display_excel_export(session_state: Dict[str, Any]) -> None: | |
""" | |
Display Excel export interface. | |
Args: | |
session_state: Streamlit session state containing calculation results | |
""" | |
st.subheader("Excel Export") | |
# Get results | |
results = session_state["calculation_results"] | |
# Create tabs for cooling, heating, and combined loads | |
tab1, tab2, tab3 = st.tabs(["Cooling Load Excel", "Heating Load Excel", "Combined Excel"]) | |
with tab1: | |
# Create cooling load DataFrames | |
cooling_dfs = DataExport.create_cooling_load_dataframes(results) | |
# Add download button | |
excel_data = DataExport.export_to_excel(cooling_dfs) | |
if excel_data: | |
filename = f"cooling_load_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx" | |
download_link = DataExport.get_download_link( | |
excel_data, | |
filename, | |
"Download Cooling Load Excel", | |
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | |
) | |
st.markdown(download_link, unsafe_allow_html=True) | |
# Display preview | |
st.write("### Excel Preview") | |
st.write("The Excel file will contain the following sheets:") | |
for sheet_name in cooling_dfs.keys(): | |
st.write(f"- {sheet_name}") | |
with tab2: | |
# Create heating load DataFrames | |
heating_dfs = DataExport.create_heating_load_dataframes(results) | |
# Add download button | |
excel_data = DataExport.export_to_excel(heating_dfs) | |
if excel_data: | |
filename = f"heating_load_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx" | |
download_link = DataExport.get_download_link( | |
excel_data, | |
filename, | |
"Download Heating Load Excel", | |
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | |
) | |
st.markdown(download_link, unsafe_allow_html=True) | |
# Display preview | |
st.write("### Excel Preview") | |
st.write("The Excel file will contain the following sheets:") | |
for sheet_name in heating_dfs.keys(): | |
st.write(f"- {sheet_name}") | |
with tab3: | |
# Create combined DataFrames | |
combined_dfs = {} | |
# Add project information | |
if "building_info" in session_state: | |
project_info = [ | |
{"Parameter": "Project Name", "Value": session_state["building_info"].get("project_name", "")}, | |
{"Parameter": "Building Name", "Value": session_state["building_info"].get("building_name", "")}, | |
{"Parameter": "Location", "Value": session_state["building_info"].get("location", "")}, | |
{"Parameter": "Climate Zone", "Value": session_state["building_info"].get("climate_zone", "")}, | |
{"Parameter": "Building Type", "Value": session_state["building_info"].get("building_type", "")}, | |
{"Parameter": "Floor Area", "Value": session_state["building_info"].get("floor_area", "")}, | |
{"Parameter": "Number of Floors", "Value": session_state["building_info"].get("num_floors", "")}, | |
{"Parameter": "Floor Height", "Value": session_state["building_info"].get("floor_height", "")}, | |
{"Parameter": "Orientation", "Value": session_state["building_info"].get("orientation", "")}, | |
{"Parameter": "Occupancy", "Value": session_state["building_info"].get("occupancy", "")}, | |
{"Parameter": "Operating Hours", "Value": session_state["building_info"].get("operating_hours", "")}, | |
{"Parameter": "Date", "Value": datetime.now().strftime("%Y-%m-%d")}, | |
{"Parameter": "Time", "Value": datetime.now().strftime("%H:%M:%S")} | |
] | |
combined_dfs["Project Information"] = pd.DataFrame(project_info) | |
# Add cooling load DataFrames | |
cooling_dfs = DataExport.create_cooling_load_dataframes(results) | |
for sheet_name, df in cooling_dfs.items(): | |
combined_dfs[sheet_name] = df | |
# Add heating load DataFrames | |
heating_dfs = DataExport.create_heating_load_dataframes(results) | |
for sheet_name, df in heating_dfs.items(): | |
combined_dfs[sheet_name] = df | |
# Add download button | |
excel_data = DataExport.export_to_excel(combined_dfs) | |
if excel_data: | |
filename = f"hvac_load_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx" | |
download_link = DataExport.get_download_link( | |
excel_data, | |
filename, | |
"Download Combined Excel Report", | |
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | |
) | |
st.markdown(download_link, unsafe_allow_html=True) | |
# Display preview | |
st.write("### Excel Preview") | |
st.write("The Excel file will contain the following sheets:") | |
for sheet_name in combined_dfs.keys(): | |
st.write(f"- {sheet_name}") | |
def _display_scenario_export(session_state: Dict[str, Any]) -> None: | |
""" | |
Display scenario export interface. | |
Args: | |
session_state: Streamlit session state containing calculation results | |
""" | |
st.subheader("Scenario Export") | |
# Check if there are saved scenarios | |
if "saved_scenarios" not in session_state or not session_state["saved_scenarios"]: | |
st.info("No saved scenarios available for export. Save the current results as a scenario to enable export.") | |
# Add button to save current results as a scenario | |
scenario_name = st.text_input("Scenario Name", value="Baseline") | |
if st.button("Save Current Results as Scenario"): | |
if "saved_scenarios" not in session_state: | |
session_state["saved_scenarios"] = {} | |
# Save current results as a scenario | |
session_state["saved_scenarios"][scenario_name] = { | |
"results": session_state["calculation_results"], | |
"building_info": session_state["building_info"], | |
"components": session_state["components"], | |
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
} | |
st.success(f"Scenario '{scenario_name}' saved successfully!") | |
st.experimental_rerun() | |
else: | |
# Display saved scenarios | |
st.write("### Saved Scenarios") | |
# Create selectbox for scenarios | |
scenario_names = list(session_state["saved_scenarios"].keys()) | |
selected_scenario = st.selectbox("Select Scenario to Export", scenario_names) | |
if selected_scenario: | |
# Get selected scenario | |
scenario = session_state["saved_scenarios"][selected_scenario] | |
# Display scenario information | |
st.write(f"**Scenario:** {selected_scenario}") | |
st.write(f"**Timestamp:** {scenario['timestamp']}") | |
# Add download button | |
json_data = DataExport.export_scenario_to_json(scenario) | |
if json_data: | |
filename = f"{selected_scenario.replace(' ', '_').lower()}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" | |
download_link = DataExport.get_download_link( | |
json_data, | |
filename, | |
"Download Scenario JSON", | |
"application/json" | |
) | |
st.markdown(download_link, unsafe_allow_html=True) | |
# Add button to export all scenarios | |
if st.button("Export All Scenarios"): | |
# Create a zip file in memory | |
import zipfile | |
from io import BytesIO | |
zip_buffer = BytesIO() | |
with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file: | |
for scenario_name, scenario in session_state["saved_scenarios"].items(): | |
# Export scenario to JSON | |
json_data = DataExport.export_scenario_to_json(scenario) | |
if json_data: | |
filename = f"{scenario_name.replace(' ', '_').lower()}.json" | |
zip_file.writestr(filename, json_data) | |
# Add download button for zip file | |
zip_buffer.seek(0) | |
zip_data = zip_buffer.getvalue() | |
filename = f"all_scenarios_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip" | |
download_link = DataExport.get_download_link( | |
zip_data, | |
filename, | |
"Download All Scenarios (ZIP)", | |
"application/zip" | |
) | |
st.markdown(download_link, unsafe_allow_html=True) | |
# Create a singleton instance | |
data_export = DataExport() | |
# Example usage | |
if __name__ == "__main__": | |
import streamlit as st | |
# Initialize session state with dummy data for testing | |
if "calculation_results" not in st.session_state: | |
st.session_state["calculation_results"] = { | |
"cooling": { | |
"total_load": 25.5, | |
"sensible_load": 20.0, | |
"latent_load": 5.5, | |
"load_per_area": 85.0, | |
"component_loads": { | |
"walls": 5.0, | |
"roof": 3.0, | |
"windows": 8.0, | |
"doors": 1.0, | |
"people": 2.5, | |
"lighting": 2.0, | |
"equipment": 1.5, | |
"infiltration": 1.0, | |
"ventilation": 1.5 | |
}, | |
"detailed_loads": { | |
"walls": [ | |
{"name": "North Wall", "orientation": "NORTH", "area": 20.0, "u_value": 0.5, "cltd": 10.0, "load": 1.0} | |
], | |
"roofs": [ | |
{"name": "Main Roof", "orientation": "HORIZONTAL", "area": 100.0, "u_value": 0.3, "cltd": 15.0, "load": 3.0} | |
], | |
"windows": [ | |
{"name": "South Window", "orientation": "SOUTH", "area": 10.0, "u_value": 2.8, "shgc": 0.7, "scl": 800.0, "load": 8.0} | |
], | |
"doors": [ | |
{"name": "Main Door", "orientation": "NORTH", "area": 2.0, "u_value": 2.0, "cltd": 10.0, "load": 1.0} | |
], | |
"internal": [ | |
{"type": "People", "name": "Occupants", "quantity": 10, "heat_gain": 250, "clf": 1.0, "load": 2.5}, | |
{"type": "Lighting", "name": "General Lighting", "quantity": 1000, "heat_gain": 2000, "clf": 1.0, "load": 2.0}, | |
{"type": "Equipment", "name": "Office Equipment", "quantity": 5, "heat_gain": 300, "clf": 1.0, "load": 1.5} | |
], | |
"infiltration": { | |
"air_flow": 0.05, | |
"sensible_load": 0.8, | |
"latent_load": 0.2, | |
"total_load": 1.0 | |
}, | |
"ventilation": { | |
"air_flow": 0.1, | |
"sensible_load": 1.0, | |
"latent_load": 0.5, | |
"total_load": 1.5 | |
} | |
} | |
}, | |
"heating": { | |
"total_load": 30.0, | |
"load_per_area": 100.0, | |
"design_heat_loss": 27.0, | |
"safety_factor": 10.0, | |
"component_loads": { | |
"walls": 8.0, | |
"roof": 5.0, | |
"floor": 4.0, | |
"windows": 7.0, | |
"doors": 1.0, | |
"infiltration": 2.0, | |
"ventilation": 3.0 | |
}, | |
"detailed_loads": { | |
"walls": [ | |
{"name": "North Wall", "orientation": "NORTH", "area": 20.0, "u_value": 0.5, "delta_t": 25.0, "load": 8.0} | |
], | |
"roofs": [ | |
{"name": "Main Roof", "orientation": "HORIZONTAL", "area": 100.0, "u_value": 0.3, "delta_t": 25.0, "load": 5.0} | |
], | |
"floors": [ | |
{"name": "Ground Floor", "area": 100.0, "u_value": 0.4, "delta_t": 10.0, "load": 4.0} | |
], | |
"windows": [ | |
{"name": "South Window", "orientation": "SOUTH", "area": 10.0, "u_value": 2.8, "delta_t": 25.0, "load": 7.0} | |
], | |
"doors": [ | |
{"name": "Main Door", "orientation": "NORTH", "area": 2.0, "u_value": 2.0, "delta_t": 25.0, "load": 1.0} | |
], | |
"infiltration": { | |
"air_flow": 0.05, | |
"delta_t": 25.0, | |
"load": 2.0 | |
}, | |
"ventilation": { | |
"air_flow": 0.1, | |
"delta_t": 25.0, | |
"load": 3.0 | |
} | |
} | |
} | |
} | |
# Display export interface | |
data_export.display_export_interface(st.session_state) | |