mabuseif commited on
Commit
31bc5f6
·
verified ·
1 Parent(s): 7c84f0f

Update app/internal_loads.py

Browse files
Files changed (1) hide show
  1. app/internal_loads.py +92 -93
app/internal_loads.py CHANGED
@@ -222,15 +222,10 @@ def display_internal_loads_page():
222
  with st.expander("Help & Information"):
223
  display_internal_loads_help()
224
 
225
- # Initialize internal loads in session state if not present
226
- initialize_internal_loads()
227
-
228
  # Check if rerun is pending
229
- if 'internal_loads_rerun_pending' not in st.session_state:
230
- st.session_state.internal_loads_rerun_pending = False
231
-
232
- if st.session_state.internal_loads_rerun_pending:
233
- st.session_state.internal_loads_rerun_pending = False
234
  st.rerun()
235
 
236
  # Create tabs for different load types
@@ -263,8 +258,13 @@ def display_internal_loads_page():
263
  st.rerun()
264
 
265
  def initialize_internal_loads():
266
- """Initialize internal loads in session state if not present."""
 
 
 
 
267
  if "internal_loads" not in st.session_state.project_data:
 
268
  st.session_state.project_data["internal_loads"] = {
269
  "people": [],
270
  "lighting": [],
@@ -419,13 +419,15 @@ def display_people_tab():
419
 
420
  # Clear editor state
421
  st.session_state.people_editor = {}
422
- st.session_state.internal_loads_rerun_pending = True
 
423
  st.rerun()
424
 
425
  if cancel:
426
  # Clear editor state
427
  st.session_state.people_editor = {}
428
- st.session_state.internal_loads_rerun_pending = True
 
429
  st.rerun()
430
 
431
  def display_lighting_tab():
@@ -468,11 +470,12 @@ def display_lighting_tab():
468
  )
469
 
470
  # Area
 
471
  area = st.number_input(
472
  "Area (m²)",
473
  min_value=1.0,
474
  max_value=100000.0,
475
- value=float(editor_state.get("area", st.session_state.building_info.get("floor_area", 100.0))),
476
  format="%.2f",
477
  help="Floor area served by this lighting system."
478
  )
@@ -580,13 +583,15 @@ def display_lighting_tab():
580
 
581
  # Clear editor state
582
  st.session_state.lighting_editor = {}
583
- st.session_state.internal_loads_rerun_pending = True
 
584
  st.rerun()
585
 
586
  if cancel:
587
  # Clear editor state
588
  st.session_state.lighting_editor = {}
589
- st.session_state.internal_loads_rerun_pending = True
 
590
  st.rerun()
591
 
592
  def display_equipment_tab():
@@ -629,11 +634,12 @@ def display_equipment_tab():
629
  )
630
 
631
  # Area
 
632
  area = st.number_input(
633
  "Area (m²)",
634
  min_value=1.0,
635
  max_value=100000.0,
636
- value=float(editor_state.get("area", st.session_state.building_info.get("floor_area", 100.0))),
637
  format="%.2f",
638
  help="Floor area served by this equipment."
639
  )
@@ -757,13 +763,15 @@ def display_equipment_tab():
757
 
758
  # Clear editor state
759
  st.session_state.equipment_editor = {}
760
- st.session_state.internal_loads_rerun_pending = True
 
761
  st.rerun()
762
 
763
  if cancel:
764
  # Clear editor state
765
  st.session_state.equipment_editor = {}
766
- st.session_state.internal_loads_rerun_pending = True
 
767
  st.rerun()
768
 
769
  def display_ventilation_infiltration_tab():
@@ -814,11 +822,12 @@ def display_ventilation_infiltration_tab():
814
  )
815
 
816
  # Area
 
817
  area = st.number_input(
818
  "Area (m²)",
819
  min_value=1.0,
820
  max_value=100000.0,
821
- value=float(editor_state.get("area", st.session_state.building_info.get("floor_area", 100.0))),
822
  format="%.2f",
823
  help="Floor area served by this system."
824
  )
@@ -910,13 +919,15 @@ def display_ventilation_infiltration_tab():
910
 
911
  # Clear editor state
912
  st.session_state.vent_inf_editor = {}
913
- st.session_state.internal_loads_rerun_pending = True
 
914
  st.rerun()
915
 
916
  if cancel:
917
  # Clear editor state
918
  st.session_state.vent_inf_editor = {}
919
- st.session_state.internal_loads_rerun_pending = True
 
920
  st.rerun()
921
 
922
  def display_schedules_tab():
@@ -1062,15 +1073,43 @@ def display_schedules_tab():
1062
 
1063
  # Clear editor state
1064
  st.session_state.schedule_editor = {}
1065
- st.session_state.internal_loads_rerun_pending = True
 
1066
  st.rerun()
1067
 
1068
  if cancel:
1069
  # Clear editor state
1070
  st.session_state.schedule_editor = {}
1071
- st.session_state.internal_loads_rerun_pending = True
 
1072
  st.rerun()
1073
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1074
  def display_people_table(people_groups: List[Dict[str, Any]]):
1075
  """Display people groups in a table format with edit/delete buttons."""
1076
  if not people_groups:
@@ -1123,7 +1162,8 @@ def display_people_table(people_groups: List[Dict[str, Any]]):
1123
  "schedule": group.get("schedule", "Continuous"),
1124
  "zone": group.get("zone", "Whole Building")
1125
  }
1126
- st.session_state.internal_loads_rerun_pending = True
 
1127
  st.rerun()
1128
 
1129
  with col3:
@@ -1133,7 +1173,8 @@ def display_people_table(people_groups: List[Dict[str, Any]]):
1133
  g for g in people_groups if g.get("id") != group_id
1134
  ]
1135
  st.success(f"People group '{group_name}' deleted!")
1136
- st.session_state.internal_loads_rerun_pending = True
 
1137
  st.rerun()
1138
 
1139
  def display_lighting_table(lighting_systems: List[Dict[str, Any]]):
@@ -1187,7 +1228,8 @@ def display_lighting_table(lighting_systems: List[Dict[str, Any]]):
1187
  "schedule": system.get("schedule", "Continuous"),
1188
  "zone": system.get("zone", "Whole Building")
1189
  }
1190
- st.session_state.internal_loads_rerun_pending = True
 
1191
  st.rerun()
1192
 
1193
  with col3:
@@ -1197,7 +1239,8 @@ def display_lighting_table(lighting_systems: List[Dict[str, Any]]):
1197
  s for s in lighting_systems if s.get("id") != system_id
1198
  ]
1199
  st.success(f"Lighting system '{system_name}' deleted!")
1200
- st.session_state.internal_loads_rerun_pending = True
 
1201
  st.rerun()
1202
 
1203
  def display_equipment_table(equipment_systems: List[Dict[str, Any]]):
@@ -1252,7 +1295,8 @@ def display_equipment_table(equipment_systems: List[Dict[str, Any]]):
1252
  "schedule": system.get("schedule", "Continuous"),
1253
  "zone": system.get("zone", "Whole Building")
1254
  }
1255
- st.session_state.internal_loads_rerun_pending = True
 
1256
  st.rerun()
1257
 
1258
  with col3:
@@ -1262,7 +1306,8 @@ def display_equipment_table(equipment_systems: List[Dict[str, Any]]):
1262
  s for s in equipment_systems if s.get("id") != system_id
1263
  ]
1264
  st.success(f"Equipment '{system_name}' deleted!")
1265
- st.session_state.internal_loads_rerun_pending = True
 
1266
  st.rerun()
1267
 
1268
  def display_ventilation_infiltration_table(vent_inf_systems: List[Dict[str, Any]]):
