open-fdd 0.1.8__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 (49) hide show
  1. open_fdd/air_handling_unit/faults/__init__.py +30 -1487
  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/faults/__init__.py +6 -2279
  22. open_fdd/chiller_plant/faults/fault_condition_one.py +113 -0
  23. open_fdd/chiller_plant/faults/fault_condition_two.py +100 -0
  24. open_fdd/tests/ahu/test_ahu_fc1.py +2 -2
  25. open_fdd/tests/ahu/test_ahu_fc10.py +1 -0
  26. open_fdd/tests/ahu/test_ahu_fc11.py +3 -4
  27. open_fdd/tests/ahu/test_ahu_fc12.py +3 -4
  28. open_fdd/tests/ahu/test_ahu_fc13.py +3 -4
  29. open_fdd/tests/ahu/test_ahu_fc14.py +3 -4
  30. open_fdd/tests/ahu/test_ahu_fc15.py +3 -4
  31. open_fdd/tests/ahu/test_ahu_fc16.py +4 -3
  32. open_fdd/tests/ahu/test_ahu_fc2.py +1 -0
  33. open_fdd/tests/ahu/test_ahu_fc3.py +1 -0
  34. open_fdd/tests/ahu/test_ahu_fc4.py +3 -1
  35. open_fdd/tests/ahu/test_ahu_fc5.py +1 -0
  36. open_fdd/tests/ahu/test_ahu_fc6.py +1 -0
  37. open_fdd/tests/ahu/test_ahu_fc7.py +1 -0
  38. open_fdd/tests/ahu/test_ahu_fc8.py +1 -0
  39. open_fdd/tests/ahu/test_ahu_fc9.py +1 -0
  40. open_fdd/tests/chiller/test_chiller_fc1.py +2 -2
  41. open_fdd/tests/chiller/test_chiller_fc2.py +2 -2
  42. {open_fdd-0.1.8.dist-info → open_fdd-0.1.9.dist-info}/METADATA +4 -3
  43. open_fdd-0.1.9.dist-info/RECORD +52 -0
  44. {open_fdd-0.1.8.dist-info → open_fdd-0.1.9.dist-info}/WHEEL +1 -1
  45. open_fdd/air_handling_unit/faults/fault_condition.py +0 -69
  46. open_fdd/air_handling_unit/faults/shared_utils.py +0 -90
  47. open_fdd-0.1.8.dist-info/RECORD +0 -36
  48. {open_fdd-0.1.8.dist-info → open_fdd-0.1.9.dist-info/licenses}/LICENSE +0 -0
  49. {open_fdd-0.1.8.dist-info → open_fdd-0.1.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,112 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+
4
+ from open_fdd.core.base_fault import BaseFaultCondition
5
+ from open_fdd.core.components import FaultInputColumn, InstanceAttribute
6
+ from open_fdd.core.mixins import FaultConditionMixin
7
+
8
+ INPUT_COLS = [
9
+ FaultInputColumn(
10
+ name="mat_col",
11
+ constant_form="MAT_COL",
12
+ description="Mixed air temperature",
13
+ unit="°F",
14
+ required=True,
15
+ type=float,
16
+ ),
17
+ FaultInputColumn(
18
+ name="rat_col",
19
+ constant_form="RAT_COL",
20
+ description="Return air temperature",
21
+ unit="°F",
22
+ required=True,
23
+ type=float,
24
+ ),
25
+ FaultInputColumn(
26
+ name="oat_col",
27
+ constant_form="OAT_COL",
28
+ description="Outside air temperature",
29
+ unit="°F",
30
+ required=True,
31
+ type=float,
32
+ ),
33
+ FaultInputColumn(
34
+ name="supply_vfd_speed_col",
35
+ constant_form="SUPPLY_VFD_SPEED_COL",
36
+ description="Supply fan VFD speed",
37
+ unit="%",
38
+ required=True,
39
+ type=float,
40
+ ),
41
+ ]
42
+
43
+ FAULT_PARAMS = [
44
+ InstanceAttribute(
45
+ name="mix_degf_err_thres",
46
+ constant_form="MIX_DEGF_ERR_THRES",
47
+ description="Mixed air temperature error threshold",
48
+ unit="°F",
49
+ type=float,
50
+ range=(0.0, 10.0),
51
+ ),
52
+ InstanceAttribute(
53
+ name="outdoor_degf_err_thres",
54
+ constant_form="OUTDOOR_DEGF_ERR_THRES",
55
+ description="Outdoor air temperature error threshold",
56
+ unit="°F",
57
+ type=float,
58
+ range=(0.0, 10.0),
59
+ ),
60
+ InstanceAttribute(
61
+ name="return_degf_err_thres",
62
+ constant_form="RETURN_DEGF_ERR_THRES",
63
+ description="Return air temperature error threshold",
64
+ unit="°F",
65
+ type=float,
66
+ range=(0.0, 10.0),
67
+ ),
68
+ ]
69
+
70
+
71
+ class FaultConditionThree(BaseFaultCondition, FaultConditionMixin):
72
+ """Class provides the definitions for Fault Condition 3.
73
+ Mix temperature too high; should be between outside and return air.
74
+ """
75
+
76
+ input_columns = INPUT_COLS
77
+ fault_params = FAULT_PARAMS
78
+ equation_string = "fc3_flag = 1 if (MAT - εMAT > max(RAT + εRAT, OAT + εOAT)) and (VFDSPD > 0) for N consecutive values else 0 \n"
79
+ description_string = "Fault Condition 3: Mix temperature too high; should be between outside and return air \n"
80
+ error_string = "One or more required columns are missing or None \n"
81
+
82
+ @FaultConditionMixin._handle_errors
83
+ def apply(self, df: pd.DataFrame) -> pd.DataFrame:
84
+ self._apply_common_checks(df)
85
+
86
+ # Get column values using accessor methods
87
+ supply_vfd_speed_col = self.get_input_column("supply_vfd_speed_col")
88
+ mat_col = self.get_input_column("mat_col")
89
+ rat_col = self.get_input_column("rat_col")
90
+ oat_col = self.get_input_column("oat_col")
91
+
92
+ # Get parameter values using accessor methods
93
+ mix_degf_err_thres = self.get_param("mix_degf_err_thres")
94
+ return_degf_err_thres = self.get_param("return_degf_err_thres")
95
+ outdoor_degf_err_thres = self.get_param("outdoor_degf_err_thres")
96
+
97
+ self._apply_analog_checks(
98
+ df, [supply_vfd_speed_col], check_greater_than_one=True
99
+ )
100
+
101
+ # Specific checks
102
+ mat_check = df[mat_col] - mix_degf_err_thres
103
+ temp_max_check = np.maximum(
104
+ df[rat_col] + return_degf_err_thres,
105
+ df[oat_col] + outdoor_degf_err_thres,
106
+ )
107
+ combined_check = (mat_check > temp_max_check) & (
108
+ df[supply_vfd_speed_col] > 0.01
109
+ )
110
+
111
+ self._set_fault_flag(df, combined_check, "fc3_flag")
112
+ return df
@@ -0,0 +1,164 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+
4
+ from open_fdd.core.base_fault import BaseFaultCondition
5
+ from open_fdd.core.components import FaultInputColumn, InstanceAttribute
6
+ from open_fdd.core.exceptions import InvalidParameterError
7
+ from open_fdd.core.mixins import FaultConditionMixin
8
+
9
+ INPUT_COLS = [
10
+ FaultInputColumn(
11
+ name="sat_col",
12
+ constant_form="SAT_COL",
13
+ description="Supply air temperature",
14
+ unit="°F",
15
+ required=True,
16
+ type=float,
17
+ ),
18
+ FaultInputColumn(
19
+ name="mat_col",
20
+ constant_form="MAT_COL",
21
+ description="Mixed air temperature",
22
+ unit="°F",
23
+ required=True,
24
+ type=float,
25
+ ),
26
+ FaultInputColumn(
27
+ name="oat_col",
28
+ constant_form="OAT_COL",
29
+ description="Outside air temperature",
30
+ unit="°F",
31
+ required=True,
32
+ type=float,
33
+ ),
34
+ FaultInputColumn(
35
+ name="cooling_sig_col",
36
+ constant_form="COOLING_SIG_COL",
37
+ description="Cooling signal",
38
+ unit="%",
39
+ required=True,
40
+ type=float,
41
+ ),
42
+ FaultInputColumn(
43
+ name="economizer_sig_col",
44
+ constant_form="ECONOMIZER_SIG_COL",
45
+ description="Economizer signal",
46
+ unit="%",
47
+ required=True,
48
+ type=float,
49
+ ),
50
+ ]
51
+
52
+ FAULT_PARAMS = [
53
+ InstanceAttribute(
54
+ name="delta_t_supply_fan",
55
+ constant_form="DELTA_T_SUPPLY_FAN",
56
+ description="Temperature rise across supply fan",
57
+ unit="°F",
58
+ type=float,
59
+ ),
60
+ InstanceAttribute(
61
+ name="mix_degf_err_thres",
62
+ constant_form="MIX_DEGF_ERR_THRES",
63
+ description="Mixed air temperature error threshold",
64
+ unit="°F",
65
+ type=float,
66
+ ),
67
+ InstanceAttribute(
68
+ name="supply_degf_err_thres",
69
+ constant_form="SUPPLY_DEGF_ERR_THRES",
70
+ description="Supply air temperature error threshold",
71
+ unit="°F",
72
+ type=float,
73
+ ),
74
+ InstanceAttribute(
75
+ name="outdoor_degf_err_thres",
76
+ constant_form="OUTDOOR_DEGF_ERR_THRES",
77
+ description="Outdoor air temperature error threshold",
78
+ unit="°F",
79
+ type=float,
80
+ ),
81
+ InstanceAttribute(
82
+ name="ahu_min_oa_dpr",
83
+ constant_form="AHU_MIN_OA_DPR",
84
+ description="Minimum outdoor air damper position",
85
+ unit="fraction",
86
+ type=float,
87
+ ),
88
+ ]
89
+
90
+
91
+ class FaultConditionTwelve(BaseFaultCondition, FaultConditionMixin):
92
+ """Class provides the definitions for Fault Condition 12.
93
+ Supply air temperature too high; should be less than mixed air temperature
94
+ in OS3 (economizer + mechanical cooling) and OS4 (mechanical cooling only) modes.
95
+
96
+ py -3.12 -m pytest open_fdd/tests/ahu/test_ahu_fc12.py -rP -s
97
+ """
98
+
99
+ input_columns = INPUT_COLS
100
+ fault_params = FAULT_PARAMS
101
+ equation_string = (
102
+ "fc12_flag = 1 if (SAT > MAT + εSAT) and "
103
+ "((CLG > 0 and ECO > 0.9) or (CLG > 0.9 and ECO = MIN_OA)) "
104
+ "for N consecutive values else 0 \n"
105
+ )
106
+ description_string = (
107
+ "Fault Condition 12: Supply air temperature too high; should be less than "
108
+ "mixed air temperature in OS3 (economizer + mechanical cooling) and "
109
+ "OS4 (mechanical cooling only) modes \n"
110
+ )
111
+ error_string = "One or more required columns are missing or None \n"
112
+
113
+ @FaultConditionMixin._handle_errors
114
+ def apply(self, df: pd.DataFrame) -> pd.DataFrame:
115
+ """Apply the fault condition to the DataFrame."""
116
+ # Apply common checks
117
+ self._apply_common_checks(df)
118
+
119
+ # Get column values using accessor methods
120
+ sat_col = self.get_input_column("sat_col")
121
+ mat_col = self.get_input_column("mat_col")
122
+ oat_col = self.get_input_column("oat_col")
123
+ cooling_sig_col = self.get_input_column("cooling_sig_col")
124
+ economizer_sig_col = self.get_input_column("economizer_sig_col")
125
+
126
+ # Get parameter values using accessor methods
127
+ delta_t_supply_fan = self.get_param("delta_t_supply_fan")
128
+ mix_degf_err_thres = self.get_param("mix_degf_err_thres")
129
+ supply_degf_err_thres = self.get_param("supply_degf_err_thres")
130
+ outdoor_degf_err_thres = self.get_param("outdoor_degf_err_thres")
131
+ ahu_min_oa_dpr = self.get_param("ahu_min_oa_dpr")
132
+
133
+ # Check analog outputs [data with units of %] are floats only
134
+ columns_to_check = [
135
+ economizer_sig_col,
136
+ cooling_sig_col,
137
+ ]
138
+ self._apply_analog_checks(df, columns_to_check, check_greater_than_one=True)
139
+
140
+ # Calculate the threshold for SAT vs MAT comparison
141
+ sat_mat_threshold = np.sqrt(supply_degf_err_thres**2 + mix_degf_err_thres**2)
142
+
143
+ # Check if SAT is too high compared to MAT (accounting for supply fan heat)
144
+ sat_too_high = df[sat_col] > (
145
+ df[mat_col] + sat_mat_threshold + delta_t_supply_fan
146
+ )
147
+
148
+ # Check operating modes:
149
+ # OS3: Economizer + mechanical cooling (ECO > 0.9 and CLG > 0)
150
+ os3_mode = (df[economizer_sig_col] > 0.9) & (df[cooling_sig_col] > 0)
151
+
152
+ # OS4: Mechanical cooling only (ECO = MIN_OA and CLG > 0.9)
153
+ os4_mode = (df[economizer_sig_col] <= ahu_min_oa_dpr) & (
154
+ df[cooling_sig_col] > 0.9
155
+ )
156
+
157
+ # Combine conditions:
158
+ # Fault occurs when SAT is too high in either OS3 or OS4 mode
159
+ combined_check = sat_too_high & (os3_mode | os4_mode)
160
+
161
+ # Set fault flag
162
+ self._set_fault_flag(df, combined_check, "fc12_flag")
163
+
164
+ return df
@@ -0,0 +1,112 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+
4
+ from open_fdd.core.base_fault import BaseFaultCondition
5
+ from open_fdd.core.components import FaultInputColumn, InstanceAttribute
6
+ from open_fdd.core.mixins import FaultConditionMixin
7
+
8
+ INPUT_COLS = [
9
+ FaultInputColumn(
10
+ name="mat_col",
11
+ constant_form="MAT_COL",
12
+ description="Mixed air temperature",
13
+ unit="°F",
14
+ required=True,
15
+ type=float,
16
+ ),
17
+ FaultInputColumn(
18
+ name="rat_col",
19
+ constant_form="RAT_COL",
20
+ description="Return air temperature",
21
+ unit="°F",
22
+ required=True,
23
+ type=float,
24
+ ),
25
+ FaultInputColumn(
26
+ name="oat_col",
27
+ constant_form="OAT_COL",
28
+ description="Outside air temperature",
29
+ unit="°F",
30
+ required=True,
31
+ type=float,
32
+ ),
33
+ FaultInputColumn(
34
+ name="supply_vfd_speed_col",
35
+ constant_form="SUPPLY_VFD_SPEED_COL",
36
+ description="Supply fan VFD speed",
37
+ unit="%",
38
+ required=True,
39
+ type=float,
40
+ ),
41
+ ]
42
+
43
+ FAULT_PARAMS = [
44
+ InstanceAttribute(
45
+ name="mix_degf_err_thres",
46
+ constant_form="MIX_DEGF_ERR_THRES",
47
+ description="Mixed air temperature error threshold",
48
+ unit="°F",
49
+ type=float,
50
+ range=(0.0, 10.0),
51
+ ),
52
+ InstanceAttribute(
53
+ name="outdoor_degf_err_thres",
54
+ constant_form="OUTDOOR_DEGF_ERR_THRES",
55
+ description="Outdoor air temperature error threshold",
56
+ unit="°F",
57
+ type=float,
58
+ range=(0.0, 10.0),
59
+ ),
60
+ InstanceAttribute(
61
+ name="return_degf_err_thres",
62
+ constant_form="RETURN_DEGF_ERR_THRES",
63
+ description="Return air temperature error threshold",
64
+ unit="°F",
65
+ type=float,
66
+ range=(0.0, 10.0),
67
+ ),
68
+ ]
69
+
70
+
71
+ class FaultConditionTwo(BaseFaultCondition, FaultConditionMixin):
72
+ """Class provides the definitions for Fault Condition 2.
73
+ Mix temperature too low; should be between outside and return air.
74
+ """
75
+
76
+ input_columns = INPUT_COLS
77
+ fault_params = FAULT_PARAMS
78
+ equation_string = "fc2_flag = 1 if (MAT - εMAT < min(RAT - εRAT, OAT - εOAT)) and (VFDSPD > 0) for N consecutive values else 0 \n"
79
+ description_string = "Fault Condition 2: Mix temperature too low; should be between outside and return air \n"
80
+ error_string = "One or more required columns are missing or None \n"
81
+
82
+ @FaultConditionMixin._handle_errors
83
+ def apply(self, df: pd.DataFrame) -> pd.DataFrame:
84
+ self._apply_common_checks(df)
85
+
86
+ # Get column values using accessor methods
87
+ supply_vfd_speed_col = self.get_input_column("supply_vfd_speed_col")
88
+ mat_col = self.get_input_column("mat_col")
89
+ rat_col = self.get_input_column("rat_col")
90
+ oat_col = self.get_input_column("oat_col")
91
+
92
+ # Get parameter values using accessor methods
93
+ mix_degf_err_thres = self.get_param("mix_degf_err_thres")
94
+ return_degf_err_thres = self.get_param("return_degf_err_thres")
95
+ outdoor_degf_err_thres = self.get_param("outdoor_degf_err_thres")
96
+
97
+ self._apply_analog_checks(
98
+ df, [supply_vfd_speed_col], check_greater_than_one=True
99
+ )
100
+
101
+ # Specific checks
102
+ mat_check = df[mat_col] - mix_degf_err_thres
103
+ temp_min_check = np.minimum(
104
+ df[rat_col] - return_degf_err_thres,
105
+ df[oat_col] - outdoor_degf_err_thres,
106
+ )
107
+ combined_check = (mat_check < temp_min_check) & (
108
+ df[supply_vfd_speed_col] > 0.01
109
+ )
110
+
111
+ self._set_fault_flag(df, combined_check, "fc2_flag")
112
+ return df
@@ -1,7 +1,17 @@
1
1
  import sys
2
- from open_fdd.air_handling_unit.faults.shared_utils import SharedUtils
2
+
3
3
  import pandas as pd
4
4
 
5
+ from open_fdd.core.utils import (
6
+ apply_rolling_average_if_needed,
7
+ clean_nan_values,
8
+ convert_to_float,
9
+ float_int_check_err,
10
+ float_max_check_err,
11
+ is_float,
12
+ not_greater_than_one,
13
+ )
14
+
5
15
 
6
16
  class HelperUtils:
7
17
 
@@ -12,25 +22,25 @@ class HelperUtils:
12
22
  self.config_dict = config_dict
13
23
 
14
24
  def clean_nan_values(self, df):
15
- return SharedUtils.clean_nan_values(df)
25
+ return clean_nan_values(df)
16
26
 
17
27
  def float_int_check_err(self, col):
18
- return SharedUtils.float_int_check_err(col)
28
+ return float_int_check_err(col)
19
29
 
20
30
  def float_max_check_err(self, col):
21
- return SharedUtils.float_max_check_err(col)
31
+ return float_max_check_err(col)
22
32
 
23
33
  def isfloat(self, num):
24
- return SharedUtils.isfloat(num)
34
+ return is_float(num)
25
35
 
26
36
  def isLessThanOnePointOne(self, num):
27
- return SharedUtils.isLessThanOnePointOne(num)
37
+ return not_greater_than_one(num)
28
38
 
29
39
  def convert_to_float(self, df, col):
30
- return SharedUtils.convert_to_float(df, col)
40
+ return convert_to_float(df, col)
31
41
 
32
42
  def apply_rolling_average_if_needed(self, df, freq="1min", rolling_window="5min"):
33
- return SharedUtils.apply_rolling_average_if_needed(df, freq, rolling_window)
43
+ return apply_rolling_average_if_needed(df, freq, rolling_window)
34
44
 
35
45
  def validate_config(self, required_columns):
36
46
  """
@@ -45,21 +55,21 @@ class HelperUtils:
45
55
  self.set_config_dict(config_dict)
46
56
 
47
57
  from open_fdd.air_handling_unit.faults import (
48
- FaultConditionOne,
49
- FaultConditionTwo,
50
- FaultConditionThree,
51
- FaultConditionFour,
52
- FaultConditionFive,
53
- FaultConditionSix,
54
- FaultConditionSeven,
55
58
  FaultConditionEight,
59
+ FaultConditionEleven,
60
+ FaultConditionFifteen,
61
+ FaultConditionFive,
62
+ FaultConditionFour,
63
+ FaultConditionFourteen,
56
64
  FaultConditionNine,
65
+ FaultConditionOne,
66
+ FaultConditionSeven,
67
+ FaultConditionSix,
57
68
  FaultConditionTen,
58
- FaultConditionEleven,
59
- FaultConditionTwelve,
60
69
  FaultConditionThirteen,
61
- FaultConditionFourteen,
62
- FaultConditionFifteen,
70
+ FaultConditionThree,
71
+ FaultConditionTwelve,
72
+ FaultConditionTwo,
63
73
  )
64
74
 
65
75
  fault_counts = {}
@@ -1,9 +1,11 @@
1
+ import sys
2
+
1
3
  import matplotlib.pyplot as plt
2
- from open_fdd.air_handling_unit.reports.fault_report import BaseFaultReport
3
- from open_fdd.air_handling_unit.faults import FaultConditionSixteen
4
- import pandas as pd
5
4
  import numpy as np
6
- import sys
5
+ import pandas as pd
6
+
7
+ from open_fdd.air_handling_unit.faults import FaultConditionSixteen
8
+ from open_fdd.air_handling_unit.reports.fault_report import BaseFaultReport
7
9
 
8
10
 
9
11
  class FaultCodeOneReport(BaseFaultReport):
@@ -1,7 +1,8 @@
1
+ import sys
2
+
1
3
  import matplotlib.pyplot as plt
2
- import pandas as pd
3
4
  import numpy as np
4
- import sys
5
+ import pandas as pd
5
6
 
6
7
 
7
8
  class BaseFaultReport: