open-fdd 0.1.7__py3-none-any.whl → 0.1.8__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.
@@ -3,6 +3,7 @@ import pytest
3
3
  from open_fdd.air_handling_unit.faults import (
4
4
  FaultConditionEleven,
5
5
  )
6
+ from open_fdd.core.exceptions import MissingColumnError
6
7
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
7
8
 
8
9
  """
@@ -13,24 +14,20 @@ OAT Temp too low for 100% cooling in OS3
13
14
  """
14
15
 
15
16
  # 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"
17
+ TEST_OUTDOOR_DEGF_ERR_THRES = 5.0
18
+ TEST_MIX_DEGF_ERR_THRES = 2.0
20
19
  TEST_OAT_COL = "out_air_temp"
21
- TEST_COOLING_COIL_SIG_COL = "cooling_sig_col"
22
- TEST_MIX_AIR_DAMPER_COL = "economizer_sig_col"
20
+ TEST_MAT_COL = "mix_air_temp"
21
+ TEST_ECONOMIZER_SIG_COL = "economizer_sig_col"
23
22
  ROLLING_WINDOW_SIZE = 5
24
23
 
25
24
  # Initialize FaultConditionEleven with a dictionary
26
25
  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,
26
+ "OUTDOOR_DEGF_ERR_THRES": TEST_OUTDOOR_DEGF_ERR_THRES,
27
+ "MIX_DEGF_ERR_THRES": TEST_MIX_DEGF_ERR_THRES,
31
28
  "OAT_COL": TEST_OAT_COL,
32
- "COOLING_SIG_COL": TEST_COOLING_COIL_SIG_COL,
33
- "ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
29
+ "MAT_COL": TEST_MAT_COL,
30
+ "ECONOMIZER_SIG_COL": TEST_ECONOMIZER_SIG_COL,
34
31
  "TROUBLESHOOT_MODE": False,
35
32
  "ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
36
33
  }
@@ -42,19 +39,17 @@ class TestFaultConditionEleven:
42
39
 
43
40
  def no_fault_df_no_econ(self) -> pd.DataFrame:
44
41
  data = {
45
- TEST_SAT_SP_COL: [55, 55, 55, 55, 55, 55],
46
42
  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],
43
+ TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
44
+ TEST_ECONOMIZER_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
49
45
  }
50
46
  return pd.DataFrame(data)
51
47
 
52
48
  def fault_df_in_econ(self) -> pd.DataFrame:
53
49
  data = {
54
- TEST_SAT_SP_COL: [55, 55, 55, 55, 55, 55],
55
50
  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],
51
+ TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
52
+ TEST_ECONOMIZER_SIG_COL: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
58
53
  }
59
54
  return pd.DataFrame(data)
60
55
 
@@ -79,17 +74,16 @@ class TestFaultOnInt:
79
74
 
80
75
  def fault_df_on_output_int(self) -> pd.DataFrame:
81
76
  data = {
82
- TEST_SAT_SP_COL: [55, 55, 55, 55, 55, 55],
83
77
  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],
78
+ TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
79
+ TEST_ECONOMIZER_SIG_COL: [1, 1, 1, 1, 1, 1], # Incorrect type
86
80
  }
87
81
  return pd.DataFrame(data)
88
82
 
89
83
  def test_fault_on_int(self):
90
84
  with pytest.raises(
91
85
  TypeError,
92
- match=HelperUtils().float_int_check_err(TEST_COOLING_COIL_SIG_COL),
86
+ match=HelperUtils().float_int_check_err(TEST_ECONOMIZER_SIG_COL),
93
87
  ):
94
88
  fc11.apply(self.fault_df_on_output_int())
95
89
 
@@ -98,17 +92,16 @@ class TestFaultOnFloatGreaterThanOne:
98
92
 
99
93
  def fault_df_on_output_greater_than_one(self) -> pd.DataFrame:
100
94
  data = {
101
- TEST_SAT_SP_COL: [55, 55, 55, 55, 55, 55],
102
95
  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],
96
+ TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
97
+ TEST_ECONOMIZER_SIG_COL: [1.1, 1.2, 1.1, 1.3, 1.1, 1.2], # Values > 1.0
105
98
  }
106
99
  return pd.DataFrame(data)
107
100
 
108
101
  def test_fault_on_float_greater_than_one(self):
109
102
  with pytest.raises(
110
103
  TypeError,
111
- match=HelperUtils().float_max_check_err(TEST_COOLING_COIL_SIG_COL),
104
+ match=HelperUtils().float_max_check_err(TEST_ECONOMIZER_SIG_COL),
112
105
  ):
