Spaces:
Sleeping
Sleeping
Update app/materials_library.py
Browse files- app/materials_library.py +101 -99
app/materials_library.py
CHANGED
@@ -332,9 +332,12 @@ def calculate_u_value(thermal_conductivity: float, thickness: float) -> float:
|
|
332 |
r_total = R_SI + r_material + R_SE
|
333 |
return 1 / r_total if r_total > 0 else 0.0
|
334 |
|
335 |
-
def calculate_thermal_mass(density: float, specific_heat: float, thickness: float) ->
|
336 |
-
"""Calculate areal thermal mass for a material
|
337 |
-
|
|
|
|
|
|
|
338 |
if thermal_mass < 30000:
|
339 |
return "Low"
|
340 |
elif 30000 <= thermal_mass <= 90000:
|
@@ -411,9 +414,10 @@ def display_materials_tab():
|
|
411 |
cols = st.columns([2, 1, 1, 1, 1])
|
412 |
name = [k for k, v in library_materials.items() if v == material][0]
|
413 |
thermal_mass = calculate_thermal_mass(material["density"], material["specific_heat"], material["default_thickness"])
|
|
|
414 |
u_value = calculate_u_value(material["thermal_conductivity"], material["default_thickness"])
|
415 |
cols[0].write(name)
|
416 |
-
cols[1].write(
|
417 |
cols[2].write(f"{u_value:.3f}")
|
418 |
if cols[3].button("Preview", key=f"preview_lib_mat_{name}"):
|
419 |
st.session_state.material_editor = {
|
@@ -434,7 +438,6 @@ def display_materials_tab():
|
|
434 |
}
|
435 |
st.session_state.active_tab = "Materials"
|
436 |
st.success(f"Previewing material '{name}'")
|
437 |
-
logger.info(f"Previewed library material '{name}'")
|
438 |
if cols[4].button("Copy", key=f"copy_lib_mat_{name}"):
|
439 |
new_name = f"{name}_Project"
|
440 |
counter = 1
|
@@ -471,9 +474,10 @@ def display_materials_tab():
|
|
471 |
cols = st.columns([2, 1, 1, 1, 1])
|
472 |
name = [k for k, v in project_materials.items() if v == material][0]
|
473 |
thermal_mass = calculate_thermal_mass(material["density"], material["specific_heat"], material["default_thickness"])
|
|
|
474 |
u_value = calculate_u_value(material["thermal_conductivity"], material["default_thickness"])
|
475 |
cols[0].write(name)
|
476 |
-
cols[1].write(
|
477 |
cols[2].write(f"{u_value:.3f}")
|
478 |
if cols[3].button("Edit", key=f"edit_proj_mat_{name}"):
|
479 |
st.session_state.material_editor = {
|
@@ -494,7 +498,6 @@ def display_materials_tab():
|
|
494 |
}
|
495 |
st.session_state.active_tab = "Materials"
|
496 |
st.success(f"Editing material '{name}'")
|
497 |
-
logger.info(f"Editing project material '{name}'")
|
498 |
if cols[4].button("Delete", key=f"delete_proj_mat_{name}"):
|
499 |
is_in_use = check_material_in_use(name)
|
500 |
if is_in_use:
|
@@ -514,6 +517,7 @@ def display_materials_tab():
|
|
514 |
data = []
|
515 |
for name, props in project_materials.items():
|
516 |
thermal_mass = calculate_thermal_mass(props["density"], props["specific_heat"], props["default_thickness"])
|
|
|
517 |
u_value = calculate_u_value(props["thermal_conductivity"], props["default_thickness"])
|
518 |
data.append({
|
519 |
"Name": name,
|
@@ -527,7 +531,7 @@ def display_materials_tab():
|
|
527 |
"Absorptivity": props["absorptivity"],
|
528 |
"Emissivity": props["emissivity"],
|
529 |
"Colour": props["colour"],
|
530 |
-
"Thermal Mass":
|
531 |
"U-Value (W/m²·K)": u_value
|
532 |
})
|
533 |
df = pd.DataFrame(data)
|
@@ -593,7 +597,6 @@ def display_fenestrations_tab():
|
|
593 |
}
|
594 |
st.session_state.active_tab = "Fenestrations"
|
595 |
st.success(f"Previewing fenestration '{name}'")
|
596 |
-
logger.info(f"Previewed library fenestration '{name}'")
|
597 |
if cols[4].button("Copy", key=f"copy_lib_fen_{name}"):
|
598 |
new_name = f"{name}_Project"
|
599 |
counter = 1
|
@@ -648,7 +651,6 @@ def display_fenestrations_tab():
|
|
648 |
}
|
649 |
st.session_state.active_tab = "Fenestrations"
|
650 |
st.success(f"Editing fenestration '{name}'")
|
651 |
-
logger.info(f"Editing project fenestration '{name}'")
|
652 |
if cols[4].button("Delete", key=f"delete_proj_fen_{name}"):
|
653 |
is_in_use = check_fenestration_in_use(name)
|
654 |
if is_in_use:
|
@@ -893,55 +895,55 @@ def display_material_editor():
|
|
893 |
with col2:
|
894 |
clear_button = st.form_submit_button("Clear Form")
|
895 |
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
if validation_errors:
|
907 |
-
for error in validation_errors:
|
908 |
-
st.error(error)
|
909 |
-
else:
|
910 |
-
# Create material data
|
911 |
-
material_data = {
|
912 |
-
"category": category,
|
913 |
-
"thermal_conductivity": thermal_conductivity,
|
914 |
-
"density": density,
|
915 |
-
"specific_heat": specific_heat,
|
916 |
-
"default_thickness": default_thickness,
|
917 |
-
"embodied_carbon": embodied_carbon,
|
918 |
-
"cost": cost,
|
919 |
-
"absorptivity": absorptivity,
|
920 |
-
"emissivity": emissivity,
|
921 |
-
"colour": colour
|
922 |
-
}
|
923 |
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
if original_name != name:
|
928 |
-
del st.session_state.project_data["materials"]["project"][original_name]
|
929 |
-
st.session_state.project_data["materials"]["project"][name] = material_data
|
930 |
-
st.success(f"Material '{name}' updated successfully.")
|
931 |
-
logger.info(f"Updated material '{name}' in project")
|
932 |
else:
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
938 |
reset_material_editor()
|
939 |
st.rerun()
|
940 |
-
|
941 |
-
# Handle clear button
|
942 |
-
if clear_button:
|
943 |
-
reset_material_editor()
|
944 |
-
st.rerun()
|
945 |
|
946 |
def display_fenestration_editor():
|
947 |
"""Display the fenestration editor form."""
|
@@ -1052,50 +1054,50 @@ def display_fenestration_editor():
|
|
1052 |
with col2:
|
1053 |
clear_button = st.form_submit_button("Clear Form")
|
1054 |
|
1055 |
-
|
1056 |
-
|
1057 |
-
|
1058 |
-
|
1059 |
-
|
1060 |
-
|
1061 |
-
|
1062 |
-
|
1063 |
-
if validation_errors:
|
1064 |
-
for error in validation_errors:
|
1065 |
-
st.error(error)
|
1066 |
-
else:
|
1067 |
-
# Create fenestration data
|
1068 |
-
fenestration_data = {
|
1069 |
-
"type": fenestration_type,
|
1070 |
-
"u_value": u_value,
|
1071 |
-
"shgc": shgc,
|
1072 |
-
"visible_transmittance": visible_transmittance,
|
1073 |
-
"thickness": thickness,
|
1074 |
-
"embodied_carbon": embodied_carbon,
|
1075 |
-
"cost": cost
|
1076 |
-
}
|
1077 |
|
1078 |
-
|
1079 |
-
|
1080 |
-
|
1081 |
-
if original_name != name:
|
1082 |
-
del st.session_state.project_data["fenestrations"]["project"][original_name]
|
1083 |
-
st.session_state.project_data["fenestrations"]["project"][name] = fenestration_data
|
1084 |
-
st.success(f"Fenestration '{name}' updated successfully.")
|
1085 |
-
logger.info(f"Updated fenestration '{name}' in project")
|
1086 |
else:
|
1087 |
-
|
1088 |
-
|
1089 |
-
|
1090 |
-
|
1091 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1092 |
reset_fenestration_editor()
|
1093 |
st.rerun()
|
1094 |
-
|
1095 |
-
# Handle clear button
|
1096 |
-
if clear_button:
|
1097 |
-
reset_fenestration_editor()
|
1098 |
-
st.rerun()
|
1099 |
|
1100 |
def validate_material(
|
1101 |
name: str, category: str, thermal_conductivity: float, density: float,
|
@@ -1114,8 +1116,8 @@ def validate_material(
|
|
1114 |
|
1115 |
# Check for name uniqueness
|
1116 |
if not edit_mode or (edit_mode and name != original_name):
|
1117 |
-
if name in st.session_state.project_data["materials"]["project"]
|
1118 |
-
errors.append(f"Material name '{name}' already exists in your project
|
1119 |
|
1120 |
# Validate category
|
1121 |
if category not in MATERIAL_CATEGORIES:
|
@@ -1186,8 +1188,8 @@ def validate_fenestration(
|
|
1186 |
|
1187 |
# Check for name uniqueness
|
1188 |
if not edit_mode or (edit_mode and name != original_name):
|
1189 |
-
if name in st.session_state.project_data["fenestrations"]["project"]
|
1190 |
-
errors.append(f"Fenestration name '{name}' already exists in your project
|
1191 |
|
1192 |
# Validate type
|
1193 |
if fenestration_type not in FENESTRATION_TYPES:
|
|
|
332 |
r_total = R_SI + r_material + R_SE
|
333 |
return 1 / r_total if r_total > 0 else 0.0
|
334 |
|
335 |
+
def calculate_thermal_mass(density: float, specific_heat: float, thickness: float) -> float:
|
336 |
+
"""Calculate areal thermal mass for a material."""
|
337 |
+
return density * specific_heat * thickness
|
338 |
+
|
339 |
+
def categorize_thermal_mass(thermal_mass: float) -> str:
|
340 |
+
"""Categorize thermal mass based on given ranges."""
|
341 |
if thermal_mass < 30000:
|
342 |
return "Low"
|
343 |
elif 30000 <= thermal_mass <= 90000:
|
|
|
414 |
cols = st.columns([2, 1, 1, 1, 1])
|
415 |
name = [k for k, v in library_materials.items() if v == material][0]
|
416 |
thermal_mass = calculate_thermal_mass(material["density"], material["specific_heat"], material["default_thickness"])
|
417 |
+
thermal_mass_category = categorize_thermal_mass(thermal_mass)
|
418 |
u_value = calculate_u_value(material["thermal_conductivity"], material["default_thickness"])
|
419 |
cols[0].write(name)
|
420 |
+
cols[1].write(thermal_mass_category)
|
421 |
cols[2].write(f"{u_value:.3f}")
|
422 |
if cols[3].button("Preview", key=f"preview_lib_mat_{name}"):
|
423 |
st.session_state.material_editor = {
|
|
|
438 |
}
|
439 |
st.session_state.active_tab = "Materials"
|
440 |
st.success(f"Previewing material '{name}'")
|
|
|
441 |
if cols[4].button("Copy", key=f"copy_lib_mat_{name}"):
|
442 |
new_name = f"{name}_Project"
|
443 |
counter = 1
|
|
|
474 |
cols = st.columns([2, 1, 1, 1, 1])
|
475 |
name = [k for k, v in project_materials.items() if v == material][0]
|
476 |
thermal_mass = calculate_thermal_mass(material["density"], material["specific_heat"], material["default_thickness"])
|
477 |
+
thermal_mass_category = categorize_thermal_mass(thermal_mass)
|
478 |
u_value = calculate_u_value(material["thermal_conductivity"], material["default_thickness"])
|
479 |
cols[0].write(name)
|
480 |
+
cols[1].write(thermal_mass_category)
|
481 |
cols[2].write(f"{u_value:.3f}")
|
482 |
if cols[3].button("Edit", key=f"edit_proj_mat_{name}"):
|
483 |
st.session_state.material_editor = {
|
|
|
498 |
}
|
499 |
st.session_state.active_tab = "Materials"
|
500 |
st.success(f"Editing material '{name}'")
|
|
|
501 |
if cols[4].button("Delete", key=f"delete_proj_mat_{name}"):
|
502 |
is_in_use = check_material_in_use(name)
|
503 |
if is_in_use:
|
|
|
517 |
data = []
|
518 |
for name, props in project_materials.items():
|
519 |
thermal_mass = calculate_thermal_mass(props["density"], props["specific_heat"], props["default_thickness"])
|
520 |
+
thermal_mass_category = categorize_thermal_mass(thermal_mass)
|
521 |
u_value = calculate_u_value(props["thermal_conductivity"], props["default_thickness"])
|
522 |
data.append({
|
523 |
"Name": name,
|
|
|
531 |
"Absorptivity": props["absorptivity"],
|
532 |
"Emissivity": props["emissivity"],
|
533 |
"Colour": props["colour"],
|
534 |
+
"Thermal Mass": thermal_mass_category,
|
535 |
"U-Value (W/m²·K)": u_value
|
536 |
})
|
537 |
df = pd.DataFrame(data)
|
|
|
597 |
}
|
598 |
st.session_state.active_tab = "Fenestrations"
|
599 |
st.success(f"Previewing fenestration '{name}'")
|
|
|
600 |
if cols[4].button("Copy", key=f"copy_lib_fen_{name}"):
|
601 |
new_name = f"{name}_Project"
|
602 |
counter = 1
|
|
|
651 |
}
|
652 |
st.session_state.active_tab = "Fenestrations"
|
653 |
st.success(f"Editing fenestration '{name}'")
|
|
|
654 |
if cols[4].button("Delete", key=f"delete_proj_fen_{name}"):
|
655 |
is_in_use = check_fenestration_in_use(name)
|
656 |
if is_in_use:
|
|
|
895 |
with col2:
|
896 |
clear_button = st.form_submit_button("Clear Form")
|
897 |
|
898 |
+
# Handle form submission
|
899 |
+
if submit_button and not is_library:
|
900 |
+
# Validate inputs
|
901 |
+
validation_errors = validate_material(
|
902 |
+
name, category, thermal_conductivity, density, specific_heat,
|
903 |
+
default_thickness, embodied_carbon, cost,
|
904 |
+
editor_state["edit_mode"], editor_state["original_name"],
|
905 |
+
absorptivity, emissivity, colour
|
906 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
907 |
|
908 |
+
if validation_errors:
|
909 |
+
for error in validation_errors:
|
910 |
+
st.error(error)
|
|
|
|
|
|
|
|
|
|
|
911 |
else:
|
912 |
+
# Create material data
|
913 |
+
material_data = {
|
914 |
+
"category": category,
|
915 |
+
"thermal_conductivity": thermal_conductivity,
|
916 |
+
"density": density,
|
917 |
+
"specific_heat": specific_heat,
|
918 |
+
"default_thickness": default_thickness,
|
919 |
+
"embodied_carbon": embodied_carbon,
|
920 |
+
"cost": cost,
|
921 |
+
"absorptivity": absorptivity,
|
922 |
+
"emissivity": emissivity,
|
923 |
+
"colour": colour
|
924 |
+
}
|
925 |
+
|
926 |
+
# Handle edit mode
|
927 |
+
if editor_state["edit_mode"]:
|
928 |
+
original_name = editor_state["original_name"]
|
929 |
+
if original_name != name:
|
930 |
+
del st.session_state.project_data["materials"]["project"][original_name]
|
931 |
+
st.session_state.project_data["materials"]["project"][name] = material_data
|
932 |
+
st.success(f"Material '{name}' updated successfully.")
|
933 |
+
logger.info(f"Updated material '{name}' in project")
|
934 |
+
else:
|
935 |
+
st.session_state.project_data["materials"]["project"][name] = material_data
|
936 |
+
st.success(f"Material '{name}' added to your project.")
|
937 |
+
logger.info(f"Added new material '{name}' to project")
|
938 |
+
|
939 |
+
# Reset editor
|
940 |
+
reset_material_editor()
|
941 |
+
st.rerun()
|
942 |
+
|
943 |
+
# Handle clear button
|
944 |
+
if clear_button:
|
945 |
reset_material_editor()
|
946 |
st.rerun()
|
|
|
|
|
|
|
|
|
|
|
947 |
|
948 |
def display_fenestration_editor():
|
949 |
"""Display the fenestration editor form."""
|
|
|
1054 |
with col2:
|
1055 |
clear_button = st.form_submit_button("Clear Form")
|
1056 |
|
1057 |
+
# Handle form submission
|
1058 |
+
if submit_button and not is_library:
|
1059 |
+
# Validate inputs
|
1060 |
+
validation_errors = validate_fenestration(
|
1061 |
+
name, fenestration_type, u_value, shgc, visible_transmittance, thickness,
|
1062 |
+
embodied_carbon, cost, editor_state["edit_mode"], editor_state["original_name"]
|
1063 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1064 |
|
1065 |
+
if validation_errors:
|
1066 |
+
for error in validation_errors:
|
1067 |
+
st.error(error)
|
|
|
|
|
|
|
|
|
|
|
1068 |
else:
|
1069 |
+
# Create fenestration data
|
1070 |
+
fenestration_data = {
|
1071 |
+
"type": fenestration_type,
|
1072 |
+
"u_value": u_value,
|
1073 |
+
"shgc": shgc,
|
1074 |
+
"visible_transmittance": visible_transmittance,
|
1075 |
+
"thickness": thickness,
|
1076 |
+
"embodied_carbon": embodied_carbon,
|
1077 |
+
"cost": cost
|
1078 |
+
}
|
1079 |
+
|
1080 |
+
# Handle edit mode
|
1081 |
+
if editor_state["edit_mode"]:
|
1082 |
+
original_name = editor_state["original_name"]
|
1083 |
+
if original_name != name:
|
1084 |
+
del st.session_state.project_data["fenestrations"]["project"][original_name]
|
1085 |
+
st.session_state.project_data["fenestrations"]["project"][name] = fenestration_data
|
1086 |
+
st.success(f"Fenestration '{name}' updated successfully.")
|
1087 |
+
logger.info(f"Updated fenestration '{name}' in project")
|
1088 |
+
else:
|
1089 |
+
st.session_state.project_data["fenestrations"]["project"][name] = fenestration_data
|
1090 |
+
st.success(f"Fenestration '{name}' added to your project.")
|
1091 |
+
logger.info(f"Added new fenestration '{name}' to project")
|
1092 |
+
|
1093 |
+
# Reset editor
|
1094 |
+
reset_fenestration_editor()
|
1095 |
+
st.rerun()
|
1096 |
+
|
1097 |
+
# Handle clear button
|
1098 |
+
if clear_button:
|
1099 |
reset_fenestration_editor()
|
1100 |
st.rerun()
|
|
|
|
|
|
|
|
|
|
|
1101 |
|
1102 |
def validate_material(
|
1103 |
name: str, category: str, thermal_conductivity: float, density: float,
|
|
|
1116 |
|
1117 |
# Check for name uniqueness
|
1118 |
if not edit_mode or (edit_mode and name != original_name):
|
1119 |
+
if name in st.session_state.project_data["materials"]["project"]:
|
1120 |
+
errors.append(f"Material name '{name}' already exists in your project.")
|
1121 |
|
1122 |
# Validate category
|
1123 |
if category not in MATERIAL_CATEGORIES:
|
|
|
1188 |
|
1189 |
# Check for name uniqueness
|
1190 |
if not edit_mode or (edit_mode and name != original_name):
|
1191 |
+
if name in st.session_state.project_data["fenestrations"]["project"]:
|
1192 |
+
errors.append(f"Fenestration name '{name}' already exists in your project.")
|
1193 |
|
1194 |
# Validate type
|
1195 |
if fenestration_type not in FENESTRATION_TYPES:
|