open-fdd 0.1.4__py3-none-any.whl → 0.1.6__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 +301 -301
- open_fdd/air_handling_unit/reports/__init__.py +988 -0
- open_fdd/air_handling_unit/reports/fault_report.py +42 -0
- open_fdd/tests/ahu/test_ahu_fc16.py +190 -0
- {open_fdd-0.1.4.dist-info → open_fdd-0.1.6.dist-info}/METADATA +21 -12
- open_fdd-0.1.6.dist-info/RECORD +31 -0
- {open_fdd-0.1.4.dist-info → open_fdd-0.1.6.dist-info}/WHEEL +1 -1
- open_fdd/air_handling_unit/faults/fault_condition_eight.py +0 -127
- open_fdd/air_handling_unit/faults/fault_condition_eleven.py +0 -126
- open_fdd/air_handling_unit/faults/fault_condition_fifteen.py +0 -152
- open_fdd/air_handling_unit/faults/fault_condition_five.py +0 -123
- open_fdd/air_handling_unit/faults/fault_condition_four.py +0 -168
- open_fdd/air_handling_unit/faults/fault_condition_fourteen.py +0 -143
- open_fdd/air_handling_unit/faults/fault_condition_nine.py +0 -128
- open_fdd/air_handling_unit/faults/fault_condition_one.py +0 -112
- open_fdd/air_handling_unit/faults/fault_condition_seven.py +0 -114
- open_fdd/air_handling_unit/faults/fault_condition_six.py +0 -181
- open_fdd/air_handling_unit/faults/fault_condition_ten.py +0 -123
- open_fdd/air_handling_unit/faults/fault_condition_thirteen.py +0 -127
- open_fdd/air_handling_unit/faults/fault_condition_three.py +0 -113
- open_fdd/air_handling_unit/faults/fault_condition_twelve.py +0 -132
- open_fdd/air_handling_unit/faults/fault_condition_two.py +0 -113
- open_fdd/air_handling_unit/images/ahu1_fc1_2024-06_1.jpg +0 -0
- open_fdd/air_handling_unit/images/ahu1_fc1_2024-06_2.jpg +0 -0
- open_fdd/air_handling_unit/images/example1.jpg +0 -0
- open_fdd/air_handling_unit/images/example2.jpg +0 -0
- open_fdd/air_handling_unit/images/fc10_definition.png +0 -0
- open_fdd/air_handling_unit/images/fc11_definition.png +0 -0
- open_fdd/air_handling_unit/images/fc12_definition.png +0 -0
- open_fdd/air_handling_unit/images/fc13_definition.png +0 -0
- open_fdd/air_handling_unit/images/fc1_definition.png +0 -0
- open_fdd/air_handling_unit/images/fc1_report_screenshot_all.png +0 -0
- open_fdd/air_handling_unit/images/fc2_definition.png +0 -0
- open_fdd/air_handling_unit/images/fc3_definition.png +0 -0
- open_fdd/air_handling_unit/images/fc4_definition.png +0 -0
- open_fdd/air_handling_unit/images/fc5_definition.png +0 -0
- open_fdd/air_handling_unit/images/fc6_definition.png +0 -0
- open_fdd/air_handling_unit/images/fc7_definition.png +0 -0
- open_fdd/air_handling_unit/images/fc8_definition.png +0 -0
- open_fdd/air_handling_unit/images/fc9_definition.png +0 -0
- open_fdd/air_handling_unit/images/latex_generator.py +0 -175
- open_fdd/air_handling_unit/images/params.docx +0 -0
- open_fdd/air_handling_unit/images/params.pdf +0 -0
- open_fdd/air_handling_unit/images/plot_for_repo.png +0 -0
- open_fdd/air_handling_unit/reports/base_report.py +0 -47
- open_fdd/air_handling_unit/reports/report_fc1.py +0 -115
- open_fdd/air_handling_unit/reports/report_fc10.py +0 -126
- open_fdd/air_handling_unit/reports/report_fc11.py +0 -128
- open_fdd/air_handling_unit/reports/report_fc12.py +0 -126
- open_fdd/air_handling_unit/reports/report_fc13.py +0 -126
- open_fdd/air_handling_unit/reports/report_fc14.py +0 -124
- open_fdd/air_handling_unit/reports/report_fc15.py +0 -124
- open_fdd/air_handling_unit/reports/report_fc2.py +0 -119
- open_fdd/air_handling_unit/reports/report_fc3.py +0 -119
- open_fdd/air_handling_unit/reports/report_fc4.py +0 -148
- open_fdd/air_handling_unit/reports/report_fc5.py +0 -132
- open_fdd/air_handling_unit/reports/report_fc6.py +0 -156
- open_fdd/air_handling_unit/reports/report_fc7.py +0 -126
- open_fdd/air_handling_unit/reports/report_fc8.py +0 -118
- open_fdd/air_handling_unit/reports/report_fc9.py +0 -120
- open_fdd-0.1.4.dist-info/RECORD +0 -82
- {open_fdd-0.1.4.dist-info → open_fdd-0.1.6.dist-info}/LICENSE +0 -0
- {open_fdd-0.1.4.dist-info → open_fdd-0.1.6.dist-info}/top_level.txt +0 -0
@@ -1,126 +0,0 @@
|
|
1
|
-
import matplotlib.pyplot as plt
|
2
|
-
import pandas as pd
|
3
|
-
import sys
|
4
|
-
|
5
|
-
|
6
|
-
class FaultCodeTwelveReport:
|
7
|
-
"""Class provides the definitions for Fault Condition 12 Report."""
|
8
|
-
|
9
|
-
def __init__(self, config):
|
10
|
-
self.sat_col = config["SAT_COL"]
|
11
|
-
self.mat_col = config["MAT_COL"]
|
12
|
-
self.cooling_sig_col = config["COOLING_SIG_COL"]
|
13
|
-
self.economizer_sig_col = config["ECONOMIZER_SIG_COL"]
|
14
|
-
self.supply_vfd_speed_col = config["SUPPLY_VFD_SPEED_COL"]
|
15
|
-
|
16
|
-
def create_plot(self, df: pd.DataFrame, output_col: str = None):
|
17
|
-
if output_col is None:
|
18
|
-
output_col = "fc12_flag"
|
19
|
-
|
20
|
-
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(25, 8))
|
21
|
-
fig.suptitle("Fault Conditions 12 Plot")
|
22
|
-
|
23
|
-
ax1.plot(df.index, df[self.sat_col], label="SAT")
|
24
|
-
ax1.plot(df.index, df[self.mat_col], label="MAT")
|
25
|
-
ax1.legend(loc="best")
|
26
|
-
ax1.set_ylabel("AHU Temps °F")
|
27
|
-
|
28
|
-
ax2.plot(df.index, df[self.cooling_sig_col], label="AHU Cool Vlv", color="r")
|
29
|
-
ax2.plot(df.index, df[self.economizer_sig_col], label="AHU Dpr Cmd", color="g")
|
30
|
-
ax2.legend(loc="best")
|
31
|
-
ax2.set_ylabel("%")
|
32
|
-
|
33
|
-
ax3.plot(df.index, df[output_col], label="Fault", color="k")
|
34
|
-
ax3.set_xlabel("Date")
|
35
|
-
ax3.set_ylabel("Fault Flags")
|
36
|
-
ax3.legend(loc="best")
|
37
|
-
|
38
|
-
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
|
39
|
-
plt.show()
|
40
|
-
plt.close()
|
41
|
-
|
42
|
-
def summarize_fault_times(self, df: pd.DataFrame, output_col: str = None) -> dict:
|
43
|
-
if output_col is None:
|
44
|
-
output_col = "fc12_flag"
|
45
|
-
|
46
|
-
delta = df.index.to_series().diff()
|
47
|
-
summary = {
|
48
|
-
"total_days": round(delta.sum() / pd.Timedelta(days=1), 2),
|
49
|
-
"total_hours": round(delta.sum() / pd.Timedelta(hours=1)),
|
50
|
-
"hours_fc12_mode": round(
|
51
|
-
(delta * df[output_col]).sum() / pd.Timedelta(hours=1)
|
52
|
-
),
|
53
|
-
"percent_true": round(df[output_col].mean() * 100, 2),
|
54
|
-
"percent_false": round((100 - round(df[output_col].mean() * 100, 2)), 2),
|
55
|
-
"flag_true_mat": round(
|
56
|
-
df[self.mat_col].where(df[output_col] == 1).mean(), 2
|
57
|
-
),
|
58
|
-
"flag_true_sat": round(
|
59
|
-
df[self.sat_col].where(df[output_col] == 1).mean(), 2
|
60
|
-
),
|
61
|
-
"hours_motor_runtime": round(
|
62
|
-
(delta * df[self.supply_vfd_speed_col].gt(0.01).astype(int)).sum()
|
63
|
-
/ pd.Timedelta(hours=1),
|
64
|
-
2,
|
65
|
-
),
|
66
|
-
}
|
67
|
-
|
68
|
-
return summary
|
69
|
-
|
70
|
-
def create_hist_plot(self, df: pd.DataFrame, output_col: str = None):
|
71
|
-
if output_col is None:
|
72
|
-
output_col = "fc12_flag"
|
73
|
-
|
74
|
-
df["hour_of_the_day_fc12"] = df.index.hour.where(df[output_col] == 1)
|
75
|
-
|
76
|
-
fig, ax = plt.subplots(tight_layout=True, figsize=(25, 8))
|
77
|
-
ax.hist(df.hour_of_the_day_fc12.dropna())
|
78
|
-
ax.set_xlabel("24 Hour Number in Day")
|
79
|
-
ax.set_ylabel("Frequency")
|
80
|
-
ax.set_title(f"Hour-Of-Day When Fault Flag 12 is TRUE")
|
81
|
-
plt.show()
|
82
|
-
plt.close()
|
83
|
-
|
84
|
-
def display_report_in_ipython(
|
85
|
-
self, df: pd.DataFrame, output_col: str = "fc12_flag"
|
86
|
-
):
|
87
|
-
print(
|
88
|
-
"Fault Condition 12: Supply air temperature too high; should be less than mix air temperature in economizer plus mech cooling mode"
|
89
|
-
)
|
90
|
-
|
91
|
-
self.create_plot(df, output_col)
|
92
|
-
|
93
|
-
summary = self.summarize_fault_times(df, output_col)
|
94
|
-
|
95
|
-
for key, value in summary.items():
|
96
|
-
formatted_key = key.replace("_", " ")
|
97
|
-
print(f"{formatted_key}: {value}")
|
98
|
-
sys.stdout.flush()
|
99
|
-
|
100
|
-
fc_max_faults_found = df[output_col].max()
|
101
|
-
print("Fault Flag Count: ", fc_max_faults_found)
|
102
|
-
sys.stdout.flush()
|
103
|
-
|
104
|
-
if fc_max_faults_found != 0:
|
105
|
-
self.create_hist_plot(df, output_col)
|
106
|
-
|
107
|
-
flag_true_mat = round(df[self.mat_col].where(df[output_col] == 1).mean(), 2)
|
108
|
-
print("Mix Air Temp Mean When In Fault: ", flag_true_mat)
|
109
|
-
|
110
|
-
flag_true_sat = round(df[self.sat_col].where(df[output_col] == 1).mean(), 2)
|
111
|
-
print("Supply Air Temp Mean When In Fault: ", flag_true_sat)
|
112
|
-
|
113
|
-
sys.stdout.flush()
|
114
|
-
|
115
|
-
if summary["percent_true"] > 5.0:
|
116
|
-
print(
|
117
|
-
"The percent True metric that represents the amount of time for when the fault flag is True is high, indicating temperature sensor error or the heating/cooling coils may be leaking. Verify AHU mix/supply temperature sensor calibration and investigate potential mechanical issues like leaking valves."
|
118
|
-
)
|
119
|
-
else:
|
120
|
-
print(
|
121
|
-
"The percent True metric that represents the amount of time for when the fault flag is True is low, indicating the AHU components are within calibration for this fault equation."
|
122
|
-
)
|
123
|
-
|
124
|
-
else:
|
125
|
-
print("NO FAULTS FOUND - Skipping time-of-day Histogram plot")
|
126
|
-
sys.stdout.flush()
|
@@ -1,126 +0,0 @@
|
|
1
|
-
import matplotlib.pyplot as plt
|
2
|
-
import pandas as pd
|
3
|
-
import sys
|
4
|
-
|
5
|
-
|
6
|
-
class FaultCodeThirteenReport:
|
7
|
-
"""Class provides the definitions for Fault Condition 13 Report."""
|
8
|
-
|
9
|
-
def __init__(self, config):
|
10
|
-
self.sat_col = config["SAT_COL"]
|
11
|
-
self.mat_col = config["MAT_COL"]
|
12
|
-
self.cooling_sig_col = config["COOLING_SIG_COL"]
|
13
|
-
self.economizer_sig_col = config["ECONOMIZER_SIG_COL"]
|
14
|
-
self.supply_vfd_speed_col = config["SUPPLY_VFD_SPEED_COL"]
|
15
|
-
|
16
|
-
def create_plot(self, df: pd.DataFrame, output_col: str = None):
|
17
|
-
if output_col is None:
|
18
|
-
output_col = "fc13_flag"
|
19
|
-
|
20
|
-
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(25, 8))
|
21
|
-
fig.suptitle("Fault Conditions 13 Plot")
|
22
|
-
|
23
|
-
ax1.plot(df.index, df[self.sat_col], label="SAT")
|
24
|
-
ax1.plot(df.index, df[self.mat_col], label="MAT")
|
25
|
-
ax1.legend(loc="best")
|
26
|
-
ax1.set_ylabel("AHU Temps °F")
|
27
|
-
|
28
|
-
ax2.plot(df.index, df[self.cooling_sig_col], label="AHU Cool Vlv", color="r")
|
29
|
-
ax2.plot(df.index, df[self.economizer_sig_col], label="AHU Dpr Cmd", color="g")
|
30
|
-
ax2.legend(loc="best")
|
31
|
-
ax2.set_ylabel("%")
|
32
|
-
|
33
|
-
ax3.plot(df.index, df[output_col], label="Fault", color="k")
|
34
|
-
ax3.set_xlabel("Date")
|
35
|
-
ax3.set_ylabel("Fault Flags")
|
36
|
-
ax3.legend(loc="best")
|
37
|
-
|
38
|
-
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
|
39
|
-
plt.show()
|
40
|
-
plt.close()
|
41
|
-
|
42
|
-
def summarize_fault_times(self, df: pd.DataFrame, output_col: str = None) -> dict:
|
43
|
-
if output_col is None:
|
44
|
-
output_col = "fc13_flag"
|
45
|
-
|
46
|
-
delta = df.index.to_series().diff()
|
47
|
-
summary = {
|
48
|
-
"total_days": round(delta.sum() / pd.Timedelta(days=1), 2),
|
49
|
-
"total_hours": round(delta.sum() / pd.Timedelta(hours=1)),
|
50
|
-
"hours_fc13_mode": round(
|
51
|
-
(delta * df[output_col]).sum() / pd.Timedelta(hours=1)
|
52
|
-
),
|
53
|
-
"percent_true": round(df[output_col].mean() * 100, 2),
|
54
|
-
"percent_false": round((100 - round(df[output_col].mean() * 100, 2)), 2),
|
55
|
-
"flag_true_mat": round(
|
56
|
-
df[self.mat_col].where(df[output_col] == 1).mean(), 2
|
57
|
-
),
|
58
|
-
"flag_true_sat": round(
|
59
|
-
df[self.sat_col].where(df[output_col] == 1).mean(), 2
|
60
|
-
),
|
61
|
-
"hours_motor_runtime": round(
|
62
|
-
(delta * df[self.supply_vfd_speed_col].gt(0.01).astype(int)).sum()
|
63
|
-
/ pd.Timedelta(hours=1),
|
64
|
-
2,
|
65
|
-
),
|
66
|
-
}
|
67
|
-
|
68
|
-
return summary
|
69
|
-
|
70
|
-
def create_hist_plot(self, df: pd.DataFrame, output_col: str = None):
|
71
|
-
if output_col is None:
|
72
|
-
output_col = "fc13_flag"
|
73
|
-
|
74
|
-
df["hour_of_the_day_fc13"] = df.index.hour.where(df[output_col] == 1)
|
75
|
-
|
76
|
-
fig, ax = plt.subplots(tight_layout=True, figsize=(25, 8))
|
77
|
-
ax.hist(df.hour_of_the_day_fc13.dropna())
|
78
|
-
ax.set_xlabel("24 Hour Number in Day")
|
79
|
-
ax.set_ylabel("Frequency")
|
80
|
-
ax.set_title(f"Hour-Of-Day When Fault Flag 13 is TRUE")
|
81
|
-
plt.show()
|
82
|
-
plt.close()
|
83
|
-
|
84
|
-
def display_report_in_ipython(
|
85
|
-
self, df: pd.DataFrame, output_col: str = "fc13_flag"
|
86
|
-
):
|
87
|
-
print(
|
88
|
-
"Fault Condition 13: Supply air temperature too high in full cooling in economizer plus mech cooling mode"
|
89
|
-
)
|
90
|
-
|
91
|
-
self.create_plot(df, output_col)
|
92
|
-
|
93
|
-
summary = self.summarize_fault_times(df, output_col)
|
94
|
-
|
95
|
-
for key, value in summary.items():
|
96
|
-
formatted_key = key.replace("_", " ")
|
97
|
-
print(f"{formatted_key}: {value}")
|
98
|
-
sys.stdout.flush()
|
99
|
-
|
100
|
-
fc_max_faults_found = df[output_col].max()
|
101
|
-
print("Fault Flag Count: ", fc_max_faults_found)
|
102
|
-
sys.stdout.flush()
|
103
|
-
|
104
|
-
if fc_max_faults_found != 0:
|
105
|
-
self.create_hist_plot(df, output_col)
|
106
|
-
|
107
|
-
flag_true_mat = round(df[self.mat_col].where(df[output_col] == 1).mean(), 2)
|
108
|
-
print("Mix Air Temp Mean When In Fault: ", flag_true_mat)
|
109
|
-
|
110
|
-
flag_true_sat = round(df[self.sat_col].where(df[output_col] == 1).mean(), 2)
|
111
|
-
print("Supply Air Temp Mean When In Fault: ", flag_true_sat)
|
112
|
-
|
113
|
-
sys.stdout.flush()
|
114
|
-
|
115
|
-
if summary["percent_true"] > 5.0:
|
116
|
-
print(
|
117
|
-
"The percent True metric that represents the amount of time for when the fault flag is True is high, indicating temperature sensor error or issues with the cooling system. Verify AHU temperature sensor calibration and investigate potential mechanical issues."
|
118
|
-
)
|
119
|
-
else:
|
120
|
-
print(
|
121
|
-
"The percent True metric that represents the amount of time for when the fault flag is True is low, indicating the AHU components are within calibration for this fault equation."
|
122
|
-
)
|
123
|
-
|
124
|
-
else:
|
125
|
-
print("NO FAULTS FOUND - Skipping time-of-day Histogram plot")
|
126
|
-
sys.stdout.flush()
|
@@ -1,124 +0,0 @@
|
|
1
|
-
import matplotlib.pyplot as plt
|
2
|
-
import pandas as pd
|
3
|
-
import sys
|
4
|
-
|
5
|
-
|
6
|
-
class FaultCodeFourteenReport:
|
7
|
-
"""Class provides the definitions for Fault Condition 14 Report."""
|
8
|
-
|
9
|
-
def __init__(self, config):
|
10
|
-
self.sat_col = config["SAT_COL"]
|
11
|
-
self.clt_col = config["CLT_COL"]
|
12
|
-
self.cooling_sig_col = config["COOLING_SIG_COL"]
|
13
|
-
self.supply_vfd_speed_col = config["SUPPLY_VFD_SPEED_COL"]
|
14
|
-
|
15
|
-
def create_plot(self, df: pd.DataFrame, output_col: str = None):
|
16
|
-
if output_col is None:
|
17
|
-
output_col = "fc14_flag"
|
18
|
-
|
19
|
-
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(25, 8))
|
20
|
-
fig.suptitle("Fault Conditions 14 Plot")
|
21
|
-
|
22
|
-
ax1.plot(df.index, df[self.sat_col], label="SAT")
|
23
|
-
ax1.plot(df.index, df[self.clt_col], label="CLT")
|
24
|
-
ax1.legend(loc="best")
|
25
|
-
ax1.set_ylabel("AHU Temps °F")
|
26
|
-
|
27
|
-
ax2.plot(df.index, df[self.cooling_sig_col], label="AHU Cool Vlv", color="r")
|
28
|
-
ax2.legend(loc="best")
|
29
|
-
ax2.set_ylabel("%")
|
30
|
-
|
31
|
-
ax3.plot(df.index, df[output_col], label="Fault", color="k")
|
32
|
-
ax3.set_xlabel("Date")
|
33
|
-
ax3.set_ylabel("Fault Flags")
|
34
|
-
ax3.legend(loc="best")
|
35
|
-
|
36
|
-
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
|
37
|
-
plt.show()
|
38
|
-
plt.close()
|
39
|
-
|
40
|
-
def summarize_fault_times(self, df: pd.DataFrame, output_col: str = None) -> dict:
|
41
|
-
if output_col is None:
|
42
|
-
output_col = "fc14_flag"
|
43
|
-
|
44
|
-
delta = df.index.to_series().diff()
|
45
|
-
summary = {
|
46
|
-
"total_days": round(delta.sum() / pd.Timedelta(days=1), 2),
|
47
|
-
"total_hours": round(delta.sum() / pd.Timedelta(hours=1)),
|
48
|
-
"hours_fc14_mode": round(
|
49
|
-
(delta * df[output_col]).sum() / pd.Timedelta(hours=1)
|
50
|
-
),
|
51
|
-
"percent_true": round(df[output_col].mean() * 100, 2),
|
52
|
-
"percent_false": round((100 - round(df[output_col].mean() * 100, 2)), 2),
|
53
|
-
"flag_true_clt": round(
|
54
|
-
df[self.clt_col].where(df[output_col] == 1).mean(), 2
|
55
|
-
),
|
56
|
-
"flag_true_sat": round(
|
57
|
-
df[self.sat_col].where(df[output_col] == 1).mean(), 2
|
58
|
-
),
|
59
|
-
"hours_motor_runtime": round(
|
60
|
-
(delta * df[self.supply_vfd_speed_col].gt(0.01).astype(int)).sum()
|
61
|
-
/ pd.Timedelta(hours=1),
|
62
|
-
2,
|
63
|
-
),
|
64
|
-
}
|
65
|
-
|
66
|
-
return summary
|
67
|
-
|
68
|
-
def create_hist_plot(self, df: pd.DataFrame, output_col: str = None):
|
69
|
-
if output_col is None:
|
70
|
-
output_col = "fc14_flag"
|
71
|
-
|
72
|
-
df["hour_of_the_day_fc14"] = df.index.hour.where(df[output_col] == 1)
|
73
|
-
|
74
|
-
fig, ax = plt.subplots(tight_layout=True, figsize=(25, 8))
|
75
|
-
ax.hist(df.hour_of_the_day_fc14.dropna())
|
76
|
-
ax.set_xlabel("24 Hour Number in Day")
|
77
|
-
ax.set_ylabel("Frequency")
|
78
|
-
ax.set_title(f"Hour-Of-Day When Fault Flag 14 is TRUE")
|
79
|
-
plt.show()
|
80
|
-
plt.close()
|
81
|
-
|
82
|
-
def display_report_in_ipython(
|
83
|
-
self, df: pd.DataFrame, output_col: str = "fc14_flag"
|
84
|
-
):
|
85
|
-
print(
|
86
|
-
"Fault Condition 14: Temperature drop across inactive cooling coil (requires coil leaving temp sensor)"
|
87
|
-
)
|
88
|
-
|
89
|
-
self.create_plot(df, output_col)
|
90
|
-
|
91
|
-
summary = self.summarize_fault_times(df, output_col)
|
92
|
-
|
93
|
-
for key, value in summary.items():
|
94
|
-
formatted_key = key.replace("_", " ")
|
95
|
-
print(f"{formatted_key}: {value}")
|
96
|
-
sys.stdout.flush()
|
97
|
-
|
98
|
-
fc_max_faults_found = df[output_col].max()
|
99
|
-
print("Fault Flag Count: ", fc_max_faults_found)
|
100
|
-
sys.stdout.flush()
|
101
|
-
|
102
|
-
if fc_max_faults_found != 0:
|
103
|
-
self.create_hist_plot(df, output_col)
|
104
|
-
|
105
|
-
flag_true_clt = round(df[self.clt_col].where(df[output_col] == 1).mean(), 2)
|
106
|
-
print("Coil Leaving Temp Mean When In Fault: ", flag_true_clt)
|
107
|
-
|
108
|
-
flag_true_sat = round(df[self.sat_col].where(df[output_col] == 1).mean(), 2)
|
109
|
-
print("Supply Air Temp Mean When In Fault: ", flag_true_sat)
|
110
|
-
|
111
|
-
sys.stdout.flush()
|
112
|
-
|
113
|
-
if summary["percent_true"] > 5.0:
|
114
|
-
print(
|
115
|
-
"The percent True metric that represents the amount of time for when the fault flag is True is high, indicating potential leakage in the cooling coil. Verify temperature sensor calibration and investigate possible mechanical issues."
|
116
|
-
)
|
117
|
-
else:
|
118
|
-
print(
|
119
|
-
"The percent True metric that represents the amount of time for when the fault flag is True is low, indicating the cooling coil is likely functioning correctly."
|
120
|
-
)
|
121
|
-
|
122
|
-
else:
|
123
|
-
print("NO FAULTS FOUND - Skipping time-of-day Histogram plot")
|
124
|
-
sys.stdout.flush()
|
@@ -1,124 +0,0 @@
|
|
1
|
-
import matplotlib.pyplot as plt
|
2
|
-
import pandas as pd
|
3
|
-
import sys
|
4
|
-
|
5
|
-
|
6
|
-
class FaultCodeFifteenReport:
|
7
|
-
"""Class provides the definitions for Fault Condition 15 Report."""
|
8
|
-
|
9
|
-
def __init__(self, config):
|
10
|
-
self.sat_col = config["SAT_COL"]
|
11
|
-
self.hlt_col = config["HLT_COL"]
|
12
|
-
self.heating_sig_col = config["HEATING_SIG_COL"]
|
13
|
-
self.supply_vfd_speed_col = config["SUPPLY_VFD_SPEED_COL"]
|
14
|
-
|
15
|
-
def create_plot(self, df: pd.DataFrame, output_col: str = None):
|
16
|
-
if output_col is None:
|
17
|
-
output_col = "fc15_flag"
|
18
|
-
|
19
|
-
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(25, 8))
|
20
|
-
fig.suptitle("Fault Conditions 15 Plot")
|
21
|
-
|
22
|
-
ax1.plot(df.index, df[self.sat_col], label="SAT")
|
23
|
-
ax1.plot(df.index, df[self.hlt_col], label="HLT")
|
24
|
-
ax1.legend(loc="best")
|
25
|
-
ax1.set_ylabel("AHU Temps °F")
|
26
|
-
|
27
|
-
ax2.plot(df.index, df[self.heating_sig_col], label="AHU Heat Vlv", color="r")
|
28
|
-
ax2.legend(loc="best")
|
29
|
-
ax2.set_ylabel("%")
|
30
|
-
|
31
|
-
ax3.plot(df.index, df[output_col], label="Fault", color="k")
|
32
|
-
ax3.set_xlabel("Date")
|
33
|
-
ax3.set_ylabel("Fault Flags")
|
34
|
-
ax3.legend(loc="best")
|
35
|
-
|
36
|
-
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
|
37
|
-
plt.show()
|
38
|
-
plt.close()
|
39
|
-
|
40
|
-
def summarize_fault_times(self, df: pd.DataFrame, output_col: str = None) -> dict:
|
41
|
-
if output_col is None:
|
42
|
-
output_col = "fc15_flag"
|
43
|
-
|
44
|
-
delta = df.index.to_series().diff()
|
45
|
-
summary = {
|
46
|
-
"total_days": round(delta.sum() / pd.Timedelta(days=1), 2),
|
47
|
-
"total_hours": round(delta.sum() / pd.Timedelta(hours=1)),
|
48
|
-
"hours_fc15_mode": round(
|
49
|
-
(delta * df[output_col]).sum() / pd.Timedelta(hours=1)
|
50
|
-
),
|
51
|
-
"percent_true": round(df[output_col].mean() * 100, 2),
|
52
|
-
"percent_false": round((100 - round(df[output_col].mean() * 100, 2)), 2),
|
53
|
-
"flag_true_hlt": round(
|
54
|
-
df[self.hlt_col].where(df[output_col] == 1).mean(), 2
|
55
|
-
),
|
56
|
-
"flag_true_sat": round(
|
57
|
-
df[self.sat_col].where(df[output_col] == 1).mean(), 2
|
58
|
-
),
|
59
|
-
"hours_motor_runtime": round(
|
60
|
-
(delta * df[self.supply_vfd_speed_col].gt(0.01).astype(int)).sum()
|
61
|
-
/ pd.Timedelta(hours=1),
|
62
|
-
2,
|
63
|
-
),
|
64
|
-
}
|
65
|
-
|
66
|
-
return summary
|
67
|
-
|
68
|
-
def create_hist_plot(self, df: pd.DataFrame, output_col: str = None):
|
69
|
-
if output_col is None:
|
70
|
-
output_col = "fc15_flag"
|
71
|
-
|
72
|
-
df["hour_of_the_day_fc15"] = df.index.hour.where(df[output_col] == 1)
|
73
|
-
|
74
|
-
fig, ax = plt.subplots(tight_layout=True, figsize=(25, 8))
|
75
|
-
ax.hist(df.hour_of_the_day_fc15.dropna())
|
76
|
-
ax.set_xlabel("24 Hour Number in Day")
|
77
|
-
ax.set_ylabel("Frequency")
|
78
|
-
ax.set_title(f"Hour-Of-Day When Fault Flag 15 is TRUE")
|
79
|
-
plt.show()
|
80
|
-
plt.close()
|
81
|
-
|
82
|
-
def display_report_in_ipython(
|
83
|
-
self, df: pd.DataFrame, output_col: str = "fc15_flag"
|
84
|
-
):
|
85
|
-
print(
|
86
|
-
"Fault Condition 15: Temperature rise across inactive heating coil (requires coil leaving temp sensor)"
|
87
|
-
)
|
88
|
-
|
89
|
-
self.create_plot(df, output_col)
|
90
|
-
|
91
|
-
summary = self.summarize_fault_times(df, output_col)
|
92
|
-
|
93
|
-
for key, value in summary.items():
|
94
|
-
formatted_key = key.replace("_", " ")
|
95
|
-
print(f"{formatted_key}: {value}")
|
96
|
-
sys.stdout.flush()
|
97
|
-
|
98
|
-
fc_max_faults_found = df[output_col].max()
|
99
|
-
print("Fault Flag Count: ", fc_max_faults_found)
|
100
|
-
sys.stdout.flush()
|
101
|
-
|
102
|
-
if fc_max_faults_found != 0:
|
103
|
-
self.create_hist_plot(df, output_col)
|
104
|
-
|
105
|
-
flag_true_hlt = round(df[self.hlt_col].where(df[output_col] == 1).mean(), 2)
|
106
|
-
print("Coil Leaving Temp Mean When In Fault: ", flag_true_hlt)
|
107
|
-
|
108
|
-
flag_true_sat = round(df[self.sat_col].where(df[output_col] == 1).mean(), 2)
|
109
|
-
print("Supply Air Temp Mean When In Fault: ", flag_true_sat)
|
110
|
-
|
111
|
-
sys.stdout.flush()
|
112
|
-
|
113
|
-
if summary["percent_true"] > 5.0:
|
114
|
-
print(
|
115
|
-
"The percent True metric that represents the amount of time for when the fault flag is True is high, indicating potential leakage in the heating coil. Verify temperature sensor calibration and investigate possible mechanical issues."
|
116
|
-
)
|
117
|
-
else:
|
118
|
-
print(
|
119
|
-
"The percent True metric that represents the amount of time for when the fault flag is True is low, indicating the heating coil is likely functioning correctly."
|
120
|
-
)
|
121
|
-
|
122
|
-
else:
|
123
|
-
print("NO FAULTS FOUND - Skipping time-of-day Histogram plot")
|
124
|
-
sys.stdout.flush()
|
@@ -1,119 +0,0 @@
|
|
1
|
-
import matplotlib.pyplot as plt
|
2
|
-
import pandas as pd
|
3
|
-
import sys
|
4
|
-
|
5
|
-
|
6
|
-
class FaultCodeTwoReport:
|
7
|
-
def __init__(self, config):
|
8
|
-
self.mix_degf_err_thres = config["MIX_DEGF_ERR_THRES"]
|
9
|
-
self.return_degf_err_thres = config["RETURN_DEGF_ERR_THRES"]
|
10
|
-
self.outdoor_degf_err_thres = config["OUTDOOR_DEGF_ERR_THRES"]
|
11
|
-
self.mat_col = config["MAT_COL"]
|
12
|
-
self.rat_col = config["RAT_COL"]
|
13
|
-
self.oat_col = config["OAT_COL"]
|
14
|
-
self.supply_vfd_speed_col = config["SUPPLY_VFD_SPEED_COL"]
|
15
|
-
|
16
|
-
def create_plot(self, df: pd.DataFrame, output_col: str = None):
|
17
|
-
if output_col is None:
|
18
|
-
output_col = "fc2_flag"
|
19
|
-
|
20
|
-
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(25, 8))
|
21
|
-
fig.suptitle("Fault Conditions 2 Plot")
|
22
|
-
|
23
|
-
ax1.plot(df.index, df[self.mat_col], color="r", label="Mix Temp")
|
24
|
-
ax1.plot(df.index, df[self.rat_col], color="b", label="Return Temp")
|
25
|
-
ax1.plot(df.index, df[self.oat_col], color="g", label="Out Temp")
|
26
|
-
ax1.legend(loc="best")
|
27
|
-
ax1.set_ylabel("°F")
|
28
|
-
|
29
|
-
ax2.plot(df.index, df[output_col], label="Fault", color="k")
|
30
|
-
ax2.set_xlabel("Date")
|
31
|
-
ax2.set_ylabel("Fault Flags")
|
32
|
-
ax2.legend(loc="best")
|
33
|
-
|
34
|
-
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
|
35
|
-
plt.show()
|
36
|
-
plt.close()
|
37
|
-
|
38
|
-
def summarize_fault_times(self, df: pd.DataFrame, output_col: str = None) -> dict:
|
39
|
-
if output_col is None:
|
40
|
-
output_col = "fc2_flag"
|
41
|
-
|
42
|
-
delta = df.index.to_series().diff()
|
43
|
-
summary = {
|
44
|
-
"total_days": round(delta.sum() / pd.Timedelta(days=1), 2),
|
45
|
-
"total_hours": round(delta.sum() / pd.Timedelta(hours=1)),
|
46
|
-
"hours_fc2_mode": round(
|
47
|
-
(delta * df[output_col]).sum() / pd.Timedelta(hours=1)
|
48
|
-
),
|
49
|
-
"percent_true": round(df[output_col].mean() * 100, 2),
|
50
|
-
"percent_false": round((100 - round(df[output_col].mean() * 100, 2)), 2),
|
51
|
-
"flag_true_mat": round(
|
52
|
-
df[self.mat_col].where(df[output_col] == 1).mean(), 2
|
53
|
-
),
|
54
|
-
"flag_true_oat": round(
|
55
|
-
df[self.oat_col].where(df[output_col] == 1).mean(), 2
|
56
|
-
),
|
57
|
-
"flag_true_rat": round(
|
58
|
-
df[self.rat_col].where(df[output_col] == 1).mean(), 2
|
59
|
-
),
|
60
|
-
"hours_motor_runtime": round(
|
61
|
-
(delta * df[self.supply_vfd_speed_col].gt(0.01).astype(int)).sum()
|
62
|
-
/ pd.Timedelta(hours=1),
|
63
|
-
2,
|
64
|
-
),
|
65
|
-
}
|
66
|
-
|
67
|
-
return summary
|
68
|
-
|
69
|
-
def create_hist_plot(self, df: pd.DataFrame, output_col: str = None):
|
70
|
-
if output_col is None:
|
71
|
-
output_col = "fc2_flag"
|
72
|
-
|
73
|
-
df["hour_of_the_day_fc2"] = df.index.hour.where(df[output_col] == 1)
|
74
|
-
|
75
|
-
fig, ax = plt.subplots(tight_layout=True, figsize=(25, 8))
|
76
|
-
ax.hist(df.hour_of_the_day_fc2.dropna())
|
77
|
-
ax.set_xlabel("24 Hour Number in Day")
|
78
|
-
ax.set_ylabel("Frequency")
|
79
|
-
ax.set_title(f"Hour-Of-Day When Fault Flag 2 is TRUE")
|
80
|
-
plt.show()
|
81
|
-
plt.close()
|
82
|
-
|
83
|
-
def display_report_in_ipython(self, df: pd.DataFrame, output_col: str = "fc2_flag"):
|
84
|
-
print(
|
85
|
-
"Fault Condition 2: Mix temperature too low; should be between outside and return air"
|
86
|
-
)
|
87
|
-
|
88
|
-
self.create_plot(df, output_col)
|
89
|
-
|
90
|
-
summary = self.summarize_fault_times(df, output_col)
|
91
|
-
|
92
|
-
for key, value in summary.items():
|
93
|
-
formatted_key = key.replace("_", " ")
|
94
|
-
print(f"{formatted_key}: {value}")
|
95
|
-
sys.stdout.flush()
|
96
|
-
|
97
|
-
fc_max_faults_found = df[output_col].max()
|
98
|
-
print("Fault Flag Count: ", fc_max_faults_found)
|
99
|
-
sys.stdout.flush()
|
100
|
-
|
101
|
-
if fc_max_faults_found != 0:
|
102
|
-
self.create_hist_plot(df, output_col)
|
103
|
-
|
104
|
-
print("Mix Air Temp Mean When In Fault: ", summary["flag_true_mat"])
|
105
|
-
print("Outside Air Temp Mean When In Fault: ", summary["flag_true_oat"])
|
106
|
-
print("Return Temp Mean When In Fault: ", summary["flag_true_rat"])
|
107
|
-
|
108
|
-
if summary["percent_true"] > 5.0:
|
109
|
-
print(
|
110
|
-
"The percent True metric that represents the amount of time for when the fault flag is True is high, indicating potential issues with the mix temperature. Verify sensor calibration and investigate possible mechanical problems."
|
111
|
-
)
|
112
|
-
else:
|
113
|
-
print(
|
114
|
-
"The percent True metric that represents the amount of time for when the fault flag is True is low, indicating the system is likely functioning correctly."
|
115
|
-
)
|
116
|
-
|
117
|
-
else:
|
118
|
-
print("NO FAULTS FOUND - Skipping time-of-day Histogram plot")
|
119
|
-
sys.stdout.flush()
|