X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.history%2Fsrc%2Forg%2Fsimantics%2Fhistory%2FHistorySampler.java;h=61f1f8bef7dfbe3864f0c7539688fecef758c015;hp=1c45a220fcf005ac80bf0e2b92f9c988127987fc;hb=f3617565a8ffe49d63016f0c1d78e0d4282214b0;hpb=fbe4ffbf25e0b35dcbd51f11b50e740bfe4c593d diff --git a/bundles/org.simantics.history/src/org/simantics/history/HistorySampler.java b/bundles/org.simantics.history/src/org/simantics/history/HistorySampler.java index 1c45a220f..61f1f8bef 100644 --- a/bundles/org.simantics.history/src/org/simantics/history/HistorySampler.java +++ b/bundles/org.simantics.history/src/org/simantics/history/HistorySampler.java @@ -226,5 +226,192 @@ public class HistorySampler { } - + 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; + + } + }