Skip to content

Commit

Permalink
ahu fault rules make over to include a check for missing cols and new…
Browse files Browse the repository at this point in the history
… method to print req cols. need to make new example ipynb for running faults one at a time and revise fc4 to not require htg and clg before publish new rev to pypi
  • Loading branch information
bbartling committed Aug 23, 2024
1 parent b3860a6 commit fbd5479
Show file tree
Hide file tree
Showing 17 changed files with 1,033 additions and 642 deletions.
34 changes: 26 additions & 8 deletions open_fdd/air_handling_unit/faults/fault_condition.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
import pandas as pd
import pandas.api.types as pdtypes
from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
import sys


class MissingColumnError(Exception):
"""Custom exception raised when a required column is missing or None."""

def __init__(self, message):
self.message = message
super().__init__(self.message)


class FaultCondition:
"""Parent class for Fault Conditions. Methods are inherited to all children."""

def set_attributes(self, dict_):
"""Passes dictionary into initialization of class instance, then uses the attributes called out below in
attributes_dict to set only the attributes that match from dict_.
def __init__(self):
self.required_columns = []

:param dict_: dictionary of all possible class attributes (loaded from config file)
"""
for attribute in self.__dict__:
def set_attributes(self, dict_):
"""Passes dictionary into initialization of class instance"""
for attribute in self.__dict__.keys():
upper = attribute.upper()
value = dict_[upper]
self.__setattr__(attribute, value)
if upper in dict_:
value = dict_[upper]
self.__setattr__(attribute, value)

def check_required_columns(self, df: pd.DataFrame):
"""Checks if required columns are present in the DataFrame."""
missing_columns = [
col for col in self.required_columns if col is None or col not in df.columns
]

if missing_columns:
raise MissingColumnError(f"Missing required columns: {missing_columns}")

def troubleshoot_cols(self, df):
"""print troubleshoot columns mapping
Expand Down
98 changes: 61 additions & 37 deletions open_fdd/air_handling_unit/faults/fault_condition_eight.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import pandas as pd
import numpy as np
from open_fdd.air_handling_unit.faults.fault_condition import FaultCondition
from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
from open_fdd.air_handling_unit.faults.fault_condition import (
FaultCondition,
MissingColumnError,
)
import sys


Expand All @@ -12,6 +14,7 @@ class FaultConditionEight(FaultCondition):
"""

def __init__(self, dict_):
super().__init__()
self.delta_t_supply_fan = float
self.mix_degf_err_thres = float
self.supply_degf_err_thres = float
Expand All @@ -25,43 +28,64 @@ def __init__(self, dict_):

self.set_attributes(dict_)

def apply(self, df: pd.DataFrame) -> pd.DataFrame:
if self.troubleshoot_mode:
self.troubleshoot_cols(df)