113
106
  fc11.apply(self.fault_df_on_output_greater_than_one())
114
107
 
@@ -117,17 +110,16 @@ class TestFaultOnMixedTypes:
117
110
 
118
111
  def fault_df_on_mixed_types(self) -> pd.DataFrame:
119
112
  data = {
120
- TEST_SAT_SP_COL: [55, 55, 55, 55, 55, 55],
121
113
  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],
114
+ TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
115
+ TEST_ECONOMIZER_SIG_COL: [1.1, 0.55, 1.2, 1.3, 0.55, 1.1], # Mixed types
124
116
  }
125
117
  return pd.DataFrame(data)
126
118
 
127
119
  def test_fault_on_mixed_types(self):
128
120
  with pytest.raises(
129
121
  TypeError,
130
- match=HelperUtils().float_max_check_err(TEST_COOLING_COIL_SIG_COL),
122
+ match=HelperUtils().float_max_check_err(TEST_ECONOMIZER_SIG_COL),
131
123
  ):
132
124
  fc11.apply(self.fault_df_on_mixed_types())
133
125
 
@@ -3,6 +3,7 @@ import pytest
3
3
  from open_fdd.air_handling_unit.faults import (
4
4
  FaultConditionTwelve,
5
5
  )
6
+ from open_fdd.core.exceptions import MissingColumnError
6
7
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
7
8
 