@@ -1321,7 +1366,8 @@ def display_ventilation_infiltration_table(vent_inf_systems: List[Dict[str, Any]
1321
  "schedule": system.get("schedule", "Continuous"),
1322
  "zone": system.get("zone", "Whole Building")
1323
  }
1324
- st.session_state.internal_loads_rerun_pending = True
 
1325
  st.rerun()
1326
 
1327
  with col3:
@@ -1331,7 +1377,8 @@ def display_ventilation_infiltration_table(vent_inf_systems: List[Dict[str, Any]
1331
  s for s in vent_inf_systems if s.get("id") != system_id
1332
  ]
1333
  st.success(f"{system.get('system_type', 'System')} '{system_name}' deleted!")
1334
- st.session_state.internal_loads_rerun_pending = True
 
1335
  st.rerun()
1336
 
1337
  def display_schedules_table(schedules: Dict[str, Any]):
@@ -1387,18 +1434,23 @@ def display_schedules_table(schedules: Dict[str, Any]):
1387
  "weekday": schedule_data.get("weekday", [0.0] * 24),
1388
  "weekend": schedule_data.get("weekend", [0.0] * 24)
1389
  }
1390
- st.session_state.internal_loads_rerun_pending = True
 
1391
  st.rerun()
1392
 
1393
  with col4:
1394
- # Don't allow deletion of default templates
1395
  if schedule_name not in DEFAULT_SCHEDULE_TEMPLATES:
1396
- if st.button("Delete", key=f"delete_schedule_{schedule_name}_{i}"):
1397
- # Delete schedule
1398
- del schedules[schedule_name]
1399
- st.success(f"Schedule '{schedule_name}' deleted!")
1400
- st.session_state.internal_loads_rerun_pending = True
1401
- st.rerun()
 
 
 
 
1402
  else:
1403
  st.write("(Default)")
1404
 
@@ -1451,7 +1503,7 @@ def display_internal_loads_help():
1451
  - Schedules control when people are present
1452
 
1453
  #### Lighting
1454
- - Define lighting systems with power densities
1455
  - Heat distribution between radiative and convective components
1456
  - Schedules control lighting operation
1457
 
@@ -1478,57 +1530,4 @@ def display_internal_loads_help():
1478
  4. Validate total loads against design expectations
1479
  """)
1480
 
1481
- # Helper functions for backward compatibility
1482
- def get_internal_loads_summary():
1483
- """Get a summary of all internal loads for use in other modules."""
1484
- summary = {
1485
- "people": {
1486
- "total_sensible": 0.0,
1487
- "total_latent": 0.0,
1488
- "count": 0
1489
- },
1490
- "lighting": {
1491
- "total_power": 0.0,
1492
- "count": 0
1493
- },
1494
- "equipment": {
1495
- "total_sensible": 0.0,
1496
- "total_latent": 0.0,
1497
- "count": 0
1498
- },
1499
- "ventilation_infiltration": {
1500
- "total_ventilation": 0.0,
1501
- "total_infiltration": 0.0,
1502
- "count": 0
1503
- }
1504
- }
1505
-
1506
- if "internal_loads" in st.session_state.project_data:
1507
- internal_loads = st.session_state.project_data["internal_loads"]
1508
-
1509
- # People summary
1510
- for group in internal_loads.get("people", []):
1511
- summary["people"]["total_sensible"] += group.get("total_sensible_heat", 0.0)
1512
- summary["people"]["total_latent"] += group.get("total_latent_heat", 0.0)
1513
- summary["people"]["count"] += 1
1514
-
1515
- # Lighting summary
1516
- for system in internal_loads.get("lighting", []):
1517
- summary["lighting"]["total_power"] += system.get("total_power", 0.0)
1518
- summary["lighting"]["count"] += 1
1519
-
1520
- # Equipment summary
1521
- for system in internal_loads.get("equipment", []):
1522
- summary["equipment"]["total_sensible"] += system.get("total_sensible_power", 0.0)
1523
- summary["equipment"]["total_latent"] += system.get("total_latent_power", 0.0)
1524
- summary["equipment"]["count"] += 1
1525
-
1526
- # Ventilation/Infiltration summary
1527
- for system in internal_loads.get("ventilation_infiltration", []):
1528
- if system.get("system_type") == "Ventilation":
1529
- summary["ventilation_infiltration"]["total_ventilation"] += system.get("ventilation_rate", 0.0) * system.get("area", 0.0)
1530
- else:
1531
- summary["ventilation_infiltration"]["total_infiltration"] += system.get("air_change_rate", 0.0)
1532
- summary["ventilation_infiltration"]["count"] += 1
1533
-
1534
- return summary
 
222
  with st.expander("Help & Information"):
223
  display_internal_loads_help()
224
 
 
 
 
225
  # Check if rerun is pending
226
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
227
+ if st.session_state.module_rerun_flags.get("internal_loads", False):
228
+ st.session_state.module_rerun_flags["internal_loads"] = False
 
 
229
  st.rerun()
230
 
231
  # Create tabs for different load types
 
258
  st.rerun()
259
 
260
  def initialize_internal_loads():
261
+ """
262
+ Initialize internal loads in session state if not present.
263
+ [FIX]: Removed redundant initialization as main.py handles this.
264
+ Logging a warning if initialization is needed for debugging.
265
+ """
266
  if "internal_loads" not in st.session_state.project_data:
267
+ logger.warning("Internal loads not initialized by main.py, using fallback initialization")
268
  st.session_state.project_data["internal_loads"] = {
269
  "people": [],
270
  "lighting": [],
 
419
 
420
  # Clear editor state
421
  st.session_state.people_editor = {}
422
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
423
+ st.session_state.module_rerun_flags["internal_loads"] = True
424
  st.rerun()
425
 
426
  if cancel:
427
  # Clear editor state
428
  st.session_state.people_editor = {}
429
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
430
+ st.session_state.module_rerun_flags["internal_loads"] = True
431
  st.rerun()
432
 
433
  def display_lighting_tab():
 
470
  )
471
 
472
  # Area
473
+ # [FIX]: Corrected session state reference from st.session_state.building_info to st.session_state.project_data["building_info"]
474
  area = st.number_input(
475
  "Area (m²)",
476
  min_value=1.0,
477
  max_value=100000.0,
478
+ value=float(editor_state.get("area", st.session_state.project_data["building_info"].get("floor_area", 100.0))),
479
  format="%.2f",
480
  help="Floor area served by this lighting system."
481
  )
 
583
 
584
  # Clear editor state
585
  st.session_state.lighting_editor = {}
586
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
587
+ st.session_state.module_rerun_flags["internal_loads"] = True
588
  st.rerun()
589
 
590
  if cancel:
591
  # Clear editor state
592
  st.session_state.lighting_editor = {}
593
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
594
+ st.session_state.module_rerun_flags["internal_loads"] = True
595
  st.rerun()
596
 
597
  def display_equipment_tab():
 
634
  )
635
 
636
  # Area
637
+ # [FIX]: Corrected session state reference from st.session_state.building_info to st.session_state.project_data["building_info"]
638
  area = st.number_input(
639
  "Area (m²)",
640
  min_value=1.0,
641
  max_value=100000.0,
642
+ value=float(editor_state.get("area", st.session_state.project_data["building_info"].get("floor_area", 100.0))),
643
  format="%.2f",
644
  help="Floor area served by this equipment."
645
  )
 
763
 
764
  # Clear editor state
765
  st.session_state.equipment_editor = {}
766
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
767
+ st.session_state.module_rerun_flags["internal_loads"] = True
768
  st.rerun()
769
 
770
  if cancel:
771
  # Clear editor state
772
  st.session_state.equipment_editor = {}
773
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
774
+ st.session_state.module_rerun_flags["internal_loads"] = True
775
  st.rerun()
776
 
777
  def display_ventilation_infiltration_tab():
 
822
  )
823
 
824
  # Area
825
+ # [FIX]: Corrected session state reference from st.session_state.building_info to st.session_state.project_data["building_info"]
826
  area = st.number_input(
827
  "Area (m²)",
828
  min_value=1.0,
829
  max_value=100000.0,
830
+ value=float(editor_state.get("area", st.session_state.project_data["building_info"].get("floor_area", 100.0))),
831
  format="%.2f",
832
  help="Floor area served by this system."
833
  )
 
919
 
920
  # Clear editor state
921
  st.session_state.vent_inf_editor = {}
922
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
923
+ st.session_state.module_rerun_flags["internal_loads"] = True
924
  st.rerun()
925
 
926
  if cancel:
927
  # Clear editor state
928
  st.session_state.vent_inf_editor = {}
929
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
930
+ st.session_state.module_rerun_flags["internal_loads"] = True
931
  st.rerun()
932
 
933
  def display_schedules_tab():
 
1073
 
1074
  # Clear editor state
1075
  st.session_state.schedule_editor = {}
1076
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
1077
+ st.session_state.module_rerun_flags["internal_loads"] = True
1078
  st.rerun()
1079
 
1080
  if cancel:
1081
  # Clear editor state
1082
  st.session_state.schedule_editor = {}
1083
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
1084
+ st.session_state.module_rerun_flags["internal_loads"] = True
1085
  st.rerun()
1086
 
1087
+ def is_schedule_in_use(schedule_name: str) -> bool:
1088
+ """
1089
+ Check if a schedule is in use by any people, lighting, equipment, or ventilation/infiltration systems.
1090
+ [FIX]: Added to prevent deletion of schedules that are referenced elsewhere.
1091
+
1092
+ Args:
1093
+ schedule_name: Name of the schedule to check.
1094
+
1095
+ Returns:
1096
+ bool: True if the schedule is in use, False otherwise.
1097
+ """
1098
+ internal_loads = st.session_state.project_data["internal_loads"]
1099
+ for group in internal_loads.get("people", []):
1100
+ if group.get("schedule") == schedule_name:
1101
+ return True
1102
+ for system in internal_loads.get("lighting", []):
1103
+ if system.get("schedule") == schedule_name:
1104
+ return True
1105
+ for system in internal_loads.get("equipment", []):
1106
+ if system.get("schedule") == schedule_name:
1107
+ return True
1108
+ for system in internal_loads.get("ventilation_infiltration", []):
1109
+ if system.get("schedule") == schedule_name:
1110
+ return True
1111
+ return False
1112
+
1113
  def display_people_table(people_groups: List[Dict[str, Any]]):
1114
  """Display people groups in a table format with edit/delete buttons."""
1115
  if not people_groups:
 
1162
  "schedule": group.get("schedule", "Continuous"),
1163
  "zone": group.get("zone", "Whole Building")
1164
  }
1165
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
1166
+ st.session_state.module_rerun_flags["internal_loads"] = True
1167
  st.rerun()
1168
 
1169
  with col3:
 
1173
  g for g in people_groups if g.get("id") != group_id
1174
  ]
1175
  st.success(f"People group '{group_name}' deleted!")
1176
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
1177
+ st.session_state.module_rerun_flags["internal_loads"] = True
1178
  st.rerun()
1179
 
1180
  def display_lighting_table(lighting_systems: List[Dict[str, Any]]):
 
1228
  "schedule": system.get("schedule", "Continuous"),
1229
  "zone": system.get("zone", "Whole Building")
1230
  }
1231
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
1232
+ st.session_state.module_rerun_flags["internal_loads"] = True
1233
  st.rerun()
1234
 
1235
  with col3:
 
1239
  s for s in lighting_systems if s.get("id") != system_id
1240
  ]
1241
  st.success(f"Lighting system '{system_name}' deleted!")
1242
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
1243
+ st.session_state.module_rerun_flags["internal_loads"] = True
1244
  st.rerun()
1245
 
1246
  def display_equipment_table(equipment_systems: List[Dict[str, Any]]):
 
1295
  "schedule": system.get("schedule", "Continuous"),
1296
  "zone": system.get("zone", "Whole Building")
1297
  }
1298
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
1299
+ st.session_state.module_rerun_flags["internal_loads"] = True
1300
  st.rerun()
1301
 
1302
  with col3:
 
1306
  s for s in equipment_systems if s.get("id") != system_id
1307
  ]
1308
  st.success(f"Equipment '{system_name}' deleted!")
1309
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
1310
+ st.session_state.module_rerun_flags["internal_loads"] = True
1311
  st.rerun()
1312
 
1313
  def display_ventilation_infiltration_table(vent_inf_systems: List[Dict[str, Any]]):
 
1366
  "schedule": system.get("schedule", "Continuous"),
1367
  "zone": system.get("zone", "Whole Building")
1368
  }
1369
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
1370
+ st.session_state.module_rerun_flags["internal_loads"] = True
1371
  st.rerun()
1372
 
1373
  with col3:
 
1377
  s for s in vent_inf_systems if s.get("id") != system_id
1378
  ]
1379
  st.success(f"{system.get('system_type', 'System')} '{system_name}' deleted!")
1380
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
1381
+ st.session_state.module_rerun_flags["internal_loads"] = True
1382
  st.rerun()
1383
 
1384
  def display_schedules_table(schedules: Dict[str, Any]):
 
1434
  "weekday": schedule_data.get("weekday", [0.0] * 24),
1435
  "weekend": schedule_data.get("weekend", [0.0] * 24)
1436
  }
1437
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
1438
+ st.session_state.module_rerun_flags["internal_loads"] = True
1439
  st.rerun()
1440
 
1441
  with col4:
1442
+ # [FIX]: Check if schedule is in use or a default template before allowing deletion
1443
  if schedule_name not in DEFAULT_SCHEDULE_TEMPLATES:
1444
+ if is_schedule_in_use(schedule_name):
1445
+ st.write("(In Use)")
1446
+ else:
1447
+ if st.button("Delete", key=f"delete_schedule_{schedule_name}_{i}"):
1448
+ # Delete schedule
1449
+ del schedules[schedule_name]
1450
+ st.success(f"Schedule '{schedule_name}' deleted!")
1451
+ # [FIX]: Use module_rerun_flags instead of internal_loads_rerun_pending
1452
+ st.session_state.module_rerun_flags["internal_loads"] = True
1453
+ st.rerun()
1454
  else:
1455
  st.write("(Default)")
1456
 
 
1503
  - Schedules control when people are present
1504
 
1505
  #### Lighting
1506
+ - Define lighting systems with power density
1507
  - Heat distribution between radiative and convective components
1508
  - Schedules control lighting operation
1509
 
 
1530
  4. Validate total loads against design expectations
1531
  """)
1532
 
1533
+ #