ecopipeline 0.8.3__py3-none-any.whl → 0.8.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.
- ecopipeline/event_tracking/event_tracking.py +38 -26
- {ecopipeline-0.8.3.dist-info → ecopipeline-0.8.5.dist-info}/METADATA +1 -1
- {ecopipeline-0.8.3.dist-info → ecopipeline-0.8.5.dist-info}/RECORD +6 -6
- {ecopipeline-0.8.3.dist-info → ecopipeline-0.8.5.dist-info}/WHEEL +0 -0
- {ecopipeline-0.8.3.dist-info → ecopipeline-0.8.5.dist-info}/licenses/LICENSE +0 -0
- {ecopipeline-0.8.3.dist-info → ecopipeline-0.8.5.dist-info}/top_level.txt +0 -0
|
@@ -3,7 +3,7 @@ import numpy as np
|
|
|
3
3
|
import datetime as dt
|
|
4
4
|
from ecopipeline import ConfigManager
|
|
5
5
|
|
|
6
|
-
def flag_boundary_alarms(df: pd.DataFrame, config : ConfigManager, default_fault_time : int = 15, site: str = "") -> pd.DataFrame:
|
|
6
|
+
def flag_boundary_alarms(df: pd.DataFrame, config : ConfigManager, default_fault_time : int = 15, site: str = "", full_days : list = None) -> pd.DataFrame:
|
|
7
7
|
"""
|
|
8
8
|
Function will take a pandas dataframe and location of alarm information in a csv,
|
|
9
9
|
and create an dataframe with applicable alarm events
|
|
@@ -24,6 +24,8 @@ def flag_boundary_alarms(df: pd.DataFrame, config : ConfigManager, default_fault
|
|
|
24
24
|
the fault_time column in Varriable_Names.csv
|
|
25
25
|
site: str
|
|
26
26
|
string of site name if processing a particular site in a Variable_Names.csv file with multiple sites. Leave as an empty string if not aplicable.
|
|
27
|
+
full_days : list
|
|
28
|
+
list of pd.Datetimes that should be considered full days here. If set to none, will take any day at all present in df
|
|
27
29
|
|
|
28
30
|
Returns
|
|
29
31
|
-------
|
|
@@ -52,7 +54,8 @@ def flag_boundary_alarms(df: pd.DataFrame, config : ConfigManager, default_fault
|
|
|
52
54
|
bounds_df['fault_time'] = default_fault_time
|
|
53
55
|
|
|
54
56
|
idx = df.index
|
|
55
|
-
|
|
57
|
+
if full_days is None:
|
|
58
|
+
full_days = pd.to_datetime(pd.Series(idx).dt.normalize().unique())
|
|
56
59
|
|
|
57
60
|
bounds_df = bounds_df.loc[:, ["variable_name", "high_alarm", "low_alarm", "fault_time", "pretty_name"]]
|
|
58
61
|
bounds_df.dropna(axis=0, thresh=2, inplace=True)
|
|
@@ -69,30 +72,11 @@ def flag_boundary_alarms(df: pd.DataFrame, config : ConfigManager, default_fault
|
|
|
69
72
|
upper_mask = df[bound_var] > bounds["high_alarm"]
|
|
70
73
|
if pd.isna(bounds['fault_time']):
|
|
71
74
|
bounds['fault_time'] = default_fault_time
|
|
72
|
-
for day in
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if low_consecutive_condition.any():
|
|
78
|
-
first_true_index = low_consecutive_condition.idxmax()
|
|
79
|
-
adjusted_time = first_true_index - pd.Timedelta(minutes=bounds["fault_time"]-1)
|
|
80
|
-
alarm_string = f"Lower bound alarm for {bounds['pretty_name']} (first one at {adjusted_time.strftime('%H:%M')})."
|
|
81
|
-
if day in alarms:
|
|
82
|
-
alarms[day].append([bound_var, alarm_string])
|
|
83
|
-
else:
|
|
84
|
-
alarms[day] = [[bound_var, alarm_string]]
|
|
85
|
-
# high alert
|
|
86
|
-
up_filtered_df = upper_mask.loc[(upper_mask.index >= day) & (upper_mask.index < next_day)]
|
|
87
|
-
up_consecutive_condition = up_filtered_df.rolling(window=bounds["fault_time"]).min() == 1
|
|
88
|
-
if up_consecutive_condition.any():
|
|
89
|
-
first_true_index = up_consecutive_condition.idxmax()
|
|
90
|
-
adjusted_time = first_true_index - pd.Timedelta(minutes=bounds["fault_time"]-1)
|
|
91
|
-
alarm_string = f"Upper bound alarm for {bounds['pretty_name']} (first one at {adjusted_time.strftime('%H:%M')})."
|
|
92
|
-
if day in alarms:
|
|
93
|
-
alarms[day].append([bound_var, alarm_string])
|
|
94
|
-
else:
|
|
95
|
-
alarms[day] = [[bound_var, alarm_string]]
|
|
75
|
+
for day in full_days:
|
|
76
|
+
if bounds['fault_time'] < 1 :
|
|
77
|
+
print(f"Could not process alarm for {bound_var}. Fault time must be greater than or equal to 1 minute.")
|
|
78
|
+
_check_and_add_alarm(df, lower_mask, alarms, day, bounds["fault_time"], bound_var, bounds['pretty_name'], 'Lower')
|
|
79
|
+
_check_and_add_alarm(df, upper_mask, alarms, day, bounds["fault_time"], bound_var, bounds['pretty_name'], 'Upper')
|
|
96
80
|
events = {
|
|
97
81
|
'start_time_pt' : [],
|
|
98
82
|
'end_time_pt' : [],
|
|
@@ -112,6 +96,34 @@ def flag_boundary_alarms(df: pd.DataFrame, config : ConfigManager, default_fault
|
|
|
112
96
|
event_df.set_index('start_time_pt', inplace=True)
|
|
113
97
|
return event_df
|
|
114
98
|
|
|
99
|
+
def _check_and_add_alarm(df : pd.DataFrame, mask : pd.Series, alarms_dict, day, fault_time : int, var_name : str, pretty_name : str, alarm_type : str = 'Lower'):
|
|
100
|
+
# KNOWN BUG : Avg value during fault time excludes the first (fault_time-1) minutes of each fault window
|
|
101
|
+
next_day = day + pd.Timedelta(days=1)
|
|
102
|
+
filtered_df = mask.loc[(mask.index >= day) & (mask.index < next_day)]
|
|
103
|
+
consecutive_condition = filtered_df.rolling(window=fault_time).min() == 1
|
|
104
|
+
if consecutive_condition.any():
|
|
105
|
+
group = (consecutive_condition != consecutive_condition.shift()).cumsum()
|
|
106
|
+
streaks = consecutive_condition.groupby(group).agg(['sum', 'size', 'idxmin'])
|
|
107
|
+
true_streaks = streaks[consecutive_condition.groupby(group).first()]
|
|
108
|
+
longest_streak_length = true_streaks['size'].max()
|
|
109
|
+
avg_streak_length = true_streaks['size'].mean() + fault_time-1
|
|
110
|
+
longest_group = true_streaks['size'].idxmax()
|
|
111
|
+
streak_indices = consecutive_condition[group == longest_group].index
|
|
112
|
+
starting_index = streak_indices[0]
|
|
113
|
+
|
|
114
|
+
day_df = df.loc[(df.index >= day) & (df.index < next_day)]
|
|
115
|
+
average_value = day_df.loc[consecutive_condition, var_name].mean()
|
|
116
|
+
|
|
117
|
+
# first_true_index = consecutive_condition.idxmax()
|
|
118
|
+
# because first (fault_time-1) minutes don't count in window
|
|
119
|
+
adjusted_time = starting_index - pd.Timedelta(minutes=fault_time-1)
|
|
120
|
+
adjusted_longest_streak_length = longest_streak_length + fault_time-1
|
|
121
|
+
alarm_string = f"{alarm_type} bound alarm for {pretty_name} (longest at {adjusted_time.strftime('%H:%M')} for {adjusted_longest_streak_length} minutes). Avg fault time : {round(avg_streak_length,1)} minutes, Avg value during fault: {round(average_value,2)}"
|
|
122
|
+
if day in alarms_dict:
|
|
123
|
+
alarms_dict[day].append([var_name, alarm_string])
|
|
124
|
+
else:
|
|
125
|
+
alarms_dict[day] = [[var_name, alarm_string]]
|
|
126
|
+
|
|
115
127
|
# def flag_dhw_outage(df: pd.DataFrame, daily_df : pd.DataFrame, dhw_outlet_column : str, supply_temp : int = 110, consecutive_minutes : int = 15) -> pd.DataFrame:
|
|
116
128
|
# """
|
|
117
129
|
# Parameters
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
ecopipeline/__init__.py,sha256=d48mO5La6OrQDkRe_qqoY6lUx7x-e8krOH388jmWjwU,218
|
|
2
2
|
ecopipeline/event_tracking/__init__.py,sha256=q49j46fXMUjNUPzL4FvXEppB93i3lUni-QUZpp61tt0,64
|
|
3
|
-
ecopipeline/event_tracking/event_tracking.py,sha256=
|
|
3
|
+
ecopipeline/event_tracking/event_tracking.py,sha256=yHyUZG8_LPnw9ppmRXkp6cWUFH8rM8yL4Wo2aHImMPI,13202
|
|
4
4
|
ecopipeline/extract/__init__.py,sha256=gQ3sak6NJ63Gpo-hZXrtZfeKOTHLRyAVXfTgxxRpqPo,675
|
|
5
5
|
ecopipeline/extract/extract.py,sha256=Fch2IvqGxMClKGniiJiKqyJhcFDwkckaeiGQRVnUGUg,46708
|
|
6
6
|
ecopipeline/load/__init__.py,sha256=NLa_efQJZ8aP-J0Y5xx9DP7mtfRH9jY6Jz1ZMZN_BAA,292
|
|
@@ -12,8 +12,8 @@ ecopipeline/transform/transform.py,sha256=DBQD4WqKmdXnGQMAj6tg75HtXiSemIc7c6nZxz
|
|
|
12
12
|
ecopipeline/utils/ConfigManager.py,sha256=-g1wtExdvhYO5Y6Q3cRbywa__DxRMFruLrB4YanwaPY,12168
|
|
13
13
|
ecopipeline/utils/__init__.py,sha256=ccWUR0m7gD9DfcgsxBCLOfi4lho6RdYuB2Ugy_g6ZdQ,28
|
|
14
14
|
ecopipeline/utils/unit_convert.py,sha256=VFh1we2Y8KV3u21BeWb-U3TlZJXo83q5vdxxkpgcuME,3064
|
|
15
|
-
ecopipeline-0.8.
|
|
16
|
-
ecopipeline-0.8.
|
|
17
|
-
ecopipeline-0.8.
|
|
18
|
-
ecopipeline-0.8.
|
|
19
|
-
ecopipeline-0.8.
|
|
15
|
+
ecopipeline-0.8.5.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
+
ecopipeline-0.8.5.dist-info/METADATA,sha256=8qs5dukSC_Z1keyDmkypmMkjbEFcNU3QwJNppqdxq9o,2329
|
|
17
|
+
ecopipeline-0.8.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
18
|
+
ecopipeline-0.8.5.dist-info/top_level.txt,sha256=WOPFJH2LIgKqm4lk2OnFF5cgVkYibkaBxIxgvLgO7y0,12
|
|
19
|
+
ecopipeline-0.8.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|