-package org.simantics.history;\r
-\r
-import gnu.trove.list.array.TDoubleArrayList;\r
-\r
-import java.io.IOException;\r
-import java.math.BigDecimal;\r
-\r
-import org.simantics.history.csv.ExportInterpolation;\r
-import org.simantics.history.util.HistoryExportUtil;\r
-import org.simantics.history.util.StreamIterator;\r
-import org.simantics.history.util.ValueBand;\r
-\r
-public class HistorySampler {\r
- \r
- public synchronized static TDoubleArrayList sample( HistorySamplerItem item, double from, double end, double timeWindow, double timeStep, boolean resample ) throws HistoryException, IOException {\r
-\r
- try {\r
- item.open();\r
- if(item.collector != null)\r
- item.collector.flush();\r
- return sample(item.iter, from, end, timeWindow, timeStep, resample);\r
- } finally {\r
- item.close();\r
- }\r
- }\r
-\r
- public static TDoubleArrayList sample( StreamIterator iter, double from, double end, double timeWindow, double timeStep, boolean resample ) throws HistoryException, IOException {\r
-\r
- ExportInterpolation numberInterpolation = ExportInterpolation.LINEAR_INTERPOLATION;\r
-\r
- double startTime = 0.0;\r
-\r
- TDoubleArrayList result = new TDoubleArrayList();\r
-\r
- if(iter.isEmpty()) return result;\r
-\r
- double allFrom = iter.getFirstTime();\r
- double allEnd = 10e10;//iter.getLastTime();\r
- \r
- if(from > (allEnd + timeStep)) {\r
- from = allEnd-timeWindow;\r
- end = allEnd;\r
- }\r
- \r
-// System.err.println("sample " + from + " " + end);\r
-// if(from < 0)\r
-// System.err.println("fgag");\r
-\r
- // Prepare time \r
- boolean hasAnyValues = allFrom != Double.MAX_VALUE && allEnd != -Double.MAX_VALUE;\r
-\r
- // Make intersection of actual data range (allFrom, allEnd) and requested data (from, end)\r
- double _from = Double.MAX_VALUE, _end = -Double.MAX_VALUE; \r
- if (hasAnyValues) {\r
- _from = Math.max(allFrom, from);\r
- _end = Math.min(allEnd, end);\r
- }\r
-\r
- if (!hasAnyValues) {\r
-// System.err.println("=> no values");\r
- return result;\r
- }\r
-\r
- // Iterate until endTime is met for all variables\r
- double time = _from;\r
-\r
- if(!resample) {\r
-\r
- // If resample is false then all samples are reported as is. The code achieves this by setting startTime to _from and timeStep to 0.0 \r
- time = _from;\r
- timeStep = 0.0;\r
-\r
- } else {\r
-\r
- // time = startTime + n*timeStep \r
-\r
- // Sampling based on given startTime and timeStep\r
- if(timeStep > 0) {\r
-\r
- // Find the first sample time that contains data \r
- double n = Math.max(0, Math.ceil((_from-startTime) / timeStep));\r
- time = startTime + n*timeStep;\r
-\r
- } else {\r
-\r
- // Start sampling from startTime but make sure that it is not less than _from\r
- if(startTime > _from) time = startTime;\r
-\r
- }\r
-\r
-\r
- }\r
-\r
- // Must convert double times to String when initializing BigDecimal.\r
- // Otherwise BigDecimal will pick up inaccuracies from beyond 15 precise digits\r
- // thus making a mess of the time step calculations.\r
-\r
- BigDecimal bigTime = new BigDecimal(String.valueOf(time));\r
- BigDecimal bigTimeStep = new BigDecimal(String.valueOf(timeStep));\r
-\r
- //System.err.println("=> goto " + time);\r
- \r
- if(!iter.gotoTime(time)) {\r
- //System.err.println("=> no sample found at " + time);\r
- return result;\r
- }\r
- \r
- //time = iter.getValueBand().getTimeDouble();\r
-\r
- boolean ignore = Math.abs(time-from) < 1e-6; \r
-\r
- do {\r
- \r
- //System.err.println("process " + time + " " + iter.getValueBand());\r
-\r
-\r
-\r
- // Check for valid value\r
- if ( iter.hasValidValue() ) {\r
- \r
- // Write time\r
- if(!ignore) {\r
-// System.err.println("Add time : " + time);\r
- result.add(time);\r
- }\r
- // Write value\r
- Object value = iter.getValueBand().getValue();\r
- //System.err.print("Add value : " + value);\r
- if (value instanceof Number) {\r
- if (value instanceof Float || value instanceof Double) {\r
- switch (numberInterpolation) {\r
- case PREVIOUS_SAMPLE:\r
-\r
- if(!ignore) {\r
-// System.err.println(" previous .. done!");\r
- result.add(((Number) value).doubleValue());\r
- }\r
- \r
- break;\r
-\r
- case LINEAR_INTERPOLATION:\r
- if (time != iter.getValueBand().getTimeDouble() && iter.hasNext()) {\r
-\r
- // Interpolate\r
- int currentIndex = iter.getIndex();\r
- ValueBand band = iter.getValueBand();\r
- //double t1 = band.getTimeDouble();\r
- Number v1 = (Number) value;\r
- double t12 = band.getEndTimeDouble();\r
- iter.next();\r
- double t2 = iter.getValueBand().getTimeDouble();\r
- Number v2 = (Number) iter.getValueBand().getValue();\r
- iter.gotoIndex(currentIndex);\r
-\r
- double vs = v1.doubleValue();\r
- if(time > t12)\r
- vs = HistoryExportUtil.biglerp(t12, v1.doubleValue(), t2, v2.doubleValue(), time);\r
-\r
- if(!ignore) {\r
-// System.err.println(" linear .. done!");\r
- result.add(vs);\r
- }\r
-\r
- } else {\r
- // Exact timestamp match, or last sample.\r
- // Don't interpolate nor extrapolate.\r
- if(!ignore) {\r
-// System.err.println(" else .. done!");\r
- result.add(((Number) value).doubleValue());\r
- }\r
- }\r
- break;\r
- default:\r
- throw new UnsupportedOperationException("Unsupported interpolation: " + numberInterpolation);\r
- }\r
- } else {\r
- throw new IllegalStateException("Value is not a number " + value);\r
- }\r
- } else if (value instanceof Boolean) {\r
- if(!ignore)\r
- result.add( (Boolean)value ? 1.0: 0.0);\r
- } else {\r
- throw new IllegalStateException("Value is not a number " + value);\r
- }\r
- }\r
- \r
- ignore = false;\r
-\r
- // Read next values, and the following times\r
- if ( timeStep>0.0 ) {\r
- bigTime = bigTime.add(bigTimeStep);\r
- time = bigTime.doubleValue();\r
- } else {\r
- // Get smallest end time that is larger than current time\r
- Double nextTime = null;\r
- // System.out.println("time = "+time);\r
- if(!iter.hasNext()) break;\r
- Double itemNextTime = iter.getNextTime( time );\r
- // System.err.println(" "+i.label+" nextTime="+itemNextTime);\r
- if ( nextTime == null || ( nextTime > itemNextTime && !itemNextTime.equals( time ) ) ) nextTime = itemNextTime; \r
- if ( nextTime == null || nextTime.equals( time ) ) break;\r
- time = nextTime;\r
- }\r
-\r
- boolean hasMore = false;\r
-\r
- iter.proceedToTime(time);\r
- if(HistoryExportUtil.contains(iter, time)) hasMore = true;\r
-\r
- if(!hasMore) break;\r
-\r
- } while (time<=_end);\r
-\r
- //System.err.println("=> " + Arrays.toString(result.toArray()));\r
- \r
- return result;\r
-\r
- }\r
-\r
- \r
-}\r
+package org.simantics.history;
+
+import gnu.trove.list.array.TDoubleArrayList;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+
+import org.simantics.history.csv.ExportInterpolation;
+import org.simantics.history.util.HistoryExportUtil;
+import org.simantics.history.util.StreamIterator;
+import org.simantics.history.util.ValueBand;
+
+public class HistorySampler {
+
+ public synchronized static TDoubleArrayList sample( HistorySamplerItem item, double from, double end, double timeWindow, double timeStep, boolean resample ) throws HistoryException, IOException {
+
+ try {
+ // If there is something pending at this point, flush before opening for read
+ if(item.collector != null)
+ item.collector.flush();
+ item.open();
+ return sample(item.iter, from, end, timeWindow, timeStep, resample);
+ } finally {
+ item.close();
+ }
+ }
+
+ public static TDoubleArrayList sample( StreamIterator iter, double from, double end, double timeWindow, double timeStep, boolean resample ) throws HistoryException, IOException {
+ return sample(iter, from, end, timeWindow, timeStep, resample, 0.0);
+ }
+
+ public static TDoubleArrayList sample( StreamIterator iter, double from, double end, double timeWindow, double timeStep, boolean resample, Double sampleFrom ) throws HistoryException, IOException {
+
+ ExportInterpolation numberInterpolation = ExportInterpolation.LINEAR_INTERPOLATION;
+
+ double startTime = from;
+ if(sampleFrom != null) {
+ // This option can be used do define the offset of sampling. Samples will be sampleFrom + n * timeStep
+ startTime = sampleFrom;
+ }
+
+ TDoubleArrayList result = new TDoubleArrayList();
+
+ if(iter.isEmpty()) return result;
+
+ double allFrom = iter.getFirstTime();
+ double allEnd = 10e10;//iter.getLastTime();
+
+ if(from > (allEnd + timeStep)) {
+ from = allEnd-timeWindow;
+ end = allEnd;
+ }
+
+// System.err.println("sample " + from + " " + end);
+// if(from < 0)
+// System.err.println("fgag");
+
+ // Prepare time
+ boolean hasAnyValues = allFrom != Double.MAX_VALUE && allEnd != -Double.MAX_VALUE;
+
+ // Make intersection of actual data range (allFrom, allEnd) and requested data (from, end)
+ double _from = Double.MAX_VALUE, _end = -Double.MAX_VALUE;
+ if (hasAnyValues) {
+ _from = Math.max(allFrom, from);
+ _end = Math.min(allEnd, end);
+ }
+
+ if (!hasAnyValues) {
+// System.err.println("=> no values");
+ return result;
+ }
+
+ // Iterate until endTime is met for all variables
+ double time = _from;
+
+ if(!resample) {
+
+ // If resample is false then all samples are reported as is. The code achieves this by setting startTime to _from and timeStep to 0.0
+ time = _from;
+ timeStep = 0.0;
+
+ } else {
+
+ // time = startTime + n*timeStep
+
+ // Sampling based on given startTime and timeStep
+ if(timeStep > 0) {
+
+ // Find the first sample time that contains data
+ double n = Math.max(0, Math.ceil((_from-startTime) / timeStep));
+ time = startTime + n*timeStep;
+
+ } else {
+
+ // Start sampling from startTime but make sure that it is not less than _from
+ if(startTime > _from) time = startTime;
+
+ }
+
+
+ }
+
+ // Must convert double times to String when initializing BigDecimal.
+ // Otherwise BigDecimal will pick up inaccuracies from beyond 15 precise digits
+ // thus making a mess of the time step calculations.
+
+ BigDecimal bigTime = new BigDecimal(String.valueOf(time));
+ BigDecimal bigTimeStep = new BigDecimal(String.valueOf(timeStep));
+
+ //System.err.println("=> goto " + time);
+
+ if(!iter.gotoTime(time)) {
+ //System.err.println("=> no sample found at " + time);
+ return result;
+ }
+
+ //time = iter.getValueBand().getTimeDouble();
+
+ boolean ignore = Math.abs(time-from) < 1e-6;
+
+ do {
+
+ //System.err.println("process " + time + " " + iter.getValueBand());
+
+
+
+ // Check for valid value
+ if ( iter.hasValidValue() ) {
+
+ // Write time
+ if(!ignore) {
+// System.err.println("Add time : " + time);
+ result.add(time);
+ }
+ // Write value
+ Object value = iter.getValueBand().getValue();
+ //System.err.print("Add value : " + value);
+ if (value instanceof Number) {
+ if (value instanceof Float || value instanceof Double) {
+ switch (numberInterpolation) {
+ case PREVIOUS_SAMPLE:
+
+ if(!ignore) {
+// System.err.println(" previous .. done!");
+ result.add(((Number) value).doubleValue());
+ }
+
+ break;
+
+ case LINEAR_INTERPOLATION:
+ if (time != iter.getValueBand().getTimeDouble() && iter.hasNext()) {
+
+ // Interpolate
+ int currentIndex = iter.getIndex();
+ ValueBand band = iter.getValueBand();
+ //double t1 = band.getTimeDouble();
+ Number v1 = (Number) value;
+ double t12 = band.getEndTimeDouble();
+ iter.next();
+ double t2 = iter.getValueBand().getTimeDouble();
+ Number v2 = (Number) iter.getValueBand().getValue();
+ iter.gotoIndex(currentIndex);
+
+ double vs = v1.doubleValue();
+ if(time > t12)
+ vs = HistoryExportUtil.biglerp(t12, v1.doubleValue(), t2, v2.doubleValue(), time);
+
+ if(!ignore) {
+// System.err.println(" linear .. done!");
+ result.add(vs);
+ }
+
+ } else {
+ // Exact timestamp match, or last sample.
+ // Don't interpolate nor extrapolate.
+ if(!ignore) {
+// System.err.println(" else .. done!");
+ result.add(((Number) value).doubleValue());
+ }
+ }
+ break;
+ default:
+ throw new UnsupportedOperationException("Unsupported interpolation: " + numberInterpolation);
+ }
+ } else {
+ throw new IllegalStateException("Value is not a number " + value);
+ }
+ } else if (value instanceof Boolean) {
+ if(!ignore)
+ result.add( (Boolean)value ? 1.0: 0.0);
+ } else {
+ throw new IllegalStateException("Value is not a number " + value);
+ }
+ }
+
+ ignore = false;
+
+ // Read next values, and the following times
+ if ( timeStep>0.0 ) {
+ bigTime = bigTime.add(bigTimeStep);
+ time = bigTime.doubleValue();
+ } else {
+ // Get smallest end time that is larger than current time
+ Double nextTime = null;
+ // System.out.println("time = "+time);
+ if(!iter.hasNext()) break;
+ Double itemNextTime = iter.getNextTime( time );
+ // System.err.println(" "+i.label+" nextTime="+itemNextTime);
+ if ( nextTime == null || ( nextTime > itemNextTime && !itemNextTime.equals( time ) ) ) nextTime = itemNextTime;
+ if ( nextTime == null || nextTime.equals( time ) ) break;
+ time = nextTime;
+ }
+
+ boolean hasMore = false;
+
+ iter.proceedToTime(time);
+ if(HistoryExportUtil.contains(iter, time)) hasMore = true;
+
+ if(!hasMore) break;
+
+ } while (time<=_end);
+
+ //System.err.println("=> " + Arrays.toString(result.toArray()));
+
+ return result;
+
+ }
+
+ public synchronized static TDoubleArrayList sample(HistorySamplerItem2 item, double end, double timeWindow, int maxSamples, boolean resample) throws HistoryException, IOException {
+ try {
+ // If there is something pending at this point, flush before opening for read
+ if (item.collector != null)
+ item.collector.flush();
+ double pixelsPerSecond = (double) maxSamples / timeWindow;
+ item.open(pixelsPerSecond);
+ return sample(item.iter, end, timeWindow, maxSamples, resample);
+ } finally {
+ item.close();
+ }
+ }
+
+ private static TDoubleArrayList sample(StreamIterator iter, double end, double timeWindow, int maxSamples, boolean resample) throws HistoryException, IOException {
+ //System.out.println("sample: " + end + ", " + timeWindow + ", " + maxSamples + ", " + resample);
+ ExportInterpolation numberInterpolation = ExportInterpolation.LINEAR_INTERPOLATION;
+
+ double timeStep = 0;
+ double startTime = -1e10;
+
+ TDoubleArrayList result = new TDoubleArrayList();
+ if (iter.isEmpty())
+ return result;
+
+ double allFrom = iter.getFirstTime();
+ double allEnd = iter.getLastTime();
+ //System.out.println("data available [" + allFrom + " .. " + allEnd + "]");
+
+ double from = allEnd-timeWindow;
+ end = allEnd;
+ //System.out.println("sample between [" + from + " .. " + end + "]");
+
+ // Prepare time
+ boolean hasAnyValues = allFrom != Double.MAX_VALUE && allEnd != -Double.MAX_VALUE;
+ if (!hasAnyValues) {
+ //System.err.println("=> no values");
+ return result;
+ }
+
+ // Make intersection of actual data range (allFrom, allEnd) and requested data (from, end)
+ double _from = Math.max(allFrom, from);
+ double _end = Math.min(allEnd, end);
+
+ // Iterate until endTime is met for all variables
+ double time = _from;
+
+ if (!resample) {
+ // If resample is false then all samples are reported as is. The code achieves this by setting startTime to _from and timeStep to 0.0
+ time = _from;
+ timeStep = 0.0;
+ } else {
+ // time = startTime + n*timeStep
+ // Sampling based on given startTime and timeStep
+ if (timeStep > 0) {
+ // Find the first sample time that contains data
+ double n = Math.max(0, Math.ceil((_from-startTime) / timeStep));
+ time = startTime + n*timeStep;
+ } else {
+ // Start sampling from startTime but make sure that it is not less than _from
+ if(startTime > _from) time = startTime;
+ }
+ }
+
+ // Must convert double times to String when initializing BigDecimal.
+ // Otherwise BigDecimal will pick up inaccuracies from beyond 15 precise digits
+ // thus making a mess of the time step calculations.
+ BigDecimal bigTime = new BigDecimal(String.valueOf(time));
+ BigDecimal bigTimeStep = new BigDecimal(String.valueOf(timeStep));
+
+ //System.err.println("=> goto " + time);
+
+ if(!iter.gotoTime(time)) {
+ //System.err.println("=> no sample found at " + time);
+ return result;
+ }
+
+ //time = iter.getValueBand().getTimeDouble();
+
+ boolean ignore = Math.abs(time-from) < 1e-6;
+
+ do {
+
+ //System.err.println("process " + time + " " + iter.getValueBand());
+
+
+
+ // Check for valid value
+ if ( iter.hasValidValue() ) {
+
+ // Write time
+ if(!ignore) {
+ //System.err.println("Add time : " + time);
+ result.add(time);
+ }
+ // Write value
+ Object value = iter.getValueBand().getValue();
+ //System.err.print("Add value : " + value);
+ if (value instanceof Number) {
+ if (value instanceof Float || value instanceof Double) {
+ switch (numberInterpolation) {
+ case PREVIOUS_SAMPLE:
+
+ if(!ignore) {
+ // System.err.println(" previous .. done!");
+ result.add(((Number) value).doubleValue());
+ }
+
+ break;
+
+ case LINEAR_INTERPOLATION:
+ if (time != iter.getValueBand().getTimeDouble() && iter.hasNext()) {
+
+ // Interpolate
+ int currentIndex = iter.getIndex();
+ ValueBand band = iter.getValueBand();
+ //double t1 = band.getTimeDouble();
+ Number v1 = (Number) value;
+ double t12 = band.getEndTimeDouble();
+ iter.next();
+ double t2 = iter.getValueBand().getTimeDouble();
+ Number v2 = (Number) iter.getValueBand().getValue();
+ iter.gotoIndex(currentIndex);
+
+ double vs = v1.doubleValue();
+ if(time > t12)
+ vs = HistoryExportUtil.biglerp(t12, v1.doubleValue(), t2, v2.doubleValue(), time);
+
+ if(!ignore) {
+ //System.err.println(" linear .. done!");
+ result.add(vs);
+ }
+
+ } else {
+ // Exact timestamp match, or last sample.
+ // Don't interpolate nor extrapolate.
+ if(!ignore) {
+ //System.err.println(" else .. done!");
+ result.add(((Number) value).doubleValue());
+ }
+ }
+ break;
+ default:
+ throw new UnsupportedOperationException("Unsupported interpolation: " + numberInterpolation);
+ }
+ } else {
+ throw new IllegalStateException("Value is not a number " + value);
+ }
+ } else if (value instanceof Boolean) {
+ if(!ignore)
+ result.add( (Boolean)value ? 1.0: 0.0);
+ } else {
+ throw new IllegalStateException("Value is not a number " + value);
+ }
+ }
+
+ ignore = false;
+
+ // Read next values, and the following times
+ if ( timeStep>0.0 ) {
+ bigTime = bigTime.add(bigTimeStep);
+ time = bigTime.doubleValue();
+ } else {
+ // Get smallest end time that is larger than current time
+ Double nextTime = null;
+ // System.out.println("time = "+time);
+ if(!iter.hasNext()) break;
+ Double itemNextTime = iter.getNextTime( time );
+ // System.err.println(" "+i.label+" nextTime="+itemNextTime);
+ if ( nextTime == null || ( nextTime > itemNextTime && !itemNextTime.equals( time ) ) ) nextTime = itemNextTime;
+ if ( nextTime == null || nextTime.equals( time ) ) break;
+ time = nextTime;
+ }
+
+ boolean hasMore = false;
+
+ iter.proceedToTime(time);
+ if(HistoryExportUtil.contains(iter, time)) hasMore = true;
+
+ if(!hasMore) break;
+
+ } while (time<=_end);
+
+ //System.err.println("=> " + Arrays.toString(result.toArray()));
+
+ return result;
+
+ }
+
+}