]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.history/src/org/simantics/history/HistorySampler.java
Added another sampling method to HistorySampler
[simantics/platform.git] / bundles / org.simantics.history / src / org / simantics / history / HistorySampler.java
index 73df6dc618bbb99e84f3638f8dbff795ea80bc28..61f1f8bef7dfbe3864f0c7539688fecef758c015 100644 (file)
@@ -15,9 +15,10 @@ public class HistorySampler {
     public synchronized static TDoubleArrayList sample( HistorySamplerItem item, double from, double end, double timeWindow, double timeStep, boolean resample ) throws HistoryException, IOException {
 
        try {
-               item.open();
+               // 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();
@@ -25,10 +26,18 @@ public class HistorySampler {
     }
 
     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 = 0.0;
+       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();
 
@@ -217,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;
+
+       }
+
 }