Spaces:
Sleeping
Sleeping
Update app/components.py
Browse files- app/components.py +53 -29
app/components.py
CHANGED
@@ -94,6 +94,14 @@ def migrate_component_types():
|
|
94 |
if comp_type != "floors" and "tilt" in component:
|
95 |
component["surface_tilt"] = component.pop("tilt")
|
96 |
logger.info(f"Renamed 'tilt' to 'surface_tilt' for component '{component['name']}'")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
|
98 |
def display_component_tab(comp_type: str):
|
99 |
"""
|
@@ -203,16 +211,19 @@ def display_component_tab(comp_type: str):
|
|
203 |
help="Tilt angle of the component relative to horizontal (0° = horizontal, 90° = vertical)."
|
204 |
)
|
205 |
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
"
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
|
|
|
|
|
|
216 |
)
|
217 |
|
218 |
# Construction or fenestration selection
|
@@ -330,8 +341,9 @@ def display_component_tab(comp_type: str):
|
|
330 |
component_data["surface_azimuth"] = surface_azimuth
|
331 |
component_data["surface_tilt"] = surface_tilt
|
332 |
|
333 |
-
if comp_type
|
334 |
-
component_data["
|
|
|
335 |
|
336 |
if comp_type in ["walls", "roofs", "floors"]:
|
337 |
component_data["construction"] = construction
|
@@ -390,15 +402,17 @@ def display_component_tab(comp_type: str):
|
|
390 |
def display_wall_window_table(comp_type: str, components: List[Dict[str, Any]]):
|
391 |
"""Display a table of walls or windows with appropriate columns."""
|
392 |
# Create column headers
|
393 |
-
cols = st.columns([2, 1, 1, 1, 1, 1, 1] if comp_type == "walls" else [2, 1, 1, 1, 1, 1, 1, 1])
|
394 |
cols[0].write("**Name**")
|
395 |
cols[1].write("**U-Value**")
|
396 |
cols[2].write("**Area (m²)**")
|
397 |
cols[3].write("**Surface Azimuth (°)**")
|
398 |
cols[4].write("**Surface Tilt (°)**")
|
399 |
if comp_type == "walls":
|
400 |
-
cols[5].write("**
|
401 |
-
cols[6].write("**
|
|
|
|
|
402 |
else: # windows
|
403 |
cols[5].write("**SC**")
|
404 |
cols[6].write("**Edit**")
|
@@ -406,18 +420,19 @@ def display_wall_window_table(comp_type: str, components: List[Dict[str, Any]]):
|
|
406 |
|
407 |
# Display each component
|
408 |
for idx, comp in enumerate(components):
|
409 |
-
cols = st.columns([2, 1, 1, 1, 1, 1, 1] if comp_type == "walls" else [2, 1, 1, 1, 1, 1, 1, 1])
|
410 |
cols[0].write(comp["name"])
|
411 |
cols[1].write(f"{comp.get('u_value', 0.0):.3f}")
|
412 |
cols[2].write(f"{comp['area']:.2f}")
|
413 |
cols[3].write(f"{comp.get('surface_azimuth', 0.0):.0f}")
|
414 |
cols[4].write(f"{comp.get('surface_tilt', 90.0):.0f}")
|
415 |
-
if comp_type == "
|
416 |
-
cols[5].write(
|
|
|
417 |
|
418 |
# Edit button
|
419 |
edit_key = f"edit_{comp_type}_{comp['name']}_{idx}"
|
420 |
-
edit_col =
|
421 |
with cols[edit_col].container():
|
422 |
if st.button("Edit", key=edit_key):
|
423 |
editor_data = {
|
@@ -432,6 +447,8 @@ def display_wall_window_table(comp_type: str, components: List[Dict[str, Any]]):
|
|
432 |
|
433 |
if comp_type == "walls":
|
434 |
editor_data["construction"] = comp.get("construction", "")
|
|
|
|
|
435 |
else: # windows
|
436 |
editor_data["fenestration"] = comp.get("fenestration", "")
|
437 |
editor_data["parent_component"] = comp.get("parent_component", "")
|
@@ -444,7 +461,7 @@ def display_wall_window_table(comp_type: str, components: List[Dict[str, Any]]):
|
|
444 |
|
445 |
# Delete button
|
446 |
delete_key = f"delete_{comp_type}_{comp['name']}_{idx}"
|
447 |
-
delete_col =
|
448 |
with cols[delete_col].container():
|
449 |
if st.button("Delete", key=delete_key):
|
450 |
st.session_state.project_data["components"][comp_type].pop(idx)
|
@@ -520,32 +537,35 @@ def display_roof_skylight_table(comp_type: str, components: List[Dict[str, Any]]
|
|
520 |
def display_floor_table(comp_type: str, components: List[Dict[str, Any]]):
|
521 |
"""Display a table of floors with appropriate columns."""
|
522 |
# Create column headers
|
523 |
-
cols = st.columns([2, 1, 1, 1, 1, 1])
|
524 |
cols[0].write("**Name**")
|
525 |
cols[1].write("**U-Value**")
|
526 |
cols[2].write("**Area (m²)**")
|
527 |
-
cols[3].write("**
|
528 |
-
cols[4].write("**
|
529 |
-
cols[5].write("**
|
|
|
530 |
|
531 |
# Display each component
|
532 |
for idx, comp in enumerate(components):
|
533 |
-
cols = st.columns([2, 1, 1, 1, 1, 1])
|
534 |
cols[0].write(comp["name"])
|
535 |
cols[1].write(f"{comp.get('u_value', 0.0):.3f}")
|
536 |
cols[2].write(f"{comp['area']:.2f}")
|
537 |
-
cols[3].write(
|
|
|
538 |
|
539 |
# Edit button
|
540 |
edit_key = f"edit_{comp_type}_{comp['name']}_{idx}"
|
541 |
-
with cols[
|
542 |
if st.button("Edit", key=edit_key):
|
543 |
editor_data = {
|
544 |
"index": idx,
|
545 |
"name": comp["name"],
|
546 |
"area": comp["area"],
|
547 |
"construction": comp.get("construction", ""),
|
548 |
-
"
|
|
|
549 |
"is_edit": True
|
550 |
}
|
551 |
|
@@ -555,7 +575,7 @@ def display_floor_table(comp_type: str, components: List[Dict[str, Any]]):
|
|
555 |
|
556 |
# Delete button
|
557 |
delete_key = f"delete_{comp_type}_{comp['name']}_{idx}"
|
558 |
-
with cols[
|
559 |
if st.button("Delete", key=delete_key):
|
560 |
st.session_state.project_data["components"][comp_type].pop(idx)
|
561 |
st.success(f"{comp_type[:-1].capitalize()} '{comp['name']}' deleted!")
|
@@ -668,6 +688,8 @@ def display_components_help():
|
|
668 |
* **Surface Tilt**: Angle of the component relative to horizontal (0° = horizontal, 90° = vertical).
|
669 |
* **Parent Component**: The wall or roof that contains a window or skylight.
|
670 |
* **Shading Coefficient (SC)**: Factor for shading devices on windows/skylights (0.0 to 1.0).
|
|
|
|
|
671 |
|
672 |
**Workflow:**
|
673 |
|
@@ -681,4 +703,6 @@ def display_components_help():
|
|
681 |
* For roofs and skylights, set surface tilt to 0° for flat surfaces.
|
682 |
* Ensure the total area of windows doesn't exceed the area of their parent walls.
|
683 |
* Ensure the total area of skylights doesn't exceed the area of their parent roofs.
|
|
|
|
|
684 |
""")
|
|
|
94 |
if comp_type != "floors" and "tilt" in component:
|
95 |
component["surface_tilt"] = component.pop("tilt")
|
96 |
logger.info(f"Renamed 'tilt' to 'surface_tilt' for component '{component['name']}'")
|
97 |
+
# Add adiabatic and ground_contact if not present for walls and floors
|
98 |
+
if comp_type in ["walls", "floors"]:
|
99 |
+
if "adiabatic" not in component:
|
100 |
+
component["adiabatic"] = False
|
101 |
+
logger.info(f"Added 'adiabatic' to component '{component['name']}'")
|
102 |
+
if "ground_contact" not in component:
|
103 |
+
component["ground_contact"] = False
|
104 |
+
logger.info(f"Added 'ground_contact' to component '{component['name']}'")
|
105 |
|
106 |
def display_component_tab(comp_type: str):
|
107 |
"""
|
|
|
211 |
help="Tilt angle of the component relative to horizontal (0° = horizontal, 90° = vertical)."
|
212 |
)
|
213 |
|
214 |
+
# Adiabatic and Ground Contact for walls and floors
|
215 |
+
if comp_type in ["walls", "floors"]:
|
216 |
+
adiabatic = st.selectbox(
|
217 |
+
"Adiabatic",
|
218 |
+
["Yes", "No"],
|
219 |
+
index=0 if editor_state.get("adiabatic", False) else 1,
|
220 |
+
help="Select 'Yes' if the component is adiabatic (no heat transfer across it)."
|
221 |
+
)
|
222 |
+
ground_contact = st.selectbox(
|
223 |
+
"Ground Contact",
|
224 |
+
["Yes", "No"],
|
225 |
+
index=0 if editor_state.get("ground_contact", False) else 1,
|
226 |
+
help="Select 'Yes' if the component is in contact with the ground."
|
227 |
)
|
228 |
|
229 |
# Construction or fenestration selection
|
|
|
341 |
component_data["surface_azimuth"] = surface_azimuth
|
342 |
component_data["surface_tilt"] = surface_tilt
|
343 |
|
344 |
+
if comp_type in ["walls", "floors"]:
|
345 |
+
component_data["adiabatic"] = adiabatic == "Yes"
|
346 |
+
component_data["ground_contact"] = ground_contact == "Yes"
|
347 |
|
348 |
if comp_type in ["walls", "roofs", "floors"]:
|
349 |
component_data["construction"] = construction
|
|
|
402 |
def display_wall_window_table(comp_type: str, components: List[Dict[str, Any]]):
|
403 |
"""Display a table of walls or windows with appropriate columns."""
|
404 |
# Create column headers
|
405 |
+
cols = st.columns([2, 1, 1, 1, 1, 1, 1, 1, 1] if comp_type == "walls" else [2, 1, 1, 1, 1, 1, 1, 1])
|
406 |
cols[0].write("**Name**")
|
407 |
cols[1].write("**U-Value**")
|
408 |
cols[2].write("**Area (m²)**")
|
409 |
cols[3].write("**Surface Azimuth (°)**")
|
410 |
cols[4].write("**Surface Tilt (°)**")
|
411 |
if comp_type == "walls":
|
412 |
+
cols[5].write("**Adiabatic**")
|
413 |
+
cols[6].write("**Ground Contact**")
|
414 |
+
cols[7].write("**Edit**")
|
415 |
+
cols[8].write("**Delete**")
|
416 |
else: # windows
|
417 |
cols[5].write("**SC**")
|
418 |
cols[6].write("**Edit**")
|
|
|
420 |
|
421 |
# Display each component
|
422 |
for idx, comp in enumerate(components):
|
423 |
+
cols = st.columns([2, 1, 1, 1, 1, 1, 1, 1, 1] if comp_type == "walls" else [2, 1, 1, 1, 1, 1, 1, 1])
|
424 |
cols[0].write(comp["name"])
|
425 |
cols[1].write(f"{comp.get('u_value', 0.0):.3f}")
|
426 |
cols[2].write(f"{comp['area']:.2f}")
|
427 |
cols[3].write(f"{comp.get('surface_azimuth', 0.0):.0f}")
|
428 |
cols[4].write(f"{comp.get('surface_tilt', 90.0):.0f}")
|
429 |
+
if comp_type == "walls":
|
430 |
+
cols[5].write("Yes" if comp.get("adiabatic", False) else "No")
|
431 |
+
cols[6].write("Yes" if comp.get("ground_contact", False) else "No")
|
432 |
|
433 |
# Edit button
|
434 |
edit_key = f"edit_{comp_type}_{comp['name']}_{idx}"
|
435 |
+
edit_col = 7 if comp_type == "walls" else 6
|
436 |
with cols[edit_col].container():
|
437 |
if st.button("Edit", key=edit_key):
|
438 |
editor_data = {
|
|
|
447 |
|
448 |
if comp_type == "walls":
|
449 |
editor_data["construction"] = comp.get("construction", "")
|
450 |
+
editor_data["adiabatic"] = comp.get("adiabatic", False)
|
451 |
+
editor_data["ground_contact"] = comp.get("ground_contact", False)
|
452 |
else: # windows
|
453 |
editor_data["fenestration"] = comp.get("fenestration", "")
|
454 |
editor_data["parent_component"] = comp.get("parent_component", "")
|
|
|
461 |
|
462 |
# Delete button
|
463 |
delete_key = f"delete_{comp_type}_{comp['name']}_{idx}"
|
464 |
+
delete_col = 8 if comp_type == "walls" else 7
|
465 |
with cols[delete_col].container():
|
466 |
if st.button("Delete", key=delete_key):
|
467 |
st.session_state.project_data["components"][comp_type].pop(idx)
|
|
|
537 |
def display_floor_table(comp_type: str, components: List[Dict[str, Any]]):
|
538 |
"""Display a table of floors with appropriate columns."""
|
539 |
# Create column headers
|
540 |
+
cols = st.columns([2, 1, 1, 1, 1, 1, 1])
|
541 |
cols[0].write("**Name**")
|
542 |
cols[1].write("**U-Value**")
|
543 |
cols[2].write("**Area (m²)**")
|
544 |
+
cols[3].write("**Adiabatic**")
|
545 |
+
cols[4].write("**Ground Contact**")
|
546 |
+
cols[5].write("**Edit**")
|
547 |
+
cols[6].write("**Delete**")
|
548 |
|
549 |
# Display each component
|
550 |
for idx, comp in enumerate(components):
|
551 |
+
cols = st.columns([2, 1, 1, 1, 1, 1, 1])
|
552 |
cols[0].write(comp["name"])
|
553 |
cols[1].write(f"{comp.get('u_value', 0.0):.3f}")
|
554 |
cols[2].write(f"{comp['area']:.2f}")
|
555 |
+
cols[3].write("Yes" if comp.get("adiabatic", False) else "No")
|
556 |
+
cols[4].write("Yes" if comp.get("ground_contact", False) else "No")
|
557 |
|
558 |
# Edit button
|
559 |
edit_key = f"edit_{comp_type}_{comp['name']}_{idx}"
|
560 |
+
with cols[5].container():
|
561 |
if st.button("Edit", key=edit_key):
|
562 |
editor_data = {
|
563 |
"index": idx,
|
564 |
"name": comp["name"],
|
565 |
"area": comp["area"],
|
566 |
"construction": comp.get("construction", ""),
|
567 |
+
"adiabatic": comp.get("adiabatic", False),
|
568 |
+
"ground_contact": comp.get("ground_contact", False),
|
569 |
"is_edit": True
|
570 |
}
|
571 |
|
|
|
575 |
|
576 |
# Delete button
|
577 |
delete_key = f"delete_{comp_type}_{comp['name']}_{idx}"
|
578 |
+
with cols[6].container():
|
579 |
if st.button("Delete", key=delete_key):
|
580 |
st.session_state.project_data["components"][comp_type].pop(idx)
|
581 |
st.success(f"{comp_type[:-1].capitalize()} '{comp['name']}' deleted!")
|
|
|
688 |
* **Surface Tilt**: Angle of the component relative to horizontal (0° = horizontal, 90° = vertical).
|
689 |
* **Parent Component**: The wall or roof that contains a window or skylight.
|
690 |
* **Shading Coefficient (SC)**: Factor for shading devices on windows/skylights (0.0 to 1.0).
|
691 |
+
* **Adiabatic**: Indicates if a wall or floor has no heat transfer across it (Yes/No).
|
692 |
+
* **Ground Contact**: Indicates if a wall or floor is in contact with the ground (Yes/No).
|
693 |
|
694 |
**Workflow:**
|
695 |
|
|
|
703 |
* For roofs and skylights, set surface tilt to 0° for flat surfaces.
|
704 |
* Ensure the total area of windows doesn't exceed the area of their parent walls.
|
705 |
* Ensure the total area of skylights doesn't exceed the area of their parent roofs.
|
706 |
+
* Set adiabatic to 'Yes' for components with no heat transfer, such as internal partitions.
|
707 |
+
* Set ground contact to 'Yes' for components in direct contact with the ground for accurate heat transfer calculations.
|
708 |
""")
|