Spaces:
Sleeping
Sleeping
File size: 10,232 Bytes
845939b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
"""
Building information input form for HVAC Load Calculator.
This module provides the UI components for entering building information.
Author: Dr Majed Abuseif
Date: March 2025
Version: 1.0.0
"""
import streamlit as st
import pandas as pd
import numpy as np
import pycountry
from typing import Dict, List, Any, Optional, Tuple
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."""
self.countries = sorted([country.name for country in pycountry.countries])
def display(self):
"""Display the building information form."""
self.display_building_info_form(st.session_state)
def display_building_info_form(self, session_state: Dict[str, Any]) -> None:
"""Display building information input form in Streamlit."""
st.header("Building Information")
if "building_info" not in session_state:
session_state["building_info"] = {
"project_name": "",
"building_name": "",
"country": "",
"city": "",
"building_type": "",
"floor_area": 0.0,
"width": 0.0,
"depth": 0.0,
"building_height": 3.0,
"orientation": "NORTH",
"operating_hours": "8:00-18:00"
}
default_values = {
"project_name": "",
"building_name": "",
"country": "",
"city": "",
"building_type": "",
"floor_area": 0.0,
"width": 0.0,
"depth": 0.0,
"building_height": 3.0,
"orientation": "NORTH",
"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
if "data_saved" not in session_state:
session_state["data_saved"] = False
with st.form(key="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 project's identification name"
)
session_state["building_info"]["building_name"] = st.text_input(
"Building Name",
value=session_state["building_info"]["building_name"],
help="Enter the building's identification name"
)
with col2:
session_state["building_info"]["country"] = st.selectbox(
"Country",
options=[""] + self.countries,
index=0 if not session_state["building_info"]["country"] else
self.countries.index(session_state["building_info"]["country"]) + 1,
help="Select the building's country location"
)
session_state["building_info"]["city"] = st.text_input(
"City",
value=session_state["building_info"]["city"],
help="Enter the building's city location"
)
st.subheader("Building Characteristics")
col1, col2 = st.columns(2)
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 building's purpose or usage type"
)
with col2:
session_state["building_info"]["building_height"] = st.number_input(
"Building Height (m)",
min_value=2.0,
max_value=1000.0,
value=float(session_state["building_info"]["building_height"]),
step=0.1,
help="Enter the total height of the building in meters"
)
st.subheader("Building Dimensions")
session_state["building_info"]["floor_area"] = st.number_input(
"Total 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 (optional if width and depth provided)"
)
# Center the OR using columns
col1, col2, col3 = st.columns([2, 1, 2])
with col2:
st.markdown("Enter the total floor area above OR the building width and depth below")
col1, col2 = st.columns(2)
with col1:
session_state["building_info"]["width"] = st.number_input(
"Width (m)",
min_value=0.0,
value=float(session_state["building_info"]["width"]),
step=1.0,
help="Enter the building's width in meters (optional if area provided)"
)
with col2:
session_state["building_info"]["depth"] = st.number_input(
"Depth (m)",
min_value=0.0,
value=float(session_state["building_info"]["depth"]),
step=1.0,
help="Enter the building's depth in meters (optional if area provided)"
)
st.subheader("Building Orientation")
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 direction of the building's main facade"
)
st.subheader("Operating Hours")
session_state["building_info"]["operating_hours"] = st.text_input(
"Operating Hours",
value=session_state["building_info"]["operating_hours"],
help="Enter the building's daily operating hours (e.g., 8:00-18:00)"
)
submitted = st.form_submit_button("Save Building Information")
if submitted:
valid, errors = self.validate_building_info(session_state["building_info"])
if not valid:
for error in errors:
st.error(error)
else:
if session_state["building_info"]["width"] > 0 and session_state["building_info"]["depth"] > 0:
calculated_area = session_state["building_info"]["width"] * session_state["building_info"]["depth"]
if session_state["building_info"]["floor_area"] == 0:
session_state["building_info"]["floor_area"] = calculated_area
total_volume = session_state["building_info"]["floor_area"] * session_state["building_info"]["building_height"]
session_state["save_results"] = {
"success": "Building information saved successfully!",
"area": f"Total Floor Area: {session_state['building_info']['floor_area']:.1f} m²",
"volume": f"Total Building Volume: {total_volume:.1f} m³"
}
session_state["data_saved"] = True
# Display results if they exist
if "save_results" in session_state and session_state["data_saved"]:
st.success(session_state["save_results"]["success"])
st.info(session_state["save_results"]["area"])
st.info(session_state["save_results"]["volume"])
# Proceed button with immediate navigation
if session_state["data_saved"]:
if st.button("Proceed to Climate Data"):
session_state["page"] = "Climate Data"
session_state["data_saved"] = False
if "save_results" in session_state:
del session_state["save_results"]
@staticmethod
def validate_building_info(building_info: Dict[str, Any]) -> Tuple[bool, List[str]]:
"""Validate building information."""
valid = True
errors = []
required_fields = ["project_name", "building_name", "country", "city", "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}")
if building_info.get("floor_area", 0) <= 0 and (building_info.get("width", 0) <= 0 or building_info.get("depth", 0) <= 0):
valid = False
errors.append("Must provide either floor area or both width and depth dimensions")
if building_info.get("building_height", 0) <= 0:
valid = False
errors.append("Building height must be greater than zero")
return valid, errors
if __name__ == "__main__":
form = BuildingInfoForm()
form.display() |