open-fdd 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- open_fdd/__init__.py +39 -0
 - open_fdd/air_handling_unit/__init__.py +0 -0
 - open_fdd/air_handling_unit/faults/__init__.py +0 -0
 - open_fdd/air_handling_unit/faults/fault_condition.py +49 -0
 - open_fdd/air_handling_unit/faults/fault_condition_eight.py +67 -0
 - open_fdd/air_handling_unit/faults/fault_condition_eleven.py +68 -0
 - open_fdd/air_handling_unit/faults/fault_condition_fifteen.py +90 -0
 - open_fdd/air_handling_unit/faults/fault_condition_five.py +68 -0
 - open_fdd/air_handling_unit/faults/fault_condition_four.py +93 -0
 - open_fdd/air_handling_unit/faults/fault_condition_fourteen.py +80 -0
 - open_fdd/air_handling_unit/faults/fault_condition_nine.py +68 -0
 - open_fdd/air_handling_unit/faults/fault_condition_one.py +60 -0
 - open_fdd/air_handling_unit/faults/fault_condition_seven.py +55 -0
 - open_fdd/air_handling_unit/faults/fault_condition_six.py +120 -0
 - open_fdd/air_handling_unit/faults/fault_condition_ten.py +62 -0
 - open_fdd/air_handling_unit/faults/fault_condition_thirteen.py +66 -0
 - open_fdd/air_handling_unit/faults/fault_condition_three.py +58 -0
 - open_fdd/air_handling_unit/faults/fault_condition_twelve.py +71 -0
 - open_fdd/air_handling_unit/faults/fault_condition_two.py +61 -0
 - open_fdd/air_handling_unit/faults/helper_utils.py +191 -0
 - open_fdd/air_handling_unit/faults/shared_utils.py +75 -0
 - open_fdd/air_handling_unit/reports/__init__.py +0 -0
 - open_fdd/air_handling_unit/reports/report_fc1.py +115 -0
 - open_fdd/air_handling_unit/reports/report_fc10.py +126 -0
 - open_fdd/air_handling_unit/reports/report_fc11.py +128 -0
 - open_fdd/air_handling_unit/reports/report_fc12.py +126 -0
 - open_fdd/air_handling_unit/reports/report_fc13.py +126 -0
 - open_fdd/air_handling_unit/reports/report_fc14.py +124 -0
 - open_fdd/air_handling_unit/reports/report_fc15.py +124 -0
 - open_fdd/air_handling_unit/reports/report_fc2.py +119 -0
 - open_fdd/air_handling_unit/reports/report_fc3.py +119 -0
 - open_fdd/air_handling_unit/reports/report_fc4.py +148 -0
 - open_fdd/air_handling_unit/reports/report_fc5.py +132 -0
 - open_fdd/air_handling_unit/reports/report_fc6.py +156 -0
 - open_fdd/air_handling_unit/reports/report_fc7.py +124 -0
 - open_fdd/air_handling_unit/reports/report_fc8.py +118 -0
 - open_fdd/air_handling_unit/reports/report_fc9.py +120 -0
 - open_fdd/tests/__init__.py +0 -0
 - open_fdd/tests/ahu/__init__.py +0 -0
 - open_fdd/tests/ahu/test_ahu_fc1.py +159 -0
 - open_fdd/tests/ahu/test_ahu_fc10.py +132 -0
 - open_fdd/tests/ahu/test_ahu_fc11.py +136 -0
 - open_fdd/tests/ahu/test_ahu_fc12.py +167 -0
 - open_fdd/tests/ahu/test_ahu_fc13.py +163 -0
 - open_fdd/tests/ahu/test_ahu_fc14.py +197 -0
 - open_fdd/tests/ahu/test_ahu_fc15.py +183 -0
 - open_fdd/tests/ahu/test_ahu_fc2.py +132 -0
 - open_fdd/tests/ahu/test_ahu_fc3.py +131 -0
 - open_fdd/tests/ahu/test_ahu_fc4.py +200 -0
 - open_fdd/tests/ahu/test_ahu_fc5.py +180 -0
 - open_fdd/tests/ahu/test_ahu_fc6.py +246 -0
 - open_fdd/tests/ahu/test_ahu_fc7.py +71 -0
 - open_fdd/tests/ahu/test_ahu_fc8.py +131 -0
 - open_fdd/tests/ahu/test_ahu_fc9.py +136 -0
 - open_fdd-0.1.0.dist-info/LICENSE +21 -0
 - open_fdd-0.1.0.dist-info/METADATA +65 -0
 - open_fdd-0.1.0.dist-info/RECORD +59 -0
 - open_fdd-0.1.0.dist-info/WHEEL +5 -0
 - open_fdd-0.1.0.dist-info/top_level.txt +1 -0
 
    
        open_fdd/__init__.py
    ADDED
    
    | 
         @@ -0,0 +1,39 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            """
         
     | 
| 
      
 2 
     | 
    
         
            +
            open-fdd/                # Repository root
         
     | 
| 
      
 3 
     | 
    
         
            +
            ├── open_fdd/            # Python package root
         
     | 
| 
      
 4 
     | 
    
         
            +
            │   ├── __init__.py
         
     | 
| 
      
 5 
     | 
    
         
            +
            │   ├── air_handling_unit/
         
     | 
| 
      
 6 
     | 
    
         
            +
            │   │   ├── __init__.py
         
     | 
| 
      
 7 
     | 
    
         
            +
            │   │   ├── faults/
         
     | 
| 
      
 8 
     | 
    
         
            +
            │   │   │   ├── __init__.py
         
     | 
| 
      
 9 
     | 
    
         
            +
            │   │   │   ├── helper_utils.pya
         
     | 
| 
      
 10 
     | 
    
         
            +
            │   │   │   ├── fault_condition.py
         
     | 
| 
      
 11 
     | 
    
         
            +
            │   │   │   ├── fault_condition_one.py
         
     | 
| 
      
 12 
     | 
    
         
            +
            │   │   │   ├── fault_condition_two.py
         
     | 
| 
      
 13 
     | 
    
         
            +
            │   │   │   └── ... # other fault conditions
         
     | 
| 
      
 14 
     | 
    
         
            +
            │   │   ├── examples/
         
     | 
| 
      
 15 
     | 
    
         
            +
            │   │   ├── reports/
         
     | 
| 
      
 16 
     | 
    
         
            +
            │   │   │   ├── __init__.py
         
     | 
| 
      
 17 
     | 
    
         
            +
            │   │   │   ├── base_report.py
         
     | 
| 
      
 18 
     | 
    
         
            +
            │   │   │   ├── report_fc1.py
         
     | 
| 
      
 19 
     | 
    
         
            +
            │   │   │   ├── report_fc2.py
         
     | 
| 
      
 20 
     | 
    
         
            +
            │   │   │   └── ... # other reports
         
     | 
| 
      
 21 
     | 
    
         
            +
            │   │   └── images/
         
     | 
| 
      
 22 
     | 
    
         
            +
            │   │       ├── fc1_definition.png
         
     | 
| 
      
 23 
     | 
    
         
            +
            │   │       ├── fc2_definition.png
         
     | 
| 
      
 24 
     | 
    
         
            +
            │   │       └── ... # other images
         
     | 
| 
      
 25 
     | 
    
         
            +
            │   ├── black_box/
         
     | 
| 
      
 26 
     | 
    
         
            +
            │   │   └── ... # subject to change being experimental
         
     | 
| 
      
 27 
     | 
    
         
            +
            ├── tests/
         
     | 
| 
      
 28 
     | 
    
         
            +
            │   ├── __init__.py
         
     | 
| 
      
 29 
     | 
    
         
            +
            │   ├── air_handling_unit/
         
     | 
| 
      
 30 
     | 
    
         
            +
            │   │   ├── __init__.py
         
     | 
| 
      
 31 
     | 
    
         
            +
            │   │   ├── test_ahu_fc1.py
         
     | 
| 
      
 32 
     | 
    
         
            +
            │   │   ├── test_ahu_fc2.py
         
     | 
| 
      
 33 
     | 
    
         
            +
            │   │   └── ... # other tests
         
     | 
| 
      
 34 
     | 
    
         
            +
            ├── setup.py
         
     | 
| 
      
 35 
     | 
    
         
            +
            ├── README.md
         
     | 
| 
      
 36 
     | 
    
         
            +
            ├── LICENSE
         
     | 
| 
      
 37 
     | 
    
         
            +
            └── requirements.txt
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            """
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     | 
| 
         @@ -0,0 +1,49 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import pandas.api.types as pdtypes
         
     | 