8
9
  """
@@ -16,9 +17,11 @@ SAT too high should be less than MAT. OS3 & OS4
16
17
  TEST_DELTA_SUPPLY_FAN = 2.0
17
18
  TEST_MIX_DEGF_ERR_THRES = 2.0
18
19
  TEST_SUPPLY_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_SAT_COL = "supply_air_temp"
21
23
  TEST_MAT_COL = "mix_air_temp"
24
+ TEST_OAT_COL = "out_air_temp"
22
25
  TEST_COOLING_COIL_SIG_COL = "cooling_sig_col"
23
26
  TEST_MIX_AIR_DAMPER_COL = "economizer_sig_col"
24
27
  ROLLING_WINDOW_SIZE = 5
@@ -28,9 +31,11 @@ fault_condition_params = {
28
31
  "DELTA_T_SUPPLY_FAN": TEST_DELTA_SUPPLY_FAN,
29
32
  "MIX_DEGF_ERR_THRES": TEST_MIX_DEGF_ERR_THRES,
30
33
  "SUPPLY_DEGF_ERR_THRES": TEST_SUPPLY_DEGF_ERR_THRES,
34
+ "OUTDOOR_DEGF_ERR_THRES": TEST_OUTDOOR_DEGF_ERR_THRES,
31
35
  "AHU_MIN_OA_DPR": TEST_AHU_MIN_OA_DPR,
32
36
  "SAT_COL": TEST_SAT_COL,
33
37
  "MAT_COL": TEST_MAT_COL,
38
+ "OAT_COL": TEST_OAT_COL,
34
39
  "COOLING_SIG_COL": TEST_COOLING_COIL_SIG_COL,
35
40
  "ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
36
41
  "TROUBLESHOOT_MODE": False,
@@ -44,8 +49,9 @@ class TestFaultConditionTwelve:
44
49
 
45
50
  def no_fault_df_no_econ(self) -> pd.DataFrame:
46
51
  data = {
47
- TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
48
- TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
52
+ TEST_SAT_COL: [55.0, 55.0, 55.0, 55.0, 55.0, 55.0],
53
+ TEST_MAT_COL: [56.0, 56.0, 56.0, 56.0, 56.0, 56.0],
54
+ TEST_OAT_COL: [50.0, 50.0, 50.0, 50.0, 50.0, 50.0],
49
55
  TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
50
56
  TEST_MIX_AIR_DAMPER_COL: [
51
57
  TEST_AHU_MIN_OA_DPR,
@@ -60,8 +66,9 @@ class TestFaultConditionTwelve:
60
66
 
61
67
  def fault_df_in_econ_plus_mech(self) -> pd.DataFrame:
62
68
  data = {
63
- TEST_SAT_COL: [66, 66, 66, 66, 66, 66],
64
- TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
69
+ TEST_SAT_COL: [66.0, 66.0, 66.0, 66.0, 66.0, 66.0],
70
+ TEST_MAT_COL: [56.0, 56.0, 56.0, 56.0, 56.0, 56.0],
71
+ TEST_OAT_COL: [50.0, 50.0, 50.0, 50.0, 50.0, 50.0],
65
72
  TEST_COOLING_COIL_SIG_COL: [0.50, 0.50, 0.50, 0.50, 0.50, 0.50],
66
73
  TEST_MIX_AIR_DAMPER_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
67
74
  }
@@ -69,9 +76,38 @@ class TestFaultConditionTwelve:
69
76
 
70
77
  def fault_df_in_mech_clg(self) -> pd.DataFrame:
71
78
  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],
79
+ TEST_SAT_COL: [
80
+ 66.0,
81
+ 66.0,
82
+ 66.0,
83
+ 66.0,
84
+ 66.0,
85
+ 66.0,
86
+ ], # SAT much higher than MAT
87
+ TEST_MAT_COL: [
88
+ 52.0,
89
+ 52.0,
90
+ 52.0,
91
+ 52.0,
92
+ 52.0,
93
+ 52.0,
94
+ ], # Lower MAT to make fault more apparent
95
+ TEST_OAT_COL: [
96
+ 75.0,
97
+ 75.0,
98
+ 75.0,
99
+ 75.0,
100
+ 75.0,
101
+ 75.0,
102
+ ], # Hot outside conditions
103
+ TEST_COOLING_COIL_SIG_COL: [
104
+ 0.99,
105
+ 0.99,
106
+ 0.99,
107
+ 0.99,
108
+ 0.99,
109
+ 0.99,
110
+ ], # Full mechanical cooling
75
111
  TEST_MIX_AIR_DAMPER_COL: [
76
112
  TEST_AHU_MIN_OA_DPR,
77
113
  TEST_AHU_MIN_OA_DPR,
@@ -79,7 +115,7 @@ class TestFaultConditionTwelve:
79
115
  TEST_AHU_MIN_OA_DPR,
80
116
  TEST_AHU_MIN_OA_DPR,
81
117
  TEST_AHU_MIN_OA_DPR,
82
- ],
118
+ ], # Minimum OA position
83
119
  }
84
120
  return pd.DataFrame(data)
85
121
 
@@ -113,10 +149,11 @@ class TestFaultOnInt:
113
149
 
114
150
  def fault_df_on_output_int(self) -> pd.DataFrame:
115
151
  data = {
116
- TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
117
- TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
152
+ TEST_SAT_COL: [55.0, 55.0, 55.0, 55.0, 55.0, 55.0],
153
+ TEST_MAT_COL: [56.0, 56.0, 56.0, 56.0, 56.0, 56.0],
154
+ TEST_OAT_COL: [50.0, 50.0, 50.0, 50.0, 50.0, 50.0],
118
155
  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
156
+ TEST_MIX_AIR_DAMPER_COL: [1, 1, 1, 1, 1, 1], # Incorrect type
120
157
  }
121
158
  return pd.DataFrame(data)
122
159
 
@@ -131,8 +168,9 @@ class TestFaultOnFloatGreaterThanOne:
131
168
 
132
169
  def fault_df_on_output_greater_than_one(self) -> pd.DataFrame:
133
170
  data = {
134
- TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
135
- TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
171
+ TEST_SAT_COL: [55.0, 55.0, 55.0, 55.0, 55.0, 55.0],
172
+ TEST_MAT_COL: [56.0, 56.0, 56.0, 56.0, 56.0, 56.0],
173
+ TEST_OAT_COL: [50.0, 50.0, 50.0, 50.0, 50.0, 50.0],
136
174
  TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
137
175
  TEST_MIX_AIR_DAMPER_COL: [1.1, 1.2, 1.1, 1.3, 1.1, 1.2], # Values > 1.0
138
176
  }
@@ -149,8 +187,9 @@ class TestFaultOnMixedTypes:
149
187
 
150
188
  def fault_df_on_mixed_types(self) -> pd.DataFrame:
151
189
  data = {
152
- TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
153
- TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
190
+ TEST_SAT_COL: [55.0, 55.0, 55.0, 55.0, 55.0, 55.0],
191
+ TEST_MAT_COL: [56.0, 56.0, 56.0, 56.0, 56.0, 56.0],
192
+ TEST_OAT_COL: [50.0, 50.0, 50.0, 50.0, 50.0, 50.0],
154
193
  TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
155
194
  TEST_MIX_AIR_DAMPER_COL: [1.1, 0.55, 1.2, 1.3, 0.55, 1.1], # Mixed types
156
195
  }
@@ -3,6 +3,7 @@ import pytest
3
3
  from open_fdd.air_handling_unit.faults import (
4
4
  FaultConditionThirteen,
5
5
  )
6
+ from open_fdd.core.exceptions import MissingColumnError
6
7
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
7
8
 
8
9
  """
