view flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQRelationCalculation.java @ 4187:21f4e4b79121

Refactor GaugeDischargeCurveFacet to be able to set a facet name For adding another output of the GaugeDischargeCurveArtifact it is necessary to provide to facet instances with different names. Therefore the GaugeDischargeCurveFacet is extended to set the facet name in the constructor.
author Björn Ricks <bjoern.ricks@intevation.de>
date Fri, 19 Oct 2012 13:25:49 +0200
parents ba2f0bff0697
children aaf810d4ec82
line wrap: on
line source
package de.intevation.flys.artifacts.model.sq;

import de.intevation.flys.artifacts.access.SQRelationAccess;

import de.intevation.flys.artifacts.math.fitting.Function;
import de.intevation.flys.artifacts.math.fitting.FunctionFactory;

import de.intevation.flys.artifacts.model.Calculation;
import de.intevation.flys.artifacts.model.CalculationResult;
import de.intevation.flys.artifacts.model.DateRange;
import de.intevation.flys.artifacts.model.Parameters;

import de.intevation.flys.backend.SedDBSessionHolder;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

public class SQRelationCalculation extends Calculation {

    private static final Logger log =
        Logger.getLogger(SQRelationCalculation.class);

    public static final String SQ_FUNCTION_NAME = "sq-pow";

    protected String    river;
    protected double    location;
    protected DateRange period;
    protected double    outliers;

    public SQRelationCalculation() {
    }

    public SQRelationCalculation(SQRelationAccess access) {

        String    river    = access.getRiver();
        Double    location = access.getLocation();
        DateRange period   = access.getPeriod();
        Double    outliers = access.getOutliers();

        //river = "Rhein";

        if (river == null) {
            // TODO: i18n
            addProblem("sq.missing.river");
        }

        if (location == null) {
            // TODO: i18n
            addProblem("sq.missing.location");
        }

        if (period == null) {
            // TODO: i18n
            addProblem("sq.missing.periods");
        }

        if (outliers == null) {
            // TODO: i18n
            addProblem("sq.missing.outliers");
        }

        if (!hasProblems()) {
            this.river    = river;
            this.location = location;
            this.period   = period;
            this.outliers = outliers;
        }
    }


    public CalculationResult calculate() {
        log.debug("SQRelationCalculation.calculate");

        if (hasProblems()) {
            return new CalculationResult(this);
        }

        SedDBSessionHolder.acquire();
        try {
            return internalCalculate();
        }
        finally {
            SedDBSessionHolder.release();
        }
    }

    protected CalculationResult internalCalculate() {

        Function function = FunctionFactory
            .getInstance()
            .getFunction(SQ_FUNCTION_NAME);

        if (function == null) {
            log.error("No '" + SQ_FUNCTION_NAME + "' function found.");
            // TODO: i18n
            addProblem("sq.missing.sq.function");
        }

        Measurements measurements =
            MeasurementFactory.getMeasurements(river, location, period);

        SQFractionResult [] fractionResults =
            new SQFractionResult[SQResult.NUMBER_FRACTIONS];

        for (int i = 0; i < fractionResults.length; ++i) {
            List<SQ> sqs = measurements.getSQs(i);

            SQFractionResult fractionResult;

            List<SQFractionResult.Iteration> iterations =
                doFitting(function, sqs);

            if (iterations == null) {
                // TODO: i18n
                addProblem("sq.fitting.failed." + i);
                fractionResult = new SQFractionResult();
            }
            else {
                fractionResult = new SQFractionResult(
                    sqs.toArray(new SQ[sqs.size()]),
                    iterations);
            }

            fractionResults[i] = fractionResult;
        }

        return new CalculationResult(
            new SQResult[] { new SQResult(location, fractionResults) },
            this);
    }

    protected List<SQFractionResult.Iteration> doFitting(
        final Function function,
        List<SQ> sqs
    ) {
        final List<SQFractionResult.Iteration> iterations =
            new ArrayList<SQFractionResult.Iteration>();

        boolean success = new Fitting(function, outliers).fit(
            sqs,
            new Fitting.Callback() {
                @Override
                public void afterIteration(
                    double [] coeffs,
                    SQ []     measurements,
                    SQ []     outliers,
                    double    standardDeviation,
                    double    chiSqr
                ) {
                    Parameters parameters = createParameters(
                        function.getParameterNames(),
                        coeffs,
                        standardDeviation,
                        chiSqr);
                    iterations.add(new SQFractionResult.Iteration(
                        parameters,
                        measurements,
                        outliers));
                }
            });

        return success ? iterations : null;
    }

    public static final Parameters createParameters(
        String [] names,
        double [] values,
        double    standardDeviation,
        double    chiSqr
    ) {
        String [] columns = new String[names.length + 2];
        columns[0] = "chi_sqr";
        columns[1] = "std_dev";
        System.arraycopy(names, 0, columns, 2, names.length);
        Parameters parameters = new Parameters(columns);
        int row = parameters.newRow();
        parameters.set(row, names, values);
        parameters.set(row, "chi_sqr", chiSqr);
        parameters.set(row, "std_dev", standardDeviation);
        return parameters;
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org