changeset 6304:152e1ba8e5bd

Rework ATWriter/Exporter - Make the write function static as both data and gauge information is necessary for writing. - Use the rivers WST unit for the gauge datum - Handle the case that we are at a gauge - Differentiate between calculated values - Always work with w in CM and thus avoid double number format problems
author Andre Heinecke <aheinecke@intevation.de>
date Wed, 12 Jun 2013 16:07:28 +0200
parents 5fda7065b74a
children 40c77429319d
files artifacts/src/main/java/org/dive4elements/river/exports/ATExporter.java artifacts/src/main/java/org/dive4elements/river/exports/ATWriter.java
diffstat 2 files changed, 132 insertions(+), 112 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ATExporter.java	Wed Jun 12 16:02:33 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ATExporter.java	Wed Jun 12 16:07:28 2013 +0200
@@ -85,15 +85,6 @@
             return;
         }
 
-        ATWriter at;
-        try {
-            at = new ATWriter(data);
-        }
-        catch (IllegalArgumentException iae) {
-            logger.error("creating ATWriter failed", iae);
-            throw new IOException(iae);
-        }
-
         River river = RiverUtils.getRiver(master);
         RangeAccess rangeAccess = new RangeAccess(master);
         double[] kms = rangeAccess.getLocations();
@@ -103,7 +94,8 @@
             // at gauge.
             TimeInterval interval =
                 gauge.fetchMasterDischargeTable().getTimeInterval();
-            at.write(
+            ATWriter.write(
+                data,
                 new OutputStreamWriter(out, DEFAULT_ENCODING),
                 context.getMeta(),
                 river.getName(),
@@ -111,11 +103,12 @@
                 gauge.getName(),
                 gauge.getDatum(),
                 interval.getStartTime(),
-                false);
+                river.getWstUnit().getName());
         }
         else {
             // at km
-            at.write(
+            ATWriter.write(
+                data,
                 new OutputStreamWriter(out),
                 context.getMeta(),
                 river.getName(),
@@ -123,7 +116,7 @@
                 null,
                 null,
                 null,
-                true);
+                river.getWstUnit().getName());
         }
 
     }
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ATWriter.java	Wed Jun 12 16:02:33 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ATWriter.java	Wed Jun 12 16:07:28 2013 +0200
@@ -46,30 +46,124 @@
     public static final String I18N_AT_GAUGE_HEADER =
         "export.discharge.curve.at.gauge.header";
 
+    public static final String I18N_AT_CALC_GAUGE_HEADER =
+        "export.discharge.curve.at.gauge.calc.header";
+
     public static final String EMPTY = "         ";
 
