teichmann@8049: /* Copyright (C) 2014 by Bundesanstalt für Gewässerkunde teichmann@8049: * Software engineering by Intevation GmbH teichmann@8049: * teichmann@8049: * This file is Free Software under the GNU AGPL (>=v3) teichmann@8049: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@8049: * documentation coming with Dive4Elements River for details. teichmann@8049: */ teichmann@8049: package org.dive4elements.river.artifacts.model.minfo; teichmann@8049: teichmann@8049: import java.util.List; teichmann@8049: import java.util.Set; teichmann@8049: teichmann@8049: import org.dive4elements.river.artifacts.access.SedimentLoadAccess; teichmann@8049: import org.dive4elements.river.artifacts.model.Calculation; teichmann@8049: import org.dive4elements.river.artifacts.model.CalculationResult; teichmann@8053: import org.dive4elements.river.artifacts.model.RiverFactory; teichmann@8049: import org.apache.log4j.Logger; teichmann@8049: import org.dive4elements.river.artifacts.model.minfo.SedimentLoadData; teichmann@8049: import org.dive4elements.river.artifacts.model.minfo.SedimentLoadData.Value; teichmann@8049: import org.dive4elements.river.artifacts.model.minfo.SedimentLoadData.Station; teichmann@8053: import org.dive4elements.river.model.River; teichmann@8053: import org.dive4elements.river.utils.DoubleUtil; teichmann@8049: teichmann@8049: public class SedimentLoadDataCalculation teichmann@8049: extends Calculation teichmann@8049: { teichmann@8049: private static final Logger log = Logger teichmann@8049: .getLogger(SedimentLoadDataCalculation.class); teichmann@8049: teichmann@8049: public static final int [] TOTAL_LOAD_FLYS = { teichmann@8049: SedimentLoadData.GF_COARSE, teichmann@8049: SedimentLoadData.GF_FINE_MIDDLE, teichmann@8049: SedimentLoadData.GF_SAND, teichmann@8049: SedimentLoadData.GF_SUSP_SEDIMENT teichmann@8049: }; teichmann@8049: teichmann@8049: public static final int [] BED_LOAD_FLYS = { teichmann@8049: SedimentLoadData.GF_COARSE, teichmann@8049: SedimentLoadData.GF_FINE_MIDDLE, teichmann@8049: SedimentLoadData.GF_SAND teichmann@8049: }; teichmann@8049: teichmann@8049: public static final int [] BED_LOAD_SUSP_SAND_FLYS = { teichmann@8049: SedimentLoadData.GF_COARSE, teichmann@8049: SedimentLoadData.GF_FINE_MIDDLE, teichmann@8049: SedimentLoadData.GF_SAND, teichmann@8049: SedimentLoadData.GF_SUSP_SAND teichmann@8049: }; teichmann@8049: teichmann@8050: public static final int [] TOTAL_LOAD_BFG = { teichmann@8050: SedimentLoadData.GF_TOTAL teichmann@8050: }; teichmann@8050: teichmann@8050: public static final int [] BED_LOAD_BFG = { teichmann@8050: SedimentLoadData.GF_BED_LOAD teichmann@8050: }; teichmann@8050: teichmann@8050: public static final int [] SUSPENDED_LOAD_BFG = { teichmann@8050: SedimentLoadData.GF_SUSPENDED_LOAD teichmann@8050: }; teichmann@8050: teichmann@8050: public static final int [] COARSE_FLYS = { teichmann@8050: SedimentLoadData.GF_COARSE teichmann@8050: }; teichmann@8050: teichmann@8050: public static final int [] FINE_MIDDLE_FLYS = { teichmann@8050: SedimentLoadData.GF_FINE_MIDDLE teichmann@8050: }; teichmann@8050: teichmann@8050: public static final int [] SAND_FLYS = { teichmann@8050: SedimentLoadData.GF_SAND teichmann@8050: }; teichmann@8050: teichmann@8050: public static final int [] SUSP_SAND_FLYS = { teichmann@8050: SedimentLoadData.GF_SUSP_SAND teichmann@8050: }; teichmann@8050: teichmann@8050: public static final int [] SUSP_SAND_BED_FLYS = { teichmann@8050: SedimentLoadData.GF_SUSP_SAND_BED teichmann@8050: }; teichmann@8050: teichmann@8050: public static final int [] SUSP_SEDIMENT_FLYS = { teichmann@8050: SedimentLoadData.GF_SUSP_SEDIMENT teichmann@8050: }; teichmann@8050: teichmann@8049: public static final class Sum implements Value.Visitor { teichmann@8049: teichmann@8052: private int n; teichmann@8049: private double sum; teichmann@8049: private double scale; teichmann@8049: teichmann@8049: public Sum() { teichmann@8049: } teichmann@8049: teichmann@8049: public Sum(double scale) { teichmann@8049: this.scale = scale; teichmann@8049: } teichmann@8049: teichmann@8049: public double getSum() { teichmann@8049: return sum * scale; teichmann@8049: } teichmann@8049: teichmann@8049: public int getN() { teichmann@8049: return n; teichmann@8049: } teichmann@8049: teichmann@8049: public double getScale() { teichmann@8049: return scale; teichmann@8049: } teichmann@8049: teichmann@8049: public void reset() { teichmann@8049: n = 0; teichmann@8049: sum = 0.0; teichmann@8049: } teichmann@8049: teichmann@8049: @Override teichmann@8049: public void visit(Value value) { teichmann@8049: sum += value.getValue(); teichmann@8049: ++n; teichmann@8049: } teichmann@8049: } // class Aggregate teichmann@8049: teichmann@8049: teichmann@8052: private String river; teichmann@8052: private String yearEpoch; teichmann@8052: private String unit; teichmann@8052: private int [][] epoch; teichmann@8052: private int [] period; teichmann@8052: private double from; teichmann@8052: private double to; teichmann@8052: teichmann@8052: teichmann@8049: public SedimentLoadDataCalculation() { teichmann@8049: } teichmann@8049: teichmann@8049: public CalculationResult calculate(SedimentLoadAccess access) { teichmann@8049: log.info("SedimentLoadDataCalculation.calculate"); teichmann@8052: teichmann@8052: String river = access.getRiverName(); teichmann@8052: String yearEpoch = access.getYearEpoch(); teichmann@8052: String unit = access.getUnit(); teichmann@8052: teichmann@8052: int [] period = null; teichmann@8052: int [][] epoch = null; teichmann@8052: teichmann@8052: double from = access.getUpperKM(); teichmann@8052: double to = access.getLowerKM(); teichmann@8052: teichmann@8052: if (yearEpoch.equals("year")) { teichmann@8052: period = access.getPeriod(); teichmann@8052: } teichmann@8052: else if (yearEpoch.equals("epoch") || yearEpoch.equals("off_epoch")) { teichmann@8052: epoch = access.getEpochs(); teichmann@8052: } teichmann@8052: else { teichmann@8052: addProblem("minfo.missing.year_epoch"); teichmann@8052: } teichmann@8052: teichmann@8052: if (river == null) { teichmann@8052: // TODO: i18n teichmann@8052: addProblem("minfo.missing.river"); teichmann@8052: } teichmann@8052: teichmann@8052: if (period == null && epoch == null) { teichmann@8052: addProblem("minfo.missing.time"); teichmann@8052: } teichmann@8052: teichmann@8052: if (!hasProblems()) { teichmann@8052: this.river = river; teichmann@8052: this.yearEpoch = yearEpoch; teichmann@8052: this.unit = unit; teichmann@8052: this.period = period; teichmann@8052: this.epoch = epoch; teichmann@8052: this.from = from; teichmann@8052: this.to = to; teichmann@8052: return internalCalculate(); teichmann@8052: } teichmann@8052: teichmann@8053: return new CalculationResult(this); teichmann@8052: } teichmann@8052: teichmann@8052: private CalculationResult internalCalculate() { teichmann@8053: if ("year".equals(yearEpoch)) return calculateYears(); teichmann@8053: if ("epoch".equals(yearEpoch)) return calculateEpochs(); teichmann@8053: if ("off_epoch".equals(yearEpoch)) return calculateOffEpochs(); teichmann@8053: teichmann@8053: // TODO: i18n teichmann@8053: addProblem("minfo.sediment.load.unknown.calc.mode"); teichmann@8053: teichmann@8053: return new CalculationResult(this); teichmann@8053: } teichmann@8053: teichmann@8053: private CalculationResult calculateYears() { teichmann@8049: // TODO: Implement me! teichmann@8049: return null; teichmann@8049: } teichmann@8049: teichmann@8053: private CalculationResult calculateEpochs() { teichmann@8053: // TODO: Implement me! teichmann@8053: return null; teichmann@8053: } teichmann@8053: teichmann@8053: private CalculationResult calculateOffEpochs() { teichmann@8053: // TODO: Implement me! teichmann@8053: return null; teichmann@8053: } teichmann@8053: teichmann@8053: /** Figure out flow direction of river. */ teichmann@8053: private boolean isKmUp() { teichmann@8053: River r = RiverFactory.getRiver(river); teichmann@8053: if (r == null) { teichmann@8053: addProblem("minfo.missing.river"); teichmann@8053: return true; teichmann@8049: } teichmann@8053: return r.getKmUp(); teichmann@8049: } teichmann@8049: teichmann@8049: public double[][] sum( teichmann@8049: SedimentLoadData sld, teichmann@8049: int [] grainFractions, teichmann@8049: Value.Filter filter, teichmann@8049: Sum sum, teichmann@8049: boolean isKMUp, teichmann@8049: Set missingFractions teichmann@8049: ) { teichmann@8049: List stations = sld.findStations(from, to); teichmann@8049: teichmann@8049: double [] values = new double[grainFractions.length]; teichmann@8049: teichmann@8049: double [][] result = new double[2][stations.size()]; teichmann@8049: teichmann@8049: for (int j = 0, S = stations.size(); j < S; ++j) { teichmann@8049: Station station = stations.get(j); teichmann@8049: for (int i = 0; i < grainFractions.length; ++i) { teichmann@8049: int gf = grainFractions[i]; teichmann@8049: sum.reset(); teichmann@8049: station.filterGrainFraction(gf, filter, sum); teichmann@8049: if (sum.getN() == 0) { // No values found teichmann@8049: int msType = SedimentLoadData.measurementStationType(gf); teichmann@8049: // Station of right fraction type already? No: take previous. teichmann@8049: if (!station.isType(msType)) { teichmann@8049: Station prev = station.prevByType(msType, isKMUp); teichmann@8049: if (prev != null) { teichmann@8049: prev.filterGrainFraction(gf, filter, sum); teichmann@8049: } teichmann@8049: } teichmann@8049: } teichmann@8049: teichmann@8049: if (sum.getN() == 0) { teichmann@8049: missingFractions.add(gf); teichmann@8049: values[i] = Double.NaN; teichmann@8049: } else { teichmann@8049: values[i] = sum.getSum(); teichmann@8049: } teichmann@8049: } teichmann@8049: result[0][j] = station.getStation(); teichmann@8053: result[1][j] = DoubleUtil.sum(values); teichmann@8049: } teichmann@8049: teichmann@8049: // TODO: Handle 'virtual' measument stations 'from' and 'to'. teichmann@8049: teichmann@8049: return result; teichmann@8049: } teichmann@8049: } teichmann@8049: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :