]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 package org.simantics.history;\r
2 \r
3 import gnu.trove.list.array.TDoubleArrayList;\r
4 \r
5 import java.io.IOException;\r
6 import java.math.BigDecimal;\r
7 \r
8 import org.simantics.history.csv.ExportInterpolation;\r
9 import org.simantics.history.util.HistoryExportUtil;\r
10 import org.simantics.history.util.StreamIterator;\r
11 import org.simantics.history.util.ValueBand;\r
12 \r
13 public class HistorySampler {\r
14     \r
15     public synchronized static TDoubleArrayList sample( HistorySamplerItem item, double from, double end, double timeWindow, double timeStep, boolean resample ) throws HistoryException, IOException {\r
16 \r
17         try {\r
18                 item.open();\r
19                 if(item.collector != null)\r
20                         item.collector.flush();\r
21                 return sample(item.iter, from, end, timeWindow, timeStep, resample);\r
22         } finally {\r
23                 item.close();\r
24         }\r
25     }\r
26 \r
27     public static TDoubleArrayList sample( StreamIterator iter, double from, double end, double timeWindow, double timeStep, boolean resample ) throws HistoryException, IOException {\r
28 \r
29         ExportInterpolation numberInterpolation = ExportInterpolation.LINEAR_INTERPOLATION;\r
30 \r
31         double startTime = 0.0;\r
32 \r
33         TDoubleArrayList result = new TDoubleArrayList();\r
34 \r
35         if(iter.isEmpty()) return result;\r
36 \r
37         double allFrom = iter.getFirstTime();\r
38         double allEnd = 10e10;//iter.getLastTime();\r
39         \r
40         if(from > (allEnd + timeStep)) {\r
41                 from = allEnd-timeWindow;\r
42                 end = allEnd;\r
43         }\r
44         \r
45 //      System.err.println("sample " + from + " " + end);\r
46 //      if(from < 0)\r
47 //              System.err.println("fgag");\r
48 \r
49         // Prepare time         \r
50         boolean hasAnyValues = allFrom != Double.MAX_VALUE && allEnd != -Double.MAX_VALUE;\r
51 \r
52         // Make intersection of actual data range (allFrom, allEnd) and requested data (from, end)\r
53         double _from = Double.MAX_VALUE, _end = -Double.MAX_VALUE;              \r
54         if (hasAnyValues) {\r
55                 _from = Math.max(allFrom, from);\r
56                 _end = Math.min(allEnd, end);\r
57         }\r
58 \r
59         if (!hasAnyValues) {\r
60 //              System.err.println("=> no values");\r
61                 return result;\r
62         }\r
63 \r
64         // Iterate until endTime is met for all variables\r
65         double time = _from;\r
66 \r
67         if(!resample) {\r
68 \r
69                 // 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
70                 time = _from;\r
71                 timeStep = 0.0;\r
72 \r
73         } else {\r
74 \r
75                 // time = startTime + n*timeStep \r
76 \r
77                 // Sampling based on given startTime and timeStep\r
78                 if(timeStep > 0) {\r
79 \r
80                         // Find the first sample time that contains data \r
81                         double n = Math.max(0, Math.ceil((_from-startTime) / timeStep));\r
82                         time = startTime + n*timeStep;\r
83 \r
84                 } else {\r
85 \r
86                         // Start sampling from startTime but make sure that it is not less than _from\r
87                         if(startTime > _from) time = startTime;\r
88 \r
89                 }\r
90 \r
91 \r
92         }\r
93 \r
94         // Must convert double times to String when initializing BigDecimal.\r
95         // Otherwise BigDecimal will pick up inaccuracies from beyond 15 precise digits\r
96         // thus making a mess of the time step calculations.\r
97 \r
98         BigDecimal bigTime = new BigDecimal(String.valueOf(time));\r
99         BigDecimal bigTimeStep = new BigDecimal(String.valueOf(timeStep));\r
100 \r
101         //System.err.println("=> goto " + time);\r
102         \r
103         if(!iter.gotoTime(time)) {\r
104                 //System.err.println("=> no sample found at " + time);\r
105                 return result;\r
106         }\r
107         \r
108         //time = iter.getValueBand().getTimeDouble();\r
109 \r
110         boolean ignore = Math.abs(time-from) < 1e-6; \r
111 \r
112         do {\r
113                 \r
114                 //System.err.println("process " + time + " " + iter.getValueBand());\r
115 \r
116 \r
117 \r
118             // Check for valid value\r
119                 if ( iter.hasValidValue() ) {\r
120                     \r
121                  // Write time\r
122                 if(!ignore) {\r
123 //                    System.err.println("Add time : " + time);\r
124                     result.add(time);\r
125                 }\r
126                 // Write value\r
127                         Object value = iter.getValueBand().getValue();\r
128                         //System.err.print("Add value : " + value);\r
129                         if (value instanceof Number) {\r
130                                 if (value instanceof Float || value instanceof Double) {\r
131                                         switch (numberInterpolation) {\r
132                                         case PREVIOUS_SAMPLE:\r
133 \r
134                                         if(!ignore) {\r
135 //                                          System.err.println(" previous .. done!");\r
136                                                 result.add(((Number) value).doubleValue());\r
137                                         }\r
138                                         \r
139                                                 break;\r
140 \r
141                                         case LINEAR_INTERPOLATION:\r
142                                                 if (time != iter.getValueBand().getTimeDouble() && iter.hasNext()) {\r
143 \r
144                                                         // Interpolate\r
145                                                         int currentIndex = iter.getIndex();\r
146                                                         ValueBand band = iter.getValueBand();\r
147                                                         //double t1 = band.getTimeDouble();\r
148                                                         Number v1 = (Number) value;\r
149                                                         double t12 = band.getEndTimeDouble();\r
150                                                         iter.next();\r
151                                                         double t2 = iter.getValueBand().getTimeDouble();\r
152                                                         Number v2 = (Number) iter.getValueBand().getValue();\r
153                                                         iter.gotoIndex(currentIndex);\r
154 \r
155                                                         double vs = v1.doubleValue();\r
156                                                         if(time > t12)\r
157                                                                 vs = HistoryExportUtil.biglerp(t12, v1.doubleValue(), t2, v2.doubleValue(), time);\r
158 \r
159                                                 if(!ignore) {\r
160 //                                                  System.err.println(" linear .. done!");\r
161                                                         result.add(vs);\r
162                                                 }\r
163 \r
164                                                 } else {\r
165                                                         // Exact timestamp match, or last sample.\r
166                                                         // Don't interpolate nor extrapolate.\r
167                                                 if(!ignore) {\r
168 //                                                  System.err.println(" else .. done!");\r
169                                                         result.add(((Number) value).doubleValue());\r
170                                                 }\r
171                                                 }\r
172                                                 break;\r
173                                         default:\r
174                                                 throw new UnsupportedOperationException("Unsupported interpolation: " + numberInterpolation);\r
175                                         }\r
176                                 } else {\r
177                                         throw new IllegalStateException("Value is not a number " + value);\r
178                                 }\r
179                         } else if (value instanceof Boolean) {\r
180                         if(!ignore)\r
181                                 result.add( (Boolean)value ? 1.0: 0.0);\r
182                         } else {\r
183                                 throw new IllegalStateException("Value is not a number " + value);\r
184                         }\r
185                 }\r
186                 \r
187                 ignore = false;\r
188 \r
189                 // Read next values, and the following times\r
190                 if ( timeStep>0.0 ) {\r
191                         bigTime = bigTime.add(bigTimeStep);\r
192                         time = bigTime.doubleValue();\r
193                 } else {\r
194                         // Get smallest end time that is larger than current time\r
195                         Double nextTime = null;\r
196                         //                      System.out.println("time = "+time);\r
197                         if(!iter.hasNext()) break;\r
198                         Double itemNextTime = iter.getNextTime( time );\r
199                         //                              System.err.println("  "+i.label+" nextTime="+itemNextTime);\r
200                         if ( nextTime == null || ( nextTime > itemNextTime && !itemNextTime.equals( time ) ) ) nextTime = itemNextTime; \r
201                         if ( nextTime == null || nextTime.equals( time ) ) break;\r
202                         time = nextTime;\r
203                 }\r
204 \r
205                 boolean hasMore = false;\r
206 \r
207                 iter.proceedToTime(time);\r
208                 if(HistoryExportUtil.contains(iter, time)) hasMore = true;\r
209 \r
210                 if(!hasMore) break;\r
211 \r
212         } while (time<=_end);\r
213 \r
214                 //System.err.println("=> " + Arrays.toString(result.toArray()));\r
215         \r
216         return result;\r
217 \r
218     }\r
219 \r
220         \r
221 }\r