Mercurial > dive4elements > river
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 : |