-    protected double minW;
-    protected double maxW;
-    protected double minQ;
-    protected double maxQ;
-
-    protected UnivariateRealFunction qFunc;
-
-    public ATWriter() {
+    public static double getQ(int w, UnivariateRealFunction qFunc) {
+        try {
+            double val = qFunc.value(w);
+            return val;
+        }
+        catch (FunctionEvaluationException aode) {
+            // should not happen
+            logger.error("spline interpolation failed", aode);
+            return Double.NaN;
+        }
     }
 
-    public ATWriter(WQ wq) throws IllegalArgumentException {
+    public static void printQ(PrintWriter out, double q) {
+        String format;
+             if (q <   1d) format = " % 8.3f";
+        else if (q <  10d) format = " % 8.2f";
+        else if (q < 100d) format = " % 8.1f";
+        else {
+            format = " % 8.0f";
+            if (q > 1000d) q = Math.rint(q/10d)*10d;
+        }
+        out.printf(Locale.US, format, q);
+    }
+
+    protected static void printCalculatedGaugeHeader(
+        PrintWriter out,
+        CallMeta    callMeta,
+        String      river,
+        double      km,
+        String      gName,
+        BigDecimal  datum,
+        Date        date,
+        String      unit
+    ) {
+        out.print("*" + Resources.getMsg(
+            callMeta,
+            I18N_AT_CALC_GAUGE_HEADER,
+            I18N_AT_CALC_GAUGE_HEADER,
+            new Object[] { river, gName, datum, unit } ));
+        out.print("\r\n");
+    }
+
+    protected static void printGaugeHeader(
+        PrintWriter out,
+        CallMeta    callMeta,
+        String      river,
+        double      km,
+        String      gName,
+        BigDecimal  datum,
+        Date        date,
+        String      unit
+    ) {
+        DateFormat f = DateFormat.getDateInstance(DateFormat.MEDIUM,
+                Resources.getLocale(callMeta));
+        out.print("*" + Resources.getMsg(
+            callMeta,
+            I18N_AT_GAUGE_HEADER,
+            I18N_AT_GAUGE_HEADER,
+            new Object[] { river, gName, f.format(date), datum, unit} ));
+        out.print("\r\n");
+    }
+
+    protected static void printHeader(
+        PrintWriter out,
+        CallMeta    callMeta,
+        String      river,
+        double      km
+    ) {
+        out.print("*" + Resources.getMsg(
+            callMeta,
+            I18N_AT_HEADER,
+            I18N_AT_HEADER,
+            new Object[] { river, km } ));
+        out.print("\r\n");
+    }
+
+    public static void write(
+        WQ values,
+        Writer writer,
+        CallMeta meta,
+        String river,
+        double km,
+        String gName,
+        BigDecimal datum,
+        Date date,
+        String unit)
+    throws IOException
+    {
+        int minW;
+        int maxW;
+        double minQ;
+        double maxQ;
+
+        UnivariateRealFunction qFunc;
+
+        WQ wq = WQ.getFixedWQforExportAtGauge(values, datum);
+
+        // If we converted to centimeter we know that the WQ table is
+        // calculated because of the assumption that all calculations
+        // are in Meter and only the discharge tables data is in meter.
+        boolean isCalculation = wq.getReferenceSystem() != values.getReferenceSystem();
 
         int [] bounds = wq.longestIncreasingWRangeIndices();
 
         if (logger.isDebugEnabled()) {
-            logger.debug("exporting w between indices " +
-                bounds[0] + " and " + bounds[1] + " (" +
-                wq.getW(bounds[0]) + ", " + wq.getW(bounds[1]));
+            logger.debug("exporting " + (isCalculation ? "calculated " : "") +
+                "w between indices " + bounds[0] + " and " + bounds[1] + " (" +
+                (int)Math.ceil(wq.getW(bounds[0])) + ", " +
+                (int)Math.floor(wq.getW(bounds[1]))+ ")");
         }
 
         if (bounds[1]-bounds[0] < 1) { // Only first w can be written out.
-            minW = maxW = wq.getW(bounds[0]);
+            minW = maxW = (int)Math.round(wq.getW(bounds[0]));
             minQ = maxQ = wq.getQ(bounds[0]);
             // constant function
             qFunc = new PolynomialFunction(new double [] { minQ });
@@ -89,117 +183,50 @@
             ? new LinearInterpolator().interpolate(ws, qs)
             : new SplineInterpolator().interpolate(ws, qs);
 
-        minW = wq.getW(bounds[0]);
-        maxW = wq.getW(bounds[1]);
+        minW = (int)Math.ceil(wq.getW(bounds[0]));
+        maxW = (int)Math.floor(wq.getW(bounds[1]));
         minQ = wq.getQ(bounds[0]);
         maxQ = wq.getQ(bounds[1]);
-    }
-
-    public double getQ(double w) {
-
-        try {
-            return qFunc.value(w);
-        }
-        catch (FunctionEvaluationException aode) {
-            // should not happen
-            logger.warn("spline interpolation failed", aode);
-            return w <= minW ? minQ : maxQ;
-        }
-    }
-
-    public static void printQ(PrintWriter out, double q) {
-        String format;
-             if (q <   1d) format = " % 8.3f";
-        else if (q <  10d) format = " % 8.2f";
-        else if (q < 100d) format = " % 8.1f";
-        else {
-            format = " % 8.0f";
-            if (q > 1000d) q = Math.rint(q/10d)*10d;
-        }
-        out.printf(Locale.US, format, q);
-    }
-
-
-    protected static void printGaugeHeader(
-        PrintWriter out,
-        CallMeta    callMeta,
-        String      river,
-        double      km,
-        String      gName,
-        BigDecimal  datum,
-        Date        date
-    ) {
-        DateFormat f = DateFormat.getDateInstance();
-        out.print("*" + Resources.getMsg(
-            callMeta,
-            I18N_AT_GAUGE_HEADER,
-            I18N_AT_GAUGE_HEADER,
-            new Object[] { river, gName, f.format(date), datum } ));
-        out.print("\r\n");
-    }
-
-    protected static void printHeader(
-        PrintWriter out,
-        CallMeta    callMeta,
-        String      river,
-        double      km
-    ) {
-        out.print("*" + Resources.getMsg(
-            callMeta,
-            I18N_AT_HEADER,
-            I18N_AT_HEADER,
-            new Object[] { river, km } ));
-        out.print("\r\n");
-    }
-
-    public void write(
-        Writer writer,
-        CallMeta meta,
-        String river,
-        double km,
-        String gName,
-        BigDecimal datum,
-        Date date,
-        boolean wOutUnitIsMeter)
-    throws IOException
-    {
         PrintWriter out = new PrintWriter(writer);
 
         // A header is required, because the desktop version of FLYS will skip
         // the first row.
         if (gName != null) {
-            printGaugeHeader(out, meta, river, km, gName, datum, date);
+            printGaugeHeader(out, meta, river, km, gName, datum, date, unit);
+            if (isCalculation) {
+                printCalculatedGaugeHeader(out, meta, river, km, gName, datum, date, unit);
+            }
         }
         else {
             printHeader(out, meta, river, km);
         }
 
-        double rest = (minW * 100.0) % 10.0;
+        int rest = minW % 10;
 
-        double startW = Math.rint((minW - rest*0.01)*10.0)*0.1;
+        int startW = minW - rest;
 
         if (logger.isDebugEnabled()) {
             logger.debug("startW: " + startW);
             logger.debug("rest: " + rest);
+            logger.debug("maxW: " + maxW);
         }
 
         int col = 0;
-        for (double w = startW; w <= maxW; w += 0.01) {
+        for (int w = startW; w < maxW; w++) {
             if (col == 0) {
-                if (wOutUnitIsMeter) {
-                    // For some crazy reason W's at a gauge should be in the
-                    // unit but W's exported elsewhere should be in Meter
-                    out.printf(Locale.US, "%5.2f", w);
-                } else {
-                    out.printf(Locale.US, "%8d", (int)Math.round(w * 100d));
-                }
+                out.printf(Locale.US, "%8d", w);
             }
 
             if (w < minW) {
                 out.print(EMPTY);
-            }
-            else {
-                printQ(out, getQ(w));
+            } else {
+                double actQ = getQ(w, qFunc);
+                if (Double.isNaN(actQ)) {
+                    // Can't happen™
+                    break;
+                } else {
+                    printQ(out, actQ);
+                }
             }
 
             if (++col >= COLUMNS) {

http://dive4elements.wald.intevation.org