| 
      
 2 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
         
     | 
| 
      
 3 
     | 
    
         
            +
            import sys
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            class FaultCondition:
         
     | 
| 
      
 7 
     | 
    
         
            +
                """Parent class for Fault Conditions. Methods are inherited to all children."""
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def set_attributes(self, dict_):
         
     | 
| 
      
 10 
     | 
    
         
            +
                    """Passes dictionary into initialization of class instance, then uses the attributes called out below in
         
     | 
| 
      
 11 
     | 
    
         
            +
                    attributes_dict to set only the attributes that match from dict_.
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    :param dict_: dictionary of all possible class attributes (loaded from config file)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    """
         
     | 
| 
      
 15 
     | 
    
         
            +
                    for attribute in self.__dict__:
         
     | 
| 
      
 16 
     | 
    
         
            +
                        upper = attribute.upper()
         
     | 
| 
      
 17 
     | 
    
         
            +
                        value = dict_[upper]
         
     | 
| 
      
 18 
     | 
    
         
            +
                        self.__setattr__(attribute, value)
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def troubleshoot_cols(self, df):
         
     | 
| 
      
 21 
     | 
    
         
            +
                    """print troubleshoot columns mapping
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    :param df:
         
     | 
| 
      
 24 
     | 
    
         
            +
                    :return:
         
     | 
| 
      
 25 
     | 
    
         
            +
                    """
         
     | 
| 
      
 26 
     | 
    
         
            +
                    print("Troubleshoot mode enabled - not removing helper columns")
         
     | 
| 
      
 27 
     | 
    
         
            +
                    for col in df.columns:
         
     | 
| 
      
 28 
     | 
    
         
            +
                        print(
         
     | 
| 
      
 29 
     | 
    
         
            +
                            "df column: ",
         
     | 
| 
      
 30 
     | 
    
         
            +
                            col,
         
     | 
| 
      
 31 
     | 
    
         
            +
                            "- max: ",
         
     | 
| 
      
 32 
     | 
    
         
            +
                            df[col].max(),
         
     | 
| 
      
 33 
     | 
    
         
            +
                            "- col type: ",
         
     | 
| 
      
 34 
     | 
    
         
            +
                            df[col].dtypes,
         
     | 
| 
      
 35 
     | 
    
         
            +
                        )
         
     | 
| 
      
 36 
     | 
    
         
            +
                        sys.stdout.flush()
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def check_analog_pct(self, df, columns):
         
     | 
| 
      
 39 
     | 
    
         
            +
                    """check analog outputs [data with units of %] are floats only
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    :param columns:
         
     | 
| 
      
 42 
     | 
    
         
            +
                    :return:
         
     | 
| 
      
 43 
     | 
    
         
            +
                    """
         
     | 
| 
      
 44 
     | 
    
         
            +
                    helper = HelperUtils()
         
     | 
| 
      
 45 
     | 
    
         
            +
                    for col in columns:
         
     | 
| 
      
 46 
     | 
    
         
            +
                        if not pdtypes.is_float_dtype(df[col]):
         
     | 
| 
      
 47 
     | 
    
         
            +
                            df = helper.convert_to_float(df, col)
         
     | 
| 
      
 48 
     | 
    
         
            +
                        if df[col].max() > 1.0:
         
     | 
| 
      
 49 
     | 
    
         
            +
                            raise TypeError(helper.float_max_check_err(col))
         
     | 
| 
         @@ -0,0 +1,67 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import pandas as pd
         
     | 
| 
      
 2 
     | 
    
         
            +
            import numpy as np
         
     | 
| 
      
 3 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.fault_condition import FaultCondition
         
     | 
| 
      
 4 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
         
     | 
| 
      
 5 
     | 
    
         
            +
            import sys
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            class FaultConditionEight(FaultCondition):
         
     | 
| 
      
 9 
     | 
    
         
            +
                """Class provides the definitions for Fault Condition 8.
         
     | 
| 
      
 10 
     | 
    
         
            +
                Supply air temperature and mix air temperature should
         
     | 
| 
      
 11 
     | 
    
         
            +
                be approx equal in economizer mode.
         
     | 
| 
      
 12 
     | 
    
         
            +
                """
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def __init__(self, dict_):
         
     | 
