Skip to content

Commit 7650947

Browse files
authored
Modify high level pattern matching (#2)
1 parent e7f952e commit 7650947

File tree

17 files changed

+138
-97
lines changed

17 files changed

+138
-97
lines changed

HISTORY.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ Add new entries to the top of the list.
44

55
## 2025-02-12, v0.1.0
66
- First release of the `cepact` package.
7+
8+
## 2025-05-16, v0.1.1
9+
- Modified, improved high-level pattern matching (allowing for intermediate, non-conforming low-level events between high-level events, except for low-level event 1, which resets the high-level event "state machine")
10+
- Dependency upgrades

cepact/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@
1919
'Any25LowLevelPatternQuery', 'Any50LowLevelPatternQuery',
2020
'Any75LowLevelPatternQuery', 'InstanceLevelDetQuery']
2121

22-
__version__ = '0.1.0'
22+
__version__ = '0.1.1'

cepact/input_processor/concrete_fetchers/local_discretization_fetcher.py

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -96,51 +96,71 @@ def get_discretization(self) -> Discretization:
9696
if source[:2] == "<=":
9797
l_bound = float("-inf")
9898
u_bound = float(source[2:])
99-
discretization_builder.add_discretization_item(sensor, l_bound,
100-
u_bound, True, True,
101-
target_casted)
99+
discretization_builder.add_discretization_item(sensor=sensor,
100+
beg=l_bound,
101+
to=u_bound,
102+
beg_incl=True,
103+
to_incl=True,
104+
target_value=target_casted)
102105
elif source[:2] == ">=":
103106
l_bound = float(source[2:])
104107
u_bound = float("inf")
105-
discretization_builder.add_discretization_item(sensor, l_bound, u_bound,
106-
True, True,
107-
target_casted)
108+
discretization_builder.add_discretization_item(sensor=sensor,
109+
beg=l_bound,
110+
to=u_bound,
111+
beg_incl=True,
112+
to_incl=True,
113+
target_value=target_casted)
108114
elif source[0] == "<":
109115
l_bound = float("-inf")
110116
u_bound = float(source[1:])
111-
discretization_builder.add_discretization_item(sensor, l_bound, u_bound,
112-
True, False,
113-
target_casted)
117+
discretization_builder.add_discretization_item(sensor=sensor,
118+
beg=l_bound,
119+
to=u_bound,
120+
beg_incl=True,
121+
to_incl=False,
122+
target_value=target_casted)
114123
elif source[0] == ">":
115124
l_bound = float(source[1:])
116125
u_bound = float("inf")
117-
discretization_builder.add_discretization_item(sensor, l_bound, u_bound,
118-
False, True,
119-
target_casted)
126+
discretization_builder.add_discretization_item(sensor=sensor,
127+
beg=l_bound,
128+
to=u_bound,
129+
beg_incl=False,
130+
to_incl=True,
131+
target_value=target_casted)
120132
elif source[0] == "[" and source[-1] == "]":
121133
bounds = source[1:-1].split(",")
122-
discretization_builder.add_discretization_item(sensor, float(bounds[0]),
123-
float(bounds[1]),
124-
True,
125-
True, target_casted)
134+
discretization_builder.add_discretization_item(sensor=sensor,
135+
beg=float(bounds[0]),
136+
to=float(bounds[1]),
137+
beg_incl=True,
138+
to_incl=True,
139+
target_value=target_casted)
126140
elif source[0] == "[" and source[-1] == "[":
127141
bounds = source[1:-1].split(",")
128-
discretization_builder.add_discretization_item(sensor, float(bounds[0]),
129-
float(bounds[1]),
130-
True,
131-
False, target_casted)
142+
discretization_builder.add_discretization_item(sensor=sensor,
143+
beg=float(bounds[0]),
144+
to=float(bounds[1]),
145+
beg_incl=True,
146+
to_incl=False,
147+
target_value=target_casted)
132148
elif source[0] == "]" and source[-1] == "]":
133149
bounds = source[1:-1].split(",")
134-
discretization_builder.add_discretization_item(sensor, float(bounds[0]),
135-
float(bounds[1]),
136-
False,
137-
True, target_casted)
150+
discretization_builder.add_discretization_item(sensor=sensor,
151+
beg=float(bounds[0]),
152+
to=float(bounds[1]),
153+
beg_incl=False,
154+
to_incl=True,
155+
target_value=target_casted)
138156
elif source[0] == "]" and source[-1] == "[":
139157
bounds = source[1:-1].split(",")
140-
discretization_builder.add_discretization_item(sensor, float(bounds[0]),
141-
float(bounds[1]),
142-
False,
143-
False, target_casted)
158+
discretization_builder.add_discretization_item(sensor=sensor,
159+
beg=float(bounds[0]),
160+
to=float(bounds[1]),
161+
beg_incl=False,
162+
to_incl=False,
163+
target_value=target_casted)
144164
else:
145165
raise ValueError(f"Source {source} for sensor {sensor} is not valid.")
146166
# make sure that the whole range is covered

