Spaces:
Running
Running
""" | |
Results display module for HVAC Load Calculator. | |
This module provides the UI components for displaying 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 plotly.graph_objects as go | |
import plotly.express as px | |
from datetime import datetime | |
# Import visualization modules | |
from utils.component_visualization import ComponentVisualization | |
from utils.scenario_comparison import ScenarioComparisonVisualization | |
from utils.psychrometric_visualization import PsychrometricVisualization | |
from utils.time_based_visualization import TimeBasedVisualization | |
class ResultsDisplay: | |
"""Class for results display interface.""" | |
def __init__(self): | |
"""Initialize results display interface.""" | |
self.component_visualization = ComponentVisualization() | |
self.scenario_comparison = ScenarioComparisonVisualization() | |
self.psychrometric_visualization = PsychrometricVisualization() | |
self.time_based_visualization = TimeBasedVisualization() | |
def display_results(self, session_state: Dict[str, Any]) -> None: | |
""" | |
Display calculation results in Streamlit. | |
Args: | |
session_state: Streamlit session state containing calculation results | |
""" | |
st.header("Calculation 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 result views | |
tab1, tab2, tab3, tab4, tab5 = st.tabs([ | |
"Summary", | |
"Component Breakdown", | |
"Psychrometric Analysis", | |
"Time Analysis", | |
"Scenario Comparison" | |
]) | |
with tab1: | |
self._display_summary_results(session_state) | |
with tab2: | |
self._display_component_breakdown(session_state) | |
with tab3: | |
self._display_psychrometric_analysis(session_state) | |
with tab4: | |
self._display_time_analysis(session_state) | |
with tab5: | |
self._display_scenario_comparison(session_state) | |
def _display_summary_results(self, session_state: Dict[str, Any]) -> None: | |
""" | |
Display summary of calculation results. | |
Args: | |
session_state: Streamlit session state containing calculation results | |
""" | |
st.subheader("Summary Results") | |
results = session_state["calculation_results"] | |
# Display project information | |
if "building_info" in session_state: | |
st.write(f"**Project:** {session_state['building_info']['project_name']}") | |
st.write(f"**Building:** {session_state['building_info']['building_name']}") | |
location = f"{session_state['building_info']['city']}, {session_state['building_info']['country']}" | |
st.write(f"**Location:** {location}") | |
st.write(f"**Climate Zone:** {session_state['building_info'].get('climate_zone', 'N/A')}") | |
st.write(f"**Floor Area:** {session_state['building_info']['floor_area']} m²") | |
# Create columns for cooling and heating loads | |
col1, col2 = st.columns(2) | |
with col1: | |
st.write("### Cooling Load Results") | |
# Check if cooling results are available | |
if not results.get("cooling") or "total_load" not in results["cooling"]: | |
st.warning("Cooling load results are not available. Please check calculation inputs and try again.") | |
else: | |
# Display cooling load metrics | |
cooling_metrics = [ | |
{"name": "Total Cooling Load", "value": results["cooling"]["total_load"], "unit": "kW"}, | |
{"name": "Sensible Cooling Load", "value": results["cooling"]["sensible_load"], "unit": "kW"}, | |
{"name": "Latent Cooling Load", "value": results["cooling"]["latent_load"], "unit": "kW"}, | |
{"name": "Cooling Load per Area", "value": results["cooling"]["load_per_area"], "unit": "W/m²"} | |
] | |
for metric in cooling_metrics: | |
st.metric( | |
label=metric["name"], | |
value=f"{metric['value']:.2f} {metric['unit']}" | |
) | |
# Display cooling load pie chart | |
cooling_breakdown = { | |
"Walls": results["cooling"]["component_loads"]["walls"], | |
"Roof": results["cooling"]["component_loads"]["roof"], | |
"Windows": results["cooling"]["component_loads"]["windows"], | |
"Doors": results["cooling"]["component_loads"]["doors"], | |
"People": results["cooling"]["component_loads"]["people"], | |
"Lighting": results["cooling"]["component_loads"]["lighting"], | |
"Equipment": results["cooling"]["component_loads"]["equipment"], | |
"Infiltration": results["cooling"]["component_loads"]["infiltration"], | |
"Ventilation": results["cooling"]["component_loads"]["ventilation"] | |
} | |
fig = px.pie( | |
values=list(cooling_breakdown.values()), | |
names=list(cooling_breakdown.keys()), | |
title="Cooling Load Breakdown", | |
color_discrete_sequence=px.colors.qualitative.Pastel | |
) | |
fig.update_traces(textposition='inside', textinfo='percent+label') | |
fig.update_layout(uniformtext_minsize=12, uniformtext_mode='hide') | |
st.plotly_chart(fig, use_container_width=True) | |
with col2: | |
st.write("### Heating Load Results") | |
# Check if heating results are available | |
if not results.get("heating") or "total_load" not in results["heating"]: | |
st.warning("Heating load results are not available. Please check calculation inputs and try again.") | |
else: | |
# Display heating load metrics | |
heating_metrics = [ | |
{"name": "Total Heating Load", "value": results["heating"]["total_load"], "unit": "kW"}, | |
{"name": "Heating Load per Area", "value": results["heating"]["load_per_area"], "unit": "W/m²"}, | |
{"name": "Design Heat Loss", "value": results["heating"]["design_heat_loss"], "unit": "kW"}, | |
{"name": "Safety Factor", "value": results["heating"]["safety_factor"], "unit": "%"} | |
] | |
for metric in heating_metrics: | |
st.metric( | |
label=metric["name"], | |
value=f"{metric['value']:.2f} {metric['unit']}" | |
) | |
# Display heating load pie chart | |
heating_breakdown = { | |
"Walls": results["heating"]["component_loads"]["walls"], | |
"Roof": results["heating"]["component_loads"]["roof"], | |
"Floor": results["heating"]["component_loads"]["floor"], | |
"Windows": results["heating"]["component_loads"]["windows"], | |
"Doors": results["heating"]["component_loads"]["doors"], | |
"Infiltration": results["heating"]["component_loads"]["infiltration"], | |
"Ventilation": results["heating"]["component_loads"]["ventilation"] | |
} | |
fig = px.pie( | |
values=list(heating_breakdown.values()), | |
names=list(heating_breakdown.keys()), | |
title="Heating Load Breakdown", | |
color_discrete_sequence=px.colors.qualitative.Pastel | |
) | |
fig.update_traces(textposition='inside', textinfo='percent+label') | |
fig.update_layout(uniformtext_minsize=12, uniformtext_mode='hide') | |
st.plotly_chart(fig, use_container_width=True) | |
# Display tabular results | |
st.subheader("Detailed Results") | |
# Create tabs for cooling and heating tables | |
tab1, tab2 = st.tabs(["Cooling Load Details", "Heating Load Details"]) | |
with tab1: | |
if not results.get("cooling") or "detailed_loads" not in results["cooling"]: | |
st.warning("Cooling load details are not available.") | |
else: | |
# Create cooling load details table | |
cooling_details = [] | |
# Add envelope components | |
for wall in results["cooling"]["detailed_loads"]["walls"]: | |
cooling_details.append({ | |
"Component Type": "Wall", | |
"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"] | |
}) | |
for roof in results["cooling"]["detailed_loads"]["roofs"]: | |
cooling_details.append({ | |
"Component Type": "Roof", | |
"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"] | |
}) | |
for window in results["cooling"]["detailed_loads"]["windows"]: | |
cooling_details.append({ | |
"Component Type": "Window", | |
"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"] | |
}) | |
for door in results["cooling"]["detailed_loads"]["doors"]: | |
cooling_details.append({ | |
"Component Type": "Door", | |
"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"] | |
}) | |
# Add internal loads | |
for internal_load in results["cooling"]["detailed_loads"]["internal"]: | |
cooling_details.append({ | |
"Component 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"] | |
}) | |
# Add infiltration and ventilation | |
cooling_details.append({ | |
"Component Type": "Infiltration", | |
"Name": "Air 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"], | |
"Load (kW)": results["cooling"]["detailed_loads"]["infiltration"]["total_load"] | |
}) | |
cooling_details.append({ | |
"Component Type": "Ventilation", | |
"Name": "Fresh Air", | |
"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"], | |
"Load (kW)": results["cooling"]["detailed_loads"]["ventilation"]["total_load"] | |
}) | |
# Display cooling details table | |
cooling_df = pd.DataFrame(cooling_details) | |
st.dataframe(cooling_df, use_container_width=True) | |
with tab2: | |
if not results.get("heating") or "detailed_loads" not in results["heating"]: | |
st.warning("Heating load details are not available.") | |
else: | |
# Create heating load details table | |
heating_details = [] | |
# Add envelope components | |
for wall in results["heating"]["detailed_loads"]["walls"]: | |
heating_details.append({ | |
"Component Type": "Wall", | |
"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"] | |
}) | |
for roof in results["heating"]["detailed_loads"]["roofs"]: | |
heating_details.append({ | |
"Component Type": "Roof", | |
"Name": roof["name"], | |
"Orientation": roof["orientation"], | |
"Area (m²)": roof["area"], | |
"U-Value (W/m²·K)": wall["u_value"], | |
"Temperature Difference (°C)": roof["delta_t"], | |
"Load (kW)": roof["load"] | |
}) | |
for floor in results["heating"]["detailed_loads"]["floors"]: | |
heating_details.append({ | |
"Component Type": "Floor", | |
"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"] | |
}) | |
for window in results["heating"]["detailed_loads"]["windows"]: | |
heating_details.append({ | |
"Component Type": "Window", | |
"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"] | |
}) | |
for door in results["heating"]["detailed_loads"]["doors"]: | |
heating_details.append({ | |
"Component Type": "Door", | |
"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"] | |
}) | |
# Add infiltration and ventilation | |
heating_details.append({ | |
"Component Type": "Infiltration", | |
"Name": "Air 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"] | |
}) | |
heating_details.append({ | |
"Component Type": "Ventilation", | |
"Name": "Fresh Air", | |
"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"] | |
}) | |
# Display heating details table | |
heating_df = pd.DataFrame(heating_details) | |
st.dataframe(heating_df, use_container_width=True) | |
# Add download buttons for results | |
st.subheader("Download Results") | |
col1, col2 = st.columns(2) | |
with col1: | |
if results.get("cooling") and "detailed_loads" in results["cooling"]: | |
if st.button("Download Cooling Load Results (CSV)"): | |
cooling_csv = cooling_df.to_csv(index=False) | |
st.download_button( | |
label="Download CSV", | |
data=cooling_csv, | |
file_name=f"cooling_load_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv", | |
mime="text/csv" | |
) | |
with col2: | |
if results.get("heating") and "detailed_loads" in results["heating"]: | |
if st.button("Download Heating Load Results (CSV)"): | |
heating_csv = heating_df.to_csv(index=False) | |
st.download_button( | |
label="Download CSV", | |
data=heating_csv, | |
file_name=f"heating_load_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv", | |
mime="text/csv" | |
) | |
# Add button to download full report | |
if st.button("Generate Full Report (Excel)"): | |
st.info("Excel report generation will be implemented in the Export module.") | |
def _display_component_breakdown(self, session_state: Dict[str, Any]) -> None: | |
""" | |
Display component breakdown visualization. | |
Args: | |
session_state: Streamlit session state containing calculation results | |
""" | |
st.subheader("Component Breakdown") | |
if not session_state["calculation_results"].get("cooling") and not session_state["calculation_results"].get("heating"): | |
st.warning("No component breakdown data available.") | |
return | |
# Try to use component visualization module | |
try: | |
self.component_visualization.display_component_breakdown( | |
session_state["calculation_results"], | |
session_state["components"] | |
) | |
except AttributeError: | |
# Fallback visualization if display_component_breakdown is not available | |
st.info("Component visualization module not fully implemented. Displaying default breakdown.") | |
results = session_state["calculation_results"] | |
# Cooling load bar chart | |
if results.get("cooling"): | |
cooling_breakdown = { | |
"Walls": results["cooling"]["component_loads"]["walls"], | |
"Roof": results["cooling"]["component_loads"]["roof"], | |
"Windows": results["cooling"]["component_loads"]["windows"], | |
"Doors": results["cooling"]["component_loads"]["doors"], | |
"People": results["cooling"]["component_loads"]["people"], | |
"Lighting": results["cooling"]["component_loads"]["lighting"], | |
"Equipment": results["cooling"]["component_loads"]["equipment"], | |
"Infiltration": results["cooling"]["component_loads"]["infiltration"], | |
"Ventilation": results["cooling"]["component_loads"]["ventilation"] | |
} | |
fig_cooling = px.bar( | |
x=list(cooling_breakdown.keys()), | |
y=list(cooling_breakdown.values()), | |
title="Cooling Load by Component", | |
labels={"x": "Component", "y": "Load (kW)"}, | |
color_discrete_sequence=px.colors.qualitative.Pastel | |
) | |
fig_cooling.update_layout(showlegend=False) | |
st.plotly_chart(fig_cooling, use_container_width=True) | |
# Heating load bar chart | |
if results.get("heating"): | |
heating_breakdown = { | |
"Walls": results["heating"]["component_loads"]["walls"], | |
"Roof": results["heating"]["component_loads"]["roof"], | |
"Floor": results["heating"]["component_loads"]["floor"], | |
"Windows": results["heating"]["component_loads"]["windows"], | |
"Doors": results["heating"]["component_loads"]["doors"], | |
"Infiltration": results["heating"]["component_loads"]["infiltration"], | |
"Ventilation": results["heating"]["component_loads"]["ventilation"] | |
} | |
fig_heating = px.bar( | |
x=list(heating_breakdown.keys()), | |
y=list(heating_breakdown.values()), | |
title="Heating Load by Component", | |
labels={"x": "Component", "y": "Load (kW)"}, | |
color_discrete_sequence=px.colors.qualitative.Pastel | |
) | |
fig_heating.update_layout(showlegend=False) | |
st.plotly_chart(fig_heating, use_container_width=True) | |
def _display_psychrometric_analysis(self, session_state: Dict[str, Any]) -> None: | |
""" | |
Display psychrometric analysis visualization. | |
Args: | |
session_state: Streamlit session state containing calculation results | |
""" | |
st.subheader("Psychrometric Analysis") | |
if not session_state["calculation_results"].get("cooling"): | |
st.warning("Psychrometric analysis requires cooling load results.") | |
return | |
# Use psychrometric visualization module | |
self.psychrometric_visualization.display_psychrometric_chart( | |
session_state["calculation_results"], | |
session_state["building_info"] | |
) | |
def _display_time_analysis(self, session_state: Dict[str, Any]) -> None: | |
""" | |
Display time-based analysis visualization. | |
Args: | |
session_state: Streamlit session state containing calculation results | |
""" | |
st.subheader("Time Analysis") | |
if not session_state["calculation_results"].get("cooling"): | |
st.warning("Time analysis requires cooling load results.") | |
return | |
# Use time-based visualization module | |
self.time_based_visualization.display_time_analysis( | |
session_state["calculation_results"] | |
) | |
def _display_scenario_comparison(self, session_state: Dict[str, Any]) -> None: | |
""" | |
Display scenario comparison visualization. | |
Args: | |
session_state: Streamlit session state containing calculation results | |
""" | |
st.subheader("Scenario Comparison") | |
# 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 comparison. Save the current results as a scenario to enable comparison.") | |
# 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.rerun() | |
else: | |
# Use scenario comparison module | |
self.scenario_comparison.display_scenario_comparison( | |
session_state["calculation_results"], | |
session_state["saved_scenarios"] | |
) | |
# Add button to save current results as a new scenario | |
st.write("### Save Current Results as New Scenario") | |
scenario_name = st.text_input("Scenario Name", value="Scenario " + str(len(session_state["saved_scenarios"]) + 1)) | |
if st.button("Save Current Results as Scenario"): | |
# 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.rerun() | |
# Add button to delete a scenario | |
st.write("### Delete Scenario") | |
scenario_to_delete = st.selectbox( | |
"Select Scenario to Delete", | |
options=list(session_state["saved_scenarios"].keys()) | |
) | |
if st.button("Delete Selected Scenario"): | |
# Delete selected scenario | |
del session_state["saved_scenarios"][scenario_to_delete] | |
st.success(f"Scenario '{scenario_to_delete}' deleted successfully!") | |
st.rerun() | |
# Create a singleton instance | |
results_display = ResultsDisplay() | |
# 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 results | |
results_display.display_results(st.session_state) |