import java.util.*;
public class AltosTimeSeries implements Iterable<AltosTimeValue> {
- public String label;
- public AltosUnits units;
- List<AltosTimeValue> values;
+ public String label;
+ public AltosUnits units;
+ ArrayList<AltosTimeValue> values;
public void add(AltosTimeValue tv) {
values.add(tv);
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();
}
return values.iterator();
}
- public double max() {
- double max = AltosLib.MISSING;
+ public AltosTimeValue max() {
+ AltosTimeValue max = null;
+ for (AltosTimeValue tv : values)
+ if (max == null || tv.value > max.value)
+ max = tv;
+ return max;
+ }
+
+ public AltosTimeValue max(double start_time, double end_time) {
+ AltosTimeValue max = null;
for (AltosTimeValue tv : values) {
- if (max == AltosLib.MISSING || tv.value > max)
- max = tv.value;
+ if (start_time <= tv.time && tv.time <= end_time)
+ if (max == null || tv.value > max.value)
+ max = tv;
}
return max;
}
- public double min() {
- double min = AltosLib.MISSING;
+ public AltosTimeValue min() {
+ AltosTimeValue min = null;
+ for (AltosTimeValue tv : values) {
+ if (min == null || tv.value < min.value)
+ min = tv;
+ }
+ return min;
+ }
+
+ public AltosTimeValue min(double start_time, double end_time) {
+ AltosTimeValue min = null;
for (AltosTimeValue tv : values) {
- if (min == AltosLib.MISSING || tv.value < min)
- min = tv.value;
+ if (start_time <= tv.time && tv.time <= end_time)
+ if (min == null || tv.value < min.value)
+ min = tv;
}
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;
}
pvalue = v.value;
time = v.time;
-// System.out.printf("%g %g %g\n", time, v.value, value);
integral.add(time, value);
}
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;
+ double value = values.get(j).value;
+ double partial = value * coeff;
+
total_coeff += coeff;
- total_value += coeff * values.get(j).value;
+ total_value += partial;
}
}
if (total_coeff != 0.0)