comparison artifacts/src/main/java/org/dive4elements/river/exports/process/MiscDischargeProcessor.java @ 8181:209f8a9e8a75

Added new processor to plot misc discharge data, e.g. from datacage or recommendations.
author Raimund Renkert <rrenkert@intevation.de>
date Thu, 04 Sep 2014 11:10:37 +0200
parents
children 407c9598352f
comparison
equal deleted inserted replaced
8171:bb770daccd1d 8181:209f8a9e8a75
1 /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
2 * Software engineering by Intevation GmbH
3 *
4 * This file is Free Software under the GNU AGPL (>=v3)
5 * and comes with ABSOLUTELY NO WARRANTY! Check out the
6 * documentation coming with Dive4Elements River for details.
7 */
8
9 package org.dive4elements.river.exports.process;
10
11 import java.util.ArrayList;
12 import java.util.List;
13
14 import org.apache.log4j.Logger;
15 import org.jfree.data.xy.XYSeries;
16
17 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
18 import org.dive4elements.artifacts.CallContext;
19 import org.dive4elements.river.artifacts.model.FacetTypes;
20 import org.dive4elements.river.artifacts.model.WQKms;
21 import org.dive4elements.river.exports.DiagramGenerator;
22 import org.dive4elements.river.exports.DischargeCurveGenerator;
23 import org.dive4elements.river.exports.StyledSeriesBuilder;
24 import org.dive4elements.river.exports.XYChartGenerator;
25 import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation;
26 import org.dive4elements.river.jfree.RiverAnnotation;
27 import org.dive4elements.river.jfree.StickyAxisAnnotation;
28 import org.dive4elements.river.jfree.StyledXYSeries;
29 import org.dive4elements.river.themes.ThemeDocument;
30
31 import org.jfree.chart.annotations.XYTextAnnotation;
32
33
34 /** Helper for data handling in discharge diagrams. */
35 public class MiscDischargeProcessor
36 extends DefaultProcessor implements FacetTypes {
37
38 private final static Logger logger =
39 Logger.getLogger(MiscDischargeProcessor.class);
40
41 /** Station for which the diagram is shown. */
42 private double km;
43
44 /** Tolerance for comparison of kilometers. */
45 public static final double KM_EPSILON = 0.001d;
46
47
48 /** This processor needs to be constructed with a given km. */
49 public MiscDischargeProcessor() {
50 km = Double.NaN;
51 }
52
53
54 public MiscDischargeProcessor(double km) {
55 this.km = km;
56 }
57
58 public void doOut(
59 DiagramGenerator generator,
60 ArtifactAndFacet bundle,
61 ThemeDocument theme,
62 boolean visible) {
63 CallContext context = generator.getCallContext();
64 Object data = bundle.getData(context);
65 if (data instanceof WQKms) {
66 doWQKmsPointOut(
67 generator, (WQKms) data, bundle, theme, visible);
68 return;
69 }
70 else if (data instanceof RiverAnnotation) {
71 doRiverAnnotationOut(
72 generator, (RiverAnnotation)data, bundle, theme, visible);
73 return;
74 }
75 else if (data instanceof double[][]) {
76 doPointsOut(generator, (double[][])data, bundle, theme, visible);
77 }
78 else {
79 logger.error("Can't process "
80 + data.getClass().getName() + " objects of facet "
81 + bundle.getFacetName());
82 }
83 }
84
85 /** Process data, add it to plot. */
86 @Override
87 public void doOut(
88 XYChartGenerator generator,
89 ArtifactAndFacet bundle,
90 ThemeDocument theme,
91 boolean visible,
92 int axisIndex
93 ) {
94 CallContext context = generator.getCallContext();
95 Object data = bundle.getData(context);
96 /* TODO: Remove the first case.*/
97 if (bundle.getFacetName().equals(STATIC_WQ)) {
98 doPointOut(
99 generator, bundle, theme, visible, axisIndex);
100 }
101 else if (data instanceof WQKms) {
102 doWQKmsPointOut(
103 generator, (WQKms) data, bundle, theme, visible, axisIndex);
104 return;
105 }
106 else if (data instanceof RiverAnnotation) {
107 doRiverAnnotationOut(
108 generator, (RiverAnnotation) data, bundle, theme, visible);
109 return;
110 }
111 else if (data instanceof double[][]) {
112 doMarksOut(
113 generator, (double[][]) data, bundle, theme, visible);
114 return;
115 }
116 else {
117 logger.error("Can't process "
118 + data.getClass().getName() + " objects of facet "
119 + bundle.getFacetName());
120 }
121 }
122
123 private void doPointOut(XYChartGenerator generator,
124 ArtifactAndFacet bundle,
125 ThemeDocument theme,
126 boolean visible,
127 int axisIndex
128 ) {
129 XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
130 Object wq = bundle.getData(generator.getCallContext());
131 if (wq instanceof double[][]) {
132 double [][] data = (double [][]) wq;
133 StyledSeriesBuilder.addPoints(series, data, true);
134 } else if (wq instanceof WQKms) {
135 WQKms wqkms = (WQKms) wq;
136 StyledSeriesBuilder.addPointsQW(series, (WQKms) wq);
137 }
138
139 generator.addAxisSeries(series, axisIndex, visible);
140 }
141
142 /** Handle WQKms data by finding w/q values at given km. */
143 protected void doWQKmsPointOut(XYChartGenerator generator,
144 WQKms wqkms,
145 ArtifactAndFacet bundle,
146 ThemeDocument theme,
147 boolean visible,
148 int axidx
149 ) {
150 logger.debug("doWQKmsPointOut");
151 String title = bundle.getFacetDescription();
152 XYSeries series = new StyledXYSeries(
153 title,
154 theme);
155
156 double[] kms = wqkms.getKms();
157
158 for (int i = 0 ; i< kms.length; i++) {
159 if (Math.abs(kms[i] - getKm()) <= KM_EPSILON) {
160 series.add(wqkms.getQ(i), wqkms.getW(i));
161 generator.addAxisSeries(series, axidx, visible);
162 if(visible && theme.parseShowPointLabel()) {
163 List<XYTextAnnotation> textAnnos = new ArrayList<XYTextAnnotation>();
164 XYTextAnnotation anno = new CollisionFreeXYTextAnnotation(
165 title,
166 wqkms.getQ(i),
167 // TODO add a percentage to the extend of W axis
168 wqkms.getW(i));
169 textAnnos.add(anno);
170 RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme);
171 flysAnno.setTextAnnotations(textAnnos);
172 generator.addAnnotations(flysAnno);
173 }
174 return;
175 }
176 }
177
178 logger.warn("No WQ found for km " + getKm());
179 }
180
181 protected void doRiverAnnotationOut(XYChartGenerator generator,
182 RiverAnnotation annotations,
183 ArtifactAndFacet bundle,
184 ThemeDocument theme,
185 boolean visible
186 ) {
187 if (!(generator instanceof DischargeCurveGenerator)) {
188 logger.error("DischargeProcessor can only be used in " +
189 " in DischargeCurveGenerator-classes.");
190 return;
191 }
192 logger.debug("doRiverAnnotationOut");
193 DischargeCurveGenerator dGenerator =
194 (DischargeCurveGenerator) generator;
195
196 dGenerator.translateRiverAnnotation(annotations);
197 dGenerator.doAnnotations(
198 annotations,
199 bundle, theme, visible);
200 }
201
202
203 /**
204 * Put Sticky Axis Markers to Y-axis for each value.
205 * @param data [[-,y1],[-,y2],...] ('x'-coordinates ignored)
206 */
207 protected void doMarksOut(XYChartGenerator generator,
208 double[][] data,
209 ArtifactAndFacet bundle,
210 ThemeDocument theme,
211 boolean visible
212 ) {
213 logger.debug("doMarksOut");
214
215 if (!visible) {
216 return;
217 }
218
219 // TODO subtract gauge null point if at gauge.
220 String title = bundle.getFacetDescription();
221 List<StickyAxisAnnotation> yMarks = new ArrayList<StickyAxisAnnotation>();
222
223 for (double yPos: data[1]) {
224 yMarks.add(new StickyAxisAnnotation(
225 title,
226 (float) yPos,
227 StickyAxisAnnotation.SimpleAxis.Y_AXIS));
228 }
229
230 generator.doAnnotations(new RiverAnnotation(title, yMarks),
231 bundle, theme, visible);
232 }
233
234 /** True if this processor knows how to deal with facetType. */
235 @Override
236 public boolean canHandle(String facetType) {
237 return STATIC_WQKMS_W.equals(facetType)
238 || COMPUTED_DISCHARGE_MAINVALUES_Q.equals(facetType)
239 || MAINVALUES_Q.equals(facetType)
240 || COMPUTED_DISCHARGE_MAINVALUES_W.equals(facetType)
241 || MAINVALUES_W.equals(facetType)
242 || STATIC_W_INTERPOL.equals(facetType)
243 || STATIC_WQ.equals(facetType)
244 || STATIC_WQ_ANNOTATIONS.equals(facetType);
245 }
246
247
248 /** The station of the current calculation/view. */
249 protected double getKm() {
250 return km;
251 }
252
253 private void doPointsOut(
254 DiagramGenerator generator,
255 double[][] data,
256 ArtifactAndFacet bundle,
257 ThemeDocument theme,
258 boolean visible
259 ) {
260 XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
261 StyledSeriesBuilder.addPoints(series, data, true);
262 generator.addAxisSeries(series, axisName, visible);
263 }
264
265 /** Handle WQKms data by finding w/q values at given km. */
266 protected void doWQKmsPointOut(
267 DiagramGenerator generator,
268 WQKms wqkms,
269 ArtifactAndFacet bundle,
270 ThemeDocument theme,
271 boolean visible
272 ) {
273 logger.debug("doWQKmsPointOut");
274 String title = bundle.getFacetDescription();
275 XYSeries series = new StyledXYSeries(
276 title,
277 theme);
278
279 double[] kms = wqkms.getKms();
280
281 for (int i = 0 ; i< kms.length; i++) {
282 if (Math.abs(kms[i] - getKm()) <= KM_EPSILON) {
283 series.add(wqkms.getQ(i), wqkms.getW(i));
284 generator.addAxisSeries(series, axisName, visible);
285 if(visible && theme.parseShowPointLabel()) {
286 List<XYTextAnnotation> textAnnos = new ArrayList<XYTextAnnotation>();
287 XYTextAnnotation anno = new CollisionFreeXYTextAnnotation(
288 title,
289 wqkms.getQ(i),
290 // TODO add a percentage to the extend of W axis
291 wqkms.getW(i));
292 textAnnos.add(anno);
293 RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme);
294 flysAnno.setTextAnnotations(textAnnos);
295 generator.addAnnotations(flysAnno);
296 }
297 return;
298 }
299 }
300
301 logger.warn("No WQ found for km " + getKm());
302 }
303
304 protected void doRiverAnnotationOut(DiagramGenerator generator,
305 RiverAnnotation annotations,
306 ArtifactAndFacet bundle,
307 ThemeDocument theme,
308 boolean visible
309 ) {
310 if (visible) {
311 annotations.setTheme(theme);
312 generator.addAnnotations(annotations);
313 }
314 }
315 }
316 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org