view flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadCalculation.java @ 5645:696d710470f5

flys/issue1077: Show loads as step line, therefore transform data in SedimentLoadFacet to stretch as in the measurement stations bounds. Deal with this new kind of data in the Generator.
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Wed, 10 Apr 2013 09:35:07 +0200
parents e357716cf346
children b6297a67823e
line wrap: on
line source
package de.intevation.flys.artifacts.model.minfo;

import gnu.trove.TDoubleArrayList;

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

import org.apache.log4j.Logger;

import de.intevation.flys.artifacts.access.SedimentLoadAccess;
import de.intevation.flys.artifacts.model.Calculation;
import de.intevation.flys.artifacts.model.CalculationResult;


/** Calculate sediment load. */
public class SedimentLoadCalculation
extends Calculation
{

    /** Private logger. */
    private static final Logger logger = Logger
        .getLogger(SedimentLoadCalculation.class);

    protected String river;
    protected String yearEpoch;
    protected double kmUp;
    protected double kmLow;
    protected int[] period;
    protected int[][] epoch;
    protected String unit;

    public SedimentLoadCalculation() {
    }

    public CalculationResult calculate(SedimentLoadAccess access) {
        logger.info("SedimentLoadCalculation.calculate");

        String river = access.getRiver();
        String yearEpoch = access.getYearEpoch();
        String unit = access.getUnit();
        int[] period = null;
        int[][] epoch = null;
        double kmUp = access.getUpperKM();
        double kmLow = access.getLowerKM();
        if (yearEpoch.equals("year")) {
            period = access.getPeriod();
            epoch = null;
        }
        else if (yearEpoch.equals("epoch") || yearEpoch.equals("off_epoch")) {
            epoch = access.getEpochs();
            period = null;
        }
        else {
            addProblem("minfo.missing.year_epoch");
        }

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

        if (period == null && epoch == null) {
            addProblem("minfo.missing.time");
        }

        if (!hasProblems()) {
            this.river = river;
            this.yearEpoch = yearEpoch;
            this.unit = unit;
            this.period = period;
            this.epoch = epoch;
            this.kmUp = kmUp;
            this.kmLow = kmLow;
            return internalCalculate();
        }

        return new CalculationResult();
    }

    private CalculationResult internalCalculate() {
        logger.debug("internalCalulate; mode:" + yearEpoch);
        if (yearEpoch.equals("year")) {
            List<SedimentLoadResult> results =
                new ArrayList<SedimentLoadResult>();
            for (int i = period[0]; i <= period[1]; i++) {
                SedimentLoadResult res = calculateYear(i);
                results.add(res);
            }
            return new CalculationResult(
                results.toArray(new SedimentLoadResult[results.size()]), this);
        }
        else if (yearEpoch.equals("epoch")) {
            List<SedimentLoadResult> results =
                new ArrayList<SedimentLoadResult>();
            for (int i = 0; i < epoch.length; i++) {
                SedimentLoadResult res = calculateEpoch(i);
                results.add(res);
            }
            return new CalculationResult(
                results.toArray(new SedimentLoadResult[results.size()]), this);
        }
        else if (yearEpoch.equals("off_epoch")) {
            List<SedimentLoadResult> results =
                new ArrayList<SedimentLoadResult>();
            for (int i = 0; i < epoch.length; i++) {
                SedimentLoadResult res = calculateOffEpoch(i);
                results.add(res);
            }
            return new CalculationResult(
                results.toArray(new SedimentLoadResult[results.size()]), this);
        }
        return null;
    }

    private SedimentLoadResult calculateEpoch(int i) {
        List<SedimentLoad> epochLoads = new ArrayList<SedimentLoad>();
        for (int j = epoch[i][0]; j < epoch[i][1]; j++) {
            epochLoads.add(SedimentLoadFactory.getLoadwithData(
                this.river,
                this.yearEpoch,
                this.kmLow,
                this.kmUp,
                j,
                j));
        }

        SedimentLoad resLoad = new SedimentLoad();
        TDoubleArrayList kms = new TDoubleArrayList();

        for (SedimentLoad load : epochLoads) {
            for (double km : load.getKms()) {
                if (!kms.contains(km)) {
                    kms.add(km);
                }
            }
        }

        for (int j = 0; j < kms.size(); j++) {
            int cSum = 0;
            int fmSum = 0;
            int sSum = 0;
            int ssSum = 0;
            int ssbSum = 0;
            int sseSum = 0;
            double km = kms.get(j);
            for (SedimentLoad load : epochLoads) {
                SedimentLoadFraction f = load.getFraction(km);
                if (f.getCoarse() > 0d) {
                    double c = resLoad.getFraction(km).getCoarse();
                    resLoad.setCoarse(km, c + f.getCoarse());
                    cSum++;
                }
                if (f.getFine_middle() > 0d) {
                    double fm = resLoad.getFraction(km).getFine_middle();
                    resLoad.setFineMiddle(km, fm + f.getFine_middle());
                    fmSum++;
                }
                if (f.getSand() > 0d) {
                    double s = resLoad.getFraction(km).getSand();
                    resLoad.setSand(km, s + f.getSand());
                    sSum++;
                }
                if (f.getSusp_sand() > 0d) {
                    double s = resLoad.getFraction(km).getSusp_sand();
                    resLoad.setSuspSand(km, s + f.getSusp_sand());
                    ssSum++;
                }
                if (f.getSusp_sand_bed() > 0d) {
                    double s = resLoad.getFraction(km).getSusp_sand_bed();
                    resLoad.setSuspSandBed(km, s + f.getSusp_sand_bed());
                    ssbSum++;
                }
                if (f.getSusp_sediment() > 0d) {
                    double s = resLoad.getFraction(km).getSusp_sediment();
                    resLoad.setSuspSediment(km, s + f.getSusp_sediment());
                    sseSum++;
                }
            }
            SedimentLoadFraction fr = resLoad.getFraction(km);
            resLoad.setCoarse(km, fr.getCoarse()/cSum);
            resLoad.setFineMiddle(km, fr.getFine_middle()/fmSum);
            resLoad.setSand(km, fr.getSand()/sSum);
            resLoad.setSuspSand(km, fr.getSusp_sand()/ssSum);
            resLoad.setSuspSandBed(km, fr.getSusp_sand_bed()/ssbSum);
            resLoad.setSuspSediment(km, fr.getSusp_sediment()/sseSum);
        }
        resLoad.setDescription("");
        resLoad.setEpoch(true);

        SedimentLoadResult result;
        SedimentLoad sl = calculateTotalLoad(resLoad, this.epoch[i][0]);
        if (this.unit.equals("m3_per_a")) {
            SedimentLoad slu = calculateUnit(sl, this.epoch[i][0]);
            result = new SedimentLoadResult(
                this.epoch[i][0],
                this.epoch[i][1],
                slu);
        }
        else {
            result = new SedimentLoadResult(
                this.epoch[i][0],
                this.epoch[i][1],
                sl);
        }

        return result;
    }

    private SedimentLoadResult calculateOffEpoch(int i) {
        SedimentLoad load = SedimentLoadFactory.getLoadwithData(
            this.river,
            this.yearEpoch,
            kmLow,
            kmUp,
            this.epoch[i][0],
            this.epoch[i][1]);
        SedimentLoadResult result;
        SedimentLoad sl = calculateTotalLoad(load, this.epoch[i][0]);
        if (unit.equals("m3_per_a")) {
            SedimentLoad slu = calculateUnit(sl, epoch[i][0]);
            result = new SedimentLoadResult(
                this.epoch[i][0],
                this.epoch[i][1],
                slu);
        }
        else {
            result = new SedimentLoadResult(
                this.epoch[i][0],
                this.epoch[i][1],
                sl);
        }

        return result;
    }

    private SedimentLoadResult calculateYear(int y) {
        SedimentLoad load = SedimentLoadFactory.getLoadwithData(
            this.river,
            this.yearEpoch,
            this.kmLow,
            this.kmUp,
            y,
            y);

        SedimentLoadResult result;
        SedimentLoad sl = calculateTotalLoad(load, y);
        if (unit.equals("m3_per_a")) {
            SedimentLoad slu = calculateUnit(sl, y);
            result = new SedimentLoadResult(y, 0, slu);
        }
        else {
            result = new SedimentLoadResult(y, 0, sl);
        }
        return result;
    }

    private SedimentLoad calculateTotalLoad(SedimentLoad load, int year) {
        logger.debug("calculateTotalLoad");
        if (!load.hasCoarse()) {
            addProblem(year, "missing.fraction.coarse");
        }
        if (!load.hasFineMiddle()) {
            addProblem(year, "missing.fraction.fine_middle");
        }
        if (!load.hasSand()) {
            addProblem(year, "missing.fraction.sand");
        }
        if (!load.hasSuspSand()) {
            addProblem(year, "missing.fraction.susp_sand");
        }
        if (!load.hasSuspSediment()) {
            addProblem(year, "missing.fraction.susp_sediment");
        }
        if (hasProblems()) {
            return load;
        }
        for(double km : load.getKms()) {
            SedimentLoadFraction fraction = load.getFraction(km);
            double total = 0d;
            if ((fraction.getCoarse() <= 0d && load.hasCoarse())){
                addProblem(km, "missing.data.coarse");
                continue;
            }
            if (fraction.getFine_middle() <= 0d && load.hasFineMiddle()) {
                addProblem(km, "missing.data.fine_middle");
                continue;
            }
            if (fraction.getSand() <= 0d && load.hasSand()) {
                addProblem(km, "missing data.sand");
                continue;
            }
            if (fraction.getSusp_sand() <= 0d && load.hasSuspSand()) {
                addProblem(km, "missing.data.susp_sand");
                continue;
            }
            if (fraction.getSusp_sediment() <= 0d && load.hasSuspSediment()) {
                addProblem(km, "missing.data.susp_sediment");
                continue;
            }
            total += fraction.getCoarse() +
                fraction.getFine_middle() +
                fraction.getSand() +
                fraction.getSusp_sand() +
                fraction.getSusp_sediment();
            load.setTotal(km, total);
        }
        return load;
    }

    private SedimentLoad calculateUnit(SedimentLoad load, int year) {
        SedimentDensity density =
            SedimentDensityFactory.getSedimentDensity(river, kmLow, kmUp, year);
        for (double km: load.getKms()) {
            double dens = density.getDensity(km, year);
            SedimentLoadFraction fraction = load.getFraction(km);
            double coarse = fraction.getCoarse();
            double fineMiddle = fraction.getFine_middle();
            double sand = fraction.getSand();
            double suspSand = fraction.getSusp_sand();
            double bedSand = fraction.getSusp_sand_bed();
            double sediment = fraction.getSusp_sediment();
            double total = fraction.getTotal();
            load.setCoarse(km, (coarse * dens));
            load.setFineMiddle(km, (fineMiddle * dens));
            load.setSand(km, (sand * dens));
            load.setSuspSand(km, (suspSand * dens));
            load.setSuspSandBed(km, (bedSand * dens));
            load.setSuspSediment(km, (sediment * dens));
            load.setTotal(km, (total * dens));
        }
        return load;
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org