view flys-artifacts/src/main/java/de/intevation/flys/exports/ATWriter.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 394b7ac58fc9
children 67bbcee26e21
line wrap: on
line source
package de.intevation.flys.exports;

import java.io.IOException;
import java.io.Writer;
import java.io.PrintWriter;

import java.util.Locale;

import de.intevation.artifacts.CallMeta;

import de.intevation.flys.artifacts.model.WQ;
import de.intevation.flys.artifacts.resources.Resources;

import org.apache.commons.math.analysis.UnivariateRealFunction;

import org.apache.commons.math.analysis.interpolation.SplineInterpolator;
import org.apache.commons.math.analysis.interpolation.LinearInterpolator;

import org.apache.commons.math.analysis.polynomials.PolynomialFunction;

import org.apache.commons.math.FunctionEvaluationException;

import org.apache.log4j.Logger;

public class ATWriter
{
    private static Logger logger = Logger.getLogger(ATWriter.class);

    public static final int COLUMNS = 10;

    public static final String I18N_AT_HEADER =
        "export.discharge.curve.at.header";

    public static final String EMPTY = "         ";

    protected double minW;
    protected double maxW;
    protected double minQ;
    protected double maxQ;

    protected UnivariateRealFunction qFunc;

    public ATWriter() {
    }

    public ATWriter(WQ wq) throws IllegalArgumentException {

        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]));
        }

        if (bounds[1]-bounds[0] < 1) { // Only first w can be written out.
            minW = maxW = wq.getW(bounds[0]);
            minQ = maxQ = wq.getQ(bounds[0]);
            // constant function
            qFunc = new PolynomialFunction(new double [] { minQ });
            return;
        }

        double [] ws = new double[bounds[1]-bounds[0]];
        double [] qs = new double[ws.length];

        for (int i = 0; i < ws.length; ++i) {
            int idx = bounds[0]+i;
            ws[i] = wq.getW(idx);
            qs[i] = wq.getQ(idx);
        }

        qFunc = ws.length < 3
            ? new LinearInterpolator().interpolate(ws, qs)
            : new SplineInterpolator().interpolate(ws, qs);

        minW = wq.getW(bounds[0]);
        maxW = 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 printHeader(
        PrintWriter out,
        CallMeta    callMeta,
        String      river,
        double      km
    ) {
        out.println(Resources.getMsg(
            callMeta,
            I18N_AT_HEADER,
            I18N_AT_HEADER,
            new Object[] { river, km } ));
    }


    public void write(Writer writer, CallMeta meta, String river, double km)
    throws IOException
    {
        PrintWriter out = new PrintWriter(writer);

        // a header is required, because the desktop version of FLYS will skip
        // the first row.
        printHeader(out, meta, river, km);

        double rest = (minW * 100.0) % 10.0;

        double startW = Math.rint((minW - rest*0.01)*10.0)*0.1;

        if (logger.isDebugEnabled()) {
            logger.debug("startW: " + startW);
            logger.debug("rest: " + rest);
        }

        int col = 0;
        for (double w = startW; w <= maxW; w += 0.01) {
            if (col == 0) {
                out.printf(Locale.US, "%8d", (int)Math.round(w*100.0));
            }

            if (w < minW) {
                out.print(EMPTY);
            }
            else {
                printQ(out, getQ(w));
            }

            if (++col >= COLUMNS) {
                out.println();
                col = 0;
            }
        }

        if (col > 0) {
            out.println();
        }

        out.flush();
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org