cepact/output_producer/concrete_instance_level_det_queries.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def generate(self, num_changes: int, act_name: str) -> str:
1414
ahli_query = (
1515
f'@info(name="Detect-AllHighLevelPattern-InstanceLevelActivity")\n'
1616
f'from every e1 = DetectedHighLevelActivityEvents[event == "HighLevel-Pattern-1"] '
17-
f'-> not HelperStream[event == "HighToLow"] and '
17+
f'-> not DetectedHighLevelActivityEvents[event == "HighLevel-Pattern-1"] and '
1818
f'e2 = DetectedHighLevelActivityEvents[event == "HighLevel-Pattern-{num_changes}"]\n'
1919
f'select "{act_name}" as activity, '
2020
f'"AllHighLevelPattern" as detection_type, '
@@ -37,7 +37,7 @@ def generate(self, num_changes: int, act_name: str) -> str:
3737
ffpi_query = (
3838
f'@info(name="Detect-First50HighLevelPattern-InstanceLevelActivity")\n'
3939
f'from every e1 = DetectedHighLevelActivityEvents[event == "HighLevel-Pattern-1"] '
40-
f'-> not HelperStream[event == "HighToLow"] '
40+
f'-> not DetectedHighLevelActivityEvents[event == "HighLevel-Pattern-1"] '
4141
f'and e2 = DetectedHighLevelActivityEvents'
4242
f'[event == "HighLevel-Pattern-{ceil(num_changes / 2)}"]\n'
4343
f'select "{act_name}" as activity, '

cepact/output_producer/sink_source_pattern_helper.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def query_hlstream(activity_params: AnnotationParams,
215215
if counter > 1:
216216
quer += (f'from every e1 = DetectedHighLevelActivityEvents[event == '
217217
f'"HighLevel-Pattern-{counter - 1}"] '
218-
f'-> not HelperStream[event == "HighToLow"] and '
218+
f'-> not DetectedHighLevelActivityEvents[event == "HighLevel-Pattern-1"] and '
219219
f'e2 = DetectedLowLevelActivityEvents[event '
220220
f'== "LowLevel-Pattern-{counter}" '
221221
f'and time:timestampInMilliseconds(e1.ts_second, \'yyyy-MM-dd HH:mm:ss.SS\') '
@@ -256,7 +256,7 @@ def get_time_from_hz(sampling_freq: float) -> str:
256256

257257

258258
# pylint: disable=too-many-arguments
259-
def low_high_level_pattern_case_multi(timestamp: datetime,
259+
def low_high_level_pattern_case_multi(*, timestamp: datetime,
260260
changes: Changes,
261261
activity_params: AnnotationParams,
262262
counter: int,
@@ -342,12 +342,12 @@ def create_low_high_level_pattern_queries(changes: Changes,
342342
counter,
343343
siddhi_config))
344344
else:
345-
queries.append(low_high_level_pattern_case_multi(timestamp,
346-
changes,
347-
activity_params,
348-
counter,
349-
sampling_freq,
350-
siddhi_config))
345+
queries.append(low_high_level_pattern_case_multi(timestamp=timestamp,
346+
changes=changes,
347+
activity_params=activity_params,
348+
counter=counter,
349+
sampling_freq=sampling_freq,
350+
siddhi_config=siddhi_config))
351351

352352
# High-Level Pattern queries
353353
queries.append(query_hlstream(

cepact/representations/discretization.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def __init__(self) -> None:
6868

6969
# pylint: disable=too-many-arguments
7070
def _check_overlapping_mapping_range(self,
71-
sensor: str,
71+
*, sensor: str,
7272
l_bound: float,
7373
u_bound: float,
7474
l_bound_type: str,
@@ -92,13 +92,17 @@ def _check_overlapping_mapping_range(self,
9292
raise ValueError(f"Sensor {sensor} already has a mapping for {u_bound}")
9393

9494
# pylint: disable=too-many-arguments
95-
def add_discretization_item(self, sensor: str,
95+
def add_discretization_item(self,
96+
*, sensor: str,
9697
beg: float, to: float,
9798
beg_incl: bool, to_incl: bool,
9899
target_value: Union[str, int, float, bool]) -> None:
99100
""" Add an item to the discretization mapping. """
100-
self._check_overlapping_mapping_range(sensor, beg, to, "incl" if beg_incl else "excl",
101-
"incl" if to_incl else "excl")
101+
self._check_overlapping_mapping_range(sensor=sensor,
102+
l_bound=beg,
103+
u_bound=to,
104+
l_bound_type="incl" if beg_incl else "excl",
105+
u_bound_type="incl" if to_incl else "excl")
102106
if sensor not in self._discretization_map:
103107
self._discretization_map[sensor] = {}
104108
beg_incl_str = "incl" if beg_incl else "excl"

requirements-dev.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
pytest~=7.4.3
2-
coverage~=7.6.4
3-
pylint~=3.0.3
4-
typing_extensions~=4.9.0
5-
mypy~=1.12.0
1+
pytest~=8.3.5
2+
coverage~=7.8.0
3+
pylint~=3.3.7
4+
typing_extensions~=4.13.2
5+
mypy~=1.15.0
66
types-requests~=2.32.0
77
pandas-stubs~=2.2.3
88
types-jsonschema~=4.23.0

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
requests~=2.31.0
1+
requests~=2.32.3
22
pandas~=2.2.3
3-
influxdb_client==1.47.0
3+
influxdb_client==1.48.0
44
jsonschema~=4.23.0

0 commit comments

Comments
 (0)