open-fdd 0.1.0__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/__init__.py +39 -0
- open_fdd/air_handling_unit/__init__.py +0 -0
- open_fdd/air_handling_unit/faults/__init__.py +0 -0
- open_fdd/air_handling_unit/faults/fault_condition.py +49 -0
- open_fdd/air_handling_unit/faults/fault_condition_eight.py +67 -0
- open_fdd/air_handling_unit/faults/fault_condition_eleven.py +68 -0
- open_fdd/air_handling_unit/faults/fault_condition_fifteen.py +90 -0
- open_fdd/air_handling_unit/faults/fault_condition_five.py +68 -0
- open_fdd/air_handling_unit/faults/fault_condition_four.py +93 -0
- open_fdd/air_handling_unit/faults/fault_condition_fourteen.py +80 -0
- open_fdd/air_handling_unit/faults/fault_condition_nine.py +68 -0
- open_fdd/air_handling_unit/faults/fault_condition_one.py +60 -0
- open_fdd/air_handling_unit/faults/fault_condition_seven.py +55 -0
- open_fdd/air_handling_unit/faults/fault_condition_six.py +120 -0
- open_fdd/air_handling_unit/faults/fault_condition_ten.py +62 -0
- open_fdd/air_handling_unit/faults/fault_condition_thirteen.py +66 -0
- open_fdd/air_handling_unit/faults/fault_condition_three.py +58 -0
- open_fdd/air_handling_unit/faults/fault_condition_twelve.py +71 -0
- open_fdd/air_handling_unit/faults/fault_condition_two.py +61 -0
- open_fdd/air_handling_unit/faults/helper_utils.py +191 -0
- open_fdd/air_handling_unit/faults/shared_utils.py +75 -0
- open_fdd/air_handling_unit/reports/__init__.py +0 -0
- open_fdd/air_handling_unit/reports/report_fc1.py +115 -0
- open_fdd/air_handling_unit/reports/report_fc10.py +126 -0
- open_fdd/air_handling_unit/reports/report_fc11.py +128 -0
- open_fdd/air_handling_unit/reports/report_fc12.py +126 -0
- open_fdd/air_handling_unit/reports/report_fc13.py +126 -0
- open_fdd/air_handling_unit/reports/report_fc14.py +124 -0
- open_fdd/air_handling_unit/reports/report_fc15.py +124 -0
- open_fdd/air_handling_unit/reports/report_fc2.py +119 -0
- open_fdd/air_handling_unit/reports/report_fc3.py +119 -0
- open_fdd/air_handling_unit/reports/report_fc4.py +148 -0
- open_fdd/air_handling_unit/reports/report_fc5.py +132 -0
- open_fdd/air_handling_unit/reports/report_fc6.py +156 -0
- open_fdd/air_handling_unit/reports/report_fc7.py +124 -0
- open_fdd/air_handling_unit/reports/report_fc8.py +118 -0
- open_fdd/air_handling_unit/reports/report_fc9.py +120 -0
- open_fdd/tests/__init__.py +0 -0
- open_fdd/tests/ahu/__init__.py +0 -0
- open_fdd/tests/ahu/test_ahu_fc1.py +159 -0
- open_fdd/tests/ahu/test_ahu_fc10.py +132 -0
- open_fdd/tests/ahu/test_ahu_fc11.py +136 -0
- open_fdd/tests/ahu/test_ahu_fc12.py +167 -0
- open_fdd/tests/ahu/test_ahu_fc13.py +163 -0
- open_fdd/tests/ahu/test_ahu_fc14.py +197 -0
- open_fdd/tests/ahu/test_ahu_fc15.py +183 -0
- open_fdd/tests/ahu/test_ahu_fc2.py +132 -0
- open_fdd/tests/ahu/test_ahu_fc3.py +131 -0
- open_fdd/tests/ahu/test_ahu_fc4.py +200 -0
- open_fdd/tests/ahu/test_ahu_fc5.py +180 -0
- open_fdd/tests/ahu/test_ahu_fc6.py +246 -0
- open_fdd/tests/ahu/test_ahu_fc7.py +71 -0
- open_fdd/tests/ahu/test_ahu_fc8.py +131 -0
- open_fdd/tests/ahu/test_ahu_fc9.py +136 -0
- open_fdd-0.1.0.dist-info/LICENSE +21 -0
- open_fdd-0.1.0.dist-info/METADATA +65 -0
- open_fdd-0.1.0.dist-info/RECORD +59 -0
- open_fdd-0.1.0.dist-info/WHEEL +5 -0
- open_fdd-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,167 @@
|
|
1
|
+
import pandas as pd
|
2
|
+
import pytest
|
3
|
+
from open_fdd.air_handling_unit.faults.fault_condition_twelve import (
|
4
|
+
FaultConditionTwelve,
|
5
|
+
)
|
6
|
+
from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
|
7
|
+
|
8
|
+
"""
|
9
|
+
To see print statements in pytest run with:
|
10
|
+
$ py -3.12 -m pytest tests/ahu/test_ahu_fc12.py -rP -s
|
11
|
+
|
12
|
+
SAT too high should be less than MAT. OS3 & OS4
|
13
|
+
"""
|
14
|
+
|
15
|
+
# Constants
|
16
|
+
TEST_DELTA_SUPPLY_FAN = 2.0
|
17
|
+
TEST_MIX_DEGF_ERR_THRES = 2.0
|
18
|
+
TEST_SUPPLY_DEGF_ERR_THRES = 2.0
|
19
|
+
TEST_AHU_MIN_OA_DPR = 0.2
|
20
|
+
TEST_SAT_COL = "supply_air_temp"
|
21
|
+
TEST_MAT_COL = "mix_air_temp"
|
22
|
+
TEST_COOLING_COIL_SIG_COL = "cooling_sig_col"
|
23
|
+
TEST_MIX_AIR_DAMPER_COL = "economizer_sig_col"
|
24
|
+
ROLLING_WINDOW_SIZE = 5
|
25
|
+
|
26
|
+
# Initialize FaultConditionTwelve with a dictionary
|
27
|
+
fault_condition_params = {
|
28
|
+
"DELTA_T_SUPPLY_FAN": TEST_DELTA_SUPPLY_FAN,
|
29
|
+
"MIX_DEGF_ERR_THRES": TEST_MIX_DEGF_ERR_THRES,
|
30
|
+
"SUPPLY_DEGF_ERR_THRES": TEST_SUPPLY_DEGF_ERR_THRES,
|
31
|
+
"AHU_MIN_OA_DPR": TEST_AHU_MIN_OA_DPR,
|
32
|
+
"SAT_COL": TEST_SAT_COL,
|
33
|
+
"MAT_COL": TEST_MAT_COL,
|
34
|
+
"COOLING_SIG_COL": TEST_COOLING_COIL_SIG_COL,
|
35
|
+
"ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
|
36
|
+
"TROUBLESHOOT_MODE": False,
|
37
|
+
"ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
|
38
|
+
}
|
39
|
+
|
40
|
+
fc12 = FaultConditionTwelve(fault_condition_params)
|
41
|
+
|
42
|
+
|
43
|
+
class TestFaultConditionTwelve:
|
44
|
+
|
45
|
+
def no_fault_df_no_econ(self) -> pd.DataFrame:
|
46
|
+
data = {
|
47
|
+
TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
|
48
|
+
TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
|
49
|
+
TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
50
|
+
TEST_MIX_AIR_DAMPER_COL: [
|
51
|
+
TEST_AHU_MIN_OA_DPR,
|
52
|
+
TEST_AHU_MIN_OA_DPR,
|
53
|
+
TEST_AHU_MIN_OA_DPR,
|
54
|
+
TEST_AHU_MIN_OA_DPR,
|
55
|
+
TEST_AHU_MIN_OA_DPR,
|
56
|
+
TEST_AHU_MIN_OA_DPR,
|
57
|
+
],
|
58
|
+
}
|
59
|
+
return pd.DataFrame(data)
|
60
|
+
|
61
|
+
def fault_df_in_econ_plus_mech(self) -> pd.DataFrame:
|
62
|
+
data = {
|
63
|
+
TEST_SAT_COL: [66, 66, 66, 66, 66, 66],
|
64
|
+
TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
|
65
|
+
TEST_COOLING_COIL_SIG_COL: [0.50, 0.50, 0.50, 0.50, 0.50, 0.50],
|
66
|
+
TEST_MIX_AIR_DAMPER_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
|
67
|
+
}
|
68
|
+
return pd.DataFrame(data)
|
69
|
+
|
70
|
+
def fault_df_in_mech_clg(self) -> pd.DataFrame:
|
71
|
+
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],
|
75
|
+
TEST_MIX_AIR_DAMPER_COL: [
|
76
|
+
TEST_AHU_MIN_OA_DPR,
|
77
|
+
TEST_AHU_MIN_OA_DPR,
|
78
|
+
TEST_AHU_MIN_OA_DPR,
|
79
|
+
TEST_AHU_MIN_OA_DPR,
|
80
|
+
TEST_AHU_MIN_OA_DPR,
|
81
|
+
TEST_AHU_MIN_OA_DPR,
|
82
|
+
],
|
83
|
+
}
|
84
|
+
return pd.DataFrame(data)
|
85
|
+
|
86
|
+
def test_no_fault_no_econ(self):
|
87
|
+
results = fc12.apply(self.no_fault_df_no_econ())
|
88
|
+
actual = results["fc12_flag"].sum()
|
89
|
+
expected = 0
|
90
|
+
message = (
|
91
|
+
f"FC12 no_fault_df_no_econ actual is {actual} and expected is {expected}"
|
92
|
+
)
|
93
|
+
assert actual == expected, message
|
94
|
+
|
95
|
+
def test_fault_in_econ_plus_mech(self):
|
96
|
+
results = fc12.apply(self.fault_df_in_econ_plus_mech())
|
97
|
+
actual = results["fc12_flag"].sum()
|
98
|
+
expected = 2
|
99
|
+
message = f"FC12 fault_df_in_econ actual is {actual} and expected is {expected}"
|
100
|
+
assert actual == expected, message
|
101
|
+
|
102
|
+
def test_fault_in_mech_clg(self):
|
103
|
+
results = fc12.apply(self.fault_df_in_mech_clg())
|
104
|
+
actual = results["fc12_flag"].sum()
|
105
|
+
expected = 2
|
106
|
+
message = (
|
107
|
+
f"FC12 fault_df_in_mech_clg actual is {actual} and expected is {expected}"
|
108
|
+
)
|
109
|
+
assert actual == expected, message
|
110
|
+
|
111
|
+
|
112
|
+
class TestFaultOnInt:
|
113
|
+
|
114
|
+
def fault_df_on_output_int(self) -> pd.DataFrame:
|
115
|
+
data = {
|
116
|
+
TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
|
117
|
+
TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
|
118
|
+
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
|
120
|
+
}
|
121
|
+
return pd.DataFrame(data)
|
122
|
+
|
123
|
+
def test_fault_on_int(self):
|
124
|
+
with pytest.raises(
|
125
|
+
TypeError, match=HelperUtils().float_int_check_err(TEST_MIX_AIR_DAMPER_COL)
|
126
|
+
):
|
127
|
+
fc12.apply(self.fault_df_on_output_int())
|
128
|
+
|
129
|
+
|
130
|
+
class TestFaultOnFloatGreaterThanOne:
|
131
|
+
|
132
|
+
def fault_df_on_output_greater_than_one(self) -> pd.DataFrame:
|
133
|
+
data = {
|
134
|
+
TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
|
135
|
+
TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
|
136
|
+
TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
137
|
+
TEST_MIX_AIR_DAMPER_COL: [1.1, 1.2, 1.1, 1.3, 1.1, 1.2], # Values > 1.0
|
138
|
+
}
|
139
|
+
return pd.DataFrame(data)
|
140
|
+
|
141
|
+
def test_fault_on_float_greater_than_one(self):
|
142
|
+
with pytest.raises(
|
143
|
+
TypeError, match=HelperUtils().float_max_check_err(TEST_MIX_AIR_DAMPER_COL)
|
144
|
+
):
|
145
|
+
fc12.apply(self.fault_df_on_output_greater_than_one())
|
146
|
+
|
147
|
+
|
148
|
+
class TestFaultOnMixedTypes:
|
149
|
+
|
150
|
+
def fault_df_on_mixed_types(self) -> pd.DataFrame:
|
151
|
+
data = {
|
152
|
+
TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
|
153
|
+
TEST_MAT_COL: [56, 56, 56, 56, 56, 56],
|
154
|
+
TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
155
|
+
TEST_MIX_AIR_DAMPER_COL: [1.1, 0.55, 1.2, 1.3, 0.55, 1.1], # Mixed types
|
156
|
+
}
|
157
|
+
return pd.DataFrame(data)
|
158
|
+
|
159
|
+
def test_fault_on_mixed_types(self):
|
160
|
+
with pytest.raises(
|
161
|
+
TypeError, match=HelperUtils().float_max_check_err(TEST_MIX_AIR_DAMPER_COL)
|
162
|
+
):
|
163
|
+
fc12.apply(self.fault_df_on_mixed_types())
|
164
|
+
|
165
|
+
|
166
|
+
if __name__ == "__main__":
|
167
|
+
pytest.main()
|
@@ -0,0 +1,163 @@
|
|
1
|
+
import pandas as pd
|
2
|
+
import pytest
|
3
|
+
from open_fdd.air_handling_unit.faults.fault_condition_thirteen import (
|
4
|
+
FaultConditionThirteen,
|
5
|
+
)
|
6
|
+
from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
|
7
|
+
|
8
|
+
"""
|
9
|
+
To see print statements in pytest run with:
|
10
|
+
$ py -3.12 -m pytest tests/ahu/test_ahu_fc13.py -rP -s
|
11
|
+
|
12
|
+
SAT too high in full cooling. OS3 & OS4
|
13
|
+
"""
|
14
|
+
|
15
|
+
# Constants
|
16
|
+
TEST_SUPPLY_DEGF_ERR_THRES = 2.0
|
17
|
+
TEST_AHU_MIN_OA_DPR = 0.2
|
18
|
+
TEST_SAT_COL = "supply_air_temp"
|
19
|
+
TEST_SAT_SP_COL = "supply_air_sp_temp"
|
20
|
+
TEST_COOLING_COIL_SIG_COL = "cooling_sig_col"
|
21
|
+
TEST_MIX_AIR_DAMPER_COL = "economizer_sig_col"
|
22
|
+
ROLLING_WINDOW_SIZE = 5
|
23
|
+
|
24
|
+
# Initialize FaultConditionThirteen with a dictionary
|
25
|
+
fault_condition_params = {
|
26
|
+
"SUPPLY_DEGF_ERR_THRES": TEST_SUPPLY_DEGF_ERR_THRES,
|
27
|
+
"AHU_MIN_OA_DPR": TEST_AHU_MIN_OA_DPR,
|
28
|
+
"SAT_COL": TEST_SAT_COL,
|
29
|
+
"SAT_SETPOINT_COL": TEST_SAT_SP_COL,
|
30
|
+
"COOLING_SIG_COL": TEST_COOLING_COIL_SIG_COL,
|
31
|
+
"ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
|
32
|
+
"TROUBLESHOOT_MODE": False,
|
33
|
+
"ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
|
34
|
+
}
|
35
|
+
|
36
|
+
fc13 = FaultConditionThirteen(fault_condition_params)
|
37
|
+
|
38
|
+
|
39
|
+
class TestFaultConditionThirteen:
|
40
|
+
|
41
|
+
def no_fault_df_no_econ(self) -> pd.DataFrame:
|
42
|
+
data = {
|
43
|
+
TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
|
44
|
+
TEST_SAT_SP_COL: [56, 56, 56, 56, 56, 56],
|
45
|
+
TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
46
|
+
TEST_MIX_AIR_DAMPER_COL: [
|
47
|
+
TEST_AHU_MIN_OA_DPR,
|
48
|
+
TEST_AHU_MIN_OA_DPR,
|
49
|
+
TEST_AHU_MIN_OA_DPR,
|
50
|
+
TEST_AHU_MIN_OA_DPR,
|
51
|
+
TEST_AHU_MIN_OA_DPR,
|
52
|
+
TEST_AHU_MIN_OA_DPR,
|
53
|
+
],
|
54
|
+
}
|
55
|
+
return pd.DataFrame(data)
|
56
|
+
|
57
|
+
def fault_df_in_econ_plus_mech(self) -> pd.DataFrame:
|
58
|
+
data = {
|
59
|
+
TEST_SAT_COL: [66, 66, 66, 66, 66, 66],
|
60
|
+
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],
|
62
|
+
TEST_MIX_AIR_DAMPER_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
|
63
|
+
}
|
64
|
+
return pd.DataFrame(data)
|
65
|
+
|
66
|
+
def fault_df_in_mech_clg(self) -> pd.DataFrame:
|
67
|
+
data = {
|
68
|
+
TEST_SAT_COL: [66, 66, 66, 66, 66, 66],
|
69
|
+
TEST_SAT_SP_COL: [56, 56, 56, 56, 56, 56],
|
70
|
+
TEST_COOLING_COIL_SIG_COL: [0.99, 0.99, 0.99, 0.99, 0.99, 0.99],
|
71
|
+
TEST_MIX_AIR_DAMPER_COL: [
|
72
|
+
TEST_AHU_MIN_OA_DPR,
|
73
|
+
TEST_AHU_MIN_OA_DPR,
|
74
|
+
TEST_AHU_MIN_OA_DPR,
|
75
|
+
TEST_AHU_MIN_OA_DPR,
|
76
|
+
TEST_AHU_MIN_OA_DPR,
|
77
|
+
TEST_AHU_MIN_OA_DPR,
|
78
|
+
],
|
79
|
+
}
|
80
|
+
return pd.DataFrame(data)
|
81
|
+
|
82
|
+
def test_no_fault_no_econ(self):
|
83
|
+
results = fc13.apply(self.no_fault_df_no_econ())
|
84
|
+
actual = results["fc13_flag"].sum()
|
85
|
+
expected = 0
|
86
|
+
message = (
|
87
|
+
f"FC13 no_fault_df_no_econ actual is {actual} and expected is {expected}"
|
88
|
+
)
|
89
|
+
assert actual == expected, message
|
90
|
+
|
91
|
+
def test_fault_in_econ_plus_mech(self):
|
92
|
+
results = fc13.apply(self.fault_df_in_econ_plus_mech())
|
93
|
+
actual = results["fc13_flag"].sum()
|
94
|
+
expected = 2
|
95
|
+
message = f"FC13 fault_df_in_econ actual is {actual} and expected is {expected}"
|
96
|
+
assert actual == expected, message
|
97
|
+
|
98
|
+
def test_fault_in_mech_clg(self):
|
99
|
+
results = fc13.apply(self.fault_df_in_mech_clg())
|
100
|
+
actual = results["fc13_flag"].sum()
|
101
|
+
expected = 2
|
102
|
+
message = (
|
103
|
+
f"FC13 fault_df_in_mech_clg actual is {actual} and expected is {expected}"
|
104
|
+
)
|
105
|
+
assert actual == expected, message
|
106
|
+
|
107
|
+
|
108
|
+
class TestFaultOnInt:
|
109
|
+
|
110
|
+
def fault_df_on_output_int(self) -> pd.DataFrame:
|
111
|
+
data = {
|
112
|
+
TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
|
113
|
+
TEST_SAT_SP_COL: [56, 56, 56, 56, 56, 56],
|
114
|
+
TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
115
|
+
TEST_MIX_AIR_DAMPER_COL: [11, 11, 11, 11, 11, 11], # Incorrect type
|
116
|
+
}
|
117
|
+
return pd.DataFrame(data)
|
118
|
+
|
119
|
+
def test_fault_on_int(self):
|
120
|
+
with pytest.raises(
|
121
|
+
TypeError, match=HelperUtils().float_int_check_err(TEST_MIX_AIR_DAMPER_COL)
|
122
|
+
):
|
123
|
+
fc13.apply(self.fault_df_on_output_int())
|
124
|
+
|
125
|
+
|
126
|
+
class TestFaultOnFloatGreaterThanOne:
|
127
|
+
|
128
|
+
def fault_df_on_output_greater_than_one(self) -> pd.DataFrame:
|
129
|
+
data = {
|
130
|
+
TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
|
131
|
+
TEST_SAT_SP_COL: [56, 56, 56, 56, 56, 56],
|
132
|
+
TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
133
|
+
TEST_MIX_AIR_DAMPER_COL: [1.1, 1.2, 1.1, 1.3, 1.1, 1.2], # Values > 1.0
|
134
|
+
}
|
135
|
+
return pd.DataFrame(data)
|
136
|
+
|
137
|
+
def test_fault_on_float_greater_than_one(self):
|
138
|
+
with pytest.raises(
|
139
|
+
TypeError, match=HelperUtils().float_max_check_err(TEST_MIX_AIR_DAMPER_COL)
|
140
|
+
):
|
141
|
+
fc13.apply(self.fault_df_on_output_greater_than_one())
|
142
|
+
|
143
|
+
|
144
|
+
class TestFaultOnMixedTypes:
|
145
|
+
|
146
|
+
def fault_df_on_mixed_types(self) -> pd.DataFrame:
|
147
|
+
data = {
|
148
|
+
TEST_SAT_COL: [55, 55, 55, 55, 55, 55],
|
149
|
+
TEST_SAT_SP_COL: [56, 56, 56, 56, 56, 56],
|
150
|
+
TEST_COOLING_COIL_SIG_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
151
|
+
TEST_MIX_AIR_DAMPER_COL: [1.1, 0.55, 1.2, 1.3, 0.55, 1.1], # Mixed types
|
152
|
+
}
|
153
|
+
return pd.DataFrame(data)
|
154
|
+
|
155
|
+
def test_fault_on_mixed_types(self):
|
156
|
+
with pytest.raises(
|
157
|
+
TypeError, match=HelperUtils().float_max_check_err(TEST_MIX_AIR_DAMPER_COL)
|
158
|
+
):
|
159
|
+
fc13.apply(self.fault_df_on_mixed_types())
|
160
|
+
|
161
|
+
|
162
|
+
if __name__ == "__main__":
|
163
|
+
pytest.main()
|
@@ -0,0 +1,197 @@
|
|
1
|
+
import pandas as pd
|
2
|
+
import pytest
|
3
|
+
from open_fdd.air_handling_unit.faults.fault_condition_fourteen import (
|
4
|
+
FaultConditionFourteen,
|
5
|
+
)
|
6
|
+
from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
|
7
|
+
|
8
|
+
"""
|
9
|
+
To see print statements in pytest run with:
|
10
|
+
$ py -3.12 -m pytest open_fdd/tests/ahu/test_ahu_fc14.py -rP -s
|
11
|
+
|
12
|
+
Temp drop across inactive clg coil in OS1 & OS2
|
13
|
+
"""
|
14
|
+
|
15
|
+
# Constants
|
16
|
+
TEST_DELTA_SUPPLY_FAN = 2.0
|
17
|
+
TEST_COIL_TEMP_ENTER_ERR_THRES = 1.0
|
18
|
+
TEST_COIL_TEMP_LEAVE_ERR_THRES = 1.0
|
19
|
+
TEST_AHU_MIN_OA_DPR = 0.2
|
20
|
+
TEST_CLG_COIL_ENTER_TEMP_COL = "clg_enter_air_temp"
|
21
|
+
TEST_CLG_COIL_LEAVE_TEMP_COL = "clg_leave_air_temp"
|
22
|
+
TEST_CLG_COIL_CMD_COL = "cooling_sig_col"
|
23
|
+
TEST_HTG_COIL_CMD_COL = "heating_sig_col"
|
24
|
+
TEST_MIX_AIR_DAMPER_COL = "economizer_sig_col"
|
25
|
+
TEST_SUPPLY_VFD_SPEED_COL = "supply_vfd_speed"
|
26
|
+
ROLLING_WINDOW_SIZE = 5
|
27
|
+
|
28
|
+
# Initialize FaultConditionFourteen with a dictionary
|
29
|
+
fault_condition_params = {
|
30
|
+
"DELTA_T_SUPPLY_FAN": TEST_DELTA_SUPPLY_FAN,
|
31
|
+
"COIL_TEMP_ENTER_ERR_THRES": TEST_COIL_TEMP_ENTER_ERR_THRES,
|
32
|
+
"COIL_TEMP_LEAV_ERR_THRES": TEST_COIL_TEMP_LEAVE_ERR_THRES,
|
33
|
+
"AHU_MIN_OA_DPR": TEST_AHU_MIN_OA_DPR,
|
34
|
+
"CLG_COIL_ENTER_TEMP_COL": TEST_CLG_COIL_ENTER_TEMP_COL,
|
35
|
+
"CLG_COIL_LEAVE_TEMP_COL": TEST_CLG_COIL_LEAVE_TEMP_COL,
|
36
|
+
"COOLING_SIG_COL": TEST_CLG_COIL_CMD_COL,
|
37
|
+
"HEATING_SIG_COL": TEST_HTG_COIL_CMD_COL,
|
38
|
+
"ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
|
39
|
+
"SUPPLY_VFD_SPEED_COL": TEST_SUPPLY_VFD_SPEED_COL,
|
40
|
+
"TROUBLESHOOT_MODE": False,
|
41
|
+
"ROLLING_WINDOW_SIZE": ROLLING_WINDOW_SIZE,
|
42
|
+
}
|
43
|
+
|
44
|
+
fc14 = FaultConditionFourteen(fault_condition_params)
|
45
|
+
|
46
|
+
|
47
|
+
class TestFaultConditionFourteen:
|
48
|
+
|
49
|
+
def no_fault_df_econ(self) -> pd.DataFrame:
|
50
|
+
data = {
|
51
|
+
TEST_CLG_COIL_ENTER_TEMP_COL: [55, 55, 55, 55, 55, 55],
|
52
|
+
TEST_CLG_COIL_LEAVE_TEMP_COL: [56.5, 56.5, 56.5, 56.5, 56.5, 56.5],
|
53
|
+
TEST_CLG_COIL_CMD_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
54
|
+
TEST_HTG_COIL_CMD_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
55
|
+
TEST_MIX_AIR_DAMPER_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
56
|
+
TEST_SUPPLY_VFD_SPEED_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
57
|
+
}
|
58
|
+
return pd.DataFrame(data)
|
59
|
+
|
60
|
+
def no_fault_df_htg(self) -> pd.DataFrame:
|
61
|
+
data = {
|
62
|
+
TEST_CLG_COIL_ENTER_TEMP_COL: [55, 55, 55, 55, 55, 55],
|
63
|
+
TEST_CLG_COIL_LEAVE_TEMP_COL: [56.5, 56.5, 56.5, 56.5, 56.5, 56.5],
|
64
|
+
TEST_CLG_COIL_CMD_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
65
|
+
TEST_HTG_COIL_CMD_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
66
|
+
TEST_MIX_AIR_DAMPER_COL: [
|
67
|
+
TEST_AHU_MIN_OA_DPR,
|
68
|
+
TEST_AHU_MIN_OA_DPR,
|
69
|
+
TEST_AHU_MIN_OA_DPR,
|
70
|
+
TEST_AHU_MIN_OA_DPR,
|
71
|
+
TEST_AHU_MIN_OA_DPR,
|
72
|
+
TEST_AHU_MIN_OA_DPR,
|
73
|
+
],
|
74
|
+
TEST_SUPPLY_VFD_SPEED_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
75
|
+
}
|
76
|
+
return pd.DataFrame(data)
|
77
|
+
|
78
|
+
def fault_df_in_econ(self) -> pd.DataFrame:
|
79
|
+
data = {
|
80
|
+
TEST_CLG_COIL_ENTER_TEMP_COL: [55, 55, 55, 55, 55, 55],
|
81
|
+
TEST_CLG_COIL_LEAVE_TEMP_COL: [50.5, 50.5, 50.5, 50.5, 50.5, 50.5],
|
82
|
+
TEST_CLG_COIL_CMD_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
83
|
+
TEST_HTG_COIL_CMD_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
84
|
+
TEST_MIX_AIR_DAMPER_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
85
|
+
TEST_SUPPLY_VFD_SPEED_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
86
|
+
}
|
87
|
+
return pd.DataFrame(data)
|
88
|
+
|
89
|
+
def fault_df_in_htg(self) -> pd.DataFrame:
|
90
|
+
data = {
|
91
|
+
TEST_CLG_COIL_ENTER_TEMP_COL: [55, 55, 55, 55, 55, 55],
|
92
|
+
TEST_CLG_COIL_LEAVE_TEMP_COL: [50.5, 50.5, 50.5, 50.5, 50.5, 50.5],
|
93
|
+
TEST_CLG_COIL_CMD_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
94
|
+
TEST_HTG_COIL_CMD_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
95
|
+
TEST_MIX_AIR_DAMPER_COL: [
|
96
|
+
TEST_AHU_MIN_OA_DPR,
|
97
|
+
TEST_AHU_MIN_OA_DPR,
|
98
|
+
TEST_AHU_MIN_OA_DPR,
|
99
|
+
TEST_AHU_MIN_OA_DPR,
|
100
|
+
TEST_AHU_MIN_OA_DPR,
|
101
|
+
TEST_AHU_MIN_OA_DPR,
|
102
|
+
],
|
103
|
+
TEST_SUPPLY_VFD_SPEED_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
104
|
+
}
|
105
|
+
return pd.DataFrame(data)
|
106
|
+
|
107
|
+
def test_no_fault_econ(self):
|
108
|
+
results = fc14.apply(self.no_fault_df_econ())
|
109
|
+
actual = results["fc14_flag"].sum()
|
110
|
+
expected = 0
|
111
|
+
message = f"FC14 no_fault_df_econ actual is {actual} and expected is {expected}"
|
112
|
+
assert actual == expected, message
|
113
|
+
|
114
|
+
def test_no_fault_htg(self):
|
115
|
+
results = fc14.apply(self.no_fault_df_htg())
|
116
|
+
actual = results["fc14_flag"].sum()
|
117
|
+
expected = 0
|
118
|
+
message = f"FC14 no_fault_df_htg actual is {actual} and expected is {expected}"
|
119
|
+
assert actual == expected, message
|
120
|
+
|
121
|
+
def test_fault_in_econ(self):
|
122
|
+
results = fc14.apply(self.fault_df_in_econ())
|
123
|
+
actual = results["fc14_flag"].sum()
|
124
|
+
expected = 2
|
125
|
+
message = f"FC14 fault_df_in_econ actual is {actual} and expected is {expected}"
|
126
|
+
assert actual == expected, message
|
127
|
+
|
128
|
+
def test_fault_in_htg(self):
|
129
|
+
results = fc14.apply(self.fault_df_in_htg())
|
130
|
+
actual = results["fc14_flag"].sum()
|
131
|
+
expected = 2
|
132
|
+
message = f"FC14 fault_df_in_htg actual is {actual} and expected is {expected}"
|
133
|
+
assert actual == expected, message
|
134
|
+
|
135
|
+
|
136
|
+
class TestFaultOnInt:
|
137
|
+
|
138
|
+
def fault_df_on_output_int(self) -> pd.DataFrame:
|
139
|
+
data = {
|
140
|
+
TEST_CLG_COIL_ENTER_TEMP_COL: [55, 55, 55, 55, 55, 55],
|
141
|
+
TEST_CLG_COIL_LEAVE_TEMP_COL: [50.5, 50.5, 50.5, 50.5, 50.5, 50.5],
|
142
|
+
TEST_CLG_COIL_CMD_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
143
|
+
TEST_HTG_COIL_CMD_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
144
|
+
TEST_MIX_AIR_DAMPER_COL: [55, 55, 55, 55, 55, 55], # Incorrect type
|
145
|
+
TEST_SUPPLY_VFD_SPEED_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
146
|
+
}
|
147
|
+
return pd.DataFrame(data)
|
148
|
+
|
149
|
+
def test_fault_on_int(self):
|
150
|
+
with pytest.raises(
|
151
|
+
TypeError, match=HelperUtils().float_int_check_err(TEST_MIX_AIR_DAMPER_COL)
|
152
|
+
):
|
153
|
+
fc14.apply(self.fault_df_on_output_int())
|
154
|
+
|
155
|
+
|
156
|
+
class TestFaultOnFloatGreaterThanOne:
|
157
|
+
|
158
|
+
def fault_df_on_output_greater_than_one(self) -> pd.DataFrame:
|
159
|
+
data = {
|
160
|
+
TEST_CLG_COIL_ENTER_TEMP_COL: [55, 55, 55, 55, 55, 55],
|
161
|
+
TEST_CLG_COIL_LEAVE_TEMP_COL: [50.5, 50.5, 50.5, 50.5, 50.5, 50.5],
|
162
|
+
TEST_CLG_COIL_CMD_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
163
|
+
TEST_HTG_COIL_CMD_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
164
|
+
TEST_MIX_AIR_DAMPER_COL: [1.1, 1.2, 1.1, 1.3, 1.1, 1.2], # Values > 1.0
|
165
|
+
TEST_SUPPLY_VFD_SPEED_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
166
|
+
}
|
167
|
+
return pd.DataFrame(data)
|
168
|
+
|
169
|
+
def test_fault_on_float_greater_than_one(self):
|
170
|
+
with pytest.raises(
|
171
|
+
TypeError, match=HelperUtils().float_max_check_err(TEST_MIX_AIR_DAMPER_COL)
|
172
|
+
):
|
173
|
+
fc14.apply(self.fault_df_on_output_greater_than_one())
|
174
|
+
|
175
|
+
|
176
|
+
class TestFaultOnMixedTypes:
|
177
|
+
|
178
|
+
def fault_df_on_mixed_types(self) -> pd.DataFrame:
|
179
|
+
data = {
|
180
|
+
TEST_CLG_COIL_ENTER_TEMP_COL: [55, 55, 55, 55, 55, 55],
|
181
|
+
TEST_CLG_COIL_LEAVE_TEMP_COL: [50.5, 50.5, 50.5, 50.5, 50.5, 50.5],
|
182
|
+
TEST_CLG_COIL_CMD_COL: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
183
|
+
TEST_HTG_COIL_CMD_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
184
|
+
TEST_MIX_AIR_DAMPER_COL: [1.1, 0.55, 1.2, 1.3, 0.55, 1.1], # Mixed types
|
185
|
+
TEST_SUPPLY_VFD_SPEED_COL: [0.55, 0.55, 0.55, 0.55, 0.55, 0.55],
|
186
|
+
}
|
187
|
+
return pd.DataFrame(data)
|
188
|
+
|
189
|
+
def test_fault_on_mixed_types(self):
|
190
|
+
with pytest.raises(
|
191
|
+
TypeError, match=HelperUtils().float_max_check_err(TEST_MIX_AIR_DAMPER_COL)
|
192
|
+
):
|
193
|
+
fc14.apply(self.fault_df_on_mixed_types())
|
194
|
+
|
195
|
+
|
196
|
+
if __name__ == "__main__":
|
197
|
+
pytest.main()
|