@@ -14,21 +15,28 @@ SAT too high in full cooling. OS3 & OS4
14
15
 
15
16
  # Constants
16
17
  TEST_SUPPLY_DEGF_ERR_THRES = 2.0
18
+ TEST_MIX_DEGF_ERR_THRES = 2.0
19
+ TEST_OUTDOOR_DEGF_ERR_THRES = 5.0
17
20
  TEST_AHU_MIN_OA_DPR = 0.2
18
21
  TEST_SAT_COL = "supply_air_temp"
19
22
  TEST_SAT_SP_COL = "supply_air_sp_temp"
20
23
  TEST_COOLING_COIL_SIG_COL = "cooling_sig_col"
21
24
  TEST_MIX_AIR_DAMPER_COL = "economizer_sig_col"
22
25
  ROLLING_WINDOW_SIZE = 5
26
+ TEST_OAT_COL = "out_air_temp"
27
+ TEST_MAT_COL = "mix_air_temp"
28
+ TEST_ECONOMIZER_SIG_COL = "economizer_sig_col"
23
29
 
24
30
  # Initialize FaultConditionThirteen with a dictionary
25
31
  fault_condition_params = {
26
- "SUPPLY_DEGF_ERR_THRES": TEST_SUPPLY_DEGF_ERR_THRES,
27
- "AHU_MIN_OA_DPR": TEST_AHU_MIN_OA_DPR,
28
32
  "SAT_COL": TEST_SAT_COL,
29
- "SAT_SETPOINT_COL": TEST_SAT_SP_COL,
33
+ "SAT_SP_COL": TEST_SAT_SP_COL,
30
34
  "COOLING_SIG_COL": TEST_COOLING_COIL_SIG_COL,
31
- "ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
35
+ "ECONOMIZER_SIG_COL": TEST_ECONOMIZER_SIG_COL,
36
+ "SUPPLY_DEGF_ERR_THRES": TEST_SUPPLY_DEGF_ERR_THRES,
37
+ "MIX_DEGF_ERR_THRES": TEST_MIX_DEGF_ERR_THRES,
38
+ "OUTDOOR_DEGF_ERR_THRES": TEST_OUTDOOR_DEGF_ERR_THRES,
39
+ "AHU_MIN_OA_DPR": TEST_AHU_MIN_OA_DPR,
32
40
  "TROUBLESHOOT_MODE": False,
33
41
  "ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
34
42
  }
@@ -58,7 +66,7 @@ class TestFaultConditionThirteen:
58
66
  data = {
59
67
  TEST_SAT_COL: [66, 66, 66, 66, 66, 66],
60
68
  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],
69
+ TEST_COOLING_COIL_SIG_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
62
70
  TEST_MIX_AIR_DAMPER_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
63
71
  }
64
72
  return pd.DataFrame(data)
@@ -3,6 +3,7 @@ import pytest
3
3
  from open_fdd.air_handling_unit.faults import (
4
4
  FaultConditionFourteen,
5
5
  )
6
+ from open_fdd.core.exceptions import MissingColumnError
6
7
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
7
8
 
