open-fdd 0.1.7__py3-none-any.whl → 0.1.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. open_fdd/air_handling_unit/faults/__init__.py +29 -2283
  2. open_fdd/air_handling_unit/faults/fault_condition_eight.py +135 -0
  3. open_fdd/air_handling_unit/faults/fault_condition_eleven.py +108 -0
  4. open_fdd/air_handling_unit/faults/fault_condition_fifteen.py +189 -0
  5. open_fdd/air_handling_unit/faults/fault_condition_five.py +126 -0
  6. open_fdd/air_handling_unit/faults/fault_condition_four.py +128 -0
  7. open_fdd/air_handling_unit/faults/fault_condition_fourteen.py +177 -0
  8. open_fdd/air_handling_unit/faults/fault_condition_nine.py +140 -0
  9. open_fdd/air_handling_unit/faults/fault_condition_one.py +113 -0
  10. open_fdd/air_handling_unit/faults/fault_condition_seven.py +106 -0
  11. open_fdd/air_handling_unit/faults/fault_condition_six.py +228 -0
  12. open_fdd/air_handling_unit/faults/fault_condition_sixteen.py +196 -0
  13. open_fdd/air_handling_unit/faults/fault_condition_ten.py +119 -0
  14. open_fdd/air_handling_unit/faults/fault_condition_thirteen.py +139 -0
  15. open_fdd/air_handling_unit/faults/fault_condition_three.py +112 -0
  16. open_fdd/air_handling_unit/faults/fault_condition_twelve.py +164 -0
  17. open_fdd/air_handling_unit/faults/fault_condition_two.py +112 -0
  18. open_fdd/air_handling_unit/faults/helper_utils.py +29 -19
  19. open_fdd/air_handling_unit/reports/__init__.py +6 -4
  20. open_fdd/air_handling_unit/reports/fault_report.py +3 -2
  21. open_fdd/chiller_plant/__init__.py +0 -0
  22. open_fdd/chiller_plant/faults/__init__.py +7 -0
  23. open_fdd/chiller_plant/faults/fault_condition_one.py +113 -0
  24. open_fdd/chiller_plant/faults/fault_condition_two.py +100 -0
  25. open_fdd/tests/ahu/test_ahu_fc1.py +2 -2
  26. open_fdd/tests/ahu/test_ahu_fc10.py +1 -0
  27. open_fdd/tests/ahu/test_ahu_fc11.py +24 -33
  28. open_fdd/tests/ahu/test_ahu_fc12.py +56 -18
  29. open_fdd/tests/ahu/test_ahu_fc13.py +15 -8
  30. open_fdd/tests/ahu/test_ahu_fc14.py +11 -3
  31. open_fdd/tests/ahu/test_ahu_fc15.py +15 -4
  32. open_fdd/tests/ahu/test_ahu_fc16.py +15 -6
  33. open_fdd/tests/ahu/test_ahu_fc2.py +1 -0
  34. open_fdd/tests/ahu/test_ahu_fc3.py +1 -0
  35. open_fdd/tests/ahu/test_ahu_fc4.py +3 -1
  36. open_fdd/tests/ahu/test_ahu_fc5.py +1 -0
  37. open_fdd/tests/ahu/test_ahu_fc6.py +1 -0
  38. open_fdd/tests/ahu/test_ahu_fc7.py +1 -0
  39. open_fdd/tests/ahu/test_ahu_fc8.py +1 -0
  40. open_fdd/tests/ahu/test_ahu_fc9.py +1 -0
  41. open_fdd/tests/chiller/__init__.py +0 -0
  42. open_fdd/tests/chiller/test_chiller_fc1.py +122 -0
  43. open_fdd/tests/chiller/test_chiller_fc2.py +95 -0
  44. open_fdd-0.1.9.dist-info/METADATA +137 -0
  45. open_fdd-0.1.9.dist-info/RECORD +52 -0
  46. {open_fdd-0.1.7.dist-info → open_fdd-0.1.9.dist-info}/WHEEL +1 -1
  47. open_fdd/air_handling_unit/faults/fault_condition.py +0 -69
  48. open_fdd/air_handling_unit/faults/shared_utils.py +0 -90
  49. open_fdd-0.1.7.dist-info/METADATA +0 -95
  50. open_fdd-0.1.7.dist-info/RECORD +0 -31
  51. {open_fdd-0.1.7.dist-info → open_fdd-0.1.9.dist-info/licenses}/LICENSE +0 -0
  52. {open_fdd-0.1.7.dist-info → open_fdd-0.1.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,100 @@
1
+ import pandas as pd
2
+
3
+ from open_fdd.core.base_fault import BaseFaultCondition
4
+ from open_fdd.core.components import FaultInputColumn, InstanceAttribute
5
+ from open_fdd.core.mixins import FaultConditionMixin
6
+
7
+ INPUT_COLS = [
8
+ FaultInputColumn(
9
+ name="flow_col",
10
+ constant_form="FLOW_COL",
11
+ description="Flow meter reading",
12
+ unit="GPM",
13
+ required=True,
14
+ type=str,
15
+ ),
16
+ FaultInputColumn(
17
+ name="pump_speed_col",
18
+ constant_form="PUMP_SPEED_COL",
19
+ description="Pump speed",
20
+ unit="%",
21
+ required=True,
22
+ type=str,
23
+ ),
24
+ ]
25
+
26
+ FAULT_PARAMS = [
27
+ InstanceAttribute(
28
+ name="flow_error_threshold",
29
+ constant_form="FLOW_ERROR_THRESHOLD",
30
+ description="Flow error threshold",
31
+ unit="GPM",
32
+ type=float,
33
+ range=(0.0, 1000.0),
34
+ ),
35
+ InstanceAttribute(
36
+ name="pump_speed_percent_max",
37
+ constant_form="PUMP_SPEED_PERCENT_MAX",
38
+ description="Maximum pump speed percentage",
39
+ unit="%",
40
+ type=float,
41
+ range=(0.0, 1.0),
42
+ ),
43
+ InstanceAttribute(
44
+ name="pump_speed_percent_err_thres",
45
+ constant_form="PUMP_SPEED_PERCENT_ERR_THRES",
46
+ description="Pump speed error threshold",
47
+ unit="%",
48
+ type=float,
49
+ range=(0.0, 1.0),
50
+ ),
51
+ ]
52
+
53
+
54
+ class FaultConditionTwo(BaseFaultCondition, FaultConditionMixin):
55
+ """
56
+ Class provides the definitions for Fault Condition 2.
57
+ Primary chilled water flow is too high with the chilled water pump running at high speed.
58
+
59
+ py -3.12 -m pytest open_fdd/tests/chiller/test_chiller_fc2.py -rP -s
60
+ """
61
+
62
+ input_columns = INPUT_COLS
63
+ fault_params = FAULT_PARAMS
64
+ equation_string = (
65
+ "fc2_flag = 1 if (FLOW > εFM) and (PUMPSPD >= PUMPSPD_max - εPUMPSPD) "
66
+ "for N consecutive values else 0 \n"
67
+ )
68
+ description_string = "Fault Condition 2: Primary chilled water flow is too high with the pump running at high speed \n"
69
+ error_string = "One or more required columns are missing or None \n"
70
+
71
+ @FaultConditionMixin._handle_errors
72
+ def apply(self, df: pd.DataFrame) -> pd.DataFrame:
73
+ self._apply_common_checks(df)
74
+
75
+ # Get column values using accessor methods
76
+ flow_col = self.get_input_column("flow_col")
77
+ pump_speed_col = self.get_input_column("pump_speed_col")
78
+
79
+ # Get parameter values using accessor methods
80
+ flow_error_threshold = self.get_param("flow_error_threshold")
81
+ pump_speed_percent_max = self.get_param("pump_speed_percent_max")
82
+ pump_speed_percent_err_thres = self.get_param("pump_speed_percent_err_thres")
83
+
84
+ # Check analog outputs are floats only
85
+ columns_to_check = [pump_speed_col]
86
+ self._apply_analog_checks(df, columns_to_check)
87
+
88
+ # Perform checks
89
+ flow_check = df[flow_col] < flow_error_threshold
90
+ pump_check = (
91
+ df[pump_speed_col] >= pump_speed_percent_max - pump_speed_percent_err_thres
92
+ )
93
+
94
+ # Combined condition check
95
+ combined_check = flow_check & pump_check
96
+
97
+ # Set fault flag
98
+ self._set_fault_flag(df, combined_check, "fc2_flag")
99
+
100
+ return df
@@ -1,9 +1,9 @@
1
1
  import pandas as pd
2
2
  import pytest
3
+
3
4
  from open_fdd.air_handling_unit.faults import FaultConditionOne
4
5
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
- from open_fdd.air_handling_unit.faults.fault_condition import MissingColumnError
6
-
6
+ from open_fdd.core.exceptions import MissingColumnError
7
7
 
8
8
  # Constants
9
9
  TEST_VFD_ERR_THRESHOLD = 0.05
@@ -1,5 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
+
3
4
  from open_fdd.air_handling_unit.faults import FaultConditionTen
4
5
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
6
 
@@ -1,9 +1,9 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults import (
4
- FaultConditionEleven,
5
- )
3
+
4
+ from open_fdd.air_handling_unit.faults import FaultConditionEleven
6
5
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
6
+ from open_fdd.core.exceptions import MissingColumnError
7
7
 
8
8
  """
9
9
  To see print statements in pytest run with:
@@ -13,24 +13,20 @@ OAT Temp too low for 100% cooling in OS3
13
13
  """
14
14
 
15
15
  # Constants
16
- TEST_DELTA_SUPPLY_FAN = 2.0
17
- TEST_OAT_DEGF_ERR_THRES = 5.0
18
- TEST_SUPPLY_DEGF_ERR_THRES = 2.0
19
- TEST_SAT_SP_COL = "supply_air_sp_temp"
16
+ TEST_OUTDOOR_DEGF_ERR_THRES = 5.0
17
+ TEST_MIX_DEGF_ERR_THRES = 2.0
20
18
  TEST_OAT_COL = "out_air_temp"
21
- TEST_COOLING_COIL_SIG_COL = "cooling_sig_col"
22
- TEST_MIX_AIR_DAMPER_COL = "economizer_sig_col"
19
+ TEST_MAT_COL = "mix_air_temp"
20
+ TEST_ECONOMIZER_SIG_COL = "economizer_sig_col"
23
21
  ROLLING_WINDOW_SIZE = 5
24
22
 
25
23
  # Initialize FaultConditionEleven with a dictionary
26
24
  fault_condition_params = {
27
- "DELTA_T_SUPPLY_FAN": TEST_DELTA_SUPPLY_FAN,
28
- "OUTDOOR_DEGF_ERR_THRES": TEST_OAT_DEGF_ERR_THRES,
29
- "SUPPLY_DEGF_ERR_THRES": TEST_SUPPLY_DEGF_ERR_THRES,
30
- "SAT_SETPOINT_COL": TEST_SAT_SP_COL,
25
+ "OUTDOOR_DEGF_ERR_THRES": TEST_OUTDOOR_DEGF_ERR_THRES,
26
+ "MIX_DEGF_ERR_THRES": TEST_MIX_DEGF_ERR_THRES,
31
27
  "OAT_COL": TEST_OAT_COL,
32
- "COOLING_SIG_COL": TEST_COOLING_COIL_SIG_COL,
33
- "ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
28
+ "MAT_COL": TEST_MAT_COL,
29
+ "ECONOMIZER_SIG_COL": TEST_ECONOMIZER_SIG_COL,
34
30
  "TROUBLESHOOT_MODE": False,
35
31
  "ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
36
32
  }
@@ -42,19 +38,17 @@ class TestFaultConditionEleven:
42
38
 
43
39
  def no_fault_df_no_econ(self) -> pd.DataFrame:
44
40
  data = {
45
- TEST_SAT_SP_COL: [55, 55, 55, 55, 55, 55],
46
41
  TEST_OAT_COL: [56, 56, 56, 56, 56, 56],
47
- TEST_COOLING_COIL_SIG_COL: [0.11, 0.11, 0.11, 0.11, 0.11, 0.11],
48
- TEST_MIX_AIR_DAMPER_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
42
+ TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
43
+ TEST_ECONOMIZER_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
49
44
  }
50
45
  return pd.DataFrame(data)
51
46
 
52
47
  def fault_df_in_econ(self) -> pd.DataFrame:
53
48
  data = {
54
- TEST_SAT_SP_COL: [55, 55, 55, 55, 55, 55],
55
49
  TEST_OAT_COL: [44, 44, 44, 44, 44, 44],
56
- TEST_COOLING_COIL_SIG_COL: [0.11, 0.11, 0.11, 0.11, 0.11, 0.11],
57
- TEST_MIX_AIR_DAMPER_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
50
+ TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
51
+ TEST_ECONOMIZER_SIG_COL: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
58
52
  }
59
53
  return pd.DataFrame(data)
60
54
 
@@ -79,17 +73,16 @@ class TestFaultOnInt:
79
73
 
80
74
  def fault_df_on_output_int(self) -> pd.DataFrame:
81
75
  data = {
82
- TEST_SAT_SP_COL: [55, 55, 55, 55, 55, 55],
83
76
  TEST_OAT_COL: [44, 44, 44, 44, 44, 44],
84
- TEST_COOLING_COIL_SIG_COL: [11, 11, 11, 11, 11, 11], # Incorrect type
85
- TEST_MIX_AIR_DAMPER_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
77
+ TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
78
+ TEST_ECONOMIZER_SIG_COL: [1, 1, 1, 1, 1, 1], # Incorrect type
86
79
  }
87
80
  return pd.DataFrame(data)
88
81
 
89
82
  def test_fault_on_int(self):
90
83
  with pytest.raises(
91
84
  TypeError,
92
- match=HelperUtils().float_int_check_err(TEST_COOLING_COIL_SIG_COL),
85
+ match=HelperUtils().float_int_check_err(TEST_ECONOMIZER_SIG_COL),
93
86
  ):
94
87
  fc11.apply(self.fault_df_on_output_int())
95
88
 
@@ -98,17 +91,16 @@ class TestFaultOnFloatGreaterThanOne:
98
91
 
99
92
  def fault_df_on_output_greater_than_one(self) -> pd.DataFrame:
100
93
  data = {
101
- TEST_SAT_SP_COL: [55, 55, 55, 55, 55, 55],
102
94
  TEST_OAT_COL: [44, 44, 44, 44, 44, 44],
103
- TEST_COOLING_COIL_SIG_COL: [1.1, 1.2, 1.1, 1.3, 1.1, 1.2], # Values > 1.0
104
- TEST_MIX_AIR_DAMPER_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
95
+ TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
96
+ TEST_ECONOMIZER_SIG_COL: [1.1, 1.2, 1.1, 1.3, 1.1, 1.2], # Values > 1.0
105
97
  }
106
98
  return pd.DataFrame(data)
107
99
 
108
100
  def test_fault_on_float_greater_than_one(self):
109
101
  with pytest.raises(
110
102
  TypeError,
111
- match=HelperUtils().float_max_check_err(TEST_COOLING_COIL_SIG_COL),
103
+ match=HelperUtils().float_max_check_err(TEST_ECONOMIZER_SIG_COL),
112
104
  ):
113
105
  fc11.apply(self.fault_df_on_output_greater_than_one())
114
106
 
@@ -117,17 +109,16 @@ class TestFaultOnMixedTypes:
117
109
 
118
110
  def fault_df_on_mixed_types(self) -> pd.DataFrame:
119
111
  data = {
120
- TEST_SAT_SP_COL: [55, 55, 55, 55, 55, 55],
121
112
  TEST_OAT_COL: [44, 44, 44, 44, 44, 44],
122
- TEST_COOLING_COIL_SIG_COL: [1.1, 0.55, 1.2, 1.3, 0.55, 1.1], # Mixed types
123
- TEST_MIX_AIR_DAMPER_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
113
+ TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
114
+ TEST_ECONOMIZER_SIG_COL: [1.1, 0.55, 1.2, 1.3, 0.55, 1.1], # Mixed types
124
115
  }
125
116
  return pd.DataFrame(data)
126
117
 
127
118
  def test_fault_on_mixed_types(self):
128
119
  with pytest.raises(
129
120
  TypeError,
130
- match=HelperUtils().float_max_check_err(TEST_COOLING_COIL_SIG_COL),
121
+ match=HelperUtils().float_max_check_err(TEST_ECONOMIZER_SIG_COL),
131
122
  ):
132
123
  fc11.apply(self.fault_df_on_mixed_types())
133
124
 
@@ -1,9 +1,9 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults import (
4
- FaultConditionTwelve,
5
- )
3
+
4
+ from open_fdd.air_handling_unit.faults import FaultConditionTwelve
6
5
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
6
+ from open_fdd.core.exceptions import MissingColumnError
7
7
 
8
8
  """
9
9
  To see print statements in pytest run with:
@@ -16,9 +16,11 @@ SAT too high should be less than MAT. OS3 & OS4
16
16
  TEST_DELTA_SUPPLY_FAN = 2.0
17
17
  TEST_MIX_DEGF_ERR_THRES = 2.0
18
18
  TEST_SUPPLY_DEGF_ERR_THRES = 2.0
19
+ TEST_OUTDOOR_DEGF_ERR_THRES = 5.0
19
20
  TEST_AHU_MIN_OA_DPR = 0.2
20
21
  TEST_SAT_COL = "supply_air_temp"
21
22
  TEST_MAT_COL = "mix_air_temp"
23
+ TEST_OAT_COL = "out_air_temp"
22
24
  TEST_COOLING_COIL_SIG_COL = "cooling_sig_col"
23
25
  TEST_MIX_AIR_DAMPER_COL = "economizer_sig_col"
24
26
  ROLLING_WINDOW_SIZE = 5
@@ -28,9 +30,11 @@ fault_condition_params = {
28
30
  "DELTA_T_SUPPLY_FAN": TEST_DELTA_SUPPLY_FAN,
29
31
  "MIX_DEGF_ERR_THRES": TEST_MIX_DEGF_ERR_THRES,
30
32
  "SUPPLY_DEGF_ERR_THRES": TEST_SUPPLY_DEGF_ERR_THRES,
33
+ "OUTDOOR_DEGF_ERR_THRES": TEST_OUTDOOR_DEGF_ERR_THRES,
31
34
  "AHU_MIN_OA_DPR": TEST_AHU_MIN_OA_DPR,
32
35
  "SAT_COL": TEST_SAT_COL,
33
36
  "MAT_COL": TEST_MAT_COL,
37
+ "OAT_COL": TEST_OAT_COL,
34
38
  "COOLING_SIG_COL": TEST_COOLING_COIL_SIG_COL,
35
39
  "ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
36
40
  "TROUBLESHOOT_MODE": False,
@@ -44,8 +48,9 @@ class TestFaultConditionTwelve:
44
48
 
45
49
  def no_fault_df_no_econ(self) -> pd.DataFrame:
46
50
  data = {
47
- TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
48
- TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
51
+ TEST_SAT_COL: [55.0, 55.0, 55.0, 55.0, 55.0, 55.0],
52
+ TEST_MAT_COL: [56.0, 56.0, 56.0, 56.0, 56.0, 56.0],
53
+ TEST_OAT_COL: [50.0, 50.0, 50.0, 50.0, 50.0, 50.0],
49
54
  TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
50
55
  TEST_MIX_AIR_DAMPER_COL: [
51
56
  TEST_AHU_MIN_OA_DPR,
@@ -60,8 +65,9 @@ class TestFaultConditionTwelve:
60
65
 
61
66
  def fault_df_in_econ_plus_mech(self) -> pd.DataFrame:
62
67
  data = {
63
- TEST_SAT_COL: [66, 66, 66, 66, 66, 66],
64
- TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
68
+ TEST_SAT_COL: [66.0, 66.0, 66.0, 66.0, 66.0, 66.0],
69
+ TEST_MAT_COL: [56.0, 56.0, 56.0, 56.0, 56.0, 56.0],
70
+ TEST_OAT_COL: [50.0, 50.0, 50.0, 50.0, 50.0, 50.0],
65
71
  TEST_COOLING_COIL_SIG_COL: [0.50, 0.50, 0.50, 0.50, 0.50, 0.50],
66
72
  TEST_MIX_AIR_DAMPER_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
67
73
  }
@@ -69,9 +75,38 @@ class TestFaultConditionTwelve:
69
75
 
70
76
  def fault_df_in_mech_clg(self) -> pd.DataFrame:
71
77
  data = {
72
- TEST_SAT_COL: [66, 66, 66, 66, 66, 66],
73
- TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
74
- TEST_COOLING_COIL_SIG_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
78
+ TEST_SAT_COL: [
79
+ 66.0,
80
+ 66.0,
81
+ 66.0,
82
+ 66.0,
83
+ 66.0,
84
+ 66.0,
85
+ ], # SAT much higher than MAT
86
+ TEST_MAT_COL: [
87
+ 52.0,
88
+ 52.0,
89
+ 52.0,
90
+ 52.0,
91
+ 52.0,
92
+ 52.0,
93
+ ], # Lower MAT to make fault more apparent
94
+ TEST_OAT_COL: [
95
+ 75.0,
96
+ 75.0,
97
+ 75.0,
98
+ 75.0,
99
+ 75.0,
100
+ 75.0,
101
+ ], # Hot outside conditions
102
+ TEST_COOLING_COIL_SIG_COL: [
103
+ 0.99,
104
+ 0.99,
105
+ 0.99,
106
+ 0.99,
107
+ 0.99,
108
+ 0.99,
109
+ ], # Full mechanical cooling
75
110
  TEST_MIX_AIR_DAMPER_COL: [
76
111
  TEST_AHU_MIN_OA_DPR,
77
112
  TEST_AHU_MIN_OA_DPR,
@@ -79,7 +114,7 @@ class TestFaultConditionTwelve:
79
114
  TEST_AHU_MIN_OA_DPR,
80
115
  TEST_AHU_MIN_OA_DPR,
81
116
  TEST_AHU_MIN_OA_DPR,
82
- ],
117
+ ], # Minimum OA position
83
118
  }
84
119
  return pd.DataFrame(data)
85
120
 
@@ -113,10 +148,11 @@ class TestFaultOnInt:
113
148
 
114
149
  def fault_df_on_output_int(self) -> pd.DataFrame:
115
150
  data = {
116
- TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
117
- TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
151
+ TEST_SAT_COL: [55.0, 55.0, 55.0, 55.0, 55.0, 55.0],
152
+ TEST_MAT_COL: [56.0, 56.0, 56.0, 56.0, 56.0, 56.0],
153
+ TEST_OAT_COL: [50.0, 50.0, 50.0, 50.0, 50.0, 50.0],
118
154
  TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
119
- TEST_MIX_AIR_DAMPER_COL: [11, 11, 11, 11, 11, 11], # Incorrect type
155
+ TEST_MIX_AIR_DAMPER_COL: [1, 1, 1, 1, 1, 1], # Incorrect type
120
156
  }
121
157
  return pd.DataFrame(data)
122
158
 
@@ -131,8 +167,9 @@ class TestFaultOnFloatGreaterThanOne:
131
167
 
132
168
  def fault_df_on_output_greater_than_one(self) -> pd.DataFrame:
133
169
  data = {
134
- TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
135
- TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
170
+ TEST_SAT_COL: [55.0, 55.0, 55.0, 55.0, 55.0, 55.0],
171
+ TEST_MAT_COL: [56.0, 56.0, 56.0, 56.0, 56.0, 56.0],
172
+ TEST_OAT_COL: [50.0, 50.0, 50.0, 50.0, 50.0, 50.0],
136
173
  TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
137
174
  TEST_MIX_AIR_DAMPER_COL: [1.1, 1.2, 1.1, 1.3, 1.1, 1.2], # Values > 1.0
138
175
  }
@@ -149,8 +186,9 @@ class TestFaultOnMixedTypes:
149
186
 
150
187
  def fault_df_on_mixed_types(self) -> pd.DataFrame:
151
188
  data = {
152
- TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
153
- TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
189
+ TEST_SAT_COL: [55.0, 55.0, 55.0, 55.0, 55.0, 55.0],
190
+ TEST_MAT_COL: [56.0, 56.0, 56.0, 56.0, 56.0, 56.0],
191
+ TEST_OAT_COL: [50.0, 50.0, 50.0, 50.0, 50.0, 50.0],
154
192
  TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
155
193
  TEST_MIX_AIR_DAMPER_COL: [1.1, 0.55, 1.2, 1.3, 0.55, 1.1], # Mixed types
156
194
  }
@@ -1,9 +1,9 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults import (
4
- FaultConditionThirteen,
5
- )
3
+
4
+ from open_fdd.air_handling_unit.faults import FaultConditionThirteen
6
5
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
6
+ from open_fdd.core.exceptions import MissingColumnError
7
7
 
8
8
  """
9
9
  To see print statements in pytest run with:
@@ -14,21 +14,28 @@ SAT too high in full cooling. OS3 & OS4
14
14
 
15
15
  # Constants
16
16
  TEST_SUPPLY_DEGF_ERR_THRES = 2.0
17
+ TEST_MIX_DEGF_ERR_THRES = 2.0
18
+ TEST_OUTDOOR_DEGF_ERR_THRES = 5.0
17
19
  TEST_AHU_MIN_OA_DPR = 0.2
18
20
  TEST_SAT_COL = "supply_air_temp"
19
21
  TEST_SAT_SP_COL = "supply_air_sp_temp"
20
22
  TEST_COOLING_COIL_SIG_COL = "cooling_sig_col"
21
23
  TEST_MIX_AIR_DAMPER_COL = "economizer_sig_col"
22
24
  ROLLING_WINDOW_SIZE = 5
25
+ TEST_OAT_COL = "out_air_temp"
26
+ TEST_MAT_COL = "mix_air_temp"
27
+ TEST_ECONOMIZER_SIG_COL = "economizer_sig_col"
23
28
 
24
29
  # Initialize FaultConditionThirteen with a dictionary
25
30
  fault_condition_params = {
26
- "SUPPLY_DEGF_ERR_THRES": TEST_SUPPLY_DEGF_ERR_THRES,
27
- "AHU_MIN_OA_DPR": TEST_AHU_MIN_OA_DPR,
28
31
  "SAT_COL": TEST_SAT_COL,
29
- "SAT_SETPOINT_COL": TEST_SAT_SP_COL,
32
+ "SAT_SP_COL": TEST_SAT_SP_COL,
30
33
  "COOLING_SIG_COL": TEST_COOLING_COIL_SIG_COL,
31
- "ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
34
+ "ECONOMIZER_SIG_COL": TEST_ECONOMIZER_SIG_COL,
35
+ "SUPPLY_DEGF_ERR_THRES": TEST_SUPPLY_DEGF_ERR_THRES,
36
+ "MIX_DEGF_ERR_THRES": TEST_MIX_DEGF_ERR_THRES,
37
+ "OUTDOOR_DEGF_ERR_THRES": TEST_OUTDOOR_DEGF_ERR_THRES,
38
+ "AHU_MIN_OA_DPR": TEST_AHU_MIN_OA_DPR,
32
39
  "TROUBLESHOOT_MODE": False,
33
40
  "ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
34
41
  }
@@ -58,7 +65,7 @@ class TestFaultConditionThirteen:
58
65
  data = {
59
66
  TEST_SAT_COL: [66, 66, 66, 66, 66, 66],
60
67
  TEST_SAT_SP_COL: [56, 56, 56, 56, 56, 56],
61
- TEST_COOLING_COIL_SIG_COL: [0.50, 0.50, 0.50, 0.50, 0.50, 0.50],
68
+ TEST_COOLING_COIL_SIG_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
62
69
  TEST_MIX_AIR_DAMPER_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
63
70
  }
64
71
  return pd.DataFrame(data)
@@ -1,9 +1,9 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults import (
4
- FaultConditionFourteen,
5
- )
3
+
4
+ from open_fdd.air_handling_unit.faults import FaultConditionFourteen
6
5
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
6
+ from open_fdd.core.exceptions import MissingColumnError
7
7
 
8
8
  """
9
9
  To see print statements in pytest run with:
@@ -16,6 +16,8 @@ Temp drop across inactive clg coil in OS1 & OS2
16
16
  TEST_DELTA_SUPPLY_FAN = 2.0
17
17
  TEST_COIL_TEMP_ENTER_ERR_THRES = 1.0
18
18
  TEST_COIL_TEMP_LEAVE_ERR_THRES = 1.0
19
+ TEST_MIX_DEGF_ERR_THRES = 2.0
20
+ TEST_OUTDOOR_DEGF_ERR_THRES = 5.0
19
21
  TEST_AHU_MIN_OA_DPR = 0.2
20
22
  TEST_CLG_COIL_ENTER_TEMP_COL = "clg_enter_air_temp"
21
23
  TEST_CLG_COIL_LEAVE_TEMP_COL = "clg_leave_air_temp"
@@ -23,6 +25,8 @@ TEST_CLG_COIL_CMD_COL = "cooling_sig_col"
23
25
  TEST_HTG_COIL_CMD_COL = "heating_sig_col"
24
26
  TEST_MIX_AIR_DAMPER_COL = "economizer_sig_col"
25
27
  TEST_SUPPLY_VFD_SPEED_COL = "supply_vfd_speed"
28
+ TEST_OAT_COL = "out_air_temp"
29
+ TEST_MAT_COL = "mix_air_temp"
26
30
  ROLLING_WINDOW_SIZE = 5
27
31
 
28
32
  # Initialize FaultConditionFourteen with a dictionary
@@ -30,6 +34,8 @@ fault_condition_params = {
30
34
  "DELTA_T_SUPPLY_FAN": TEST_DELTA_SUPPLY_FAN,
31
35
  "COIL_TEMP_ENTER_ERR_THRES": TEST_COIL_TEMP_ENTER_ERR_THRES,
32
36
  "COIL_TEMP_LEAV_ERR_THRES": TEST_COIL_TEMP_LEAVE_ERR_THRES,
37
+ "MIX_DEGF_ERR_THRES": TEST_MIX_DEGF_ERR_THRES,
38
+ "OUTDOOR_DEGF_ERR_THRES": TEST_OUTDOOR_DEGF_ERR_THRES,
33
39
  "AHU_MIN_OA_DPR": TEST_AHU_MIN_OA_DPR,
34
40
  "CLG_COIL_ENTER_TEMP_COL": TEST_CLG_COIL_ENTER_TEMP_COL,
35
41
  "CLG_COIL_LEAVE_TEMP_COL": TEST_CLG_COIL_LEAVE_TEMP_COL,
@@ -37,6 +43,8 @@ fault_condition_params = {
37
43
  "HEATING_SIG_COL": TEST_HTG_COIL_CMD_COL,
38
44
  "ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
39
45
  "SUPPLY_VFD_SPEED_COL": TEST_SUPPLY_VFD_SPEED_COL,
46
+ "OAT_COL": TEST_OAT_COL,
47
+ "MAT_COL": TEST_MAT_COL,
40
48
  "TROUBLESHOOT_MODE": False,
41
49
  "ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
42
50
  }
@@ -1,9 +1,9 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults import (
4
- FaultConditionFifteen,
5
- )
3
+
4
+ from open_fdd.air_handling_unit.faults import FaultConditionFifteen
6
5
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
6
+ from open_fdd.core.exceptions import MissingColumnError
7
7
 
8
8
  """
9
9
  To see print statements in pytest run with:
@@ -16,6 +16,9 @@ Temp rise across inactive htg coil in OS2, OS3, & OS4
16
16
  TEST_DELTA_SUPPLY_FAN = 2.0
17
17
  TEST_COIL_TEMP_ENTER_ERR_THRES = 1.0
18
18
  TEST_COIL_TEMP_LEAVE_ERR_THRES = 1.0
19
+ TEST_SUPPLY_DEGF_ERR_THRES = 2.0
20
+ TEST_MIX_DEGF_ERR_THRES = 2.0
21
+ TEST_OUTDOOR_DEGF_ERR_THRES = 5.0
19
22
  TEST_AHU_MIN_OA_DPR = 0.2
20
23
  TEST_HTG_COIL_ENTER_TEMP_COL = "htg_enter_air_temp"
21
24
  TEST_HTG_COIL_LEAVE_TEMP_COL = "htg_leave_air_temp"
@@ -24,21 +27,29 @@ TEST_HTG_COIL_CMD_COL = "heating_sig_col"
24
27
  TEST_MIX_AIR_DAMPER_COL = "economizer_sig_col"
25
28
  TEST_SUPPLY_VFD_SPEED_COL = "supply_vfd_speed"
26
29
  ROLLING_WINDOW_SIZE = 5
30
+ TEST_OAT_COL = "out_air_temp"
31
+ TEST_MAT_COL = "mix_air_temp"
32
+ TEST_ECONOMIZER_SIG_COL = "economizer_sig_col"
27
33
 
28
34
  # Initialize FaultConditionFifteen with a dictionary
29
35
  fault_condition_params = {
30
36
  "DELTA_SUPPLY_FAN": TEST_DELTA_SUPPLY_FAN,
31
37
  "COIL_TEMP_ENTER_ERR_THRES": TEST_COIL_TEMP_ENTER_ERR_THRES,
32
38
  "COIL_TEMP_LEAV_ERR_THRES": TEST_COIL_TEMP_LEAVE_ERR_THRES,
39
+ "SUPPLY_DEGF_ERR_THRES": TEST_SUPPLY_DEGF_ERR_THRES,
40
+ "MIX_DEGF_ERR_THRES": TEST_MIX_DEGF_ERR_THRES,
41
+ "OUTDOOR_DEGF_ERR_THRES": TEST_OUTDOOR_DEGF_ERR_THRES,
33
42
  "AHU_MIN_OA_DPR": TEST_AHU_MIN_OA_DPR,
34
43
  "HTG_COIL_ENTER_TEMP_COL": TEST_HTG_COIL_ENTER_TEMP_COL,
35
44
  "HTG_COIL_LEAVE_TEMP_COL": TEST_HTG_COIL_LEAVE_TEMP_COL,
36
45
  "COOLING_SIG_COL": TEST_CLG_COIL_CMD_COL,
37
46
  "HEATING_SIG_COL": TEST_HTG_COIL_CMD_COL,
38
- "ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
47
+ "ECONOMIZER_SIG_COL": TEST_ECONOMIZER_SIG_COL,
39
48
  "SUPPLY_VFD_SPEED_COL": TEST_SUPPLY_VFD_SPEED_COL,
40
49
  "TROUBLESHOOT_MODE": False,
41
50
  "ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
51
+ "OAT_COL": TEST_OAT_COL,
52
+ "MAT_COL": TEST_MAT_COL,
42
53
  }
43
54
 
44
55
  fc15 = FaultConditionFifteen(fault_condition_params)
@@ -1,10 +1,9 @@
1
1
  import pandas as pd
2
2
  import pytest
3
+
3
4
  from open_fdd.air_handling_unit.faults import FaultConditionSixteen
4
- from open_fdd.air_handling_unit.faults.fault_condition import (
5
- InvalidParameterError,
6
- MissingColumnError,
7
- )
5
+ from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
6
+ from open_fdd.core.exceptions import InvalidParameterError, MissingColumnError
8
7
 
9
8
  """
10
9
  To see print statements in pytest run with:
@@ -21,11 +20,16 @@ TEST_ERV_EFFICIENCY_MAX_COOLING = 0.6
21
20
  TEST_OAT_LOW_THRESHOLD = 32.0
22
21
  TEST_OAT_HIGH_THRESHOLD = 80.0
23
22
  TEST_OAT_RAT_DELTA_THRES = 15.0
23
+ TEST_MIX_DEGF_ERR_THRES = 2.0
24
+ TEST_OUTDOOR_DEGF_ERR_THRES = 5.0
24
25
  TEST_ERV_OAT_ENTER_COL = "erv_oat_enter"
25
26
  TEST_ERV_OAT_LEAVING_COL = "erv_oat_leaving"
26
27
  TEST_ERV_EAT_ENTER_COL = "erv_eat_enter"
27
28
  TEST_ERV_EAT_LEAVING_COL = "erv_eat_leaving"
28
29
  TEST_SUPPLY_VFD_SPEED_COL = "supply_vfd_speed"
30
+ TEST_OAT_COL = "out_air_temp"
31
+ TEST_MAT_COL = "mix_air_temp"
32
+ TEST_ECONOMIZER_SIG_COL = "economizer_sig_col"
29
33
  ROLLING_WINDOW_SIZE = 1
30
34
 
31
35
  # Initialize FaultConditionSixteen with a dictionary
@@ -37,11 +41,16 @@ fault_condition_params = {
37
41
  "OAT_LOW_THRESHOLD": TEST_OAT_LOW_THRESHOLD,
38
42
  "OAT_HIGH_THRESHOLD": TEST_OAT_HIGH_THRESHOLD,
39
43
  "OAT_RAT_DELTA_MIN": TEST_OAT_RAT_DELTA_THRES,
44
+ "MIX_DEGF_ERR_THRES": TEST_MIX_DEGF_ERR_THRES,
45
+ "OUTDOOR_DEGF_ERR_THRES": TEST_OUTDOOR_DEGF_ERR_THRES,
40
46
  "ERV_OAT_ENTER_COL": TEST_ERV_OAT_ENTER_COL,
41
47
  "ERV_OAT_LEAVING_COL": TEST_ERV_OAT_LEAVING_COL,
42
48
  "ERV_EAT_ENTER_COL": TEST_ERV_EAT_ENTER_COL,
43
49
  "ERV_EAT_LEAVING_COL": TEST_ERV_EAT_LEAVING_COL,
44
50
  "SUPPLY_VFD_SPEED_COL": TEST_SUPPLY_VFD_SPEED_COL,
51
+ "OAT_COL": TEST_OAT_COL,
52
+ "MAT_COL": TEST_MAT_COL,
53
+ "ECONOMIZER_SIG_COL": TEST_ECONOMIZER_SIG_COL,
45
54
  "TROUBLESHOOT_MODE": False,
46
55
  "ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
47
56
  }
@@ -144,7 +153,7 @@ class TestFaultOnInvalidParams:
144
153
  "SUPPLY_VFD_SPEED_COL": TEST_SUPPLY_VFD_SPEED_COL,
145
154
  }
146
155
  )
147
- assert "should be a float" in str(excinfo.value)
156
+ assert "should be of type float" in str(excinfo.value)
148
157
 
149
158
  def test_invalid_efficiency_value(self):
150
159
  """Test that InvalidParameterError is raised if efficiency values are out of 0.0 - 1.0 range."""
@@ -165,7 +174,7 @@ class TestFaultOnInvalidParams:
165
174
  "SUPPLY_VFD_SPEED_COL": TEST_SUPPLY_VFD_SPEED_COL,
166
175
  }
167
176
  )
168
- assert "should be a float between 0.0 and 1.0" in str(excinfo.value)
177
+ assert "should be between 0.0 and 1.0" in str(excinfo.value)
169
178
 
170
179
 
171
180
  class TestFaultOnMissingColumns:
@@ -1,5 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
+
3
4
  from open_fdd.air_handling_unit.faults import FaultConditionTwo
4
5
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
6
 
@@ -1,5 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
+
3
4
  from open_fdd.air_handling_unit.faults import FaultConditionThree
4
5
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
6
 
@@ -1,8 +1,10 @@
1
+ from datetime import datetime, timezone
2
+
1
3
  import pandas as pd
2
4
  import pytest
5
+
3
6
  from open_fdd.air_handling_unit.faults import FaultConditionFour
4
7
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
- from datetime import datetime, timezone
6
8
 
7
9
  """
8
10
  To see print statements in pytest run with:
@@ -1,5 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
+
3
4
  from open_fdd.air_handling_unit.faults import FaultConditionFive
4
5
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
6
 
@@ -1,5 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
+
3
4
  from open_fdd.air_handling_unit.faults import FaultConditionSix
4
5
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
6