Coverage for src/evutils/_checker.py: 77%
30 statements
« prev ^ index » next coverage.py v7.15.1, created at 2026-07-18 05:24 +0000
« prev ^ index » next coverage.py v7.15.1, created at 2026-07-18 05:24 +0000
1"""Module providing utilities to check the validity of event arrays."""
3import numpy as np
4from .types import EventArray
6class EventsChecker():
7 """Class to check if events are valid.
9 Parameters
10 ----------
11 events : np.ndarray
12 Array of events to check.
14 """
16 def __init__(self, events: 'np.ndarray | EventArray'):
17 from .types import Event_dtype, SoaArray
18 if isinstance(events, SoaArray):
19 if events._aos_dtype != Event_dtype:
20 raise ValueError("events must be of type Events")
21 else:
22 if not hasattr(events, 'dtype'):
23 raise TypeError("events must be a NumPy array or SoaArray")
24 if events.dtype != Event_dtype:
25 raise ValueError("events must be of type Events")
27 self.events = events
29 def is_sorted(self) -> bool:
30 """Check if events are sorted by timestamp.
32 Returns
33 -------
34 bool
35 True if events are sorted in non-decreasing order of timestamps.
37 """
38 return bool(np.all(np.diff(self.events['t']) >= 0))
40 def has_valid_polarity(self) -> bool:
41 """Check if events have valid polarity (0 or 1).
43 Returns
44 -------
45 bool
46 True if all events have polarity 0 or 1.
48 """
49 return bool(np.all((self.events['p'] <= 1) & (self.events['p'] >= 0)))
51 def has_valid_x(self, width: int) -> bool:
52 """Check if events have valid x coordinates.
54 Parameters
55 ----------
56 width : int
57 Maximum valid width (exclusive).
59 Returns
60 -------
61 bool
62 True if all events have x coordinates in [0, width).
64 """
65 return bool(np.all((self.events['x'] >= 0) & (self.events['x'] < width)))
67 def has_valid_y(self, height: int) -> bool:
68 """Check if events have valid y coordinates.
70 Parameters
71 ----------
72 height : int
73 Maximum valid height (exclusive).
75 Returns
76 -------
77 bool
78 True if all events have y coordinates in [0, height).
80 """
81 return bool(np.all((self.events['y'] >= 0) & (self.events['y'] < height)))
83 def is_valid(self, width: int | None = None, height: int | None = None) -> bool:
84 """Check if all events are valid (sorted, valid polarity, and valid coordinates).
86 Parameters
87 ----------
88 width : int, optional
89 Maximum valid width. If None, x coordinates are not checked.
90 height : int, optional
91 Maximum valid height. If None, y coordinates are not checked.
93 Returns
94 -------
95 bool
96 True if all checks pass.
98 """
99 valid = self.is_sorted() and self.has_valid_polarity()
100 if width is not None:
101 valid = valid and self.has_valid_x(width)
102 if height is not None:
103 valid = valid and self.has_valid_y(height)
104 return valid
106 def __repr__(self) -> str:
107 """Return string representation of the EventsChecker.
109 Returns
110 -------
111 str
112 String representation indicating the EventsChecker and number of events.
114 """
115 return f"EventsChecker(events={len(self.events)})"