8
9
  """
@@ -16,6 +17,8 @@ Temp drop across inactive clg coil in OS1 & OS2
16
17
  TEST_DELTA_SUPPLY_FAN = 2.0
17
18
  TEST_COIL_TEMP_ENTER_ERR_THRES = 1.0
18
19
  TEST_COIL_TEMP_LEAVE_ERR_THRES = 1.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_CLG_COIL_ENTER_TEMP_COL = "clg_enter_air_temp"
21
24
  TEST_CLG_COIL_LEAVE_TEMP_COL = "clg_leave_air_temp"
@@ -23,6 +26,8 @@ TEST_CLG_COIL_CMD_COL = "cooling_sig_col"
23
26
  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"
29
+ TEST_OAT_COL = "out_air_temp"
30
+ TEST_MAT_COL = "mix_air_temp"
26
31
  ROLLING_WINDOW_SIZE = 5
27
32
 
28
33
  # Initialize FaultConditionFourteen with a dictionary
@@ -30,6 +35,8 @@ fault_condition_params = {
30
35
  "DELTA_T_SUPPLY_FAN": TEST_DELTA_SUPPLY_FAN,
31
36
  "COIL_TEMP_ENTER_ERR_THRES": TEST_COIL_TEMP_ENTER_ERR_THRES,
32
37
  "COIL_TEMP_LEAV_ERR_THRES": TEST_COIL_TEMP_LEAVE_ERR_THRES,
38
+ "MIX_DEGF_ERR_THRES": TEST_MIX_DEGF_ERR_THRES,
39
+ "OUTDOOR_DEGF_ERR_THRES": TEST_OUTDOOR_DEGF_ERR_THRES,
33
40
  "AHU_MIN_OA_DPR": TEST_AHU_MIN_OA_DPR,
34
41
  "CLG_COIL_ENTER_TEMP_COL": TEST_CLG_COIL_ENTER_TEMP_COL,
35
42
  "CLG_COIL_LEAVE_TEMP_COL": TEST_CLG_COIL_LEAVE_TEMP_COL,
@@ -37,6 +44,8 @@ fault_condition_params = {
37
44
  "HEATING_SIG_COL": TEST_HTG_COIL_CMD_COL,
38
45
  "ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
39
46
  "SUPPLY_VFD_SPEED_COL": TEST_SUPPLY_VFD_SPEED_COL,
47
+ "OAT_COL": TEST_OAT_COL,
48
+ "MAT_COL": TEST_MAT_COL,
40
49
  "TROUBLESHOOT_MODE": False,
41
50
  "ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
42
51
  }
@@ -3,6 +3,7 @@ import pytest
3
3
  from open_fdd.air_handling_unit.faults import (
4
4
  FaultConditionFifteen,
5
5
  )
6
+ from open_fdd.core.exceptions import MissingColumnError
6
7
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
7
8
 
8
9
  """
@@ -16,6 +17,9 @@ Temp rise across inactive htg coil in OS2, OS3, & OS4
16
17
  TEST_DELTA_SUPPLY_FAN = 2.0
17
18
  TEST_COIL_TEMP_ENTER_ERR_THRES = 1.0
18
19
  TEST_COIL_TEMP_LEAVE_ERR_THRES = 1.0
20
+ TEST_SUPPLY_DEGF_ERR_THRES = 2.0
21
+ TEST_MIX_DEGF_ERR_THRES = 2.0
22
+ TEST_OUTDOOR_DEGF_ERR_THRES = 5.0
19
23
  TEST_AHU_MIN_OA_DPR = 0.2
20
24
  TEST_HTG_COIL_ENTER_TEMP_COL = "htg_enter_air_temp"
21
25
  TEST_HTG_COIL_LEAVE_TEMP_COL = "htg_leave_air_temp"
@@ -24,21 +28,29 @@ TEST_HTG_COIL_CMD_COL = "heating_sig_col"
24
28
  TEST_MIX_AIR_DAMPER_COL = "economizer_sig_col"
25
29
  TEST_SUPPLY_VFD_SPEED_COL = "supply_vfd_speed"
26
30
  ROLLING_WINDOW_SIZE = 5
31
+ TEST_OAT_COL = "out_air_temp"
32
+ TEST_MAT_COL = "mix_air_temp"
33
+ TEST_ECONOMIZER_SIG_COL = "economizer_sig_col"
27
34
 
28
35
  # Initialize FaultConditionFifteen with a dictionary
29
36
  fault_condition_params = {
30
37
  "DELTA_SUPPLY_FAN": TEST_DELTA_SUPPLY_FAN,
31
38
  "COIL_TEMP_ENTER_ERR_THRES": TEST_COIL_TEMP_ENTER_ERR_THRES,
32
39
  "COIL_TEMP_LEAV_ERR_THRES": TEST_COIL_TEMP_LEAVE_ERR_THRES,
40
+ "SUPPLY_DEGF_ERR_THRES": TEST_SUPPLY_DEGF_ERR_THRES,
41
+ "MIX_DEGF_ERR_THRES": TEST_MIX_DEGF_ERR_THRES,
42
+ "OUTDOOR_DEGF_ERR_THRES": TEST_OUTDOOR_DEGF_ERR_THRES,
33
43
  "AHU_MIN_OA_DPR": TEST_AHU_MIN_OA_DPR,
34
44
  "HTG_COIL_ENTER_TEMP_COL": TEST_HTG_COIL_ENTER_TEMP_COL,
35
45
  "HTG_COIL_LEAVE_TEMP_COL": TEST_HTG_COIL_LEAVE_TEMP_COL,
36
46
  "COOLING_SIG_COL": TEST_CLG_COIL_CMD_COL,
37
47
  "HEATING_SIG_COL": TEST_HTG_COIL_CMD_COL,
38
- "ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
48
+ "ECONOMIZER_SIG_COL": TEST_ECONOMIZER_SIG_COL,
39
49
  "SUPPLY_VFD_SPEED_COL": TEST_SUPPLY_VFD_SPEED_COL,
40
50
  "TROUBLESHOOT_MODE": False,
41
51
  "ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
52
+ "OAT_COL": TEST_OAT_COL,
53
+ "MAT_COL": TEST_MAT_COL,
42
54
  }
