view artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffCalculation.java @ 6147:073268a137d5

Bed height differences: Some refactoring of the calculation to improve readability and performance.
author Sascha L. Teichmann <teichmann@intevation.de>
date Sat, 01 Jun 2013 18:59:52 +0200
parents 0c3301fe23bd
children b12ec9f240bc
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
 * Software engineering by Intevation GmbH
 *
 * This file is Free Software under the GNU AGPL (>=v3)
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details.
 */

package org.dive4elements.river.artifacts.model.minfo;

import gnu.trove.TDoubleArrayList;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;

import org.dive4elements.river.artifacts.D4EArtifact;
import org.dive4elements.river.artifacts.access.BedDifferencesAccess;
import org.dive4elements.river.artifacts.model.Calculation;
import org.dive4elements.river.artifacts.model.CalculationResult;


public class BedDiffCalculation
extends Calculation
{

    private static final Logger logger = Logger
        .getLogger(BedDiffCalculation.class);

    protected String river;
    protected String yearEpoch;
    protected D4EArtifact[][] artifacts;

    public BedDiffCalculation() {
    }

    public CalculationResult calculate(BedDifferencesAccess access) {
        logger.info("BedDiffCalculation.calculate");

        String river = access.getRiver();
        String yearEpoch = access.getYearEpoch();
        D4EArtifact[][] artifacts = access.getDifferenceArtifacts();

        logger.debug("got artifacts: " + artifacts.length + "; " + artifacts[0].length);
        if (river == null) {
            // TODO: i18n
            addProblem("minfo.missing.river");
        }

        if (yearEpoch == null) {
            addProblem("minfo.missing.year_epoch");
        }

        if (artifacts == null) {
            addProblem("minfo.missing.differences");
        }

        if (!hasProblems()) {
            this.river = river;
            this.yearEpoch = yearEpoch;
            this.artifacts = artifacts;
            return internalCalculate();
        }

        return new CalculationResult();
    }

    private CalculationResult internalCalculate() {

        if (yearEpoch.equals("year")) {
            List<BedDiffYearResult> results =
                new LinkedList<BedDiffYearResult>();

            for (int i = 0; i < artifacts.length; i++) {
                BedHeight[] pair =
                    getHeightPair(artifacts[i][0], artifacts[i][1], "single");
                BedDiffYearResult res = calculateYearDifference(pair);
                results.add(res);
            }
            return new CalculationResult(
                results.toArray(new BedDiffYearResult[results.size()]), this);
        }
        if (yearEpoch.equals("epoch")) {
            List<BedDiffEpochResult> results =
                new LinkedList<BedDiffEpochResult>();
            for (int i = 0; i < artifacts.length; i++) {
                BedHeight[] pair =
                    getHeightPair(artifacts[i][0], artifacts[i][1], "epoch");
                BedDiffEpochResult res = calculateEpochDifference(pair);
                results.add(res);
            }
            return new CalculationResult(
                results.toArray(new BedDiffEpochResult[results.size()]), this);
        }

       return new CalculationResult();
    }

    private BedHeight[] getHeightPair(
        D4EArtifact art1,
        D4EArtifact art2,
        String type
    ) {
        int id1 = BedDifferencesAccess.getHeightId(art1);
        int id2 = BedDifferencesAccess.getHeightId(art2);

        BedHeight[] heights = new BedHeight[2];
        heights[0] = BedHeightFactory.getHeight(type, id1, 0);
        heights[1] = BedHeightFactory.getHeight(type, id2, 0);
        return heights;
    }

    private BedDiffEpochResult calculateEpochDifference(BedHeight[] pair) {

        BedHeight bh1 = pair[0];
        BedHeight bh2 = pair[1];

        TDoubleArrayList stations = bh1.getStations();
        int size = stations.size();

        TDoubleArrayList diffRes  = new TDoubleArrayList(size);
        TDoubleArrayList kms      = new TDoubleArrayList(size);
        TDoubleArrayList heights1 = new TDoubleArrayList(size);
        TDoubleArrayList heights2 = new TDoubleArrayList(size);

        for (int i = 0; i < size; i++) {
            double station = stations.getQuick(i);
            double h1      = bh1.getHeight(station);
            double h2      = bh2.getHeight(station);
            double hDiff   = h1 - h2;
            if (!Double.isNaN(hDiff)) {
                diffRes.add(hDiff);
                kms.add(station);
                heights1.add(h1);
                heights2.add(h2);
            }
        }
        Date start = ((BedHeightEpoch)bh1).getStart();
        Date end   = ((BedHeightEpoch)bh2).getEnd();
        return new BedDiffEpochResult(kms, diffRes, heights1, heights2, start, end);
    }

    private BedDiffYearResult calculateYearDifference(BedHeight[] pair) {

        BedHeightSingle s1 = (BedHeightSingle)pair[0];
        BedHeightSingle s2 = (BedHeightSingle)pair[1];

        TDoubleArrayList stations = s1.getStations();
        int size = stations.size();

        TDoubleArrayList diffRes  = new TDoubleArrayList(size);
        TDoubleArrayList kms      = new TDoubleArrayList(size);
        TDoubleArrayList morphs   = new TDoubleArrayList(size);
        TDoubleArrayList absolute = new TDoubleArrayList(size);
        TDoubleArrayList gap      = new TDoubleArrayList(size);
        TDoubleArrayList heights1 = new TDoubleArrayList(size);
        TDoubleArrayList heights2 = new TDoubleArrayList(size);

        int range = Math.abs(s1.getYear() - s2.getYear());

        for (int i = 0; i < size; i++) {
            double station = stations.getQuick(i);
            double h1      = s1.getHeight(station);
            double h2      = s2.getHeight(station);
            double hDiff   = h1 - h2;

            if (!Double.isNaN(hDiff)) {
                diffRes.add(hDiff);
                kms.add(station);

                morphs.add(Math.max(
                    s1.getMorphWidth(station),
                    s2.getMorphWidth(station)));

                gap.add(Math.max(
                    s1.getDataGap(station),
                    s2.getDataGap(station)));

                absolute.add((hDiff / range) * 100d);
                heights1.add(h1);
                heights2.add(h2);
            }
        }
        return new BedDiffYearResult(
            kms,
            diffRes,
            heights1,
            heights2,
            morphs,
            absolute,
            gap,
            s1.getYear(),
            s2.getYear(),
            s1.getName(),
            s2.getName());
    }
}

http://dive4elements.wald.intevation.org