X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=altoslib%2FAltosTimeSeries.java;h=64fb399e8a23974797f01f94e2327840be4e8bcd;hb=855a7d243a5a85728a7b23fdfe9485d4ecaf71cf;hp=1d3d9a6c5185878fb6400412f400c23d2a831581;hpb=f26cfe417c6977cf1e7e75a4f050e25f64d41859;p=fw%2Faltos diff --git a/altoslib/AltosTimeSeries.java b/altoslib/AltosTimeSeries.java index 1d3d9a6c..64fb399e 100644 --- a/altoslib/AltosTimeSeries.java +++ b/altoslib/AltosTimeSeries.java @@ -17,9 +17,9 @@ package org.altusmetrum.altoslib_11; import java.util.*; public class AltosTimeSeries implements Iterable { - public String label; - public AltosUnits units; - List values; + public String label; + public AltosUnits units; + ArrayList values; public void add(AltosTimeValue tv) { values.add(tv); @@ -33,6 +33,74 @@ public class AltosTimeSeries implements Iterable { return values.get(i); } + private double lerp(AltosTimeValue v0, AltosTimeValue v1, double t) { + /* degenerate case */ + if (v0.time == v1.time) + return (v0.value + v1.value) / 2; + + return (v0.value * (v1.time - t) + v1.value * (t - v0.time)) / (v1.time - v0.time); + } + + private int after_index(double time) { + int lo = 0; + int hi = values.size() - 1; + + while (lo <= hi) { + int mid = (lo + hi) / 2; + + if (values.get(mid).time < time) + lo = mid + 1; + else + hi = mid - 1; + } + return lo; + } + + /* Compute a value for an arbitrary time */ + public double value(double time) { + int after = after_index(time); + double ret; + + if (after == 0) + ret = values.get(0).value; + else if (after == values.size()) + ret = values.get(after - 1).value; + else { + AltosTimeValue b = values.get(after-1); + AltosTimeValue a = values.get(after); + ret = lerp(b, a, time); + } + return ret; + } + + /* Find the value just before an arbitrary time */ + public double value_before(double time) { + int after = after_index(time); + + if (after == 0) + return values.get(0).value; + return values.get(after-1).value; + } + + /* Find the value just after an arbitrary time */ + public double value_after(double time) { + int after = after_index(time); + + if (after == values.size()) + return values.get(after-1).value; + return values.get(after).value; + } + + public double time_of(double value) { + double last = AltosLib.MISSING; + for (AltosTimeValue v : values) { + if (v.value >= value) + return v.time; + last = v.time; + } + return last; + } + public int size() { return values.size(); } @@ -50,6 +118,16 @@ public class AltosTimeSeries implements Iterable { return max; } + public double max(double start_time, double end_time) { + double max = AltosLib.MISSING; + for (AltosTimeValue tv : values) { + if (start_time <= tv.time && tv.time <= end_time) + if (max == AltosLib.MISSING || tv.value > max) + max = tv.value; + } + return max; + } + public double min() { double min = AltosLib.MISSING; for (AltosTimeValue tv : values) { @@ -59,6 +137,42 @@ public class AltosTimeSeries implements Iterable { return min; } + public double min(double start_time, double end_time) { + double min = AltosLib.MISSING; + for (AltosTimeValue tv : values) { + if (start_time <= tv.time && tv.time <= end_time) + if (min == AltosLib.MISSING || tv.value < min) + min = tv.value; + } + return min; + } + + public double average() { + double total = 0; + int count = 0; + for (AltosTimeValue tv : values) { + total += tv.value; + count++; + } + if (count == 0) + return AltosLib.MISSING; + return total / count; + } + + public double average(double start_time, double end_time) { + double total = 0; + int count = 0; + for (AltosTimeValue tv : values) { + if (start_time <= tv.time && tv.time <= end_time) { + total += tv.value; + count++; + } + } + if (count == 0) + return AltosLib.MISSING; + return total / count; + } + public AltosTimeSeries integrate(AltosTimeSeries integral) { double value = 0.0; double pvalue = 0.0; @@ -74,7 +188,6 @@ public class AltosTimeSeries implements Iterable { } pvalue = v.value; time = v.time; -// System.out.printf("%g %g %g\n", time, v.value, value); integral.add(time, value); } @@ -144,11 +257,16 @@ public class AltosTimeSeries implements Iterable { int left = find_left(i, half_width); int right = find_right(i, half_width); + for (int j = left; j <= right; j++) { double j_time = values.get(j).time; if (left_time <= j_time && j_time <= right_time) { - double coeff = filter_coeff(j_time - center_time, width); + double j_left = j == left ? left_time : values.get(j-1).time; + double j_right = j == right ? right_time : values.get(j+1).time; + double interval = (j_right - j_left) / 2.0; + double coeff = filter_coeff(j_time - center_time, width) * interval; + total_coeff += coeff; total_value += coeff * values.get(j).value; }