# Check analog outputs [data with units of %] are floats only
columns_to_check = [
# Set required columns specific to this fault condition
self.required_columns = [
self.mat_col,
self.sat_col,
self.economizer_sig_col,
self.cooling_sig_col,
]

self.check_analog_pct(df, columns_to_check)

df["sat_fan_mat"] = abs(
df[self.sat_col] - self.delta_t_supply_fan - df[self.mat_col]
)
df["sat_mat_sqrted"] = np.sqrt(
self.supply_degf_err_thres**2 + self.mix_degf_err_thres**2
)

df["combined_check"] = (
(df["sat_fan_mat"] > df["sat_mat_sqrted"])
& (df[self.economizer_sig_col] > self.ahu_min_oa_dpr)
& (df[self.cooling_sig_col] < 0.1)
)

# Rolling sum to count consecutive trues
rolling_sum = (
df["combined_check"].rolling(window=self.rolling_window_size).sum()
)
# Set flag to 1 if rolling sum equals the window size
df["fc8_flag"] = (rolling_sum >= self.rolling_window_size).astype(int)

if self.troubleshoot_mode:
print("Troubleshoot mode enabled - not removing helper columns")
sys.stdout.flush()
del df["sat_fan_mat"]
del df["sat_mat_sqrted"]
del df["combined_check"]
def get_required_columns(self) -> str:
"""Returns a string representation of the required columns."""
return f"Required columns for FaultConditionEight: {', '.join(self.required_columns)}"

def apply(self, df: pd.DataFrame) -> pd.DataFrame:
try:
# Ensure all required columns are present
self.check_required_columns(df)

if self.troubleshoot_mode:
self.troubleshoot_cols(df)

# Check analog outputs [data with units of %] are floats only
columns_to_check = [
self.economizer_sig_col,
self.cooling_sig_col,
]

return df
self.check_analog_pct(df, columns_to_check)

df["sat_fan_mat"] = abs(
df[self.sat_col] - self.delta_t_supply_fan - df[self.mat_col]
)
df["sat_mat_sqrted"] = np.sqrt(
self.supply_degf_err_thres**2 + self.mix_degf_err_thres**2
)

df["combined_check"] = (
(df["sat_fan_mat"] > df["sat_mat_sqrted"])
& (df[self.economizer_sig_col] > self.ahu_min_oa_dpr)
& (df[self.cooling_sig_col] < 0.1)
)

# Rolling sum to count consecutive trues
rolling_sum = (
df["combined_check"].rolling(window=self.rolling_window_size).sum()
)
# Set flag to 1 if rolling sum equals the window size
df["fc8_flag"] = (rolling_sum >= self.rolling_window_size).astype(int)

if self.troubleshoot_mode:
print("Troubleshoot mode enabled - not removing helper columns")
sys.stdout.flush()
del df["sat_fan_mat"]
del df["sat_mat_sqrted"]
del df["combined_check"]

return df

except MissingColumnError as e:
print(f"Error: {e.message}")
sys.stdout.flush()
raise e # Re-raise the exception so it can be caught by pytest
96 changes: 59 additions & 37 deletions open_fdd/air_handling_unit/faults/fault_condition_eleven.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import pandas as pd
import numpy as np
from open_fdd.air_handling_unit.faults.fault_condition import FaultCondition
from open_fdd.air_handling_unit.faults.helper_utils import HelperUtils
from open_fdd.air_handling_unit.faults.fault_condition import (
FaultCondition,
MissingColumnError,
)
import sys


class FaultConditionEleven(FaultCondition):
"""Class provides the definitions for Fault Condition 11.
Outside air temperature too low for 100% outdoor
air cooling in economizer cooling mode.
Economizer performance fault
"""

def __init__(self, dict_):
super().__init__()
self.delta_t_supply_fan = float
self.outdoor_degf_err_thres = float
self.supply_degf_err_thres = float
Expand All @@ -26,43 +27,64 @@ def __init__(self, dict_):

self.set_attributes(dict_)

def apply(self, df: pd.DataFrame) -> pd.DataFrame:
if self.troubleshoot_mode:
self.troubleshoot_cols(df)

# Check analog outputs [data with units of %] are floats only
columns_to_check = [
self.economizer_sig_col,
# Set required columns specific to this fault condition
self.required_columns = [
self.sat_setpoint_col,
self.oat_col,
self.cooling_sig_col,
self.economizer_sig_col,
]
self.check_analog_pct(df, columns_to_check)

df["oat_plus_oaterror"] = df[self.oat_col] + self.outdoor_degf_err_thres
df["satsp_delta_saterr"] = (
df[self.sat_setpoint_col]
- self.delta_t_supply_fan
- self.supply_degf_err_thres
)
def get_required_columns(self) -> str:
"""Returns a string representation of the required columns."""
return f"Required columns for FaultConditionEleven: {', '.join(self.required_columns)}"

df["combined_check"] = (
(df["oat_plus_oaterror"] < df["satsp_delta_saterr"])
# verify ahu is running in OS 3 clg mode in 100 OA
& (df[self.cooling_sig_col] > 0.01)
& (df[self.economizer_sig_col] > 0.9)
)
def apply(self, df: pd.DataFrame) -> pd.DataFrame:
try:
# Ensure all required columns are present
self.check_required_columns(df)

# Rolling sum to count consecutive trues
rolling_sum = (
df["combined_check"].rolling(window=self.rolling_window_size).sum()
)
# Set flag to 1 if rolling sum equals the window size
df["fc11_flag"] = (rolling_sum >= self.rolling_window_size).astype(int)
if self.troubleshoot_mode:
self.troubleshoot_cols(df)

if self.troubleshoot_mode:
print("Troubleshoot mode enabled - not removing helper columns")
sys.stdout.flush()
del df["oat_plus_oaterror"]
del df["satsp_delta_saterr"]
del df["combined_check"]
# Check analog outputs [data with units of %] are floats only
columns_to_check = [
self.economizer_sig_col,
self.cooling_sig_col,
]
self.check_analog_pct(df, columns_to_check)

return df
df["oat_plus_oaterror"] = df[self.oat_col] + self.outdoor_degf_err_thres
df["satsp_delta_saterr"] = (
df[self.sat_setpoint_col]
- self.delta_t_supply_fan
- self.supply_degf_err_thres
)

df["combined_check"] = (
(df["oat_plus_oaterror"] < df["satsp_delta_saterr"])
# verify ahu is running in OS 3 clg mode in 100 OA
& (df[self.cooling_sig_col] > 0.01)
& (df[self.economizer_sig_col] > 0.9)
)

# Rolling sum to count consecutive trues
rolling_sum = (
df["combined_check"].rolling(window=self.rolling_window_size).sum()
)
# Set flag to 1 if rolling sum equals the window size
df["fc11_flag"] = (rolling_sum >= self.rolling_window_size).astype(int)

if self.troubleshoot_mode:
print("Troubleshoot mode enabled - not removing helper columns")
sys.stdout.flush()
del df["oat_plus_oaterror"]
del df["satsp_delta_saterr"]
del df["combined_check"]

return df

except MissingColumnError as e:
print(f"Error: {e.message}")
sys.stdout.flush()
raise e # Re-raise the exception so it can be caught by pytest
Loading

0 comments on commit fbd5479

Please sign in to comment.