43
55
 
44
56
  fc15 = FaultConditionFifteen(fault_condition_params)
@@ -1,10 +1,8 @@
1
1
  import pandas as pd
2
2
  import pytest
3
3
  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
- )
4
+ from open_fdd.core.exceptions import MissingColumnError, InvalidParameterError
5
+ from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
8
6
 
9
7
  """
10
8
  To see print statements in pytest run with:
@@ -21,11 +19,16 @@ TEST_ERV_EFFICIENCY_MAX_COOLING = 0.6
21
19
  TEST_OAT_LOW_THRESHOLD = 32.0
22
20
  TEST_OAT_HIGH_THRESHOLD = 80.0
23
21
  TEST_OAT_RAT_DELTA_THRES = 15.0
22
+ TEST_MIX_DEGF_ERR_THRES = 2.0
23
+ TEST_OUTDOOR_DEGF_ERR_THRES = 5.0
24
24
  TEST_ERV_OAT_ENTER_COL = "erv_oat_enter"
25
25
  TEST_ERV_OAT_LEAVING_COL = "erv_oat_leaving"
26
26
  TEST_ERV_EAT_ENTER_COL = "erv_eat_enter"
27
27
  TEST_ERV_EAT_LEAVING_COL = "erv_eat_leaving"
28
28
  TEST_SUPPLY_VFD_SPEED_COL = "supply_vfd_speed"
29
+ TEST_OAT_COL = "out_air_temp"
30
+ TEST_MAT_COL = "mix_air_temp"
31
+ TEST_ECONOMIZER_SIG_COL = "economizer_sig_col"
29
32
  ROLLING_WINDOW_SIZE = 1
30
33
 
31
34
  # Initialize FaultConditionSixteen with a dictionary
@@ -37,11 +40,16 @@ fault_condition_params = {
37
40
  "OAT_LOW_THRESHOLD": TEST_OAT_LOW_THRESHOLD,
38
41
  "OAT_HIGH_THRESHOLD": TEST_OAT_HIGH_THRESHOLD,
39
42
  "OAT_RAT_DELTA_MIN": TEST_OAT_RAT_DELTA_THRES,
43
+ "MIX_DEGF_ERR_THRES": TEST_MIX_DEGF_ERR_THRES,
44
+ "OUTDOOR_DEGF_ERR_THRES": TEST_OUTDOOR_DEGF_ERR_THRES,
40
45
  "ERV_OAT_ENTER_COL": TEST_ERV_OAT_ENTER_COL,
41
46
  "ERV_OAT_LEAVING_COL": TEST_ERV_OAT_LEAVING_COL,
42
47
  "ERV_EAT_ENTER_COL": TEST_ERV_EAT_ENTER_COL,
43
48
  "ERV_EAT_LEAVING_COL": TEST_ERV_EAT_LEAVING_COL,
44
49
  "SUPPLY_VFD_SPEED_COL": TEST_SUPPLY_VFD_SPEED_COL,
50
+ "OAT_COL": TEST_OAT_COL,
51
+ "MAT_COL": TEST_MAT_COL,
52
+ "ECONOMIZER_SIG_COL": TEST_ECONOMIZER_SIG_COL,
45
53
  "TROUBLESHOOT_MODE": False,
46
54
  "ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
47
55
  }
File without changes
@@ -0,0 +1,122 @@
1
+ import pandas as pd
2
+ import pytest
3
+ from open_fdd.chiller_plant.faults import FaultConditionOne
4
+ from open_fdd.air_handling_unit.faults.fault_condition import MissingColumnError
5
+
6
+
7
+ # Constants for test cases
8
+ TEST_PUMP_ERR_THRESHOLD = 0.05
9
+ TEST_PUMP_SPEED_MAX = 0.9
10
+ TEST_DIFF_PRESSURE_ERR_THRESHOLD = 0.1
11
+ TEST_DIFF_PRESSURE_COL = "diff_pressure"
12
+ TEST_DIFF_PRESSURE_SETPOINT_COL = "diff_pressure_setpoint"
13
+ TEST_PUMP_SPEED_COL = "pump_speed"
14
+
15
+ ROLLING_WINDOW_SIZE = 5
16
+
17
+ # Initialize FaultConditionPump with a dictionary
18
+ fault_condition_params = {
19
+ "PUMP_SPEED_PERCENT_ERR_THRES": TEST_PUMP_ERR_THRESHOLD,
20
+ "PUMP_SPEED_PERCENT_MAX": TEST_PUMP_SPEED_MAX,
21
+ "DIFF_PRESSURE_PSI_ERR_THRES": TEST_DIFF_PRESSURE_ERR_THRESHOLD,
22
+ "DIFF_PRESSURE_COL": TEST_DIFF_PRESSURE_COL,
23
+ "PUMP_SPEED_COL": TEST_PUMP_SPEED_COL,
24
+ "DIFF_PRESSURE_SETPOINT_COL": TEST_DIFF_PRESSURE_SETPOINT_COL,
25
+ "TROUBLESHOOT_MODE": False,
26
+ "ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
27
+ }
28
+
29
+ fc_pump = FaultConditionOne(fault_condition_params)
30
+
31
+
32
+ class TestMissingColumn:
33
+ def missing_col_df(self) -> pd.DataFrame:
34
+ data = {
35
+ TEST_DIFF_PRESSURE_COL: [8.0, 8.1, 8.2, 8.1, 8.0, 8.0],
36
+ # Missing TEST_PUMP_SPEED_COL
37
+ TEST_DIFF_PRESSURE_SETPOINT_COL: [10.0, 10.0, 10.0, 10.0, 10.0, 10.0],
38
+ }
39
+ return pd.DataFrame(data)
40
+
41
+ def test_missing_column(self):
42
+ with pytest.raises(MissingColumnError):
43
+ fc_pump.apply(self.missing_col_df())
44
+
45
+
46
+ class TestNoFault:
47
+ def no_fault_df(self) -> pd.DataFrame:
48
+ data = {
49
+ TEST_DIFF_PRESSURE_COL: [9.8, 9.9, 9.8, 9.8, 9.9, 9.8],
50
+ TEST_DIFF_PRESSURE_SETPOINT_COL: [10.0, 10.0, 10.0, 10.0, 10.0, 10.0],
51
+ TEST_PUMP_SPEED_COL: [0.7, 0.7, 0.7, 0.7, 0.7, 0.7],
52
+ }
53
+ return pd.DataFrame(data)
54
+
55
+ def test_no_fault(self):
56
+ results = fc_pump.apply(self.no_fault_df())
57
+ actual = results["fc_pump_flag"].sum()
58
+ expected = 0
59
+ message = f"FC Pump no_fault_df actual is {actual} and expected is {expected}"
60
+ assert actual == expected, message
61
+
62
+
63
+ class TestFault:
64
+ def fault_df(self) -> pd.DataFrame:
65
+ data = {
66
+ TEST_DIFF_PRESSURE_COL: [
67
+ 8.0,
68
+ 8.1,
69
+ 8.0,
70
+ 7.9,
71
+ 8.0,
72
+ 8.0,
73
+ 9.9,
74
+ 9.9,
75
+ 8.0,
76
+ 8.1,
77
+ 8.0,
78
+ 7.9,
79
+ 8.0,
80
+ 8.1,
81
+ ],
82
+ TEST_DIFF_PRESSURE_SETPOINT_COL: [
83
+ 10.0,
84
+ 10.0,
85
+ 10.0,
86
+ 10.0,
87
+ 10.0,
88
+ 10.0,
89
+ 10.0,
90
+ 10.0,
91
+ 10.0,
92
+ 10.0,
93
+ 10.0,
94
+ 10.0,
95
+ 10.0,
96
+ 10.0,
97
+ ],
98
+ TEST_PUMP_SPEED_COL: [
99
+ 0.9,
100
+ 0.9,
101
+ 0.9,
102
+ 0.9,
103
+ 0.9,
104
+ 0.9,
105
+ 0.5,
106
+ 0.55,
107
+ 0.9,
108
+ 0.9,
109
+ 0.9,
110
+ 0.9,
111
+ 0.9,
112
+ 0.9,
113
+ ],
114
+ }
115
+ return pd.DataFrame(data)
116
+
117
+ def test_fault(self):
118
+ results = fc_pump.apply(self.fault_df())
119
+ actual = results["fc_pump_flag"].sum()
120
+ expected = 4 # Adjusted based on the rolling window and fault conditions
121
+ message = f"FC Pump fault_df actual is {actual} and expected is {expected}"
122
+ assert actual == expected, message
@@ -0,0 +1,95 @@
1
+ import pandas as pd
2
+ import pytest
3
+ from open_fdd.chiller_plant.faults import FaultConditionTwo
4
+ from open_fdd.air_handling_unit.faults.fault_condition import MissingColumnError
5
+
6
+
7
+ # Constants for test cases
8
+ TEST_FLOW_ERR_THRESHOLD = 10.0 # Error threshold for flow in GPM
9
+ TEST_PUMP_SPEED_MAX = 0.9 # Maximum pump speed percentage
10
+ TEST_PUMP_SPEED_ERR_THRESHOLD = 0.05 # Error threshold for pump speed percentage
11
+ TEST_FLOW_COL = "flow_gpm"
12
+ TEST_PUMP_SPEED_COL = "pump_speed"
13
+
14
+ ROLLING_WINDOW_SIZE = 5
15
+
16
+ # Initialize FaultConditionTwo with a dictionary
17
+ fault_condition_params = {
18
+ "FLOW_ERROR_THRESHOLD": TEST_FLOW_ERR_THRESHOLD,
19
+ "PUMP_SPEED_PERCENT_MAX": TEST_PUMP_SPEED_MAX,
20
+ "PUMP_SPEED_PERCENT_ERR_THRES": TEST_PUMP_SPEED_ERR_THRESHOLD,
21
+ "FLOW_COL": TEST_FLOW_COL,
22
+ "PUMP_SPEED_COL": TEST_PUMP_SPEED_COL,
23
+ "ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
24
+ }
25
+
26
+ fc_flow = FaultConditionTwo(fault_condition_params)
27
+
28
+
29
+ class TestMissingColumn:
30
+ def missing_col_df(self) -> pd.DataFrame:
31
+ data = {
32
+ TEST_FLOW_COL: [5.0, 8.0, 9.0, 15.0, 7.0],
33
+ # Missing pump speed column
34
+ }
35
+ return pd.DataFrame(data)
36
+
37
+ def test_missing_column(self):
38
+ with pytest.raises(MissingColumnError):
39
+ fc_flow.apply(self.missing_col_df())
40
+
41
+
42
+ class TestNoFault:
43
+ def no_fault_df(self) -> pd.DataFrame:
44
+ data = {
45
+ TEST_FLOW_COL: [11.0, 11.0, 12.0, 12.0, 12.5], # Flow above threshold
46
+ TEST_PUMP_SPEED_COL: [0.5, 0.45, 0.55, 0.45, 0.55], # Above threshold
47
+ }
48
+ return pd.DataFrame(data)
49
+
50
+ def test_no_fault(self):
51
+ results = fc_flow.apply(self.no_fault_df())
52
+ actual = results["fc2_flag"].sum()
53
+ expected = 0
54
+ message = f"FC2 no_fault_df actual is {actual} and expected is {expected}"
55
+ assert actual == expected, message
56
+
57
+
58
+ class TestFault:
59
+ def fault_df(self) -> pd.DataFrame:
60
+ data = {
61
+ TEST_FLOW_COL: [
62
+ 6.0,
63
+ 6.1,
64
+ 6.2,
65
+ 6.3,
66
+ 6.4,
67
+ 12.0,
68
+ 6.0,
69
+ 6.1,
70
+ 6.2,
71
+ 6.3,
72
+ 6.4,
73
+ ], # 6th row interrupts the fault condition
74
+ TEST_PUMP_SPEED_COL: [
75
+ 0.97,
76
+ 0.98,
77
+ 0.98,
78
+ 0.97,
79
+ 0.99,
80
+ 0.95,
81
+ 0.97,
82
+ 0.98,
83
+ 0.98,
84
+ 0.97,
85
+ 0.99,
86
+ ], # All above threshold
87
+ }
88
+ return pd.DataFrame(data)
89
+
90
+ def test_fault(self):
91
+ results = fc_flow.apply(self.fault_df())
92
+ actual = results["fc2_flag"].sum() # Fault flags counted
93
+ expected = 2 # 5 faults, interruption, then 5 more faults = 2 total flags
94
+ message = f"FC2 fault_df actual is {actual} and expected is {expected}"
95
+ assert actual == expected, message