test-29 / app /building_info_form.py
mabuseif's picture
Upload 31 files
76fc39e verified
"""
Building information input form for HVAC Load Calculator.
This module provides the UI components for entering building information.
"""
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 data models
from data.building_components import Orientation, ComponentType
class BuildingInfoForm:
"""Class for building information input form."""
def __init__(self):
"""Initialize the building information form."""
pass
def display(self):
"""
Display the building information form.
This method is called from main.py.
"""
self.display_building_info_form(st.session_state)
@staticmethod
def display_building_info_form(session_state: Dict[str, Any]) -> None:
"""
Display building information input form in Streamlit.
Args:
session_state: Streamlit session state for storing form data
"""
st.header("Building Information")
# Initialize building info in session state if not exists
if "building_info" not in session_state:
session_state["building_info"] = {
"project_name": "",
"building_name": "",
"location": "",
"climate_zone": "",
"building_type": "",
"floor_area": 0.0,
"num_floors": 1,
"floor_height": 3.0,
"orientation": "NORTH",
"occupancy": 0,
"operating_hours": "8:00-18:00",
"design_conditions": {
"summer_outdoor_db": 35.0,
"summer_outdoor_wb": 25.0,
"summer_indoor_db": 24.0,
"summer_indoor_rh": 50.0,
"winter_outdoor_db": -5.0,
"winter_outdoor_rh": 80.0,
"winter_indoor_db": 21.0,
"winter_indoor_rh": 40.0
}
}
# Ensure design_conditions exists
elif "design_conditions" not in session_state["building_info"]:
session_state["building_info"]["design_conditions"] = {
"summer_outdoor_db": 35.0,
"summer_outdoor_wb": 25.0,
"summer_indoor_db": 24.0,
"summer_indoor_rh": 50.0,
"winter_outdoor_db": -5.0,
"winter_outdoor_rh": 80.0,
"winter_indoor_db": 21.0,
"winter_indoor_rh": 40.0
}
# Initialize missing fields with default values
default_values = {
"project_name": "",
"building_name": "",
"location": "",
"climate_zone": "",
"building_type": "",
"floor_area": 0.0,
"num_floors": 1,
"floor_height": 3.0,
"orientation": "NORTH",
"occupancy": 0,
"operating_hours": "8:00-18:00"
}
for key, default_value in default_values.items():
if key not in session_state["building_info"]:
session_state["building_info"][key] = default_value
# Create form
with st.form("building_info_form"):
st.subheader("Project Information")
col1, col2 = st.columns(2)
with col1:
session_state["building_info"]["project_name"] = st.text_input(
"Project Name",
value=session_state["building_info"]["project_name"],
help="Enter the name of the project"
)
session_state["building_info"]["building_name"] = st.text_input(
"Building Name",
value=session_state["building_info"]["building_name"],
help="Enter the name of the building"
)
with col2:
session_state["building_info"]["location"] = st.text_input(
"Location",
value=session_state["building_info"]["location"],
help="Enter the location of the building (city, country)"
)
session_state["building_info"]["climate_zone"] = st.selectbox(
"Climate Zone",
["1A", "1B", "2A", "2B", "3A", "3B", "3C", "4A", "4B", "4C", "5A", "5B", "5C", "6A", "6B", "7", "8"],
index=4 if session_state["building_info"]["climate_zone"] == "" else
["1A", "1B", "2A", "2B", "3A", "3B", "3C", "4A", "4B", "4C", "5A", "5B", "5C", "6A", "6B", "7", "8"].index(session_state["building_info"]["climate_zone"]),
help="Select the ASHRAE climate zone for the building location"
)
st.subheader("Building Characteristics")
col1, col2, col3 = st.columns(3)
with col1:
session_state["building_info"]["building_type"] = st.selectbox(
"Building Type",
["Residential", "Office", "Retail", "Educational", "Healthcare", "Industrial", "Other"],
index=1 if session_state["building_info"]["building_type"] == "" else
["Residential", "Office", "Retail", "Educational", "Healthcare", "Industrial", "Other"].index(session_state["building_info"]["building_type"]),
help="Select the type of building"
)
with col2:
session_state["building_info"]["floor_area"] = st.number_input(
"Floor Area (m²)",
min_value=0.0,
value=float(session_state["building_info"]["floor_area"]),
step=10.0,
help="Enter the total floor area of the building in square meters"
)
with col3:
session_state["building_info"]["num_floors"] = st.number_input(
"Number of Floors",
min_value=1,
value=int(session_state["building_info"]["num_floors"]),
step=1,
help="Enter the number of floors in the building"
)
col1, col2, col3 = st.columns(3)
with col1:
session_state["building_info"]["floor_height"] = st.number_input(
"Floor Height (m)",
min_value=2.0,
max_value=10.0,
value=float(session_state["building_info"]["floor_height"]),
step=0.1,
help="Enter the floor-to-floor height in meters"
)
with col2:
session_state["building_info"]["orientation"] = st.selectbox(
"Building Orientation",
["NORTH", "NORTHEAST", "EAST", "SOUTHEAST", "SOUTH", "SOUTHWEST", "WEST", "NORTHWEST"],
index=["NORTH", "NORTHEAST", "EAST", "SOUTHEAST", "SOUTH", "SOUTHWEST", "WEST", "NORTHWEST"].index(session_state["building_info"]["orientation"]),
help="Select the orientation of the building's main facade"
)
with col3:
session_state["building_info"]["occupancy"] = st.number_input(
"Occupancy (people)",
min_value=0,
value=int(session_state["building_info"]["occupancy"]),
step=1,
help="Enter the total number of occupants"
)
session_state["building_info"]["operating_hours"] = st.text_input(
"Operating Hours",
value=session_state["building_info"]["operating_hours"],
help="Enter the operating hours of the building (e.g., 8:00-18:00)"
)
st.subheader("Design Conditions")
st.write("Summer Design Conditions")
col1, col2, col3, col4 = st.columns(4)
with col1:
session_state["building_info"]["design_conditions"]["summer_outdoor_db"] = st.number_input(
"Outdoor Dry-Bulb (°C)",
min_value=-10.0,
max_value=50.0,
value=float(session_state["building_info"]["design_conditions"]["summer_outdoor_db"]),
step=0.5,
key="summer_outdoor_db",
help="Enter the summer outdoor design dry-bulb temperature"
)
with col2:
session_state["building_info"]["design_conditions"]["summer_outdoor_wb"] = st.number_input(
"Outdoor Wet-Bulb (°C)",
min_value=-10.0,
max_value=40.0,
value=float(session_state["building_info"]["design_conditions"]["summer_outdoor_wb"]),
step=0.5,
key="summer_outdoor_wb",
help="Enter the summer outdoor design wet-bulb temperature"
)
with col3:
session_state["building_info"]["design_conditions"]["summer_indoor_db"] = st.number_input(
"Indoor Dry-Bulb (°C)",
min_value=18.0,
max_value=30.0,
value=float(session_state["building_info"]["design_conditions"]["summer_indoor_db"]),
step=0.5,
key="summer_indoor_db",
help="Enter the summer indoor design dry-bulb temperature"
)
with col4:
session_state["building_info"]["design_conditions"]["summer_indoor_rh"] = st.number_input(
"Indoor RH (%)",
min_value=30.0,
max_value=70.0,
value=float(session_state["building_info"]["design_conditions"]["summer_indoor_rh"]),
step=5.0,
key="summer_indoor_rh",
help="Enter the summer indoor design relative humidity"
)
st.write("Winter Design Conditions")
col1, col2, col3, col4 = st.columns(4)
with col1:
session_state["building_info"]["design_conditions"]["winter_outdoor_db"] = st.number_input(
"Outdoor Dry-Bulb (°C)",
min_value=-40.0,
max_value=20.0,
value=float(session_state["building_info"]["design_conditions"]["winter_outdoor_db"]),
step=0.5,
key="winter_outdoor_db",
help="Enter the winter outdoor design dry-bulb temperature"
)
with col2:
session_state["building_info"]["design_conditions"]["winter_outdoor_rh"] = st.number_input(
"Outdoor RH (%)",
min_value=0.0,
max_value=100.0,
value=float(session_state["building_info"]["design_conditions"]["winter_outdoor_rh"]),
step=5.0,
key="winter_outdoor_rh",
help="Enter the winter outdoor design relative humidity"
)
with col3:
session_state["building_info"]["design_conditions"]["winter_indoor_db"] = st.number_input(
"Indoor Dry-Bulb (°C)",
min_value=18.0,
max_value=25.0,
value=float(session_state["building_info"]["design_conditions"]["winter_indoor_db"]),
step=0.5,
key="winter_indoor_db",
help="Enter the winter indoor design dry-bulb temperature"
)
with col4:
session_state["building_info"]["design_conditions"]["winter_indoor_rh"] = st.number_input(
"Indoor RH (%)",
min_value=20.0,
max_value=60.0,
value=float(session_state["building_info"]["design_conditions"]["winter_indoor_rh"]),
step=5.0,
key="winter_indoor_rh",
help="Enter the winter indoor design relative humidity"
)
# Submit button
submitted = st.form_submit_button("Save Building Information")
if submitted:
st.success("Building information saved successfully!")
# Calculate derived values
total_height = session_state["building_info"]["floor_height"] * session_state["building_info"]["num_floors"]
total_volume = session_state["building_info"]["floor_area"] * total_height
# Display derived values
st.info(f"Total Building Height: {total_height:.1f} m")
st.info(f"Total Building Volume: {total_volume:.1f} m³")
# Set next page
if "page" in session_state and session_state["page"] == "building_info":
session_state["page"] = "climate_data"
@staticmethod
def validate_building_info(building_info: Dict[str, Any]) -> Tuple[bool, List[str]]:
"""
Validate building information.
Args:
building_info: Dictionary with building information
Returns:
Tuple with validation result (True if valid) and list of error messages
"""
valid = True
errors = []
# Check required fields
required_fields = ["project_name", "building_name", "location", "climate_zone", "building_type"]
for field in required_fields:
if field not in building_info or not building_info[field]:
valid = False
errors.append(f"Missing required field: {field}")
# Check numeric fields
if building_info.get("floor_area", 0) <= 0:
valid = False
errors.append("Floor area must be greater than zero")
if building_info.get("num_floors", 0) <= 0:
valid = False
errors.append("Number of floors must be greater than zero")
if building_info.get("floor_height", 0) <= 0:
valid = False
errors.append("Floor height must be greater than zero")
# Check design conditions
design_conditions = building_info.get("design_conditions", {})
if design_conditions.get("summer_indoor_db", 0) >= design_conditions.get("summer_outdoor_db", 0):
valid = False
errors.append("Summer indoor dry-bulb temperature must be less than outdoor dry-bulb temperature")
if design_conditions.get("winter_indoor_db", 0) <= design_conditions.get("winter_outdoor_db", 0):
valid = False
errors.append("Winter indoor dry-bulb temperature must be greater than outdoor dry-bulb temperature")
return valid, errors