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 :

http://dive4elements.wald.intevation.org