Skip to content

Commit 5288816

Browse files
committed
Fix library UDF edge cases
1 parent 7b1b673 commit 5288816

31 files changed

Lines changed: 770 additions & 65 deletions

library-udf/src/main/java/org/apache/iotdb/library/anomaly/UDTFIQR.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,12 @@ public void beforeStart(UDFParameters parameters, UDTFConfigurations configurati
9090

9191
@Override
9292
public void transform(Row row, PointCollector collector) throws Exception {
93+
if (row.isNull(0)) {
94+
return;
95+
}
9396
if (compute.equalsIgnoreCase(STREAM_COMPUTE) && q3 > q1) {
9497
double v = Util.getValueAsDouble(row);
95-
if (v < q1 - 1.5 * iqr || v > q3 + 1.5 * iqr) {
98+
if (Double.isFinite(v) && (v < q1 - 1.5 * iqr || v > q3 + 1.5 * iqr)) {
9699
collector.putDouble(row.getTime(), v);
97100
}
98101
} else if (compute.equalsIgnoreCase(BATCH_COMPUTE)) {

library-udf/src/main/java/org/apache/iotdb/library/anomaly/UDTFKSigma.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,19 @@ public void beforeStart(UDFParameters udfParameters, UDTFConfigurations udtfConf
6969
this.multipleK = udfParameters.getDoubleOrDefault("k", 3);
7070
this.dataType = udfParameters.getDataType(0);
7171
this.windowSize = udfParameters.getIntOrDefault("window", DEFAULT_WINDOW_SIZE);
72+
this.mean = 0.0;
73+
this.variance = 0.0;
74+
this.sumX1 = 0.0;
75+
this.sumX2 = 0.0;
7276
this.v = new CircularQueue<>(windowSize);
7377
this.t = new LongCircularQueue(windowSize);
7478
}
7579

7680
@Override
7781
public void transform(Row row, PointCollector collector) throws Exception {
82+
if (row.isNull(0)) {
83+
return;
84+
}
7885
double value = Util.getValueAsDouble(row);
7986
long timestamp = row.getTime();
8087
if (Double.isFinite(value) && !Double.isNaN(value)) {

library-udf/src/main/java/org/apache/iotdb/library/anomaly/UDTFMissDetect.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,12 @@ public void beforeStart(UDFParameters udfp, UDTFConfigurations udtfc) throws Exc
5555

5656
@Override
5757
public void transform(Row row, PointCollector collector) throws Exception {
58-
detector.insert(row.getTime(), Util.getValueAsDouble(row));
58+
if (!row.isNull(0)) {
59+
double v = Util.getValueAsDouble(row);
60+
if (Double.isFinite(v)) {
61+
detector.insert(row.getTime(), v);
62+
}
63+
}
5964
while (detector.hasNext()) {
6065
collector.putBoolean(detector.getOutTime(), detector.getOutValue());
6166
detector.next();

library-udf/src/main/java/org/apache/iotdb/library/anomaly/UDTFOutlier.java

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.iotdb.udf.api.access.Row;
2525
import org.apache.iotdb.udf.api.collector.PointCollector;
2626
import org.apache.iotdb.udf.api.customizer.config.UDTFConfigurations;
27+
import org.apache.iotdb.udf.api.customizer.parameter.UDFParameterValidator;
2728
import org.apache.iotdb.udf.api.customizer.parameter.UDFParameters;
2829
import org.apache.iotdb.udf.api.customizer.strategy.RowByRowAccessStrategy;
2930
import org.apache.iotdb.udf.api.type.Type;
@@ -47,38 +48,66 @@ public class UDTFOutlier implements UDTF {
4748
private ArrayList<Double> currentValueWindow = new ArrayList<>();
4849
private Map<Long, Double> outliers = new HashMap<>();
4950

51+
@Override
52+
public void validate(UDFParameterValidator validator) throws Exception {
53+
validator
54+
.validateInputSeriesNumber(1)
55+
.validateInputSeriesDataType(0, Type.INT32, Type.INT64, Type.FLOAT, Type.DOUBLE)
56+
.validate(
57+
x -> (int) x > 0,
58+
"Parameter k should be a positive integer.",
59+
validator.getParameters().getIntOrDefault("k", 3))
60+
.validate(
61+
x -> (double) x >= 0,
62+
"Parameter r should be non-negative.",
63+
validator.getParameters().getDoubleOrDefault("r", 5))
64+
.validate(
65+
x -> (int) x > 0,
66+
"Parameter w should be a positive integer.",
67+
validator.getParameters().getIntOrDefault("w", 1000))
68+
.validate(
69+
x -> (int) x > 0,
70+
"Parameter s should be a positive integer.",
71+
validator.getParameters().getIntOrDefault("s", 500));
72+
}
73+
5074
@Override
5175
public void beforeStart(UDFParameters udfParameters, UDTFConfigurations udtfConfigurations)
5276
throws Exception {
5377
udtfConfigurations
5478
.setAccessStrategy(new RowByRowAccessStrategy())
55-
.setOutputDataType(udfParameters.getDataType(0));
79+
.setOutputDataType(Type.DOUBLE);
5680
this.k = udfParameters.getIntOrDefault("k", 3);
5781
this.r = udfParameters.getDoubleOrDefault("r", 5);
5882
this.w = udfParameters.getIntOrDefault("w", 1000);
5983
this.s = udfParameters.getIntOrDefault("s", 500);
6084

6185
this.i = 0;
62-
63-
udtfConfigurations.setAccessStrategy(new RowByRowAccessStrategy());
64-
udtfConfigurations.setOutputDataType(Type.DOUBLE);
86+
currentTimeWindow.clear();
87+
currentValueWindow.clear();
88+
outliers.clear();
6589
}
6690

6791
@Override
6892
public void transform(Row row, PointCollector collector) throws Exception {
69-
if (!row.isNull(0)) {
70-
if (i >= w && (i - w) % s == 0) {
71-
detect();
72-
}
93+
if (row.isNull(0)) {
94+
return;
95+
}
96+
double v = Util.getValueAsDouble(row);
97+
if (!Double.isFinite(v)) {
98+
return;
99+
}
100+
if (i >= w && (i - w) % s == 0) {
101+
detect();
102+
}
73103

74-
if (i >= w) {
75-
currentValueWindow.remove(0);
76-
currentTimeWindow.remove(0);
77-
}
78-
currentTimeWindow.add(row.getTime());
79-
currentValueWindow.add(Util.getValueAsDouble(row));
80-
i += 1;
104+
if (i >= w) {
105+
currentValueWindow.remove(0);
106+
currentTimeWindow.remove(0);
81107
}
108+
currentTimeWindow.add(row.getTime());
109+
currentValueWindow.add(v);
110+
i += 1;
82111
}
83112

84113
@Override

library-udf/src/main/java/org/apache/iotdb/library/anomaly/UDTFRange.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ public void beforeStart(UDFParameters parameters, UDTFConfigurations configurati
6363

6464
@Override
6565
public void transform(Row row, PointCollector collector) throws Exception {
66+
if (row.isNull(0)) {
67+
return;
68+
}
6669
int intValue;
6770
long longValue;
6871
float floatValue;

library-udf/src/main/java/org/apache/iotdb/library/anomaly/util/MissDetector.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ public class MissDetector {
4949
public MissDetector(RowIterator iterator, int minLength) throws Exception {
5050
while (iterator.hasNextRow()) {
5151
Row row = iterator.next();
52+
if (row.isNull(0)) {
53+
continue;
54+
}
5255
double v = Util.getValueAsDouble(row);
5356
if (Double.isFinite(v)) {
5457
this.time.add(row.getTime());

library-udf/src/main/java/org/apache/iotdb/library/anomaly/util/StreamMissDetector.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,23 @@ public class StreamMissDetector {
3737
private int minLength;
3838
private int state;
3939
private long startTime;
40+
private boolean hasStartTime;
4041
private int missingStartIndex;
4142
private boolean horizon;
4243
private double standard;
4344

4445
public StreamMissDetector(int minLength) {
4546
this.state = 0;
46-
this.startTime = -1;
47+
this.hasStartTime = false;
4748
this.minLength = minLength;
4849
}
4950

5051
public void insert(long time, double value) {
5152
timeWindow.push(time);
5253
valueWindow.push(value);
53-
if (startTime < 0) {
54+
if (!hasStartTime) {
5455
startTime = time;
56+
hasStartTime = true;
5557
}
5658
switch (state) {
5759
case 0:

library-udf/src/main/java/org/apache/iotdb/library/anomaly/util/WindowDetect.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ public WindowDetect(RowIterator dataIterator, double l, double t) throws Excepti
4141
ArrayList<Double> originList = new ArrayList<>();
4242
while (dataIterator.hasNextRow()) {
4343
Row row = dataIterator.next();
44-
Double v = Util.getValueAsDouble(row);
4544
timeList.add(row.getTime());
46-
if (v == null || !Double.isFinite(v)) {
45+
if (row.isNull(0)) {
4746
originList.add(Double.NaN);
4847
} else {
49-
originList.add(v);
48+
double v = Util.getValueAsDouble(row);
49+
originList.add(Double.isFinite(v) ? v : Double.NaN);
5050
}
5151
}
5252
time = Util.toLongArray(timeList);

library-udf/src/main/java/org/apache/iotdb/library/dprofile/UDAFIntegral.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,15 @@ public class UDAFIntegral implements UDTF {
4040

4141
long unitTime;
4242
long lastTime = -1;
43+
boolean hasLastValue;
4344
double lastValue;
4445
double integralValue = 0;
4546

4647
@Override
4748
public void validate(UDFParameterValidator validator) throws Exception {
4849
validator
4950
.validateInputSeriesNumber(1)
51+
.validateInputSeriesDataType(0, Type.INT32, Type.INT64, Type.FLOAT, Type.DOUBLE)
5052
.validate(
5153
x -> (long) x > 0,
5254
"Unknown time unit input. Supported units are ns, us, ms, s, m, h, d.",
@@ -61,20 +63,28 @@ public void beforeStart(UDFParameters parameters, UDTFConfigurations configurati
6163
configurations.setAccessStrategy(new RowByRowAccessStrategy()).setOutputDataType(Type.DOUBLE);
6264
unitTime =
6365
Util.parseTime(parameters.getStringOrDefault(TIME_UNIT_KEY, TIME_UNIT_S), parameters);
66+
lastTime = -1;
67+
hasLastValue = false;
68+
lastValue = 0;
69+
integralValue = 0;
6470
}
6571

6672
@Override
6773
public void transform(Row row, PointCollector collector) throws Exception {
74+
if (row.isNull(0)) {
75+
return;
76+
}
6877
long nowTime = row.getTime();
6978
double nowValue = Util.getValueAsDouble(row);
7079
if (Double.isFinite(nowValue)) {
7180
// calculate the ladder-shaped area between last point and this one
7281
// skip and initialize the memory if no existing previous point is available
73-
if (lastTime >= 0) {
82+
if (hasLastValue) {
7483
integralValue += (lastValue + nowValue) * (nowTime - lastTime) / 2.0 / unitTime;
7584
}
7685
lastTime = nowTime;
7786
lastValue = nowValue;
87+
hasLastValue = true;
7888
}
7989
}
8090

library-udf/src/main/java/org/apache/iotdb/library/dprofile/UDAFIntegralAvg.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public class UDAFIntegralAvg implements UDTF {
3737

3838
long startTime = -1;
3939
long lastTime = -1;
40+
boolean hasValue;
4041
double lastValue = 0;
4142
double integralValue = 0;
4243

@@ -51,29 +52,36 @@ public void validate(UDFParameterValidator validator) throws Exception {
5152
public void beforeStart(UDFParameters parameters, UDTFConfigurations configurations)
5253
throws Exception {
5354
configurations.setAccessStrategy(new RowByRowAccessStrategy()).setOutputDataType(Type.DOUBLE);
55+
startTime = -1;
56+
lastTime = -1;
57+
hasValue = false;
58+
lastValue = 0;
59+
integralValue = 0;
5460
}
5561

5662
@Override
5763
public void transform(Row row, PointCollector collector) throws Exception {
64+
if (row.isNull(0)) {
65+
return;
66+
}
5867
long nowTime = row.getTime();
5968
double nowValue = Util.getValueAsDouble(row);
60-
if (startTime < 0) {
61-
startTime = nowTime;
62-
}
6369
if (Double.isFinite(nowValue)) {
64-
// calculate the ladder-shaped area between last point and this one
65-
// skip and initialize the memory if no existing previous point is available
66-
if (lastTime >= 0) {
70+
if (!hasValue) {
71+
startTime = nowTime;
72+
} else {
73+
// calculate the ladder-shaped area between last point and this one
6774
integralValue += (lastValue + nowValue) * (nowTime - lastTime) / 2.0;
6875
}
6976
lastTime = nowTime;
7077
lastValue = nowValue;
78+
hasValue = true;
7179
}
7280
}
7381

7482
@Override
7583
public void terminate(PointCollector collector) throws Exception {
76-
if (startTime < 0) {
84+
if (!hasValue) {
7785
// empty input
7886
collector.putDouble(0, 0);
7987
} else if (startTime == lastTime) {

0 commit comments

Comments
 (0)