]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.history/src/org/simantics/history/HistorySampler.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.history / src / org / simantics / history / HistorySampler.java
diff --git a/bundles/org.simantics.history/src/org/simantics/history/HistorySampler.java b/bundles/org.simantics.history/src/org/simantics/history/HistorySampler.java
new file mode 100644 (file)
index 0000000..7d34401
--- /dev/null
@@ -0,0 +1,221 @@
+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