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.
- open_fdd/air_handling_unit/faults/__init__.py +623 -1420
- open_fdd/chiller_plant/__init__.py +0 -0
- open_fdd/chiller_plant/faults/__init__.py +2280 -0
- open_fdd/tests/ahu/test_ahu_fc11.py +22 -30
- open_fdd/tests/ahu/test_ahu_fc12.py +54 -15
- open_fdd/tests/ahu/test_ahu_fc13.py +13 -5
- open_fdd/tests/ahu/test_ahu_fc14.py +9 -0
- open_fdd/tests/ahu/test_ahu_fc15.py +13 -1
- open_fdd/tests/ahu/test_ahu_fc16.py +12 -4
- open_fdd/tests/chiller/__init__.py +0 -0
- open_fdd/tests/chiller/test_chiller_fc1.py +122 -0
- open_fdd/tests/chiller/test_chiller_fc2.py +95 -0
- open_fdd-0.1.8.dist-info/METADATA +136 -0
- {open_fdd-0.1.7.dist-info → open_fdd-0.1.8.dist-info}/RECORD +17 -12
- {open_fdd-0.1.7.dist-info → open_fdd-0.1.8.dist-info}/WHEEL +1 -1
- open_fdd-0.1.7.dist-info/METADATA +0 -95
- {open_fdd-0.1.7.dist-info → open_fdd-0.1.8.dist-info}/LICENSE +0 -0
- {open_fdd-0.1.7.dist-info → open_fdd-0.1.8.dist-info}/top_level.txt +0 -0
@@ -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
|
-
|
17
|
-
|
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
|
-
|
22
|
-
|
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
|
-
"
|
28
|
-
"
|
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
|
-
"
|
33
|
-
"ECONOMIZER_SIG_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
|
-
|
48
|
-
|
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
|
-
|
57
|
-
|
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
|
-
|
85
|
-
|
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(
|
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
|
-
|
104
|
-
|
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(
|
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
|
-
|
123
|
-
|
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(
|
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: [
|
73
|
-
|
74
|
-
|
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: [
|
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
|
-
"
|
33
|
+
"SAT_SP_COL": TEST_SAT_SP_COL,
|
30
34
|
"COOLING_SIG_COL": TEST_COOLING_COIL_SIG_COL,
|
31
|
-
"ECONOMIZER_SIG_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.
|
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":
|
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.
|
5
|
-
|
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
|