From 23d7a61dd5f915b0455a2082de7950567e2d44d3 Mon Sep 17 00:00:00 2001 From: architjain19 Date: Wed, 10 Dec 2025 18:11:55 -0800 Subject: [PATCH 1/3] test: add global severity constants and validation in Anomaly class --- src/roboqa_temporal/constants.py | 7 +++++++ src/roboqa_temporal/detection/detector.py | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 src/roboqa_temporal/constants.py diff --git a/src/roboqa_temporal/constants.py b/src/roboqa_temporal/constants.py new file mode 100644 index 0000000..e3b396f --- /dev/null +++ b/src/roboqa_temporal/constants.py @@ -0,0 +1,7 @@ +"""Global constants used across roboqa_temporal.""" + +# Severity bounds for anomaly scores (inclusive) +MIN_SEVERITY = 0.0 +MAX_SEVERITY = 1.0 + +__all__ = ["MIN_SEVERITY", "MAX_SEVERITY"] diff --git a/src/roboqa_temporal/detection/detector.py b/src/roboqa_temporal/detection/detector.py index 5e99dea..1a7ab1e 100644 --- a/src/roboqa_temporal/detection/detector.py +++ b/src/roboqa_temporal/detection/detector.py @@ -31,6 +31,7 @@ import numpy as np from roboqa_temporal.loader.bag_loader import PointCloudFrame +from roboqa_temporal.constants import MIN_SEVERITY, MAX_SEVERITY from roboqa_temporal.detection.detectors import ( DensityDropDetector, SpatialDiscontinuityDetector, @@ -54,6 +55,12 @@ class Anomaly: description: str metadata: Dict[str, Any] = field(default_factory=dict) + def __post_init__(self) -> None: + if not (MIN_SEVERITY <= self.severity <= MAX_SEVERITY): + raise ValueError( + f"severity {self.severity} outside bounds [{MIN_SEVERITY}, {MAX_SEVERITY}]" + ) + @dataclass class DetectionResult: From 4dbe66a6dd851974c593dc0bd56e67d37b3498f9 Mon Sep 17 00:00:00 2001 From: architjain19 Date: Thu, 11 Dec 2025 21:14:03 -0800 Subject: [PATCH 2/3] test: add validation to ensure at least one anomaly detector is enabled --- src/roboqa_temporal/detection/detector.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/roboqa_temporal/detection/detector.py b/src/roboqa_temporal/detection/detector.py index 1a7ab1e..6ff8df6 100644 --- a/src/roboqa_temporal/detection/detector.py +++ b/src/roboqa_temporal/detection/detector.py @@ -128,6 +128,11 @@ def __init__( threshold=temporal_threshold ) + if not self.detectors: + raise ValueError( + "No detectors enabled. Enable at least one anomaly detector or adjust configuration." + ) + def detect(self, frames: List[PointCloudFrame]) -> DetectionResult: """ Run anomaly detection on a sequence of frames. From 97237a987de1152206dca41e122e0f0f2c39f52c Mon Sep 17 00:00:00 2001 From: architjain19 Date: Thu, 11 Dec 2025 21:29:15 -0800 Subject: [PATCH 3/3] test: refactor detector test to validate error on all detectors disabled --- tests/test_edge.py | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/tests/test_edge.py b/tests/test_edge.py index 22614b0..6457a2d 100644 --- a/tests/test_edge.py +++ b/tests/test_edge.py @@ -59,19 +59,13 @@ def test_detector_with_all_detectors_disabled(): reviewer: dharinesh category: edge test """ - detector = AnomalyDetector( - enable_density_detection=False, - enable_spatial_detection=False, - enable_ghost_detection=False, - enable_temporal_detection=False, - ) - - points = np.random.rand(50, 3) - frame = PointCloudFrame(timestamp=1000.0, frame_id="test", points=points) - result = detector.detect([frame]) - - assert isinstance(result, DetectionResult) - assert len(result.detector_results) == 0 + with pytest.raises(ValueError, match="No detectors enabled"): + AnomalyDetector( + enable_density_detection=False, + enable_spatial_detection=False, + enable_ghost_detection=False, + enable_temporal_detection=False, + ) def test_detector_with_extreme_thresholds():