Mercurial > dive4elements > gnv-client
comparison gnv-artifacts/src/main/java/de/intevation/gnv/chart/TimeSeriesChart.java @ 329:42a5269636eb
Added time gap detection to time series charts.
gnv-artifacts/trunk@395 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Ingo Weinzierl <ingo.weinzierl@intevation.de> |
---|---|
date | Wed, 02 Dec 2009 15:42:46 +0000 |
parents | 22a6493e8460 |
children | 19571fd1d0e8 |
comparison
equal
deleted
inserted
replaced
328:861d939e587c | 329:42a5269636eb |
---|---|
1 package de.intevation.gnv.chart; | 1 package de.intevation.gnv.chart; |
2 | 2 |
3 import java.text.DateFormat; | 3 import java.text.DateFormat; |
4 import java.text.SimpleDateFormat; | 4 import java.text.SimpleDateFormat; |
5 import java.util.Collection; | 5 import java.util.Collection; |
6 import java.util.Date; | |
6 import java.util.Iterator; | 7 import java.util.Iterator; |
7 import java.util.Locale; | 8 import java.util.Locale; |
8 | 9 |
9 import org.apache.log4j.Logger; | 10 import org.apache.log4j.Logger; |
10 | 11 |
19 import org.jfree.data.time.TimeSeries; | 20 import org.jfree.data.time.TimeSeries; |
20 import org.jfree.data.time.Minute; | 21 import org.jfree.data.time.Minute; |
21 import org.jfree.data.time.TimeSeriesCollection; | 22 import org.jfree.data.time.TimeSeriesCollection; |
22 | 23 |
23 import de.intevation.gnv.geobackend.base.Result; | 24 import de.intevation.gnv.geobackend.base.Result; |
25 import de.intevation.gnv.timeseries.gap.TimeGap; | |
24 | 26 |
25 | 27 |
26 /** | 28 /** |
27 * @author Ingo Weinzierl <ingo.weinzierl@intevation.de> | 29 * @author Ingo Weinzierl <ingo.weinzierl@intevation.de> |
28 */ | 30 */ |
29 public class TimeSeriesChart | 31 public class TimeSeriesChart |
30 extends AbstractXYLineChart | 32 extends AbstractXYLineChart |
31 { | 33 { |
32 | 34 |
33 private static final String DATE_FORMAT = "dd-MMM"; | 35 private static final String DATE_FORMAT = "dd-MMM"; |
36 | |
37 private static final long NO_TIME_GAP = Long.MAX_VALUE - 1000; | |
34 | 38 |
35 private static Logger log = Logger.getLogger(TimeSeriesChart.class); | 39 private static Logger log = Logger.getLogger(TimeSeriesChart.class); |
36 | 40 |
37 | 41 |
38 public TimeSeriesChart( | 42 public TimeSeriesChart( |
94 Iterator iter = resultSet.iterator(); | 98 Iterator iter = resultSet.iterator(); |
95 Result row = null; | 99 Result row = null; |
96 String seriesName = null; | 100 String seriesName = null; |
97 TimeSeries series = null; | 101 TimeSeries series = null; |
98 | 102 |
99 int idx = 0; | 103 int idx = 0; |
104 int startPos = 0; | |
105 int endPos = 0; | |
106 Date startDate = null; | |
107 Date endDate = null; | |
108 | |
109 Result[] results = | |
110 (Result[]) resultSet.toArray(new Result[resultSet.size()]); | |
100 | 111 |
101 while (iter.hasNext()) { | 112 while (iter.hasNext()) { |
102 row = (Result) iter.next(); | 113 row = (Result) iter.next(); |
103 | 114 |
104 // add current data to plot and prepare for next one | 115 // add current data to plot and prepare for next one |
107 !row.getString("GROUP3").equals(breakPoint3) | 118 !row.getString("GROUP3").equals(breakPoint3) |
108 ) { | 119 ) { |
109 log.debug("prepare data/plot for next dataset"); | 120 log.debug("prepare data/plot for next dataset"); |
110 | 121 |
111 if(series != null) { | 122 if(series != null) { |
123 // add gaps before adding series to chart | |
124 startDate = results[startPos].getDate("XORDINATE"); | |
125 endDate = results[endPos-1].getDate("XORDINATE"); | |
126 addGaps(results,series,startDate,endDate,startPos,endPos); | |
112 addSeries(series, idx); | 127 addSeries(series, idx); |
128 | |
113 prepareAxis(((String)series.getKey()), idx); | 129 prepareAxis(((String)series.getKey()), idx); |
114 adjustRenderer(idx++, linesVisible, shapesVisible); | 130 adjustRenderer(idx++, linesVisible, shapesVisible); |
131 startPos = endPos + 1; | |
115 } | 132 } |
116 | 133 |
117 // prepare variables for next plot | 134 // prepare variables for next plot |
118 breakPoint1 = row.getString("GROUP1"); | 135 breakPoint1 = row.getString("GROUP1"); |
119 breakPoint2 = row.getString("GROUP2"); | 136 breakPoint2 = row.getString("GROUP2"); |
125 breakPoint3 | 142 breakPoint3 |
126 ); | 143 ); |
127 | 144 |
128 log.debug("next dataset is '" + seriesName + "'"); | 145 log.debug("next dataset is '" + seriesName + "'"); |
129 series = new TimeSeries(seriesName, Minute.class); | 146 series = new TimeSeries(seriesName, Minute.class); |
147 | |
148 // set values of start date and start position in collection for | |
149 // next parameter | |
130 } | 150 } |
131 | 151 |
132 addValue(row, series); | 152 addValue(row, series); |
153 endPos++; | |
133 } | 154 } |
134 | 155 |
135 // add the last dataset if existing to plot and prepare its axis | 156 // add the last dataset if existing to plot and prepare its axis |
157 startDate = results[startPos].getDate("XORDINATE"); | |
158 endDate = results[endPos-1].getDate("XORDINATE"); | |
159 addGaps(results, series, startDate, endDate, startPos, endPos); | |
136 addSeries(series, idx); | 160 addSeries(series, idx); |
137 | 161 |
138 if (series != null) { | 162 if (series != null) { |
139 prepareAxis(((String)series.getKey()), idx); | 163 prepareAxis(((String)series.getKey()), idx); |
140 adjustRenderer(idx++, linesVisible, shapesVisible); | 164 adjustRenderer(idx++, linesVisible, shapesVisible); |
141 } | 165 } |
142 } | 166 } |
143 | 167 |
144 | 168 |
145 protected void addValue(Result row, Series series) { | 169 protected void addValue(Result row, Series series) { |
146 // TODO look for gaps between two values | |
147 ((TimeSeries) series).addOrUpdate( | 170 ((TimeSeries) series).addOrUpdate( |
148 new Minute(row.getDate("XORDINATE")), | 171 new Minute(row.getDate("XORDINATE")), |
149 row.getDouble("YORDINATE") | 172 row.getDouble("YORDINATE") |
150 ); | 173 ); |
151 } | 174 } |
188 return findValueTitle(parameters, breakPoint1) + | 211 return findValueTitle(parameters, breakPoint1) + |
189 " " + | 212 " " + |
190 findValueTitle(measurements, breakPoint2) + | 213 findValueTitle(measurements, breakPoint2) + |
191 "m"; | 214 "m"; |
192 } | 215 } |
216 | |
217 | |
218 protected void addGaps( | |
219 Result[] results, | |
220 Series series, | |
221 Date startDate, | |
222 Date endDate, | |
223 int startPos, | |
224 int endPos | |
225 ) { | |
226 int gapID = results[startPos].getInteger("GAPID"); | |
227 long maxDiff = calculateGapSize( | |
228 startDate, endDate, startPos, endPos, gapID | |
229 ); | |
230 | |
231 Date last = startDate; | |
232 for (int i = startPos+1; i < endPos; i++) { | |
233 Result res = results[i]; | |
234 Date now = res.getDate("XORDINATE"); | |
235 | |
236 if ((now.getTime() - last.getTime()) > maxDiff) { | |
237 // add gap, add 1 minute to last date and add null value | |
238 log.info( | |
239 "Gap between " + | |
240 last.toString() + " and " + now.toString() | |
241 ); | |
242 last.setTime(last.getTime() + 60000); | |
243 ((TimeSeries) series).addOrUpdate(new Minute(last), null); | |
244 } | |
245 | |
246 last = now; | |
247 } | |
248 } | |
249 | |
250 | |
251 protected long calculateGapSize( | |
252 Date start, | |
253 Date end, | |
254 int startPos, | |
255 int endPos, | |
256 int gapID | |
257 ){ | |
258 long maxGap = (end.getTime() - start.getTime()) / 20; | |
259 long interval = getTimeGapValue(start, end, startPos, endPos, gapID); | |
260 | |
261 if (maxGap < interval) | |
262 maxGap = interval + 10; | |
263 | |
264 return maxGap; | |
265 } | |
266 | |
267 | |
268 protected long getTimeGapValue( | |
269 Date dStart, | |
270 Date dEnd, | |
271 int pStart, | |
272 int pEnd, | |
273 int gapID | |
274 ){ | |
275 long gap = 0; | |
276 | |
277 if (gapID < 0 || gapID >= 99) { | |
278 | |
279 if (gapID == -1) { | |
280 // no gaps in meshes | |
281 gap = NO_TIME_GAP; | |
282 } | |
283 else if (pEnd-pStart < 60) { | |
284 gap = (3/(pEnd-pStart)) * (dEnd.getTime() - dStart.getTime()); | |
285 } | |
286 } | |
287 else{ | |
288 Iterator it = timeGaps.iterator(); | |
289 | |
290 while (it.hasNext()) { | |
291 TimeGap tempTimeGap = (TimeGap) it.next(); | |
292 | |
293 if (tempTimeGap.getKey() == gapID){ | |
294 String unit = tempTimeGap.getUnit(); | |
295 int gapValue = tempTimeGap.getValue(); | |
296 | |
297 if (unit.equals(TimeGap.TIME_UNIT_MINUTE)) { | |
298 gap = gapValue * TimeGap.MINUTE_IN_MILLIS; | |
299 } | |
300 else if (unit.equals(TimeGap.TIME_UNIT_HOUR)) { | |
301 gap = gapValue * TimeGap.HOUR_IN_MILLIS; | |
302 } | |
303 else if (unit.equals(TimeGap.TIME_UNIT_DAY)) { | |
304 gap = gapValue * TimeGap.DAY_IN_MILLIS; | |
305 } | |
306 else if (unit.equals(TimeGap.TIME_UNIT_WEEK)) { | |
307 gap = gapValue * TimeGap.WEEK_IN_MILLIS; | |
308 } | |
309 else if (unit.equals(TimeGap.TIME_UNIT_MONTH)) { | |
310 gap = gapValue * (TimeGap.DAY_IN_MILLIS *30); | |
311 } | |
312 else if (unit.equals(TimeGap.TIME_UNIT_YEAR)) { | |
313 gap = gapValue * (TimeGap.DAY_IN_MILLIS *365); | |
314 } | |
315 break; | |
316 } | |
317 } | |
318 } | |
319 | |
320 return gap; | |
321 } | |
193 } | 322 } |
194 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : | 323 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : |