Skip to content

Commit a5a4806

Browse files
committed
Anomaly rules return None (no result) when the values are flat and the anomaly cannot be determined.
1 parent 0d6a4c4 commit a5a4806

13 files changed

+29
-56
lines changed

dqops/src/test/java/com/dqops/rules/percentile/AnomalyDifferencingPercentileMovingAverage30DaysRuleParametersSpecTests.java

+4-10
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ void executeRule_whenActualValueIsBelowMaxValueAndPastValuesAreNormal_thenReturn
8686
}
8787

8888
@Test
89-
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreSteady_thenReturnsPassed() {
89+
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreSteady_thenReturnsNull() {
9090
this.sut.setAnomalyPercent(20.0);
9191

9292
Double increment = 7.0;
@@ -102,10 +102,7 @@ void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreSteady_thenRetur
102102
RuleExecutionResult ruleExecutionResult = PythonRuleRunnerObjectMother.executeBuiltInRule(actualValue,
103103
this.sut, this.readoutTimestamp, historicDataPoints, this.timeWindowSettings);
104104

105-
Assertions.assertTrue(ruleExecutionResult.getPassed());
106-
Assertions.assertEquals(actualValue, ruleExecutionResult.getExpectedValue());
107-
Assertions.assertEquals(actualValue, ruleExecutionResult.getLowerBound());
108-
Assertions.assertEquals(actualValue, ruleExecutionResult.getUpperBound());
105+
Assertions.assertNull(ruleExecutionResult.getPassed());
109106
}
110107

111108
@Test
@@ -129,7 +126,7 @@ void executeRule_whenActualValueIsNotEqualToLastValueAndAllPastValuesArePresentC
129126
}
130127

131128
@Test
132-
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreEqual_thenReturnsPassed() {
129+
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreEqual_thenReturnsNull() {
133130
this.sut.setAnomalyPercent(20.0);
134131

135132
Arrays.fill(this.sensorReadouts, 10.0);
@@ -140,10 +137,7 @@ void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreEqual_thenReturn
140137
RuleExecutionResult ruleExecutionResult = PythonRuleRunnerObjectMother.executeBuiltInRule(10.0,
141138
this.sut, this.readoutTimestamp, historicDataPoints, this.timeWindowSettings);
142139

143-
Assertions.assertTrue(ruleExecutionResult.getPassed());
144-
Assertions.assertEquals(10.0, ruleExecutionResult.getExpectedValue());
145-
Assertions.assertEquals(10.0, ruleExecutionResult.getLowerBound());
146-
Assertions.assertEquals(10.0, ruleExecutionResult.getUpperBound());
140+
Assertions.assertNull(ruleExecutionResult.getPassed());
147141
}
148142

149143
@Test

dqops/src/test/java/com/dqops/rules/percentile/AnomalyDifferencingPercentileMovingAverageRuleParametersSpecTests.java

+6-15
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ void executeRule_whenActualValueIsAboveMaxValueAndPastValuesAreNormalFrom1_thenR
167167
}
168168

169169
@Test
170-
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreSteadyFrom1_thenReturnsPassed() {
170+
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreSteadyFrom1_thenReturnsNull() {
171171
this.sut.setAnomalyPercent(20.0);
172172

173173
Double increment = 7.0;
@@ -183,14 +183,11 @@ void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreSteadyFrom1_then
183183
RuleExecutionResult ruleExecutionResult = PythonRuleRunnerObjectMother.executeBuiltInRule(actualValue,
184184
this.sut, this.readoutTimestamp, historicDataPoints, this.timeWindowSettings);
185185

186-
Assertions.assertTrue(ruleExecutionResult.getPassed());
187-
Assertions.assertEquals(actualValue, ruleExecutionResult.getExpectedValue());
188-
Assertions.assertEquals(actualValue, ruleExecutionResult.getLowerBound());
189-
Assertions.assertEquals(actualValue, ruleExecutionResult.getUpperBound());
186+
Assertions.assertNull(ruleExecutionResult.getPassed());
190187
}
191188

192189
@Test
193-
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreSteadyFrom0_thenReturnsPassed() {
190+
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreSteadyFrom0_thenReturnsNull() {
194191
this.sut.setAnomalyPercent(20.0);
195192

196193
Double increment = 7.0;
@@ -206,10 +203,7 @@ void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreSteadyFrom0_then
206203
RuleExecutionResult ruleExecutionResult = PythonRuleRunnerObjectMother.executeBuiltInRule(actualValue,
207204
this.sut, this.readoutTimestamp, historicDataPoints, this.timeWindowSettings);
208205

209-
Assertions.assertTrue(ruleExecutionResult.getPassed());
210-
Assertions.assertEquals(actualValue, ruleExecutionResult.getExpectedValue());
211-
Assertions.assertEquals(actualValue, ruleExecutionResult.getLowerBound());
212-
Assertions.assertEquals(actualValue, ruleExecutionResult.getUpperBound());
206+
Assertions.assertNull(ruleExecutionResult.getPassed());
213207
}
214208

215209
@Test
@@ -233,7 +227,7 @@ void executeRule_whenActualValueIsNotEqualToLastValueAndAllPastValuesArePresentC
233227
}
234228

235229
@Test
236-
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreEqual_thenReturnsPassed() {
230+
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreEqual_thenReturnsNull() {
237231
this.sut.setAnomalyPercent(20.0);
238232

239233
Arrays.fill(this.sensorReadouts, 10.0);
@@ -244,10 +238,7 @@ void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreEqual_thenReturn
244238
RuleExecutionResult ruleExecutionResult = PythonRuleRunnerObjectMother.executeBuiltInRule(10.0,
245239
this.sut, this.readoutTimestamp, historicDataPoints, this.timeWindowSettings);
246240

247-
Assertions.assertTrue(ruleExecutionResult.getPassed());
248-
Assertions.assertEquals(10.0, ruleExecutionResult.getExpectedValue());
249-
Assertions.assertEquals(10.0, ruleExecutionResult.getLowerBound());
250-
Assertions.assertEquals(10.0, ruleExecutionResult.getUpperBound());
241+
Assertions.assertNull(ruleExecutionResult.getPassed());
251242
}
252243

253244
@Test

dqops/src/test/java/com/dqops/rules/percentile/AnomalyStationaryPercentileMovingAverage30DaysRuleParametersSpecTests.java

+4-10
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ void executeRule_whenActualValueIsBelowMinValueAndAllPastValuesArePresentAndChan
118118
}
119119

120120
@Test
121-
void executeRule_whenActualValueIsEqualToLastValueAndAllPastValuesArePresentChangeAndEqual_thenReturnsPassed() {
121+
void executeRule_whenActualValueIsEqualToLastValueAndAllPastValuesArePresentChangeAndEqual_thenReturnsNull() {
122122
this.sut.setAnomalyPercent(20.0);
123123

124124
for (int i = 0; i < this.sensorReadouts.length; i++) {
@@ -131,10 +131,7 @@ void executeRule_whenActualValueIsEqualToLastValueAndAllPastValuesArePresentChan
131131
RuleExecutionResult ruleExecutionResult = PythonRuleRunnerObjectMother.executeBuiltInRule(20.0,
132132
this.sut, this.readoutTimestamp, historicDataPoints, this.timeWindowSettings);
133133

134-
Assertions.assertTrue(ruleExecutionResult.getPassed());
135-
Assertions.assertEquals(20.0, ruleExecutionResult.getExpectedValue());
136-
Assertions.assertEquals(20.0, ruleExecutionResult.getLowerBound(), 0.1);
137-
Assertions.assertEquals(20.0, ruleExecutionResult.getUpperBound(), 0.1);
134+
Assertions.assertNull(ruleExecutionResult.getPassed());
138135
}
139136

140137
@Test
@@ -158,7 +155,7 @@ void executeRule_whenActualValueIsNotEqualToLastValueAndAllPastValuesArePresentC
158155
}
159156

160157
@Test
161-
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreEqual_thenReturnsPassed() {
158+
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreEqual_thenReturnsNull() {
162159
this.sut.setAnomalyPercent(20.0);
163160

164161
Arrays.fill(this.sensorReadouts, 10.0);
@@ -169,10 +166,7 @@ void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreEqual_thenReturn
169166
RuleExecutionResult ruleExecutionResult = PythonRuleRunnerObjectMother.executeBuiltInRule(10.0,
170167
this.sut, this.readoutTimestamp, historicDataPoints, this.timeWindowSettings);
171168

172-
Assertions.assertTrue(ruleExecutionResult.getPassed());
173-
Assertions.assertEquals(10.0, ruleExecutionResult.getExpectedValue());
174-
Assertions.assertEquals(10.0, ruleExecutionResult.getLowerBound());
175-
Assertions.assertEquals(10.0, ruleExecutionResult.getUpperBound());
169+
Assertions.assertNull(ruleExecutionResult.getPassed());
176170
}
177171

178172
@Test

dqops/src/test/java/com/dqops/rules/percentile/AnomalyStationaryPercentileMovingAverageRuleParametersSpecTests.java

+4-10
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ void executeRule_whenActualValueIsBelowMinValueAndAllPastValuesArePresentAndChan
118118
}
119119

120120
@Test
121-
void executeRule_whenActualValueIsEqualToLastValueAndAllPastValuesArePresentChangeAndEqual_thenReturnsPassed() {
121+
void executeRule_whenActualValueIsEqualToLastValueAndAllPastValuesArePresentChangeAndEqual_thenReturnsNull() {
122122
this.sut.setAnomalyPercent(20.0);
123123

124124
for (int i = 0; i < this.sensorReadouts.length; i++) {
@@ -131,10 +131,7 @@ void executeRule_whenActualValueIsEqualToLastValueAndAllPastValuesArePresentChan
131131
RuleExecutionResult ruleExecutionResult = PythonRuleRunnerObjectMother.executeBuiltInRule(20.0,
132132
this.sut, this.readoutTimestamp, historicDataPoints, this.timeWindowSettings);
133133

134-
Assertions.assertTrue(ruleExecutionResult.getPassed());
135-
Assertions.assertEquals(20.0, ruleExecutionResult.getExpectedValue());
136-
Assertions.assertEquals(20.0, ruleExecutionResult.getLowerBound(), 0.1);
137-
Assertions.assertEquals(20.0, ruleExecutionResult.getUpperBound(), 0.1);
134+
Assertions.assertNull(ruleExecutionResult.getPassed());
138135
}
139136

140137
@Test
@@ -158,7 +155,7 @@ void executeRule_whenActualValueIsNotEqualToLastValueAndAllPastValuesArePresentC
158155
}
159156

160157
@Test
161-
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreEqual_thenReturnsPassed() {
158+
void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreEqual_thenReturnsNull() {
162159
this.sut.setAnomalyPercent(20.0);
163160

164161
Arrays.fill(this.sensorReadouts, 10.0);
@@ -169,10 +166,7 @@ void executeRule_whenActualValueIsWithinQuantileAndPastValuesAreEqual_thenReturn
169166
RuleExecutionResult ruleExecutionResult = PythonRuleRunnerObjectMother.executeBuiltInRule(10.0,
170167
this.sut, this.readoutTimestamp, historicDataPoints, this.timeWindowSettings);
171168

172-
Assertions.assertTrue(ruleExecutionResult.getPassed());
173-
Assertions.assertEquals(10.0, ruleExecutionResult.getExpectedValue());
174-
Assertions.assertEquals(10.0, ruleExecutionResult.getLowerBound());
175-
Assertions.assertEquals(10.0, ruleExecutionResult.getUpperBound());
169+
Assertions.assertNull(ruleExecutionResult.getPassed());
176170
}
177171

178172
@Test

home/rules/percentile/anomaly_differencing_percentile_moving_average.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def evaluate_rule(rule_parameters: RuleExecutionRunParameters) -> RuleExecutionR
101101
actual_difference = rule_parameters.actual_value - last_readout
102102

103103
if float(differences_std) == 0:
104-
return RuleExecutionResult(actual_difference == differences_median_float,
104+
return RuleExecutionResult(None if actual_difference == differences_median_float else False,
105105
last_readout + differences_median_float, last_readout + differences_median_float,
106106
last_readout + differences_median_float)
107107

home/rules/percentile/anomaly_differencing_percentile_moving_average_30_days.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def evaluate_rule(rule_parameters: RuleExecutionRunParameters) -> RuleExecutionR
101101
actual_difference = rule_parameters.actual_value - last_readout
102102

103103
if float(differences_std) == 0:
104-
return RuleExecutionResult(actual_difference == differences_median_float,
104+
return RuleExecutionResult(None if actual_difference == differences_median_float else False,
105105
last_readout + differences_median_float, last_readout + differences_median_float,
106106
last_readout + differences_median_float)
107107

home/rules/percentile/anomaly_partition_row_count.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def evaluate_rule(rule_parameters: RuleExecutionRunParameters) -> RuleExecutionR
9595
filtered_std = scipy.stats.tstd(filtered)
9696

9797
if float(filtered_std) == 0:
98-
return RuleExecutionResult(rule_parameters.actual_value == filtered_median_float,
98+
return RuleExecutionResult(None if rule_parameters.actual_value == filtered_median_float else False,
9999
filtered_median_float, filtered_median_float, filtered_median_float)
100100

101101
degrees_of_freedom = float(rule_parameters.configuration_parameters.degrees_of_freedom)

home/rules/percentile/anomaly_stationary_count_values.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ def evaluate_rule(rule_parameters: RuleExecutionRunParameters) -> RuleExecutionR
9696
filtered_std = scipy.stats.tstd(filtered)
9797

9898
if float(filtered_std) == 0:
99-
return RuleExecutionResult(rule_parameters.actual_value == filtered_median_float or
100-
(rule_parameters.actual_value == 0 and 0 in all_extracted),
99+
return RuleExecutionResult(None if (rule_parameters.actual_value == filtered_median_float or
100+
(rule_parameters.actual_value == 0 and 0 in all_extracted)) else False,
101101
filtered_median_float, filtered_median_float if 0 not in all_extracted else 0,
102102
filtered_median_float)
103103

home/rules/percentile/anomaly_stationary_percent_values.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ def evaluate_rule(rule_parameters: RuleExecutionRunParameters) -> RuleExecutionR
9696
filtered_std = scipy.stats.tstd(filtered)
9797

9898
if float(filtered_std) == 0.0:
99-
return RuleExecutionResult(rule_parameters.actual_value == filtered_median_float or
99+
return RuleExecutionResult(None if (rule_parameters.actual_value == filtered_median_float or
100100
(rule_parameters.actual_value == 0.0 and 0.0 in all_extracted) or
101-
(rule_parameters.actual_value == 100.0 and 100.0 in all_extracted),
101+
(rule_parameters.actual_value == 100.0 and 100.0 in all_extracted)) else False,
102102
filtered_median_float,
103103
filtered_median_float if 0.0 not in all_extracted else 0.0,
104104
filtered_median_float if 100.0 not in all_extracted else 100.0)

home/rules/percentile/anomaly_stationary_percentile_moving_average.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def evaluate_rule(rule_parameters: RuleExecutionRunParameters) -> RuleExecutionR
9595
filtered_std = scipy.stats.tstd(filtered)
9696

9797
if float(filtered_std) == 0:
98-
return RuleExecutionResult(rule_parameters.actual_value == filtered_median_float,
98+
return RuleExecutionResult(None if rule_parameters.actual_value == filtered_median_float else False,
9999
filtered_median_float, filtered_median_float, filtered_median_float)
100100

101101
degrees_of_freedom = float(rule_parameters.configuration_parameters.degrees_of_freedom)

home/rules/percentile/anomaly_stationary_percentile_moving_average_30_days.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def evaluate_rule(rule_parameters: RuleExecutionRunParameters) -> RuleExecutionR
9898
filtered_std = scipy.stats.tstd(filtered)
9999

100100
if float(filtered_std) == 0:
101-
return RuleExecutionResult(rule_parameters.actual_value == filtered_median_float,
101+
return RuleExecutionResult(None if rule_parameters.actual_value == filtered_median_float else False,
102102
filtered_median_float, filtered_median_float, filtered_median_float)
103103

104104
degrees_of_freedom = float(rule_parameters.configuration_parameters.degrees_of_freedom)

home/rules/percentile/anomaly_timeliness_delay.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def evaluate_rule(rule_parameters: RuleExecutionRunParameters) -> RuleExecutionR
9595
filtered_std = scipy.stats.tstd(filtered)
9696

9797
if float(filtered_std) == 0:
98-
return RuleExecutionResult(rule_parameters.actual_value == filtered_median_float,
98+
return RuleExecutionResult(None if rule_parameters.actual_value == filtered_median_float else False,
9999
filtered_median_float, 0.0, filtered_median_float)
100100

101101
degrees_of_freedom = float(rule_parameters.configuration_parameters.degrees_of_freedom)

home/rules/percentile/change_percentile_moving_7_days.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,4 @@ def evaluate_rule(rule_parameters: RuleExecutionRunParameters) -> RuleExecutionR
107107
expected_value = last_readout + differences_mean
108108
lower_bound = last_readout + threshold_lower if threshold_lower is not None else None
109109
upper_bound = last_readout + threshold_upper if threshold_upper is not None else None
110-
return RuleExecutionResult(passed, expected_value, lower_bound, upper_bound)
110+
return RuleExecutionResult(passed, expected_value, lower_bound, upper_bound)

0 commit comments

Comments
 (0)