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