| 
      
 15 
     | 
    
         
            +
                    self.delta_t_supply_fan = float
         
     | 
| 
      
 16 
     | 
    
         
            +
                    self.mix_degf_err_thres = float
         
     | 
| 
      
 17 
     | 
    
         
            +
                    self.supply_degf_err_thres = float
         
     | 
| 
      
 18 
     | 
    
         
            +
                    self.ahu_min_oa_dpr = float
         
     | 
| 
      
 19 
     | 
    
         
            +
                    self.mat_col = str
         
     | 
| 
      
 20 
     | 
    
         
            +
                    self.sat_col = str
         
     | 
| 
      
 21 
     | 
    
         
            +
                    self.economizer_sig_col = str
         
     | 
| 
      
 22 
     | 
    
         
            +
                    self.cooling_sig_col = str
         
     | 
| 
      
 23 
     | 
    
         
            +
                    self.troubleshoot_mode = bool  # default should be False
         
     | 
| 
      
 24 
     | 
    
         
            +
                    self.rolling_window_size = int
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    self.set_attributes(dict_)
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                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 = [
         
     | 
| 
      
 34 
     | 
    
         
            +
                        self.economizer_sig_col,
         
     | 
| 
      
 35 
     | 
    
         
            +
                        self.cooling_sig_col,
         
     | 
| 
      
 36 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    self.check_analog_pct(df, columns_to_check)
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    df["sat_fan_mat"] = abs(
         
     | 
| 
      
 41 
     | 
    
         
            +
                        df[self.sat_col] - self.delta_t_supply_fan - df[self.mat_col]
         
     | 
| 
      
 42 
     | 
    
         
            +
                    )
         
     | 
| 
      
 43 
     | 
    
         
            +
                    df["sat_mat_sqrted"] = np.sqrt(
         
     | 
| 
      
 44 
     | 
    
         
            +
                        self.supply_degf_err_thres**2 + self.mix_degf_err_thres**2
         
     | 
| 
      
 45 
     | 
    
         
            +
                    )
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    df["combined_check"] = (
         
     | 
| 
      
 48 
     | 
    
         
            +
                        (df["sat_fan_mat"] > df["sat_mat_sqrted"])
         
     | 
| 
      
 49 
     | 
    
         
            +
                        & (df[self.economizer_sig_col] > self.ahu_min_oa_dpr)
         
     | 
| 
      
 50 
     | 
    
         
            +
                        & (df[self.cooling_sig_col] < 0.1)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    )
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                    # Rolling sum to count consecutive trues
         
     | 
| 
      
 54 
     | 
    
         
            +
                    rolling_sum = (
         
     | 
| 
      
 55 
     | 
    
         
            +
                        df["combined_check"].rolling(window=self.rolling_window_size).sum()
         
     | 
| 
      
 56 
     | 
    
         
            +
                    )
         
     | 
| 
      
 57 
     | 
    
         
            +
                    # Set flag to 1 if rolling sum equals the window size
         
     | 
| 
      
 58 
     | 
    
         
            +
                    df["fc8_flag"] = (rolling_sum >= self.rolling_window_size).astype(int)
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    if self.troubleshoot_mode:
         
     | 
| 
      
 61 
     | 
    
         
            +
                        print("Troubleshoot mode enabled - not removing helper columns")
         
     | 
| 
      
 62 
     | 
    
         
            +
                        sys.stdout.flush()
         
     | 
| 
      
 63 
     | 
    
         
            +
                        del df["sat_fan_mat"]
         
     | 
| 
      
 64 
     | 
    
         
            +
                        del df["sat_mat_sqrted"]
         
     | 
| 
      
 65 
     | 
    
         
            +
                        del df["combined_check"]
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                    return df
         
     | 
| 
         @@ -0,0 +1,68 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import pandas as pd
         
     | 
| 
      
 2 
     | 
    
         
            +
            import numpy as np
         
     | 
| 
      
 3 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.fault_condition import FaultCondition
         
     | 
| 
      
 4 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
         
     | 
| 
      
 5 
     | 
    
         
            +
            import sys
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            class FaultConditionEleven(FaultCondition):
         
     | 
| 
      
 9 
     | 
    
         
            +
                """Class provides the definitions for Fault Condition 11.
         
     | 
| 
      
 10 
     | 
    
         
            +
                Outside air temperature too low for 100% outdoor
         
     | 
| 
      
 11 
     | 
    
         
            +
                air cooling in economizer cooling mode.
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                Economizer performance fault
         
     | 
| 
      
 14 
     | 
    
         
            +
                """
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def __init__(self, dict_):
         
     | 
| 
      
 17 
     | 
    
         
            +
                    self.delta_t_supply_fan = float
         
     | 
| 
      
 18 
     | 
    
         
            +
                    self.outdoor_degf_err_thres = float
         
     | 
| 
      
 19 
     | 
    
         
            +
                    self.supply_degf_err_thres = float
         
     | 
| 
      
 20 
     | 
    
         
            +
                    self.sat_setpoint_col = str
         
     | 
| 
      
 21 
     | 
    
         
            +
                    self.oat_col = str
         
     | 
| 
      
 22 
     | 
    
         
            +
                    self.cooling_sig_col = str
         
     | 
| 
      
 23 
     | 
    
         
            +
                    self.economizer_sig_col = str
         
     | 
| 
      
 24 
     | 
    
         
            +
                    self.troubleshoot_mode = bool  # default False
         
     | 
| 
      
 25 
     | 
    
         
            +
                    self.rolling_window_size = int
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    self.set_attributes(dict_)
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 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,
         
     | 
| 
      
 36 
     | 
    
         
            +
                        self.cooling_sig_col,
         
     | 
| 
      
 37 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 38 
     | 
    
         
            +
                    self.check_analog_pct(df, columns_to_check)
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    df["oat_plus_oaterror"] = df[self.oat_col] + self.outdoor_degf_err_thres
         
     | 
| 
      
 41 
     | 
    
         
            +
                    df["satsp_delta_saterr"] = (
         
     | 
| 
      
 42 
     | 
    
         
            +
                        df[self.sat_setpoint_col]
         
     | 
| 
      
 43 
     | 
    
         
            +
                        - self.delta_t_supply_fan
         
     | 
| 
      
 44 
     | 
    
         
            +
                        - self.supply_degf_err_thres
         
     | 
| 
      
 45 
     | 
    
         
            +
                    )
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    df["combined_check"] = (
         
     | 
| 
      
 48 
     | 
    
         
            +
                        (df["oat_plus_oaterror"] < df["satsp_delta_saterr"])
         
     | 
| 
      
 49 
     | 
    
         
            +
                        # verify ahu is running in OS 3 clg mode in 100 OA
         
     | 
| 
      
 50 
     | 
    
         
            +
                        & (df[self.cooling_sig_col] > 0.01)
         
     | 
| 
      
 51 
     | 
    
         
            +
                        & (df[self.economizer_sig_col] > 0.9)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    )
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    # Rolling sum to count consecutive trues
         
     | 
| 
      
 55 
     | 
    
         
            +
                    rolling_sum = (
         
     | 
| 
      
 56 
     | 
    
         
            +
                        df["combined_check"].rolling(window=self.rolling_window_size).sum()
         
     | 
| 
      
 57 
     | 
    
         
            +
                    )
         
     | 
| 
      
 58 
     | 
    
         
            +
                    # Set flag to 1 if rolling sum equals the window size
         
     | 
| 
      
 59 
     | 
    
         
            +
                    df["fc11_flag"] = (rolling_sum >= self.rolling_window_size).astype(int)
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                    if self.troubleshoot_mode:
         
     | 
| 
      
 62 
     | 
    
         
            +
                        print("Troubleshoot mode enabled - not removing helper columns")
         
     | 
| 
      
 63 
     | 
    
         
            +
                        sys.stdout.flush()
         
     | 
| 
      
 64 
     | 
    
         
            +
                        del df["oat_plus_oaterror"]
         
     | 
| 
      
 65 
     | 
    
         
            +
                        del df["satsp_delta_saterr"]
         
     | 
| 
      
 66 
     | 
    
         
            +
                        del df["combined_check"]
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                    return df
         
     | 
| 
         @@ -0,0 +1,90 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import pandas as pd
         
     | 
| 
      
 2 
     | 
    
         
            +
            import numpy as np
         
     | 
| 
      
 3 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.fault_condition import FaultCondition
         
     | 
| 
      
 4 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
         
     | 
| 
      
 5 
     | 
    
         
            +
            import sys
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            class FaultConditionFifteen(FaultCondition):
         
     | 
| 
      
 9 
     | 
    
         
            +
                """Class provides the definitions for Fault Condition 15.
         
     | 
| 
      
 10 
     | 
    
         
            +
                Temperature rise across inactive heating coi.
         
     | 
| 
      
 11 
     | 
    
         
            +
                Requires coil leaving temp sensor.
         
     | 
| 
      
 12 
     | 
    
         
            +
                """
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def __init__(self, dict_):
         
     | 
| 
      
 15 
     | 
    
         
            +
                    self.delta_supply_fan = float
         
     | 
| 
      
 16 
     | 
    
         
            +
                    self.coil_temp_enter_err_thres = float
         
     | 
| 
      
 17 
     | 
    
         
            +
                    self.coil_temp_leav_err_thres = float
         
     | 
| 
      
 18 
     | 
    
         
            +
                    self.htg_coil_enter_temp_col = str
         
     | 
| 
      
 19 
     | 
    
         
            +
                    self.htg_coil_leave_temp_col = str
         
     | 
| 
      
 20 
     | 
    
         
            +
                    self.ahu_min_oa_dpr = float
         
     | 
| 
      
 21 
     | 
    
         
            +
                    self.cooling_sig_col = str
         
     | 
| 
      
 22 
     | 
    
         
            +
                    self.heating_sig_col = str
         
     | 
| 
      
 23 
     | 
    
         
            +
                    self.economizer_sig_col = str
         
     | 
| 
      
 24 
     | 
    
         
            +
                    self.supply_vfd_speed_col = str
         
     | 
| 
      
 25 
     | 
    
         
            +
                    self.troubleshoot_mode = bool  # default to False
         
     | 
| 
      
 26 
     | 
    
         
            +
                    self.rolling_window_size = int
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    self.set_attributes(dict_)
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def apply(self, df: pd.DataFrame) -> pd.DataFrame:
         
     | 
| 
      
 31 
     | 
    
         
            +
                    if self.troubleshoot_mode:
         
     | 
| 
      
 32 
     | 
    
         
            +
                        self.troubleshoot_cols(df)
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    # Check analog outputs [data with units of %] are floats only
         
     | 
| 
      
 35 
     | 
    
         
            +
                    columns_to_check = [
         
     | 
| 
      
 36 
     | 
    
         
            +
                        self.economizer_sig_col,
         
     | 
| 
      
 37 
     | 
    
         
            +
                        self.cooling_sig_col,
         
     | 
| 
      
 38 
     | 
    
         
            +
                        self.heating_sig_col,
         
     | 
| 
      
 39 
     | 
    
         
            +
                        self.supply_vfd_speed_col,
         
     | 
| 
      
 40 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 41 
     | 
    
         
            +
                    self.check_analog_pct(df, columns_to_check)
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    # Create helper columns
         
     | 
| 
      
 44 
     | 
    
         
            +
                    df["htg_delta_temp"] = (
         
     | 
| 
      
 45 
     | 
    
         
            +
                        df[self.htg_coil_leave_temp_col] - df[self.htg_coil_enter_temp_col]
         
     | 
| 
      
 46 
     | 
    
         
            +
                    )
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                    df["htg_delta_sqrted"] = (
         
     | 
| 
      
 49 
     | 
    
         
            +
                        np.sqrt(
         
     | 
| 
      
 50 
     | 
    
         
            +
                            self.coil_temp_enter_err_thres**2 + self.coil_temp_leav_err_thres**2
         
     | 
| 
      
 51 
     | 
    
         
            +
                        )
         
     | 
| 
      
 52 
     | 
    
         
            +
                        + self.delta_supply_fan
         
     | 
| 
      
 53 
     | 
    
         
            +
                    )
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                    df["combined_check"] = (
         
     | 
| 
      
 56 
     | 
    
         
            +
                        (
         
     | 
| 
      
 57 
     | 
    
         
            +
                            (df["htg_delta_temp"] >= df["htg_delta_sqrted"])
         
     | 
| 
      
 58 
     | 
    
         
            +
                            # verify AHU is in OS2 only free cooling mode
         
     | 
| 
      
 59 
     | 
    
         
            +
                            & (df[self.economizer_sig_col] > self.ahu_min_oa_dpr)
         
     | 
| 
      
 60 
     | 
    
         
            +
                            & (df[self.cooling_sig_col] < 0.1)
         
     | 
| 
      
 61 
     | 
    
         
            +
                        )
         
     | 
| 
      
 62 
     | 
    
         
            +
                        | (
         
     | 
| 
      
 63 
     | 
    
         
            +
                            (df["htg_delta_temp"] >= df["htg_delta_sqrted"])
         
     | 
| 
      
 64 
     | 
    
         
            +
                            # OS4 AHU state clg @ min OA
         
     | 
| 
      
 65 
     | 
    
         
            +
                            & (df[self.cooling_sig_col] > 0.01)
         
     | 
| 
      
 66 
     | 
    
         
            +
                            & (df[self.economizer_sig_col] == self.ahu_min_oa_dpr)
         
     | 
| 
      
 67 
     | 
    
         
            +
                        )
         
     | 
| 
      
 68 
     | 
    
         
            +
                        | (
         
     | 
| 
      
 69 
     | 
    
         
            +
                            (df["htg_delta_temp"] >= df["htg_delta_sqrted"])
         
     | 
| 
      
 70 
     | 
    
         
            +
                            # verify AHU is running in OS 3 clg mode in 100 OA
         
     | 
| 
      
 71 
     | 
    
         
            +
                            & (df[self.cooling_sig_col] > 0.01)
         
     | 
| 
      
 72 
     | 
    
         
            +
                            & (df[self.economizer_sig_col] > 0.9)
         
     | 
| 
      
 73 
     | 
    
         
            +
                        )
         
     | 
| 
      
 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["fc15_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["htg_delta_temp"]
         
     | 
| 
      
 87 
     | 
    
         
            +
                        del df["htg_delta_sqrted"]
         
     | 
| 
      
 88 
     | 
    
         
            +
                        del df["combined_check"]
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                    return df
         
     | 
| 
         @@ -0,0 +1,68 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import pandas as pd
         
     | 
| 
      
 2 
     | 
    
         
            +
            import pandas.api.types as pdtypes
         
     | 
| 
      
 3 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.fault_condition import FaultCondition
         
     | 
| 
      
 4 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
         
     | 
| 
      
 5 
     | 
    
         
            +
            import sys
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            class FaultConditionFive(FaultCondition):
         
     | 
| 
      
 9 
     | 
    
         
            +
                """Class provides the definitions for Fault Condition 5.
         
     | 
| 
      
 10 
     | 
    
         
            +
                SAT too low; should be higher than MAT in HTG MODE
         
     | 
| 
      
 11 
     | 
    
         
            +
                --Broken heating valve or other mechanical issue
         
     | 
| 
      
 12 
     | 
    
         
            +
                related to heat valve not working as designed
         
     | 
| 
      
 13 
     | 
    
         
            +
                """
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def __init__(self, dict_):
         
     | 
| 
      
 16 
     | 
    
         
            +
                    self.mix_degf_err_thres = float
         
     | 
| 
      
 17 
     | 
    
         
            +
                    self.supply_degf_err_thres = float
         
     | 
| 
      
 18 
     | 
    
         
            +
                    self.delta_t_supply_fan = float
         
     | 
| 
      
 19 
     | 
    
         
            +
                    self.mat_col = str
         
     | 
| 
      
 20 
     | 
    
         
            +
                    self.sat_col = str
         
     | 
| 
      
 21 
     | 
    
         
            +
                    self.heating_sig_col = str
         
     | 
| 
      
 22 
     | 
    
         
            +
                    self.supply_vfd_speed_col = str
         
     | 
| 
      
 23 
     | 
    
         
            +
                    self.troubleshoot_mode = bool  # default to False
         
     | 
| 
      
 24 
     | 
    
         
            +
                    self.rolling_window_size = int
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    self.set_attributes(dict_)
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                # fault only active if fan is running and htg vlv is modulating
         
     | 
| 
      
 29 
     | 
    
         
            +
                # OS 1 is heating mode only fault
         
     | 
| 
      
 30 
     | 
    
         
            +
                def apply(self, df: pd.DataFrame) -> pd.DataFrame:
         
     | 
| 
      
 31 
     | 
    
         
            +
                    if self.troubleshoot_mode:
         
     | 
| 
      
 32 
     | 
    
         
            +
                        self.troubleshoot_cols(df)
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    # check analog outputs [data with units of %] are floats only
         
     | 
| 
      
 35 
     | 
    
         
            +
                    columns_to_check = [self.supply_vfd_speed_col, self.heating_sig_col]
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    for col in columns_to_check:
         
     | 
| 
      
 38 
     | 
    
         
            +
                        self.check_analog_pct(df, [col])
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    df["sat_check"] = df[self.sat_col] + self.supply_degf_err_thres
         
     | 
| 
      
 41 
     | 
    
         
            +
                    df["mat_check"] = (
         
     | 
| 
      
 42 
     | 
    
         
            +
                        df[self.mat_col] - self.mix_degf_err_thres + self.delta_t_supply_fan
         
     | 
| 
      
 43 
     | 
    
         
            +
                    )
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    df["combined_check"] = (
         
     | 
| 
      
 46 
     | 
    
         
            +
                        (df["sat_check"] <= df["mat_check"])
         
     | 
| 
      
 47 
     | 
    
         
            +
                        # this is to make fault only active in OS1 for htg mode only
         
     | 
| 
      
 48 
     | 
    
         
            +
                        # and fan is running. Some control programming may use htg
         
     | 
| 
      
 49 
     | 
    
         
            +
                        # vlv when AHU is off to prevent low limit freeze alarms
         
     | 
| 
      
 50 
     | 
    
         
            +
                        & (df[self.heating_sig_col] > 0.01)
         
     | 
| 
      
 51 
     | 
    
         
            +
                        & (df[self.supply_vfd_speed_col] > 0.01)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    )
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    # Rolling sum to count consecutive trues
         
     | 
| 
      
 55 
     | 
    
         
            +
                    rolling_sum = (
         
     | 
| 
      
 56 
     | 
    
         
            +
                        df["combined_check"].rolling(window=self.rolling_window_size).sum()
         
     | 
| 
      
 57 
     | 
    
         
            +
                    )
         
     | 
| 
      
 58 
     | 
    
         
            +
                    # Set flag to 1 if rolling sum equals the window size
         
     | 
| 
      
 59 
     | 
    
         
            +
                    df["fc5_flag"] = (rolling_sum == self.rolling_window_size).astype(int)
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                    if self.troubleshoot_mode:
         
     | 
| 
      
 62 
     | 
    
         
            +
                        print("Troubleshoot mode enabled - not removing helper columns")
         
     | 
| 
      
 63 
     | 
    
         
            +
                        sys.stdout.flush()
         
     | 
| 
      
 64 
     | 
    
         
            +
                        del df["mat_check"]
         
     | 
| 
      
 65 
     | 
    
         
            +
                        del df["sat_check"]
         
     | 
| 
      
 66 
     | 
    
         
            +
                        del df["combined_check"]
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                    return df
         
     | 
| 
         @@ -0,0 +1,93 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import pandas as pd
         
     | 
| 
      
 2 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.fault_condition import FaultCondition
         
     | 
| 
      
 3 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
         
     | 
| 
      
 4 
     | 
    
         
            +
            import sys
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            class FaultConditionFour(FaultCondition):
         
     | 
| 
      
 8 
     | 
    
         
            +
                """Class provides the definitions for Fault Condition 4.
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                This fault flags excessive operating states on the AHU
         
     | 
| 
      
 11 
     | 
    
         
            +
                if its hunting between heating, econ, econ+mech, and
         
     | 
| 
      
 12 
     | 
    
         
            +
                a mech clg modes. The code counts how many operating
         
     | 
| 
      
 13 
     | 
    
         
            +
                changes in an hour and will throw a fault if there is
         
     | 
| 
      
 14 
     | 
    
         
            +
                excessive OS changes to flag control sys hunting.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                """
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def __init__(self, dict_):
         
     | 
| 
      
 19 
     | 
    
         
            +
                    self.delta_os_max = float
         
     | 
| 
      
 20 
     | 
    
         
            +
                    self.ahu_min_oa_dpr = float
         
     | 
| 
      
 21 
     | 
    
         
            +
                    self.economizer_sig_col = str
         
     | 
| 
      
 22 
     | 
    
         
            +
                    self.heating_sig_col = str
         
     | 
| 
      
 23 
     | 
    
         
            +
                    self.cooling_sig_col = str
         
     | 
| 
      
 24 
     | 
    
         
            +
                    self.supply_vfd_speed_col = str
         
     | 
| 
      
 25 
     | 
    
         
            +
                    self.troubleshoot_mode = bool  # default to False
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    self.set_attributes(dict_)
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                # adds in these boolean columns to the dataframe
         
     | 
| 
      
 30 
     | 
    
         
            +
                def apply(self, df: pd.DataFrame) -> pd.DataFrame:
         
     | 
| 
      
 31 
     | 
    
         
            +
                    if self.troubleshoot_mode:
         
     | 
| 
      
 32 
     | 
    
         
            +
                        self.troubleshoot_cols(df)
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    # check analog outputs [data with units of %] are floats only
         
     | 
| 
      
 35 
     | 
    
         
            +
                    columns_to_check = [
         
     | 
| 
      
 36 
     | 
    
         
            +
                        self.economizer_sig_col,
         
     | 
| 
      
 37 
     | 
    
         
            +
                        self.heating_sig_col,
         
     | 
| 
      
 38 
     | 
    
         
            +
                        self.cooling_sig_col,
         
     | 
| 
      
 39 
     | 
    
         
            +
                        self.supply_vfd_speed_col,
         
     | 
| 
      
 40 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                    for col in columns_to_check:
         
     | 
| 
      
 43 
     | 
    
         
            +
                        self.check_analog_pct(df, [col])
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    print("=" * 50)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    print("Warning: The program is in FC4 and resampling the data")
         
     | 
| 
      
 47 
     | 
    
         
            +
                    print("to compute AHU OS state changes per hour")
         
     | 
| 
      
 48 
     | 
    
         
            +
                    print("to flag any hunting issue")
         
     | 
| 
      
 49 
     | 
    
         
            +
                    print("and this usually takes a while to run...")
         
     | 
| 
      
 50 
     | 
    
         
            +
                    print("=" * 50)
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                    sys.stdout.flush()
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    # AHU htg only mode based on OA damper @ min oa and only htg pid/vlv modulating
         
     | 
| 
      
 55 
     | 
    
         
            +
                    df["heating_mode"] = (
         
     | 
| 
      
 56 
     | 
    
         
            +
                        (df[self.heating_sig_col] > 0)
         
     | 
| 
      
 57 
     | 
    
         
            +
                        & (df[self.cooling_sig_col] == 0)
         
     | 
| 
      
 58 
     | 
    
         
            +
                        & (df[self.supply_vfd_speed_col] > 0)
         
     | 
| 
      
 59 
     | 
    
         
            +
                        & (df[self.economizer_sig_col] == self.ahu_min_oa_dpr)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    )
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                    # AHU econ only mode based on OA damper modulating and clg htg = zero
         
     | 
| 
      
 63 
     | 
    
         
            +
                    df["econ_only_cooling_mode"] = (
         
     | 
| 
      
 64 
     | 
    
         
            +
                        (df[self.heating_sig_col] == 0)
         
     | 
| 
      
 65 
     | 
    
         
            +
                        & (df[self.cooling_sig_col] == 0)
         
     | 
| 
      
 66 
     | 
    
         
            +
                        & (df[self.supply_vfd_speed_col] > 0)
         
     | 
| 
      
 67 
     | 
    
         
            +
                        & (df[self.economizer_sig_col] > self.ahu_min_oa_dpr)
         
     | 
| 
      
 68 
     | 
    
         
            +
                    )
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    # AHU econ+mech clg mode based on OA damper modulating for cooling and clg pid/vlv modulating
         
     | 
| 
      
 71 
     | 
    
         
            +
                    df["econ_plus_mech_cooling_mode"] = (
         
     | 
| 
      
 72 
     | 
    
         
            +
                        (df[self.heating_sig_col] == 0)
         
     | 
| 
      
 73 
     | 
    
         
            +
                        & (df[self.cooling_sig_col] > 0)
         
     | 
| 
      
 74 
     | 
    
         
            +
                        & (df[self.supply_vfd_speed_col] > 0)
         
     | 
| 
      
 75 
     | 
    
         
            +
                        & (df[self.economizer_sig_col] > self.ahu_min_oa_dpr)
         
     | 
| 
      
 76 
     | 
    
         
            +
                    )
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                    # AHU mech mode based on OA damper @ min OA and clg pid/vlv modulating
         
     | 
| 
      
 79 
     | 
    
         
            +
                    df["mech_cooling_only_mode"] = (
         
     | 
| 
      
 80 
     | 
    
         
            +
                        (df[self.heating_sig_col] == 0)
         
     | 
| 
      
 81 
     | 
    
         
            +
                        & (df[self.cooling_sig_col] > 0)
         
     | 
| 
      
 82 
     | 
    
         
            +
                        & (df[self.supply_vfd_speed_col] > 0)
         
     | 
| 
      
 83 
     | 
    
         
            +
                        & (df[self.economizer_sig_col] == self.ahu_min_oa_dpr)
         
     | 
| 
      
 84 
     | 
    
         
            +
                    )
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                    # Fill non-finite values with zero or drop them
         
     | 
| 
      
 87 
     | 
    
         
            +
                    df = df.fillna(0)
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                    df = df.astype(int)
         
     | 
| 
      
 90 
     | 
    
         
            +
                    df = df.resample("60min").apply(lambda x: (x.eq(1) & x.shift().ne(1)).sum())
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                    df["fc4_flag"] = df[df.columns].gt(self.delta_os_max).any(axis=1).astype(int)
         
     | 
| 
      
 93 
     | 
    
         
            +
                    return df
         
     | 
| 
         @@ -0,0 +1,80 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import pandas as pd
         
     | 
| 
      
 2 
     | 
    
         
            +
            import numpy as np
         
     | 
| 
      
 3 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.fault_condition import FaultCondition
         
     | 
| 
      
 4 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
         
     | 
| 
      
 5 
     | 
    
         
            +
            import operator
         
     | 
| 
      
 6 
     | 
    
         
            +
            import sys
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            class FaultConditionFourteen(FaultCondition):
         
     | 
| 
      
 10 
     | 
    
         
            +
                """Class provides the definitions for Fault Condition 14.
         
     | 
| 
      
 11 
     | 
    
         
            +
                Temperature drop across inactive cooling coil.
         
     | 
| 
      
 12 
     | 
    
         
            +
                Requires coil leaving temp sensor.
         
     | 
| 
      
 13 
     | 
    
         
            +
                """
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def __init__(self, dict_):
         
     | 
| 
      
 16 
     | 
    
         
            +
                    self.delta_t_supply_fan = float
         
     | 
| 
      
 17 
     | 
    
         
            +
                    self.coil_temp_enter_err_thres = float
         
     | 
| 
      
 18 
     | 
    
         
            +
                    self.coil_temp_leav_err_thres = float
         
     | 
| 
      
 19 
     | 
    
         
            +
                    self.clg_coil_enter_temp_col = str
         
     | 
| 
      
 20 
     | 
    
         
            +
                    self.clg_coil_leave_temp_col = str
         
     | 
| 
      
 21 
     | 
    
         
            +
                    self.ahu_min_oa_dpr = float
         
     | 
| 
      
 22 
     | 
    
         
            +
                    self.cooling_sig_col = str
         
     | 
| 
      
 23 
     | 
    
         
            +
                    self.heating_sig_col = str
         
     | 
| 
      
 24 
     | 
    
         
            +
                    self.economizer_sig_col = str
         
     | 
| 
      
 25 
     | 
    
         
            +
                    self.supply_vfd_speed_col = str
         
     | 
| 
      
 26 
     | 
    
         
            +
                    self.troubleshoot_mode = bool  # default to False
         
     | 
| 
      
 27 
     | 
    
         
            +
                    self.rolling_window_size = int
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                    self.set_attributes(dict_)
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def apply(self, df: pd.DataFrame) -> pd.DataFrame:
         
     | 
| 
      
 32 
     | 
    
         
            +
                    if self.troubleshoot_mode:
         
     | 
| 
      
 33 
     | 
    
         
            +
                        self.troubleshoot_cols(df)
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    # Check analog outputs [data with units of %] are floats only
         
     | 
| 
      
 36 
     | 
    
         
            +
                    columns_to_check = [
         
     | 
| 
      
 37 
     | 
    
         
            +
                        self.economizer_sig_col,
         
     | 
| 
      
 38 
     | 
    
         
            +
                        self.cooling_sig_col,
         
     | 
| 
      
 39 
     | 
    
         
            +
                        self.heating_sig_col,
         
     | 
| 
      
 40 
     | 
    
         
            +
                        self.supply_vfd_speed_col,
         
     | 
| 
      
 41 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 42 
     | 
    
         
            +
                    self.check_analog_pct(df, columns_to_check)
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    # Create helper columns
         
     | 
| 
      
 45 
     | 
    
         
            +
                    df["clg_delta_temp"] = (
         
     | 
| 
      
 46 
     | 
    
         
            +
                        df[self.clg_coil_enter_temp_col] - df[self.clg_coil_leave_temp_col]
         
     | 
| 
      
 47 
     | 
    
         
            +
                    )
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                    df["clg_delta_sqrted"] = (
         
     | 
| 
      
 50 
     | 
    
         
            +
                        np.sqrt(
         
     | 
| 
      
 51 
     | 
    
         
            +
                            self.coil_temp_enter_err_thres**2 + self.coil_temp_leav_err_thres**2
         
     | 
| 
      
 52 
     | 
    
         
            +
                        )
         
     | 
| 
      
 53 
     | 
    
         
            +
                        + self.delta_t_supply_fan
         
     | 
| 
      
 54 
     | 
    
         
            +
                    )
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                    df["combined_check"] = operator.or_(
         
     | 
| 
      
 57 
     | 
    
         
            +
                        (df["clg_delta_temp"] >= df["clg_delta_sqrted"])
         
     | 
| 
      
 58 
     | 
    
         
            +
                        # verify AHU is in OS2 only free cooling mode
         
     | 
| 
      
 59 
     | 
    
         
            +
                        & (df[self.economizer_sig_col] > self.ahu_min_oa_dpr)
         
     | 
| 
      
 60 
     | 
    
         
            +
                        & (df[self.cooling_sig_col] < 0.1),  # OR
         
     | 
| 
      
 61 
     | 
    
         
            +
                        (df["clg_delta_temp"] >= df["clg_delta_sqrted"])
         
     | 
| 
      
 62 
     | 
    
         
            +
                        # verify AHU is running in OS 1 at near full heat
         
     | 
| 
      
 63 
     | 
    
         
            +
                        & (df[self.heating_sig_col] > 0.0) & (df[self.supply_vfd_speed_col] > 0.0),
         
     | 
| 
      
 64 
     | 
    
         
            +
                    )
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                    # Rolling sum to count consecutive trues
         
     | 
| 
      
 67 
     | 
    
         
            +
                    rolling_sum = (
         
     | 
| 
      
 68 
     | 
    
         
            +
                        df["combined_check"].rolling(window=self.rolling_window_size).sum()
         
     | 
| 
      
 69 
     | 
    
         
            +
                    )
         
     | 
| 
      
 70 
     | 
    
         
            +
                    # Set flag to 1 if rolling sum equals the window size
         
     | 
| 
      
 71 
     | 
    
         
            +
                    df["fc14_flag"] = (rolling_sum >= self.rolling_window_size).astype(int)
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                    if self.troubleshoot_mode:
         
     | 
| 
      
 74 
     | 
    
         
            +
                        print("Troubleshoot mode enabled - not removing helper columns")
         
     | 
| 
      
 75 
     | 
    
         
            +
                        sys.stdout.flush()
         
     | 
| 
      
 76 
     | 
    
         
            +
                        del df["clg_delta_temp"]
         
     | 
| 
      
 77 
     | 
    
         
            +
                        del df["clg_delta_sqrted"]
         
     | 
| 
      
 78 
     | 
    
         
            +
                        del df["combined_check"]
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                    return df
         
     | 
| 
         @@ -0,0 +1,68 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import pandas as pd
         
     | 
| 
      
 2 
     | 
    
         
            +
            import numpy as np
         
     | 
| 
      
 3 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.fault_condition import FaultCondition
         
     | 
| 
      
 4 
     | 
    
         
            +
            from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
         
     | 
| 
      
 5 
     | 
    
         
            +
            import sys
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            class FaultConditionNine(FaultCondition):
         
     | 
| 
      
 9 
     | 
    
         
            +
                """Class provides the definitions for Fault Condition 9.
         
     | 
| 
      
 10 
     | 
    
         
            +
                Outside air temperature too high in free cooling without
         
     | 
| 
      
 11 
     | 
    
         
            +
                additional mechanical cooling in economizer mode.
         
     | 
| 
      
 12 
     | 
    
         
            +
                """
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def __init__(self, dict_):
         
     | 
| 
      
 15 
     | 
    
         
            +
                    self.delta_t_supply_fan = float
         
     | 
| 
      
 16 
     | 
    
         
            +
                    self.outdoor_degf_err_thres = float
         
     | 
| 
      
 17 
     | 
    
         
            +
                    self.supply_degf_err_thres = float
         
     | 
| 
      
 18 
     | 
    
         
            +
                    self.ahu_min_oa_dpr = float
         
     | 
| 
      
 19 
     | 
    
         
            +
                    self.sat_setpoint_col = str
         
     | 
| 
      
 20 
     | 
    
         
            +
                    self.oat_col = str
         
     | 
| 
      
 21 
     | 
    
         
            +
                    self.cooling_sig_col = str
         
     | 
| 
      
 22 
     | 
    
         
            +
                    self.economizer_sig_col = str
         
     | 
| 
      
 23 
     | 
    
         
            +
                    self.troubleshoot_mode = bool  # default should be False
         
     | 
| 
      
 24 
     | 
    
         
            +
                    self.rolling_window_size = int
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    self.set_attributes(dict_)
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                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 = [
         
     | 
| 
      
 34 
     | 
    
         
            +
                        self.economizer_sig_col,
         
     | 
| 
      
 35 
     | 
    
         
            +
                        self.cooling_sig_col,
         
     | 
| 
      
 36 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 37 
     | 
    
         
            +
                    self.check_analog_pct(df, columns_to_check)
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    # Create helper columns
         
     | 
| 
      
 40 
     | 
    
         
            +
                    df["oat_minus_oaterror"] = df[self.oat_col] - self.outdoor_degf_err_thres
         
     | 
| 
      
 41 
     | 
    
         
            +
                    df["satsp_delta_saterr"] = (
         
     | 
| 
      
 42 
     | 
    
         
            +
                        df[self.sat_setpoint_col]
         
     | 
| 
      
 43 
     | 
    
         
            +
                        - self.delta_t_supply_fan
         
     | 
| 
      
 44 
     | 
    
         
            +
                        + self.supply_degf_err_thres
         
     | 
| 
      
 45 
     | 
    
         
            +
                    )
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    df["combined_check"] = (
         
     | 
| 
      
 48 
     | 
    
         
            +
                        (df["oat_minus_oaterror"] > df["satsp_delta_saterr"])
         
     | 
| 
      
 49 
     | 
    
         
            +
                        # verify AHU is in OS2 only free cooling mode
         
     | 
| 
      
 50 
     | 
    
         
            +
                        & (df[self.economizer_sig_col] > self.ahu_min_oa_dpr)
         
     | 
| 
      
 51 
     | 
    
         
            +
                        & (df[self.cooling_sig_col] < 0.1)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    )
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    # Rolling sum to count consecutive trues
         
     | 
| 
      
 55 
     | 
    
         
            +
                    rolling_sum = (
         
     | 
| 
      
 56 
     | 
    
         
            +
                        df["combined_check"].rolling(window=self.rolling_window_size).sum()
         
     | 
| 
      
 57 
     | 
    
         
            +
                    )
         
     | 
| 
      
 58 
     | 
    
         
            +
                    # Set flag to 1 if rolling sum equals the window size
         
     | 
| 
      
 59 
     | 
    
         
            +
                    df["fc9_flag"] = (rolling_sum >= self.rolling_window_size).astype(int)
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                    if self.troubleshoot_mode:
         
     | 
| 
      
 62 
     | 
    
         
            +
                        print("Troubleshoot mode enabled - not removing helper columns")
         
     | 
| 
      
 63 
     | 
    
         
            +
                        sys.stdout.flush()
         
     | 
| 
      
 64 
     | 
    
         
            +
                        del df["oat_minus_oaterror"]
         
     | 
| 
      
 65 
     | 
    
         
            +
                        del df["satsp_delta_saterr"]
         
     | 
| 
      
 66 
     | 
    
         
            +
                        del df["combined_check"]
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                    return df
         
     |