open-fdd 0.1.3__py3-none-any.whl → 0.1.5__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 (40) hide show
  1. open_fdd/air_handling_unit/faults/__init__.py +2253 -0
  2. open_fdd/air_handling_unit/faults/fault_condition.py +12 -10
  3. open_fdd/air_handling_unit/faults/fault_condition_eight.py +38 -2
  4. open_fdd/air_handling_unit/faults/fault_condition_eleven.py +38 -2
  5. open_fdd/air_handling_unit/faults/fault_condition_fifteen.py +38 -2
  6. open_fdd/air_handling_unit/faults/fault_condition_five.py +38 -2
  7. open_fdd/air_handling_unit/faults/fault_condition_four.py +34 -2
  8. open_fdd/air_handling_unit/faults/fault_condition_fourteen.py +38 -2
  9. open_fdd/air_handling_unit/faults/fault_condition_nine.py +38 -2
  10. open_fdd/air_handling_unit/faults/fault_condition_one.py +37 -6
  11. open_fdd/air_handling_unit/faults/fault_condition_seven.py +38 -2
  12. open_fdd/air_handling_unit/faults/fault_condition_six.py +39 -2
  13. open_fdd/air_handling_unit/faults/fault_condition_ten.py +39 -3
  14. open_fdd/air_handling_unit/faults/fault_condition_thirteen.py +38 -2
  15. open_fdd/air_handling_unit/faults/fault_condition_three.py +32 -2
  16. open_fdd/air_handling_unit/faults/fault_condition_twelve.py +40 -3
  17. open_fdd/air_handling_unit/faults/fault_condition_two.py +32 -2
  18. open_fdd/air_handling_unit/faults/helper_utils.py +1 -29
  19. open_fdd/air_handling_unit/reports/__init__.py +894 -0
  20. open_fdd/air_handling_unit/reports/fault_report.py +41 -0
  21. open_fdd/tests/ahu/test_ahu_fc1.py +1 -1
  22. open_fdd/tests/ahu/test_ahu_fc10.py +1 -1
  23. open_fdd/tests/ahu/test_ahu_fc11.py +1 -1
  24. open_fdd/tests/ahu/test_ahu_fc12.py +1 -1
  25. open_fdd/tests/ahu/test_ahu_fc13.py +1 -1
  26. open_fdd/tests/ahu/test_ahu_fc14.py +1 -1
  27. open_fdd/tests/ahu/test_ahu_fc15.py +1 -1
  28. open_fdd/tests/ahu/test_ahu_fc2.py +1 -1
  29. open_fdd/tests/ahu/test_ahu_fc3.py +1 -1
  30. open_fdd/tests/ahu/test_ahu_fc4.py +199 -127
  31. open_fdd/tests/ahu/test_ahu_fc5.py +1 -1
  32. open_fdd/tests/ahu/test_ahu_fc6.py +2 -2
  33. open_fdd/tests/ahu/test_ahu_fc7.py +1 -1
  34. open_fdd/tests/ahu/test_ahu_fc8.py +1 -1
  35. open_fdd/tests/ahu/test_ahu_fc9.py +1 -1
  36. {open_fdd-0.1.3.dist-info → open_fdd-0.1.5.dist-info}/METADATA +21 -14
  37. {open_fdd-0.1.3.dist-info → open_fdd-0.1.5.dist-info}/RECORD +40 -39
  38. {open_fdd-0.1.3.dist-info → open_fdd-0.1.5.dist-info}/LICENSE +0 -0
  39. {open_fdd-0.1.3.dist-info → open_fdd-0.1.5.dist-info}/WHEEL +0 -0
  40. {open_fdd-0.1.3.dist-info → open_fdd-0.1.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,41 @@
1
+ import matplotlib.pyplot as plt
2
+ import pandas as pd
3
+ import numpy as np
4
+ import sys
5
+
6
+
7
+ class BaseFaultReport:
8
+ def __init__(self, config, fault_col):
9
+ self.config = config
10
+ self.fault_col = fault_col
11
+
12
+ def create_plot(self, df: pd.DataFrame):
13
+ raise NotImplementedError
14
+
15
+ def summarize_fault_times(self, df: pd.DataFrame) -> dict:
16
+ raise NotImplementedError
17
+
18
+ def create_hist_plot(self, df: pd.DataFrame):
19
+ df[f"hour_of_the_day_{self.fault_col}"] = df.index.hour.where(
20
+ df[self.fault_col] == 1
21
+ )
22
+ fig, ax = plt.subplots(tight_layout=True, figsize=(25, 8))
23
+ ax.hist(df[f"hour_of_the_day_{self.fault_col}"].dropna())
24
+ ax.set_xlabel("Hour of the Day")
25
+ ax.set_ylabel("Frequency")
26
+ ax.set_title(f"Hour-Of-Day When Fault Flag {self.fault_col} is TRUE")
27
+ plt.show()
28
+ plt.close()
29
+
30
+ def display_report_in_ipython(self, df: pd.DataFrame):
31
+ summary = self.summarize_fault_times(df)
32
+ for key, value in summary.items():
33
+ formatted_key = key.replace("_", " ")
34
+ print(f"{formatted_key}: {value}")
35
+ sys.stdout.flush()
36
+
37
+ if df[self.fault_col].max() != 0:
38
+ self.create_hist_plot(df)
39
+ else:
40
+ print("NO FAULTS FOUND - Skipping time-of-day Histogram plot")
41
+ sys.stdout.flush()
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_one import FaultConditionOne
3
+ from open_fdd.air_handling_unit.faults import FaultConditionOne
4
4
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
5
  from open_fdd.air_handling_unit.faults.fault_condition import MissingColumnError
6
6
 
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_ten import FaultConditionTen
3
+ from open_fdd.air_handling_unit.faults import FaultConditionTen
4
4
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
5
 
6
6
  """
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_eleven import (
3
+ from open_fdd.air_handling_unit.faults import (
4
4
  FaultConditionEleven,
5
5
  )
6
6
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_twelve import (
3
+ from open_fdd.air_handling_unit.faults import (
4
4
  FaultConditionTwelve,
5
5
  )
6
6
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_thirteen import (
3
+ from open_fdd.air_handling_unit.faults import (
4
4
  FaultConditionThirteen,
5
5
  )
6
6
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_fourteen import (
3
+ from open_fdd.air_handling_unit.faults import (
4
4
  FaultConditionFourteen,
5
5
  )
6
6
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_fifteen import (
3
+ from open_fdd.air_handling_unit.faults import (
4
4
  FaultConditionFifteen,
5
5
  )
6
6
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_two import FaultConditionTwo
3
+ from open_fdd.air_handling_unit.faults import FaultConditionTwo
4
4
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
5
 
6
6
  """
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_three import FaultConditionThree
3
+ from open_fdd.air_handling_unit.faults import FaultConditionThree
4
4
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
5
 
6
6
  """
@@ -1,128 +1,200 @@
1
1
  import pandas as pd
2
- from open_fdd.air_handling_unit.faults.fault_condition import (
3
- FaultCondition,
4
- MissingColumnError,
5
- )
6
- import sys
7
-
8
-
9
- class FaultConditionFour(FaultCondition):
10
- """Class provides the definitions for Fault Condition 4.
11
-
12
- This fault flags excessive operating states on the AHU
13
- if it's hunting between heating, econ, econ+mech, and
14
- a mech clg modes. The code counts how many operating
15
- changes in an hour and will throw a fault if there is
16
- excessive OS changes to flag control sys hunting.
17
- """
18
-
19
- def __init__(self, dict_):
20
- super().__init__()
21
- self.delta_os_max = float
22
- self.ahu_min_oa_dpr = float
23
- self.economizer_sig_col = str
24
- self.heating_sig_col = str
25
- self.cooling_sig_col = str
26
- self.supply_vfd_speed_col = str
27
- self.troubleshoot_mode = bool # default to False
28
-
29
- self.set_attributes(dict_)
30
-
31
- # Set required columns, making heating and cooling optional
32
- self.required_columns = [
33
- self.economizer_sig_col,
34
- self.supply_vfd_speed_col,
35
- ]
36
-
37
- # If heating or cooling columns are provided, add them to the required columns
38
- if self.heating_sig_col:
39
- self.required_columns.append(self.heating_sig_col)
40
- if self.cooling_sig_col:
41
- self.required_columns.append(self.cooling_sig_col)
42
-
43
- def get_required_columns(self) -> str:
44
- """Returns a string representation of the required columns."""
45
- return f"Required columns for FaultConditionFour: {', '.join(self.required_columns)}"
46
-
47
- def apply(self, df: pd.DataFrame) -> pd.DataFrame:
48
- try:
49
- # Ensure all required columns are present
50
- self.check_required_columns(df)
51
-
52
- # If the optional columns are not present, create them with all values set to 0.0
53
- if self.heating_sig_col not in df.columns:
54
- df[self.heating_sig_col] = 0.0
55
- if self.cooling_sig_col not in df.columns:
56
- df[self.cooling_sig_col] = 0.0
57
-
58
- if self.troubleshoot_mode:
59
- self.troubleshoot_cols(df)
60
-
61
- # Check analog outputs [data with units of %] are floats only
62
- columns_to_check = [
63
- self.economizer_sig_col,
64
- self.heating_sig_col,
65
- self.cooling_sig_col,
66
- self.supply_vfd_speed_col,
67
- ]
68
-
69
- for col in columns_to_check:
70
- self.check_analog_pct(df, [col])
71
-
72
- print("=" * 50)
73
- print("Warning: The program is in FC4 and resampling the data")
74
- print("to compute AHU OS state changes per hour")
75
- print("to flag any hunting issue")
76
- print("and this usually takes a while to run...")
77
- print("=" * 50)
78
-
79
- sys.stdout.flush()
80
-
81
- # AHU htg only mode based on OA damper @ min oa and only htg pid/vlv modulating
82
- df["heating_mode"] = (
83
- (df[self.heating_sig_col] > 0)
84
- & (df[self.cooling_sig_col] == 0)
85
- & (df[self.supply_vfd_speed_col] > 0)
86
- & (df[self.economizer_sig_col] == self.ahu_min_oa_dpr)
87
- )
88
-
89
- # AHU econ only mode based on OA damper modulating and clg htg = zero
90
- df["econ_only_cooling_mode"] = (
91
- (df[self.heating_sig_col] == 0)
92
- & (df[self.cooling_sig_col] == 0)
93
- & (df[self.supply_vfd_speed_col] > 0)
94
- & (df[self.economizer_sig_col] > self.ahu_min_oa_dpr)
95
- )
96
-
97
- # AHU econ+mech clg mode based on OA damper modulating for cooling and clg pid/vlv modulating
98
- df["econ_plus_mech_cooling_mode"] = (
99
- (df[self.heating_sig_col] == 0)
100
- & (df[self.cooling_sig_col] > 0)
101
- & (df[self.supply_vfd_speed_col] > 0)
102
- & (df[self.economizer_sig_col] > self.ahu_min_oa_dpr)
103
- )
104
-
105
- # AHU mech mode based on OA damper @ min OA and clg pid/vlv modulating
106
- df["mech_cooling_only_mode"] = (
107
- (df[self.heating_sig_col] == 0)
108
- & (df[self.cooling_sig_col] > 0)
109
- & (df[self.supply_vfd_speed_col] > 0)
110
- & (df[self.economizer_sig_col] == self.ahu_min_oa_dpr)
111
- )
112
-
113
- # Fill non-finite values with zero or drop them
114
- df = df.fillna(0)
115
-
116
- df = df.astype(int)
117
- df = df.resample("60min").apply(lambda x: (x.eq(1) & x.shift().ne(1)).sum())
118
-
119
- df["fc4_flag"] = (
120
- df[df.columns].gt(self.delta_os_max).any(axis=1).astype(int)
121
- )
122
-
123
- return df
124
-
125
- except MissingColumnError as e:
126
- print(f"Error: {e.message}")
127
- sys.stdout.flush()
128
- raise e # Re-raise the exception so it can be caught by pytest
2
+ import pytest
3
+ from open_fdd.air_handling_unit.faults import FaultConditionFour
4
+ from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
+ from datetime import datetime, timezone
6
+
7
+ """
8
+ To see print statements in pytest run with:
9
+ $ py -3.12 -m pytest tests/ahu/test_ahu_fc4.py -rP -s
10
+
11
+ Too much hunting in control system
12
+ OS state changes greater than 7 in an hour
13
+ """
14
+
15
+ # Constants
16
+ DELTA_OS_MAX = 7
17
+ AHU_MIN_OA = 0.20
18
+ TEST_MIX_AIR_DAMPER_COL = "economizer_sig_col"
19
+ TEST_HEATING_COIL_SIG_COL = "heating_sig_col"
20
+ TEST_COOLING_COIL_SIG_COL = "cooling_sig_col"
21
+ TEST_SUPPLY_VFD_SPEED_COL = "fan_vfd_speed_col"
22
+ TEST_DATASET_ROWS = 60
23
+
24
+ # Initialize FaultConditionFour with a dictionary
25
+ fault_condition_params = {
26
+ "DELTA_OS_MAX": DELTA_OS_MAX,
27
+ "AHU_MIN_OA_DPR": AHU_MIN_OA,
28
+ "ECONOMIZER_SIG_COL": TEST_MIX_AIR_DAMPER_COL,
29
+ "HEATING_SIG_COL": TEST_HEATING_COIL_SIG_COL,
30
+ "COOLING_SIG_COL": TEST_COOLING_COIL_SIG_COL,
31
+ "SUPPLY_VFD_SPEED_COL": TEST_SUPPLY_VFD_SPEED_COL,
32
+ "TROUBLESHOOT_MODE": False, # default value
33
+ }
34
+
35
+ fc4 = FaultConditionFour(fault_condition_params)
36
+
37
+
38
+ def generate_timestamp() -> pd.Series:
39
+ df = pd.DataFrame()
40
+ date_range = pd.period_range(
41
+ # make a time stamp starting at top of
42
+ # the hour with one min intervals
43
+ start=datetime(2022, 6, 6, 14, 30, 0, 0, tzinfo=timezone.utc),
44
+ periods=TEST_DATASET_ROWS,
45
+ freq="min",
46
+ )
47
+ df["Date"] = [x.to_timestamp() for x in date_range]
48
+ return df["Date"]
49
+
50
+
51
+ def econ_plus_mech_clg_row() -> dict:
52
+ data = {
53
+ TEST_MIX_AIR_DAMPER_COL: 0.6,
54
+ TEST_HEATING_COIL_SIG_COL: 0.0,
55
+ TEST_COOLING_COIL_SIG_COL: 0.6,
56
+ TEST_SUPPLY_VFD_SPEED_COL: 0.8,
57
+ }
58
+ return data
59
+
60
+
61
+ def mech_clg_row() -> dict:
62
+ data = {
63
+ TEST_MIX_AIR_DAMPER_COL: 0.0,
64
+ TEST_HEATING_COIL_SIG_COL: 0.0,
65
+ TEST_COOLING_COIL_SIG_COL: 0.6,
66
+ TEST_SUPPLY_VFD_SPEED_COL: 0.8,
67
+ }
68
+ return data
69
+
70
+
71
+ def econ_plus_mech_clg_row_int() -> dict:
72
+ data = {
73
+ TEST_MIX_AIR_DAMPER_COL: 0.6,
74
+ TEST_HEATING_COIL_SIG_COL: 0.0,
75
+ TEST_COOLING_COIL_SIG_COL: 0.6,
76
+ TEST_SUPPLY_VFD_SPEED_COL: 88,
77
+ }
78
+ return data
79
+
80
+
81
+ def econ_plus_mech_clg_row_float_greater_than_one() -> dict:
82
+ data = {
83
+ TEST_MIX_AIR_DAMPER_COL: 0.6,
84
+ TEST_HEATING_COIL_SIG_COL: 0.0,
85
+ TEST_COOLING_COIL_SIG_COL: 0.6,
86
+ TEST_SUPPLY_VFD_SPEED_COL: 88.8,
87
+ }
88
+ return data
89
+
90
+
91
+ class TestFault(object):
92
+
93
+ def fault_df(self) -> pd.DataFrame:
94
+ data = []
95
+ counter = 0
96
+ for i in range(TEST_DATASET_ROWS):
97
+ if i % 2 == 0 and counter < 11:
98
+ data.append(econ_plus_mech_clg_row())
99
+ counter += 1 # only simulate 10 OS changes
100
+ else:
101
+ data.append(mech_clg_row())
102
+ return pd.DataFrame(data)
103
+
104
+ def test_fault(self):
105
+ fault_df = self.fault_df().set_index(generate_timestamp())
106
+ results = fc4.apply(fault_df)
107
+ actual = results["fc4_flag"].sum()
108
+ expected = 1
109
+ message = f"FC4 fault_df actual is {actual} and expected is {expected}"
110
+ assert actual == expected, message
111
+
112
+
113
+ class TestNoFault(object):
114
+
115
+ def no_fault_df(self) -> pd.DataFrame:
116
+ data = []
117
+ for i in range(TEST_DATASET_ROWS):
118
+ data.append(mech_clg_row())
119
+ return pd.DataFrame(data)
120
+
121
+ def test_no_fault(self):
122
+ no_fault_df = self.no_fault_df().set_index(generate_timestamp())
123
+ results = fc4.apply(no_fault_df)
124
+ actual = results["fc4_flag"].sum()
125
+ expected = 0
126
+ message = f"FC4 no_fault_df actual is {actual} and expected is {expected}"
127
+ assert actual == expected, message
128
+
129
+
130
+ class TestFaultOnInt(object):
131
+
132
+ def fault_df_on_output_int(self) -> pd.DataFrame:
133
+ data = []
134
+ for i in range(TEST_DATASET_ROWS):
135
+ if i % 2 == 0:
136
+ data.append(econ_plus_mech_clg_row_int())
137
+ else:
138
+ data.append(mech_clg_row())
139
+ return pd.DataFrame(data)
140
+
141
+ def test_fault_on_int(self):
142
+ fault_df_on_output_int = self.fault_df_on_output_int().set_index(
143
+ generate_timestamp()
144
+ )
145
+ with pytest.raises(
146
+ TypeError,
147
+ match=HelperUtils().float_int_check_err(TEST_SUPPLY_VFD_SPEED_COL),
148
+ ):
149
+ fc4.apply(fault_df_on_output_int)
150
+
151
+
152
+ class TestFaultOnFloatGreaterThanOne(object):
153
+
154
+ def fault_df_on_output_greater_than_one(self) -> pd.DataFrame:
155
+ data = []
156
+ for i in range(TEST_DATASET_ROWS):
157
+ if i % 2 == 0:
158
+ data.append(econ_plus_mech_clg_row_float_greater_than_one())
159
+ else:
160
+ data.append(mech_clg_row())
161
+ return pd.DataFrame(data)
162
+
163
+ def test_fault_on_float_greater_than_one(self):
164
+ fault_df_on_output_greater_than_one = (
165
+ self.fault_df_on_output_greater_than_one().set_index(generate_timestamp())
166
+ )
167
+ with pytest.raises(
168
+ TypeError,
169
+ match=HelperUtils().float_max_check_err(TEST_SUPPLY_VFD_SPEED_COL),
170
+ ):
171
+ fc4.apply(fault_df_on_output_greater_than_one)
172
+
173
+
174
+ class TestFaultOnMixedTypes(object):
175
+
176
+ def fault_df_on_mixed_types(self) -> pd.DataFrame:
177
+ data = []
178
+ for i in range(TEST_DATASET_ROWS):
179
+ if i % 2 == 0:
180
+ data.append(
181
+ {
182
+ TEST_MIX_AIR_DAMPER_COL: 0.6,
183
+ TEST_HEATING_COIL_SIG_COL: 0.0,
184
+ TEST_COOLING_COIL_SIG_COL: 0.6,
185
+ TEST_SUPPLY_VFD_SPEED_COL: 1.1,
186
+ }
187
+ )
188
+ else:
189
+ data.append(mech_clg_row())
190
+ return pd.DataFrame(data)
191
+
192
+ def test_fault_on_mixed_types(self):
193
+ fault_df_on_mixed_types = self.fault_df_on_mixed_types().set_index(
194
+ generate_timestamp()
195
+ )
196
+ with pytest.raises(
197
+ TypeError,
198
+ match=HelperUtils().float_max_check_err(TEST_SUPPLY_VFD_SPEED_COL),
199
+ ):
200
+ fc4.apply(fault_df_on_mixed_types)
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_five import FaultConditionFive
3
+ from open_fdd.air_handling_unit.faults import FaultConditionFive
4
4
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
5
 
6
6
  """
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_six import FaultConditionSix
3
+ from open_fdd.air_handling_unit.faults import FaultConditionSix
4
4
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
5
 
6
6
  """
@@ -12,7 +12,7 @@ OA FRACTION TOO LOW OR TOO HIGH; SHOULD BE EQUAL TO %OAmin
12
12
 
13
13
  # Constants
14
14
  TEST_AIRFLOW_ERR_THRES = 0.3
15
- TEST_AHU_MIN_CFM_DESIGN = 3000
15
+ TEST_AHU_MIN_CFM_DESIGN = 3000.0
16
16
  TEST_OAT_DEGF_ERR_THRES = 5.0
17
17
  TEST_RAT_DEGF_ERR_THRES = 2.0
18
18
  TEST_DELTA_TEMP_MIN = 10.0
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_seven import FaultConditionSeven
3
+ from open_fdd.air_handling_unit.faults import FaultConditionSeven
4
4
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
5
 
6
6
  """
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_eight import FaultConditionEight
3
+ from open_fdd.air_handling_unit.faults import FaultConditionEight
4
4
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
5
 
6
6
  """
@@ -1,6 +1,6 @@
1
1
  import pandas as pd
2
2
  import pytest
3
- from open_fdd.air_handling_unit.faults.fault_condition_nine import FaultConditionNine
3
+ from open_fdd.air_handling_unit.faults import FaultConditionNine
4
4
  from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
5
5
 
6
6
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: open_fdd
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: A package for fault detection and diagnosis in HVAC systems
5
5
  Home-page: https://github.com/bbartling/open-fdd
6
6
  Author: Ben Bartling
@@ -39,21 +39,28 @@ pip install open-fdd
39
39
  For running Jupyter notebooks, I recommend using Visual Studio Code with the Jupyter notebook extension installed, which offers a seamless experience directly within the editor. Be sure to explore the `examples` directory for Jupyter notebook tutorials. If you have your own FDD experiences to share, feel free to contribute by creating a notebook (`.ipynb`). You’re welcome to reach out to me directly, and I can push your example to GitHub on your behalf, which might be a simpler process than submitting a pull request (PR), especially if you're just sharing an example rather than developing `open-fdd`.
40
40
 
41
41
  ## Project goals
42
- These are some basic project goals to make this into an interactive FDD application.
43
- - [x] finish `air_handling_unit` faults and reports based on ASHRAE and NIST
44
- - [x] publish to PyPI as Python library
45
- - [ ] make a few IPython notebook tutorials AHU FDD examples with `BRICK` meta data integration.
46
- - [ ] make a guide for fault `parameters` like error thresholds, etc.
47
- - [ ] make `central_plant` faults, IPython reports, and examples.
48
- - [ ] make `energy_efficiency` faults, IPython reports, and examples to `optimize` in reducing energy consumption.
49
- - [ ] make `metering`, faults, IPython reports, and examples to possibly model utility metering data.
50
- - [ ] create SQL example to read data from time series db and write back to SQL to then read faults in Grafana.
51
- - [ ] other?
52
-
53
- Certainly! Here's a revised version of your contribution guidelines:
42
+ The following are key objectives to enhance this project into a fully interactive Fault Detection and Diagnostics (FDD) application.
54
43
 
55
- ## Contribute
44
+ ### Completed
45
+ - [x] Develop and finalize `air_handling_unit` fault conditions and reports, aligning with ASHRAE and NIST standards.
46
+ - [x] Publish the project as a Python library on PyPI.
47
+
48
+ ### In Progress
49
+ - [ ] Create IPython notebook tutorials showcasing AHU FDD examples, incorporating BRICK metadata integration.
50
+ - [ ] Develop a comprehensive guide on a github.io website (or other?) for defining fault parameters, including error thresholds and other critical settings.
51
+
52
+ ### Upcoming
53
+ - [ ] Extend the project to include `central_plant` fault conditions, IPython reports, and example applications.
54
+ - [ ] Design `energy_efficiency` fault detection modules, including IPython reports and examples focused on optimizing energy consumption.
55
+ - [ ] Develop `metering` fault conditions, along with IPython reports and examples, potentially modeling utility metering data.
56
+ - [ ] Implement SQL integration examples for reading data from a time series database, writing back to SQL, and visualizing faults in Grafana.
56
57
 
58
+ ### Future Considerations
59
+ Explore additional features and enhancements as the project evolves.
60
+ - [ ] Explore additional features and enhancements as the project evolves.
61
+
62
+
63
+ ## Contribute
57
64
  If you have suggestions for improving developer best practices or solutions, please feel free to reach out to me directly using my contact information or Git issue/discussion. I primarily work on Windows with multiple versions of Python installed, with Python 3.12.x as my default version. You can download the latest version of Python here:
58
65
  * https://www.python.org/downloads/
59
66