open-fdd 0.1.0__py3-none-any.whl → 0.1.3__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/fault_condition.py +26 -8
  2. open_fdd/air_handling_unit/faults/fault_condition_eight.py +61 -37
  3. open_fdd/air_handling_unit/faults/fault_condition_eleven.py +59 -37
  4. open_fdd/air_handling_unit/faults/fault_condition_fifteen.py +77 -51
  5. open_fdd/air_handling_unit/faults/fault_condition_five.py +60 -41
  6. open_fdd/air_handling_unit/faults/fault_condition_four.py +108 -65
  7. open_fdd/air_handling_unit/faults/fault_condition_fourteen.py +71 -44
  8. open_fdd/air_handling_unit/faults/fault_condition_nine.py +60 -36
  9. open_fdd/air_handling_unit/faults/fault_condition_one.py +58 -37
  10. open_fdd/air_handling_unit/faults/fault_condition_seven.py +55 -32
  11. open_fdd/air_handling_unit/faults/fault_condition_six.py +100 -76
  12. open_fdd/air_handling_unit/faults/fault_condition_ten.py +62 -37
  13. open_fdd/air_handling_unit/faults/fault_condition_thirteen.py +61 -36
  14. open_fdd/air_handling_unit/faults/fault_condition_three.py +58 -33
  15. open_fdd/air_handling_unit/faults/fault_condition_twelve.py +63 -39
  16. open_fdd/air_handling_unit/faults/fault_condition_two.py +58 -36
  17. open_fdd/air_handling_unit/faults/helper_utils.py +294 -64
  18. open_fdd/air_handling_unit/images/ahu1_fc1_2024-06_1.jpg +0 -0
  19. open_fdd/air_handling_unit/images/ahu1_fc1_2024-06_2.jpg +0 -0
  20. open_fdd/air_handling_unit/images/example1.jpg +0 -0
  21. open_fdd/air_handling_unit/images/example2.jpg +0 -0
  22. open_fdd/air_handling_unit/images/fc10_definition.png +0 -0
  23. open_fdd/air_handling_unit/images/fc11_definition.png +0 -0
  24. open_fdd/air_handling_unit/images/fc12_definition.png +0 -0
  25. open_fdd/air_handling_unit/images/fc13_definition.png +0 -0
  26. open_fdd/air_handling_unit/images/fc1_definition.png +0 -0
  27. open_fdd/air_handling_unit/images/fc1_report_screenshot_all.png +0 -0
  28. open_fdd/air_handling_unit/images/fc2_definition.png +0 -0
  29. open_fdd/air_handling_unit/images/fc3_definition.png +0 -0
  30. open_fdd/air_handling_unit/images/fc4_definition.png +0 -0
  31. open_fdd/air_handling_unit/images/fc5_definition.png +0 -0
  32. open_fdd/air_handling_unit/images/fc6_definition.png +0 -0
  33. open_fdd/air_handling_unit/images/fc7_definition.png +0 -0
  34. open_fdd/air_handling_unit/images/fc8_definition.png +0 -0
  35. open_fdd/air_handling_unit/images/fc9_definition.png +0 -0
  36. open_fdd/air_handling_unit/images/latex_generator.py +175 -0
  37. open_fdd/air_handling_unit/images/params.docx +0 -0
  38. open_fdd/air_handling_unit/images/params.pdf +0 -0
  39. open_fdd/air_handling_unit/images/plot_for_repo.png +0 -0
  40. open_fdd/air_handling_unit/reports/base_report.py +47 -0
  41. open_fdd/air_handling_unit/reports/report_fc7.py +3 -1
  42. open_fdd/tests/ahu/test_ahu_fc1.py +17 -0
  43. open_fdd/tests/ahu/test_ahu_fc4.py +127 -199
  44. open_fdd-0.1.3.dist-info/METADATA +87 -0
  45. {open_fdd-0.1.0.dist-info → open_fdd-0.1.3.dist-info}/RECORD +48 -25
  46. open_fdd-0.1.0.dist-info/METADATA +0 -65
  47. {open_fdd-0.1.0.dist-info → open_fdd-0.1.3.dist-info}/LICENSE +0 -0
  48. {open_fdd-0.1.0.dist-info → open_fdd-0.1.3.dist-info}/WHEEL +0 -0
  49. {open_fdd-0.1.0.dist-info → open_fdd-0.1.3.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,9 @@
1
1
  import pandas as pd
2
- import numpy as np
3
2
  import operator
4
- from open_fdd.air_handling_unit.faults.fault_condition import FaultCondition
5
- from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
3
+ from open_fdd.air_handling_unit.faults.fault_condition import (
4
+ FaultCondition,
5
+ MissingColumnError,
6
+ )
6
7
  import sys
7
8
 
8
9
 
@@ -13,6 +14,7 @@ class FaultConditionTwelve(FaultCondition):
13
14
  """
14
15
 
15
16
  def __init__(self, dict_):
17
+ super().__init__()
16
18
  self.delta_t_supply_fan = float
17
19
  self.mix_degf_err_thres = float
18
20
  self.supply_degf_err_thres = float
@@ -26,46 +28,68 @@ class FaultConditionTwelve(FaultCondition):
26
28
 
27
29
  self.set_attributes(dict_)
28
30
 
29
- def apply(self, df: pd.DataFrame) -> pd.DataFrame:
30
- if self.troubleshoot_mode:
31
- self.troubleshoot_cols(df)
32
-
33
- # Check analog outputs [data with units of %] are floats only
34
- columns_to_check = [
35
- self.economizer_sig_col,
31
+ # Set required columns specific to this fault condition
32
+ self.required_columns = [
33
+ self.sat_col,
34
+ self.mat_col,
36
35
  self.cooling_sig_col,
36
+ self.economizer_sig_col,
37
37
  ]
38
- self.check_analog_pct(df, columns_to_check)
39
38
 
40
- # Create helper columns
41
- df["sat_minus_saterr_delta_supply_fan"] = (
42
- df[self.sat_col] - self.supply_degf_err_thres - self.delta_t_supply_fan
43
- )
44
- df["mat_plus_materr"] = df[self.mat_col] + self.mix_degf_err_thres
39
+ def get_required_columns(self) -> str:
40
+ """Returns a string representation of the required columns."""
41
+ return f"Required columns for FaultConditionTwelve: {', '.join(self.required_columns)}"
45
42
 
46
- df["combined_check"] = operator.or_(
47
- # OS4 AHU state clg @ min OA
48
- (df["sat_minus_saterr_delta_supply_fan"] > df["mat_plus_materr"])
49
- # verify AHU in OS4 mode
50
- & (df[self.cooling_sig_col] > 0.01)
51
- & (df[self.economizer_sig_col] == self.ahu_min_oa_dpr), # OR
52
- (df["sat_minus_saterr_delta_supply_fan"] > df["mat_plus_materr"])
53
- # verify ahu is running in OS 3 clg mode in 100 OA
54
- & (df[self.cooling_sig_col] > 0.01) & (df[self.economizer_sig_col] > 0.9),
55
- )
43
+ def apply(self, df: pd.DataFrame) -> pd.DataFrame:
44
+ try:
45
+ # Ensure all required columns are present
46
+ self.check_required_columns(df)
56
47
 
57
- # Rolling sum to count consecutive trues
58
- rolling_sum = (
59
- df["combined_check"].rolling(window=self.rolling_window_size).sum()
60
- )
61
- # Set flag to 1 if rolling sum equals the window size
62
- df["fc12_flag"] = (rolling_sum >= self.rolling_window_size).astype(int)
48
+ if self.troubleshoot_mode:
49
+ self.troubleshoot_cols(df)
63
50
 
64
- if self.troubleshoot_mode:
65
- print("Troubleshoot mode enabled - not removing helper columns")
66
- sys.stdout.flush()
67
- del df["sat_minus_saterr_delta_supply_fan"]
68
- del df["mat_plus_materr"]
69
- del df["combined_check"]
51
+ # Check analog outputs [data with units of %] are floats only
52
+ columns_to_check = [
53
+ self.economizer_sig_col,
54
+ self.cooling_sig_col,
55
+ ]
56
+ self.check_analog_pct(df, columns_to_check)
70
57
 
71
- return df
58
+ # Create helper columns
59
+ df["sat_minus_saterr_delta_supply_fan"] = (
60
+ df[self.sat_col] - self.supply_degf_err_thres - self.delta_t_supply_fan
61
+ )
62
+ df["mat_plus_materr"] = df[self.mat_col] + self.mix_degf_err_thres
63
+
64
+ df["combined_check"] = operator.or_(
65
+ # OS4 AHU state clg @ min OA
66
+ (df["sat_minus_saterr_delta_supply_fan"] > df["mat_plus_materr"])
67
+ # verify AHU in OS4 mode
68
+ & (df[self.cooling_sig_col] > 0.01)
69
+ & (df[self.economizer_sig_col] == self.ahu_min_oa_dpr), # OR
70
+ (df["sat_minus_saterr_delta_supply_fan"] > df["mat_plus_materr"])
71
+ # verify ahu is running in OS 3 clg mode in 100 OA
72
+ & (df[self.cooling_sig_col] > 0.01)
73
+ & (df[self.economizer_sig_col] > 0.9),
74
+ )
75
+
76
+ # Rolling sum to count consecutive trues
77
+ rolling_sum = (
78
+ df["combined_check"].rolling(window=self.rolling_window_size).sum()
79
+ )
80
+ # Set flag to 1 if rolling sum equals the window size
81
+ df["fc12_flag"] = (rolling_sum >= self.rolling_window_size).astype(int)
82
+
83
+ if self.troubleshoot_mode:
84
+ print("Troubleshoot mode enabled - not removing helper columns")
85
+ sys.stdout.flush()
86
+ del df["sat_minus_saterr_delta_supply_fan"]
87
+ del df["mat_plus_materr"]
88
+ del df["combined_check"]
89
+
90
+ return df
91
+
92
+ except MissingColumnError as e:
93
+ print(f"Error: {e.message}")
94
+ sys.stdout.flush()
95
+ raise e # Re-raise the exception so it can be caught by pytest
@@ -1,6 +1,9 @@
1
1
  import pandas as pd
2
2
  import numpy as np
3
- from open_fdd.air_handling_unit.faults.fault_condition import FaultCondition
3
+ from open_fdd.air_handling_unit.faults.fault_condition import (
4
+ FaultCondition,
5
+ MissingColumnError,
6
+ )
4
7
  import sys
5
8
 
6
9
 
@@ -10,9 +13,7 @@ class FaultConditionTwo(FaultCondition):
10
13
  """
11
14
 
12
15
  def __init__(self, dict_):
13
- """
14
- :param dict_:
15
- """
16
+ super().__init__()
16
17
  self.mix_degf_err_thres = float
17
18
  self.return_degf_err_thres = float
18
19
  self.outdoor_degf_err_thres = float
@@ -25,37 +26,58 @@ class FaultConditionTwo(FaultCondition):
25
26
 
26
27
  self.set_attributes(dict_)
27
28
 
29
+ # Set required columns specific to this fault condition
30
+ self.required_columns = [
31
+ self.mat_col,
32
+ self.rat_col,
33
+ self.oat_col,
34
+ self.supply_vfd_speed_col,
35
+ ]
36
+
37
+ def get_required_columns(self) -> str:
38
+ """Returns a string representation of the required columns."""
39
+ return f"Required columns for FaultConditionTwo: {', '.join(self.required_columns)}"
40
+
28
41
  def apply(self, df: pd.DataFrame) -> pd.DataFrame:
29
- if self.troubleshoot_mode:
30
- self.troubleshoot_cols(df)
31
-
32
- # Check analog outputs [data with units of %] are floats only
33
- columns_to_check = [self.supply_vfd_speed_col]
34
- self.check_analog_pct(df, columns_to_check)
35
-
36
- # Fault condition-specific checks / flags
37
- df["mat_check"] = df[self.mat_col] + self.mix_degf_err_thres
38
- df["temp_min_check"] = np.minimum(
39
- df[self.rat_col] - self.return_degf_err_thres,
40
- df[self.oat_col] - self.outdoor_degf_err_thres,
41
- )
42
-
43
- df["combined_check"] = (df["mat_check"] < df["temp_min_check"]) & (
44
- df[self.supply_vfd_speed_col] > 0.01
45
- )
46
-
47
- # Rolling sum to count consecutive trues
48
- rolling_sum = (
49
- df["combined_check"].rolling(window=self.rolling_window_size).sum()
50
- )
51
- # Set flag to 1 if rolling sum equals the window size
52
- df["fc2_flag"] = (rolling_sum >= self.rolling_window_size).astype(int)
53
-
54
- if self.troubleshoot_mode:
55
- print("Troubleshoot mode enabled - not removing helper columns")
56
- sys.stdout.flush()
57
- del df["mat_check"]
58
- del df["temp_min_check"]
59
- del df["combined_check"]
42
+ try:
43
+ # Ensure all required columns are present
44
+ self.check_required_columns(df)
45
+
46
+ if self.troubleshoot_mode:
47
+ self.troubleshoot_cols(df)
48
+
49
+ # Check analog outputs [data with units of %] are floats only
50
+ columns_to_check = [self.supply_vfd_speed_col]
51
+ self.check_analog_pct(df, columns_to_check)
52
+
53
+ # Fault condition-specific checks / flags
54
+ df["mat_check"] = df[self.mat_col] + self.mix_degf_err_thres
55
+ df["temp_min_check"] = np.minimum(
56
+ df[self.rat_col] - self.return_degf_err_thres,
57
+ df[self.oat_col] - self.outdoor_degf_err_thres,
58
+ )
60
59
 
61
- return df
60
+ df["combined_check"] = (df["mat_check"] < df["temp_min_check"]) & (
61
+ df[self.supply_vfd_speed_col] > 0.01
62
+ )
63
+
64
+ # Rolling sum to count consecutive trues
65
+ rolling_sum = (
66
+ df["combined_check"].rolling(window=self.rolling_window_size).sum()
67
+ )
68
+ # Set flag to 1 if rolling sum equals the window size
69
+ df["fc2_flag"] = (rolling_sum >= self.rolling_window_size).astype(int)
70
+
71
+ if self.troubleshoot_mode:
72
+ print("Troubleshoot mode enabled - not removing helper columns")
73
+ sys.stdout.flush()
74
+ del df["mat_check"]
75
+ del df["temp_min_check"]
76
+ del df["combined_check"]
77
+
78
+ return df
79
+
80
+ except MissingColumnError as e:
81
+ print(f"Error: {e.message}")
82
+ sys.stdout.flush()
83
+ raise e # Re-raise the exception so it can be caught by pytest
@@ -4,6 +4,13 @@ import pandas as pd
4
4
 
5
5
 
6
6
  class HelperUtils:
7
+
8
+ def __init__(self):
9
+ self.config_dict = None
10
+
11
+ def set_config_dict(self, config_dict):
12
+ self.config_dict = config_dict
13
+
7
14
  def float_int_check_err(self, col):
8
15
  return SharedUtils.float_int_check_err(col)
9
16
 
@@ -22,8 +29,18 @@ class HelperUtils:
22
29
  def apply_rolling_average_if_needed(self, df, freq="1min", rolling_window="5min"):
23
30
  return SharedUtils.apply_rolling_average_if_needed(df, freq, rolling_window)
24
31
 
32
+ def validate_config(self, required_columns):
33
+ """
34
+ Check if all required columns are present and not None in the config dictionary.
35
+ """
36
+ if not self.config_dict:
37
+ raise ValueError("Config dictionary is not set.")
38
+ return all(self.config_dict.get(col) is not None for col in required_columns)
39
+
25
40
  def process_all_faults(self, df, config_dict):
26
- # Import fault conditions
41
+ # Set the config dictionary
42
+ self.set_config_dict(config_dict)
43
+
27
44
  from open_fdd.air_handling_unit.faults.fault_condition_one import (
28
45
  FaultConditionOne,
29
46
  )
@@ -75,112 +92,325 @@ class HelperUtils:
75
92
  # Apply rolling average if needed
76
93
  df = self.apply_rolling_average_if_needed(df)
77
94
 
78
- # Initialize Fault Condition Classes
79
- fc1 = FaultConditionOne(config_dict)
80
- fc2 = FaultConditionTwo(config_dict)
81
- fc3 = FaultConditionThree(config_dict)
82
- fc4 = FaultConditionFour(config_dict)
83
- fc5 = FaultConditionFive(config_dict)
84
- fc7 = FaultConditionSeven(config_dict)
85
- fc8 = FaultConditionEight(config_dict)
86
- fc9 = FaultConditionNine(config_dict)
87
- fc10 = FaultConditionTen(config_dict)
88
- fc11 = FaultConditionEleven(config_dict)
89
- fc12 = FaultConditionTwelve(config_dict)
90
- fc13 = FaultConditionThirteen(config_dict)
91
-
92
- # Optionally initialize Fault Condition Six
95
+ # Initialize Fault Condition Classes with necessary checks
96
+ fc1 = None
97
+ if self.validate_config(
98
+ ["DUCT_STATIC_COL", "DUCT_STATIC_SETPOINT_COL", "SUPPLY_VFD_SPEED_COL"]
99
+ ):
100
+ print("Info: Running fc1")
101
+ fc1 = FaultConditionOne(config_dict)
102
+ else:
103
+ print("Info: Skipping fc1")
104
+
105
+ sys.stdout.flush()
106
+
107
+ fc2 = None
108
+ if self.validate_config(
109
+ ["SUPPLY_VFD_SPEED_COL", "MAT_COL", "OAT_COL", "SAT_COL", "RAT_COL"]
110
+ ):
111
+ print("Info: Running fc2 Go!")
112
+ fc2 = FaultConditionTwo(config_dict)
113
+ else:
114
+ print("Info: Skipping fc2")
115
+
116
+ sys.stdout.flush()
117
+
118
+ fc3 = None
119
+ if self.validate_config(
120
+ ["SUPPLY_VFD_SPEED_COL", "MAT_COL", "OAT_COL", "SAT_COL", "RAT_COL"]
121
+ ):
122
+ print("Info: Running fc3 Go!")
123
+ fc3 = FaultConditionThree(config_dict)
124
+ else:
125
+ print("Info: Skipping fc3")
126
+
127
+ sys.stdout.flush()
128
+
129
+ fc4 = None
130
+ if self.validate_config(
131
+ [
132
+ "SUPPLY_VFD_SPEED_COL",
133
+ "COOLING_SIG_COL",
134
+ "HEATING_SIG_COL",
135
+ "ECONOMIZER_SIG_COL",
136
+ ]
137
+ ):
138
+ print("Info: Running fc4 Go!")
139
+ fc4 = FaultConditionFour(config_dict)
140
+ else:
141
+ print("Info: Skipping fc4")
142
+
143
+ sys.stdout.flush()
144
+
145
+ fc5 = None
146
+ if self.validate_config(
147
+ ["SUPPLY_VFD_SPEED_COL", "HEATING_SIG_COL", "SAT_COL", "MAT_COL"]
148
+ ):
149
+ print("Info: Running fc5 Go!")
150
+ fc5 = FaultConditionFive(config_dict)
151
+ else:
152
+ print("Info: Skipping fc5")
153
+
154
+ sys.stdout.flush()
155
+
93
156
  fc6 = None
94
- if config_dict.get("SUPPLY_FAN_AIR_VOLUME_COL") is not None:
157
+ if self.validate_config(
158
+ [
159
+ "SUPPLY_VFD_SPEED_COL",
160
+ "COOLING_SIG_COL",
161
+ "HEATING_SIG_COL",
162
+ "ECONOMIZER_SIG_COL",
163
+ "SUPPLY_FAN_AIR_VOLUME_COL",
164
+ ]
165
+ ):
166
+ print("Info: Running fc6 Go!")
95
167
  fc6 = FaultConditionSix(config_dict)
168
+ else:
169
+ print("Info: Skipping fc6")
170
+
171
+ sys.stdout.flush()
172
+
173
+ fc7 = None
174
+ if self.validate_config(
175
+ ["SUPPLY_VFD_SPEED_COL", "SAT_COL", "SAT_SETPOINT_COL", "HEATING_SIG_COL"]
176
+ ):
177
+ print("Info: Running fc7 Go!")
178
+ fc7 = FaultConditionSeven(config_dict)
179
+ else:
180
+ print("Info: Skipping fc7")
181
+
182
+ sys.stdout.flush()
183
+
184
+ fc8 = None
185
+ if self.validate_config(
186
+ [
187
+ "COOLING_SIG_COL",
188
+ "ECONOMIZER_SIG_COL",
189
+ "MAT_COL",
190
+ "SUPPLY_VFD_SPEED_COL",
191
+ "SAT_COL",
192
+ ]
193
+ ):
194
+ print("Info: Running fc8 Go!")
195
+ fc8 = FaultConditionEight(config_dict)
196
+ else:
197
+ print("Info: Skipping fc8")
198
+
199
+ sys.stdout.flush()
200
+
201
+ fc9 = None
202
+ if self.validate_config(
203
+ [
204
+ "OAT_COL",
205
+ "SUPPLY_VFD_SPEED_COL",
206
+ "SAT_COL",
207
+ "SAT_SETPOINT_COL",
208
+ "COOLING_SIG_COL",
209
+ "ECONOMIZER_SIG_COL",
210
+ ]
211
+ ):
212
+ print("Info: Running fc9 Go!")
213
+ fc9 = FaultConditionNine(config_dict)
214
+ else:
215
+ print("Info: Skipping fc9")
216
+
217
+ sys.stdout.flush()
218
+
219
+ fc10 = None
220
+ if self.validate_config(
221
+ [
222
+ "MAT_COL",
223
+ "OAT_COL",
224
+ "SUPPLY_VFD_SPEED_COL",
225
+ "COOLING_SIG_COL",
226
+ "ECONOMIZER_SIG_COL",
227
+ ]
228
+ ):
229
+ print("Info: Running fc10 Go!")
230
+ fc10 = FaultConditionTen(config_dict)
231
+ else:
232
+ print("Info: Skipping fc10")
233
+
234
+ sys.stdout.flush()
235
+
236
+ fc11 = None
237
+ if self.validate_config(
238
+ [
239
+ "OAT_COL",
240
+ "SUPPLY_VFD_SPEED_COL",
241
+ "COOLING_SIG_COL",
242
+ "ECONOMIZER_SIG_COL",
243
+ "SAT_SETPOINT_COL",
244
+ ]
245
+ ):
246
+ print("Info: Running fc11 Go!")
247
+ fc11 = FaultConditionEleven(config_dict)
248
+ else:
249
+ print("Info: Skipping fc11")
250
+
251
+ sys.stdout.flush()
252
+
253
+ fc12 = None
254
+ if self.validate_config(
255
+ [
256
+ "SUPPLY_VFD_SPEED_COL",
257
+ "ECONOMIZER_SIG_COL",
258
+ "COOLING_SIG_COL",
259
+ "SAT_COL",
260
+ "MAT_COL",
261
+ ]
262
+ ):
263
+ print("Info: Running fc12 Go!")
264
+ fc12 = FaultConditionTwelve(config_dict)
265
+ else:
266
+ print("Info: Skipping fc12")
267
+
268
+ sys.stdout.flush()
269
+
270
+ fc13 = None
271
+ if self.validate_config(
272
+ [
273
+ "SUPPLY_VFD_SPEED_COL",
274
+ "ECONOMIZER_SIG_COL",
275
+ "COOLING_SIG_COL",
276
+ "SAT_SETPOINT_COL",
277
+ "SAT_COL",
278
+ ]
279
+ ):
280
+ print("Info: Running fc13 Go!")
281
+ fc13 = FaultConditionThirteen(config_dict)
282
+ else:
283
+ print("Info: Skipping fc13")
284
+
285
+ sys.stdout.flush()
96
286
 
97
- # Optionally initialize Fault Condition Fourteen
98
287
  fc14 = None
99
288
  if (
100
289
  config_dict.get("COOLING_SIG_COL") is not None
101
290
  and config_dict.get("CLG_COIL_LEAVE_TEMP_COL") is not None
102
291
  ):
292
+ print("Info: Running fc14 Go!")
103
293
  fc14 = FaultConditionFourteen(config_dict)
294
+ else:
295
+ print("Info: Skipping fc14")
296
+
297
+ sys.stdout.flush()
104
298
 
105
- # Optionally initialize Fault Condition Fifteen
106
299
  fc15 = None
107
300
  if (
108
301
  config_dict.get("HTG_COIL_ENTER_TEMP_COL") is not None
109
302
  and config_dict.get("HTG_COIL_LEAVE_TEMP_COL") is not None
110
303
  ):
304
+ print("Info: Running fc15 Go!")
111
305
  fc15 = FaultConditionFifteen(config_dict)
306
+ else:
307
+ print("Info: Skipping fc15")
308
+
309
+ sys.stdout.flush()
112
310
 
113
311
  # Apply fault conditions and calculate fault counts
114
- df_fc1 = fc1.apply(df.copy())
115
- fault_counts["fc1_fault_sum"] = df_fc1["fc1_flag"].sum()
312
+ df_fc1 = fc1.apply(df.copy()) if fc1 is not None else None
313
+ if df_fc1 is not None:
314
+ fault_counts["fc1_fault_sum"] = df_fc1["fc1_flag"].sum()
116
315
 
117
- df_fc2 = fc2.apply(df.copy())
118
- fault_counts["fc2_fault_sum"] = df_fc2["fc2_flag"].sum()
316
+ df_fc2 = fc2.apply(df.copy()) if fc2 is not None else None
317
+ if df_fc2 is not None:
318
+ fault_counts["fc2_fault_sum"] = df_fc2["fc2_flag"].sum()
119
319
 
120
- df_fc3 = fc3.apply(df.copy())
121
- fault_counts["fc3_fault_sum"] = df_fc3["fc3_flag"].sum()
320
+ df_fc3 = fc3.apply(df.copy()) if fc3 is not None else None
321
+ if df_fc3 is not None:
322
+ fault_counts["fc3_fault_sum"] = df_fc3["fc3_flag"].sum()
122
323
 
123
- df_fc4 = fc4.apply(df.copy())
124
- fault_counts["fc4_fault_sum"] = df_fc4["fc4_flag"].sum()
324
+ df_fc4 = fc4.apply(df.copy()) if fc4 is not None else pd.DataFrame()
325
+ if not df_fc4.empty:
326
+ fault_counts["fc4_fault_sum"] = df_fc4["fc4_flag"].sum()
125
327
 
126
- df_fc5 = fc5.apply(df.copy())
127
- fault_counts["fc5_fault_sum"] = df_fc5["fc5_flag"].sum()
328
+ df_fc5 = fc5.apply(df.copy()) if fc5 is not None else None
329
+ if df_fc5 is not None:
330
+ fault_counts["fc5_fault_sum"] = df_fc5["fc5_flag"].sum()
128
331
 
129
- if fc6 is not None:
130
- df_fc6 = fc6.apply(df.copy())
332
+ df_fc6 = fc6.apply(df.copy()) if fc6 is not None else None
333
+ if df_fc6 is not None:
131
334
  fault_counts["fc6_fault_sum"] = df_fc6["fc6_flag"].sum()
132
335
 
133
- df_fc7 = fc7.apply(df.copy())
134
- fault_counts["fc7_fault_sum"] = df_fc7["fc7_flag"].sum()
336
+ df_fc7 = fc7.apply(df.copy()) if fc7 is not None else None
337
+ if df_fc7 is not None:
338
+ fault_counts["fc7_fault_sum"] = df_fc7["fc7_flag"].sum()
135
339
 
136
- df_fc8 = fc8.apply(df.copy())
137
- fault_counts["fc8_fault_sum"] = df_fc8["fc8_flag"].sum()
340
+ df_fc8 = fc8.apply(df.copy()) if fc8 is not None else None
341
+ if df_fc8 is not None:
342
+ fault_counts["fc8_fault_sum"] = df_fc8["fc8_flag"].sum()
138
343
 
139
- df_fc9 = fc9.apply(df.copy())
140
- fault_counts["fc9_fault_sum"] = df_fc9["fc9_flag"].sum()
344
+ df_fc9 = fc9.apply(df.copy()) if fc9 is not None else None
345
+ if df_fc9 is not None:
346
+ fault_counts["fc9_fault_sum"] = df_fc9["fc9_flag"].sum()
141
347
 
142
- df_fc10 = fc10.apply(df.copy())
143
- fault_counts["fc10_fault_sum"] = df_fc10["fc10_flag"].sum()
348
+ df_fc10 = fc10.apply(df.copy()) if fc10 is not None else None
349
+ if df_fc10 is not None:
350
+ fault_counts["fc10_fault_sum"] = df_fc10["fc10_flag"].sum()
144
351
 
145
- df_fc11 = fc11.apply(df.copy())
146
- fault_counts["fc11_fault_sum"] = df_fc11["fc11_flag"].sum()
352
+ df_fc11 = fc11.apply(df.copy()) if fc11 is not None else None
353
+ if df_fc11 is not None:
354
+ fault_counts["fc11_fault_sum"] = df_fc11["fc11_flag"].sum()
147
355
 
148
- df_fc12 = fc12.apply(df.copy())
149
- fault_counts["fc12_fault_sum"] = df_fc12["fc12_flag"].sum()
356
+ df_fc12 = fc12.apply(df.copy()) if fc12 is not None else None
357
+ if df_fc12 is not None:
358
+ fault_counts["fc12_fault_sum"] = df_fc12["fc12_flag"].sum()
150
359
 
151
- df_fc13 = fc13.apply(df.copy())
152
- fault_counts["fc13_fault_sum"] = df_fc13["fc13_flag"].sum()
360
+ df_fc13 = fc13.apply(df.copy()) if fc13 is not None else None
361
+ if df_fc13 is not None:
362
+ fault_counts["fc13_fault_sum"] = df_fc13["fc13_flag"].sum()
153
363
 
154
- if fc14 is not None:
155
- df_fc14 = fc14.apply(df.copy())
364
+ df_fc14 = fc14.apply(df.copy()) if fc14 is not None else None
365
+ if df_fc14 is not None:
156
366
  fault_counts["fc14_fault_sum"] = df_fc14["fc14_flag"].sum()
157
367
 
158
- if fc15 is not None:
159
- df_fc15 = fc15.apply(df.copy())
368
+ df_fc15 = fc15.apply(df.copy()) if fc15 is not None else None
369
+ if df_fc15 is not None:
160
370
  fault_counts["fc15_fault_sum"] = df_fc15["fc15_flag"].sum()
161
371
 
162
372
  # Combine fault condition results
163
- df_combined = df_fc1.copy()
164
- df_combined["fc2_flag"] = df_fc2["fc2_flag"]
165
- df_combined["fc3_flag"] = df_fc3["fc3_flag"]
166
- df_combined["fc4_flag"] = df_fc4["fc4_flag"]
167
- df_combined["fc5_flag"] = df_fc5["fc5_flag"]
373
+ df_combined = df_fc1.copy() if df_fc1 is not None else df.copy()
168
374
 
169
- if fc6 is not None:
375
+ if df_fc2 is not None:
376
+ df_combined["fc2_flag"] = df_fc2["fc2_flag"]
377
+
378
+ if df_fc3 is not None:
379
+ df_combined["fc3_flag"] = df_fc3["fc3_flag"]
380
+
381
+ # Skip combining df_fc4 since it is resampled
382
+
383
+ if df_fc5 is not None:
384
+ df_combined["fc5_flag"] = df_fc5["fc5_flag"]
385
+
386
+ if df_fc6 is not None:
170
387
  df_combined["fc6_flag"] = df_fc6["fc6_flag"]
171
388
 
172
- df_combined["fc7_flag"] = df_fc7["fc7_flag"]
173
- df_combined["fc8_flag"] = df_fc8["fc8_flag"]
174
- df_combined["fc9_flag"] = df_fc9["fc9_flag"]
175
- df_combined["fc10_flag"] = df_fc10["fc10_flag"]
176
- df_combined["fc11_flag"] = df_fc11["fc11_flag"]
177
- df_combined["fc12_flag"] = df_fc12["fc12_flag"]
178
- df_combined["fc13_flag"] = df_fc13["fc13_flag"]
389
+ if df_fc7 is not None:
390
+ df_combined["fc7_flag"] = df_fc7["fc7_flag"]
391
+
392
+ if df_fc8 is not None:
393
+ df_combined["fc8_flag"] = df_fc8["fc8_flag"]
394
+
395
+ if df_fc9 is not None:
396
+ df_combined["fc9_flag"] = df_fc9["fc9_flag"]
397
+
398
+ if df_fc10 is not None:
399
+ df_combined["fc10_flag"] = df_fc10["fc10_flag"]
400
+
401
+ if df_fc11 is not None:
402
+ df_combined["fc11_flag"] = df_fc11["fc11_flag"]
403
+
404
+ if df_fc12 is not None:
405
+ df_combined["fc12_flag"] = df_fc12["fc12_flag"]
406
+
407
+ if df_fc13 is not None:
408
+ df_combined["fc13_flag"] = df_fc13["fc13_flag"]
179
409
 
180
- if fc14 is not None:
410
+ if df_fc14 is not None:
181
411
  df_combined["fc14_flag"] = df_fc14["fc14_flag"]
182
412
 
183
- if fc15 is not None:
413
+ if df_fc15 is not None:
184
414
  df_combined["fc15_flag"] = df_fc15["fc15_flag"]
185
415
 
186
416
  # Save fault counts to CSV