Spaces:
Sleeping
Sleeping
Update app/intro.py
Browse files- app/intro.py +155 -33
app/intro.py
CHANGED
@@ -76,9 +76,6 @@ def display_about_section():
|
|
76 |
|
77 |
Beta Version 0.4.1 (2025)
|
78 |
""")
|
79 |
-
|
80 |
-
# Add Deakin University logo or other relevant images if available
|
81 |
-
# st.image("path_to_logo.png", width=200)
|
82 |
|
83 |
def display_instructions_section():
|
84 |
"""Display instructions on how to use the application."""
|
@@ -115,9 +112,6 @@ def display_instructions_section():
|
|
115 |
* **Sol-Air Temperature**: For solar radiation effects on opaque surfaces
|
116 |
* **Dynamic Solar Heat Gain**: For fenestration with angle-dependent properties
|
117 |
""")
|
118 |
-
|
119 |
-
# Add any diagrams or flowcharts if available
|
120 |
-
# st.image("path_to_flowchart.png", width=600)
|
121 |
|
122 |
def display_project_management_section():
|
123 |
"""Display project management options (new, import, export)."""
|
@@ -159,21 +153,61 @@ def start_new_project():
|
|
159 |
backup_timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
160 |
st.session_state.project_data_backup[backup_timestamp] = st.session_state.project_data.copy()
|
161 |
|
162 |
-
# Reset project data to
|
163 |
st.session_state.project_data = {
|
164 |
"project_name": "",
|
165 |
"building_info": {
|
166 |
"project_name": "",
|
167 |
"floor_area": 100.0,
|
168 |
"building_height": 3.0,
|
169 |
-
"
|
170 |
-
"
|
171 |
-
"
|
172 |
-
"
|
173 |
-
"
|
174 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
},
|
176 |
-
"climate_data": {},
|
177 |
"materials": {
|
178 |
"library": {},
|
179 |
"project": {}
|
@@ -191,27 +225,74 @@ def start_new_project():
|
|
191 |
"roofs": [],
|
192 |
"floors": [],
|
193 |
"windows": [],
|
194 |
-
"doors": [],
|
195 |
"skylights": []
|
196 |
},
|
197 |
"internal_loads": {
|
|
|
198 |
"people": [],
|
199 |
-
"lighting":
|
200 |
-
"equipment":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
},
|
202 |
"hvac_loads": {
|
203 |
"cooling": {
|
204 |
"hourly": [],
|
205 |
-
"peak": 0,
|
206 |
"summary_tables": {},
|
207 |
-
"charts": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
208 |
},
|
209 |
"heating": {
|
210 |
"hourly": [],
|
211 |
-
"peak": 0,
|
212 |
"summary_tables": {},
|
213 |
-
"charts": {
|
214 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
215 |
},
|
216 |
"building_energy": {
|
217 |
"hvac_type": "",
|
@@ -235,12 +316,14 @@ def start_new_project():
|
|
235 |
"embodied_energy": {
|
236 |
"total_embodied_carbon_kgco2e": 0,
|
237 |
"breakdown_by_component": {},
|
238 |
-
"charts": {}
|
|
|
239 |
},
|
240 |
"materials_cost": {
|
241 |
"total_cost_usd": 0,
|
242 |
"breakdown_by_component": {},
|
243 |
-
"charts": {}
|
|
|
244 |
}
|
245 |
}
|
246 |
|
@@ -275,6 +358,12 @@ def load_project(uploaded_file) -> bool:
|
|
275 |
backup_timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
276 |
st.session_state.project_data_backup[backup_timestamp] = st.session_state.project_data.copy()
|
277 |
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
# Update session state with the loaded project data
|
279 |
st.session_state.project_data = project_data
|
280 |
|
@@ -297,6 +386,7 @@ def validate_project_data(project_data: Dict[str, Any]) -> bool:
|
|
297 |
"""
|
298 |
# Check for required top-level keys
|
299 |
required_keys = [
|
|
|
300 |
"building_info",
|
301 |
"climate_data",
|
302 |
"materials",
|
@@ -304,7 +394,11 @@ def validate_project_data(project_data: Dict[str, Any]) -> bool:
|
|
304 |
"constructions",
|
305 |
"components",
|
306 |
"internal_loads",
|
|
|
307 |
"hvac_loads",
|
|
|
|
|
|
|
308 |
"building_energy",
|
309 |
"renewable_energy",
|
310 |
"embodied_energy",
|
@@ -321,11 +415,12 @@ def validate_project_data(project_data: Dict[str, Any]) -> bool:
|
|
321 |
"project_name",
|
322 |
"floor_area",
|
323 |
"building_height",
|
324 |
-
"
|
325 |
-
"
|
326 |
-
"
|
327 |
-
"
|
328 |
-
"
|
|
|
329 |
]
|
330 |
|
331 |
for key in building_info_keys:
|
@@ -333,8 +428,26 @@ def validate_project_data(project_data: Dict[str, Any]) -> bool:
|
|
333 |
logger.error(f"Missing required key in building_info: {key}")
|
334 |
return False
|
335 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
336 |
# Check components structure
|
337 |
-
component_types = ["walls", "roofs", "floors", "windows", "
|
338 |
for component_type in component_types:
|
339 |
if component_type not in project_data["components"]:
|
340 |
logger.error(f"Missing component type in components: {component_type}")
|
@@ -351,11 +464,20 @@ def validate_project_data(project_data: Dict[str, Any]) -> bool:
|
|
351 |
def export_project():
|
352 |
"""Export the current project as a downloadable JSON file."""
|
353 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
354 |
# Convert project data to JSON
|
355 |
-
project_json = json.dumps(
|
356 |
|
357 |
# Generate filename based on project name
|
358 |
-
project_name =
|
359 |
safe_project_name = "".join(c if c.isalnum() else "_" for c in project_name)
|
360 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
361 |
filename = f"{safe_project_name}_{timestamp}.json"
|
@@ -390,4 +512,4 @@ def get_download_link(data, filename, link_text):
|
|
390 |
"""
|
391 |
b64 = base64.b64encode(data.encode()).decode()
|
392 |
href = f'<a href="data:application/json;base64,{b64}" download="{filename}">{link_text}</a>'
|
393 |
-
return href
|
|
|
76 |
|
77 |
Beta Version 0.4.1 (2025)
|
78 |
""")
|
|
|
|
|
|
|
79 |
|
80 |
def display_instructions_section():
|
81 |
"""Display instructions on how to use the application."""
|
|
|
112 |
* **Sol-Air Temperature**: For solar radiation effects on opaque surfaces
|
113 |
* **Dynamic Solar Heat Gain**: For fenestration with angle-dependent properties
|
114 |
""")
|
|
|
|
|
|
|
115 |
|
116 |
def display_project_management_section():
|
117 |
"""Display project management options (new, import, export)."""
|
|
|
153 |
backup_timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
154 |
st.session_state.project_data_backup[backup_timestamp] = st.session_state.project_data.copy()
|
155 |
|
156 |
+
# Reset project data to match main.py structure
|
157 |
st.session_state.project_data = {
|
158 |
"project_name": "",
|
159 |
"building_info": {
|
160 |
"project_name": "",
|
161 |
"floor_area": 100.0,
|
162 |
"building_height": 3.0,
|
163 |
+
"building_type": "Office",
|
164 |
+
"summer_indoor_design_temp": 24.0,
|
165 |
+
"summer_indoor_design_rh": 50.0,
|
166 |
+
"winter_indoor_design_temp": 20.0,
|
167 |
+
"winter_indoor_design_rh": 50.0,
|
168 |
+
"orientation_angle": 0.0
|
169 |
+
},
|
170 |
+
"climate_data": {
|
171 |
+
"id": "",
|
172 |
+
"location": {
|
173 |
+
"city": "",
|
174 |
+
"state_province": "",
|
175 |
+
"country": "",
|
176 |
+
"source": "",
|
177 |
+
"wmo": "",
|
178 |
+
"latitude": 0.0,
|
179 |
+
"longitude": 0.0,
|
180 |
+
"timezone": 0.0,
|
181 |
+
"elevation": 0.0
|
182 |
+
},
|
183 |
+
"design_conditions": {
|
184 |
+
"winter_design_temp": 0.0,
|
185 |
+
"summer_design_temp_db": 30.0,
|
186 |
+
"summer_design_temp_wb": 25.0,
|
187 |
+
"heating_degree_days": 0,
|
188 |
+
"cooling_degree_days": 0,
|
189 |
+
"monthly_average_temps": [20.0] * 12,
|
190 |
+
"monthly_average_radiation": [150.0] * 12,
|
191 |
+
"summer_daily_range": 8.0,
|
192 |
+
"wind_speed": 3.0,
|
193 |
+
"pressure": 101325.0
|
194 |
+
},
|
195 |
+
"climate_zone": "",
|
196 |
+
"hourly_data": [],
|
197 |
+
"epw_filename": "",
|
198 |
+
"typical_extreme_periods": {
|
199 |
+
"summer_extreme": {"start": {"month": 7, "day": 1}, "end": {"month": 7, "day": 7}},
|
200 |
+
"summer_typical": {"start": {"month": 6, "day": 1}, "end": {"month": 6, "day": 7}},
|
201 |
+
"winter_extreme": {"start": {"month": 1, "day": 1}, "end": {"month": 1, "day": 7}},
|
202 |
+
"winter_typical": {"start": {"month": 12, "day": 1}, "end": {"month": 12, "day": 7}}
|
203 |
+
},
|
204 |
+
"ground_temperatures": {
|
205 |
+
"0.5": [20.0] * 12,
|
206 |
+
"2": [18.0] * 12,
|
207 |
+
"4": [16.0] * 12
|
208 |
+
},
|
209 |
+
"ground_reflectivity": 0.2
|
210 |
},
|
|
|
211 |
"materials": {
|
212 |
"library": {},
|
213 |
"project": {}
|
|
|
225 |
"roofs": [],
|
226 |
"floors": [],
|
227 |
"windows": [],
|
|
|
228 |
"skylights": []
|
229 |
},
|
230 |
"internal_loads": {
|
231 |
+
"schedules": {},
|
232 |
"people": [],
|
233 |
+
"lighting": [],
|
234 |
+
"equipment": [],
|
235 |
+
"ventilation": [],
|
236 |
+
"infiltration": []
|
237 |
+
},
|
238 |
+
"internal_loads_conditions": {
|
239 |
+
"air_velocity": 0.1,
|
240 |
+
"lighting_convective_fraction": 0.5,
|
241 |
+
"lighting_radiative_fraction": 0.5,
|
242 |
+
"equipment_convective_fraction": 0.5,
|
243 |
+
"equipment_radiative_fraction": 0.5
|
244 |
},
|
245 |
"hvac_loads": {
|
246 |
"cooling": {
|
247 |
"hourly": [],
|
248 |
+
"peak": 0.0,
|
249 |
"summary_tables": {},
|
250 |
+
"charts": {
|
251 |
+
"pie_by_component": {},
|
252 |
+
"pie_by_orientation": {}
|
253 |
+
},
|
254 |
+
"breakdown": {
|
255 |
+
"conduction": 0.0,
|
256 |
+
"solar": 0.0,
|
257 |
+
"internal": 0.0,
|
258 |
+
"ventilation_sensible": 0.0,
|
259 |
+
"ventilation_latent": 0.0,
|
260 |
+
"infiltration_sensible": 0.0,
|
261 |
+
"infiltration_latent": 0.0
|
262 |
+
}
|
263 |
},
|
264 |
"heating": {
|
265 |
"hourly": [],
|
266 |
+
"peak": 0.0,
|
267 |
"summary_tables": {},
|
268 |
+
"charts": {
|
269 |
+
"pie_by_component": {},
|
270 |
+
"pie_by_orientation": {}
|
271 |
+
},
|
272 |
+
"breakdown": {
|
273 |
+
"conduction": 0.0,
|
274 |
+
"ventilation": 0.0,
|
275 |
+
"infiltration": 0.0
|
276 |
+
}
|
277 |
+
},
|
278 |
+
"monthly_summary": {}
|
279 |
+
},
|
280 |
+
"hvac_settings": {
|
281 |
+
"operating_hours": [{"start": 8, "end": 18}],
|
282 |
+
"system_type": "Default"
|
283 |
+
},
|
284 |
+
"sim_period": {
|
285 |
+
"type": "Full Year",
|
286 |
+
"start_date": datetime(2025, 1, 1),
|
287 |
+
"end_date": datetime(2025, 12, 31),
|
288 |
+
"base_temp": 18.3
|
289 |
+
},
|
290 |
+
"indoor_conditions": {
|
291 |
+
"type": "Fixed Setpoints",
|
292 |
+
"cooling_setpoint": {"temperature": 24.0, "rh": 50.0},
|
293 |
+
"heating_setpoint": {"temperature": 20.0, "rh": 50.0},
|
294 |
+
"adaptive_acceptability": "90",
|
295 |
+
"schedule": []
|
296 |
},
|
297 |
"building_energy": {
|
298 |
"hvac_type": "",
|
|
|
316 |
"embodied_energy": {
|
317 |
"total_embodied_carbon_kgco2e": 0,
|
318 |
"breakdown_by_component": {},
|
319 |
+
"charts": {},
|
320 |
+
"material_inventory": []
|
321 |
},
|
322 |
"materials_cost": {
|
323 |
"total_cost_usd": 0,
|
324 |
"breakdown_by_component": {},
|
325 |
+
"charts": {},
|
326 |
+
"material_inventory": []
|
327 |
}
|
328 |
}
|
329 |
|
|
|
358 |
backup_timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
359 |
st.session_state.project_data_backup[backup_timestamp] = st.session_state.project_data.copy()
|
360 |
|
361 |
+
# Convert datetime strings back to datetime objects if necessary
|
362 |
+
if project_data.get("sim_period", {}).get("start_date"):
|
363 |
+
project_data["sim_period"]["start_date"] = datetime.fromisoformat(project_data["sim_period"]["start_date"])
|
364 |
+
if project_data.get("sim_period", {}).get("end_date"):
|
365 |
+
project_data["sim_period"]["end_date"] = datetime.fromisoformat(project_data["sim_period"]["end_date"])
|
366 |
+
|
367 |
# Update session state with the loaded project data
|
368 |
st.session_state.project_data = project_data
|
369 |
|
|
|
386 |
"""
|
387 |
# Check for required top-level keys
|
388 |
required_keys = [
|
389 |
+
"project_name",
|
390 |
"building_info",
|
391 |
"climate_data",
|
392 |
"materials",
|
|
|
394 |
"constructions",
|
395 |
"components",
|
396 |
"internal_loads",
|
397 |
+
"internal_loads_conditions",
|
398 |
"hvac_loads",
|
399 |
+
"hvac_settings",
|
400 |
+
"sim_period",
|
401 |
+
"indoor_conditions",
|
402 |
"building_energy",
|
403 |
"renewable_energy",
|
404 |
"embodied_energy",
|
|
|
415 |
"project_name",
|
416 |
"floor_area",
|
417 |
"building_height",
|
418 |
+
"building_type",
|
419 |
+
"summer_indoor_design_temp",
|
420 |
+
"summer_indoor_design_rh",
|
421 |
+
"winter_indoor_design_temp",
|
422 |
+
"winter_indoor_design_rh",
|
423 |
+
"orientation_angle"
|
424 |
]
|
425 |
|
426 |
for key in building_info_keys:
|
|
|
428 |
logger.error(f"Missing required key in building_info: {key}")
|
429 |
return False
|
430 |
|
431 |
+
# Check climate_data structure
|
432 |
+
climate_data_keys = [
|
433 |
+
"id",
|
434 |
+
"location",
|
435 |
+
"design_conditions",
|
436 |
+
"climate_zone",
|
437 |
+
"hourly_data",
|
438 |
+
"epw_filename",
|
439 |
+
"typical_extreme_periods",
|
440 |
+
"ground_temperatures",
|
441 |
+
"ground_reflectivity"
|
442 |
+
]
|
443 |
+
|
444 |
+
for key in climate_data_keys:
|
445 |
+
if key not in project_data["climate_data"]:
|
446 |
+
logger.error(f"Missing required key in climate_data: {key}")
|
447 |
+
return False
|
448 |
+
|
449 |
# Check components structure
|
450 |
+
component_types = ["walls", "roofs", "floors", "windows", "skylights"]
|
451 |
for component_type in component_types:
|
452 |
if component_type not in project_data["components"]:
|
453 |
logger.error(f"Missing component type in components: {component_type}")
|
|
|
464 |
def export_project():
|
465 |
"""Export the current project as a downloadable JSON file."""
|
466 |
try:
|
467 |
+
# Create a deep copy of project data to avoid modifying session state
|
468 |
+
project_data = st.session_state.project_data.copy()
|
469 |
+
|
470 |
+
# Convert datetime objects to ISO format strings for JSON serialization
|
471 |
+
if project_data.get("sim_period", {}).get("start_date"):
|
472 |
+
project_data["sim_period"]["start_date"] = project_data["sim_period"]["start_date"].isoformat()
|
473 |
+
if project_data.get("sim_period", {}).get("end_date"):
|
474 |
+
project_data["sim_period"]["end_date"] = project_data["sim_period"]["end_date"].isoformat()
|
475 |
+
|
476 |
# Convert project data to JSON
|
477 |
+
project_json = json.dumps(project_data, indent=2)
|
478 |
|
479 |
# Generate filename based on project name
|
480 |
+
project_name = project_data.get("project_name", "unnamed_project")
|
481 |
safe_project_name = "".join(c if c.isalnum() else "_" for c in project_name)
|
482 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
483 |
filename = f"{safe_project_name}_{timestamp}.json"
|
|
|
512 |
"""
|
513 |
b64 = base64.b64encode(data.encode()).decode()
|
514 |
href = f'<a href="data:application/json;base64,{b64}" download="{filename}">{link_text}</a>'
|
515 |
+
return href
|