comparison flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixATWriter.java @ 3220:0c8a6145098b

FixA: Added AT writer for fitted functions. flys-artifacts/trunk@4843 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Sun, 01 Jul 2012 11:18:59 +0000
parents
children 1dc904370a64
comparison
equal deleted inserted replaced
3219:fa30e6322ef3 3220:0c8a6145098b
1 package de.intevation.flys.exports.fixings;
2
3 import de.intevation.artifacts.CallMeta;
4
5 import de.intevation.flys.artifacts.math.fitting.Function;
6
7 import de.intevation.flys.artifacts.model.Parameters;
8
9 import de.intevation.flys.artifacts.resources.Resources;
10
11 import de.intevation.flys.exports.ATWriter;
12
13 import java.io.IOException;
14 import java.io.PrintWriter;
15 import java.io.Writer;
16
17 import java.util.ArrayDeque;
18 import java.util.Collection;
19 import java.util.Locale;
20
21 import org.apache.log4j.Logger;
22
23 public class FixATWriter
24 {
25 private static Logger log = Logger.getLogger(FixATWriter.class);
26
27 public static final String I18N_HEADER_KEY =
28 "fix.export.at.header";
29
30 public static final String I18N_HEADER_DEFAULT =
31 "Exported fixings discharge curve for {0} {0}-km: {1}";
32
33 public static final String [] Q_MAX_COLUMN = new String [] { "max_q" };
34
35 public static class WQ {
36
37 protected double w;
38 protected double q;
39
40 public WQ() {
41 }
42
43 public WQ(double w, double q) {
44 this.w = w;
45 this.q = q;
46 }
47 } // class WQ
48
49 protected Function function;
50 protected Parameters parameters;
51
52 public FixATWriter() {
53 }
54
55 public FixATWriter(Function function, Parameters parameters) {
56 this.function = function;
57 this.parameters = parameters;
58 }
59
60 public void write(
61 Writer writer,
62 CallMeta meta,
63 String river,
64 double km
65 )
66 throws IOException {
67 PrintWriter out = new PrintWriter(writer);
68 printHeader(out, meta, river, km);
69
70 double [] coeffs = parameters.interpolate(
71 "km", km, function.getParameterNames());
72
73 double [] qMax = parameters.interpolate(
74 "km", km, Q_MAX_COLUMN);
75
76 if (coeffs == null || qMax == null) {
77 log.debug("No data found at km " + km + ".");
78 return;
79 }
80
81 de.intevation.flys.artifacts.math.Function funcInst =
82 function.instantiate(coeffs);
83
84 double wMax = funcInst.value(qMax[0]);
85
86 if (Double.isNaN(wMax) || wMax < 0d) {
87 log.debug("function '" + function.getName() +
88 "' eval failed at " + wMax);
89 return;
90 }
91
92 Function inverse = function.getInverse();
93
94 de.intevation.flys.artifacts.math.Function invInst =
95 inverse.instantiate(coeffs);
96
97 /* TODO: Do some fancy root finding stuff with the
98 * first derivative of the inverse function to find
99 * the minimum of function and directly export
100 * the longest strict monotonous ascending run of
101 * ws of the inverse in range [0, wMax].
102 *
103 * To simplify the situation we iterate in steps
104 * of 10cm over the range and export the longest
105 * run.
106 */
107
108 ArrayDeque<WQ> longest = new ArrayDeque<WQ>();
109 ArrayDeque<WQ> current = new ArrayDeque<WQ>();
110
111 for (double w = 0d; w <= wMax; w += 0.1d) {
112 double q = invInst.value(w);
113
114 if (Double.isNaN(q)) {
115 log.debug("Eval of inverse for " + w + " failed.");
116 continue;
117 }
118
119 WQ wq = new WQ(w, q);
120
121 if (current.isEmpty() || current.getLast().q < q) {
122 current.add(wq);
123 }
124 else {
125 if (current.size() >= longest.size()) {
126 longest = current;
127 }
128 current = new ArrayDeque<WQ>();
129 current.add(wq);
130 }
131 }
132
133 if (current.size() >= longest.size()) {
134 longest = current;
135 }
136
137 printWQs(out, longest);
138 out.flush();
139 }
140
141 protected void printWQs(PrintWriter out, Collection<WQ> wqs) {
142 int lastColumn = 10;
143 for (WQ wq: wqs) {
144 int column = (int)(wq.w * 10d) % 10;
145
146 if (lastColumn > column) {
147 for (; lastColumn < 10; ++lastColumn) {
148 out.print(ATWriter.EMPTY);
149 }
150 out.println();
151 out.printf(Locale.US, "%8d", (int)Math.round(wq.w*100.0));
152 lastColumn = 0;
153 }
154 for (;lastColumn < column-1; ++lastColumn) {
155 out.print(ATWriter.EMPTY);
156 }
157 ATWriter.printQ(out, wq.q);
158
159 lastColumn = column;
160 }
161 out.println();
162 }
163
164 protected void printHeader(
165 PrintWriter out,
166 CallMeta meta,
167 String river,
168 double km
169 ) {
170 out.println(Resources.format(
171 meta,
172 I18N_HEADER_KEY,
173 I18N_HEADER_DEFAULT,
174 river, km));
175 }
176 }
177 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org