teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5831: package org.dive4elements.river.artifacts.model.minfo; raimund@3887: raimund@3887: import gnu.trove.TDoubleArrayList; raimund@3887: raimund@3898: import java.util.Date; raimund@3887: raimund@3887: import org.apache.log4j.Logger; raimund@3887: teichmann@6148: import org.dive4elements.artifacts.CallContext; teichmann@5831: import org.dive4elements.river.artifacts.access.BedDifferencesAccess; teichmann@5831: import org.dive4elements.river.artifacts.model.Calculation; teichmann@5831: import org.dive4elements.river.artifacts.model.CalculationResult; raimund@3887: felix@6573: /** felix@6573: * Perform calculation of differences of bed height (german Sohlhoehe). felix@6573: * The input are either single year data or epochs. felix@6573: */ raimund@3887: public class BedDiffCalculation raimund@3887: extends Calculation raimund@3887: { teichmann@6148: private static final Logger logger = teichmann@6148: Logger.getLogger(BedDiffCalculation.class); raimund@3887: teichmann@6148: protected String river; teichmann@6148: protected String yearEpoch; teichmann@6148: protected int [][] heightIds; raimund@3887: raimund@3887: public BedDiffCalculation() { raimund@3887: } raimund@3887: teichmann@6148: public CalculationResult calculate(BedDifferencesAccess access, CallContext context) { raimund@3898: logger.info("BedDiffCalculation.calculate"); raimund@3887: felix@7261: String river = access.getRiverName(); teichmann@6148: String yearEpoch = access.getYearEpoch(); teichmann@6148: int [][] heightIds = access.extractHeightIds(context); raimund@3887: raimund@3887: if (river == null) { raimund@3887: // TODO: i18n raimund@3887: addProblem("minfo.missing.river"); raimund@3887: } raimund@3887: raimund@3887: if (yearEpoch == null) { raimund@3887: addProblem("minfo.missing.year_epoch"); raimund@3887: } raimund@3887: raimund@3887: if (!hasProblems()) { teichmann@6148: this.river = river; raimund@3887: this.yearEpoch = yearEpoch; teichmann@6148: this.heightIds = heightIds; raimund@3887: return internalCalculate(); raimund@3887: } raimund@3887: raimund@3887: return new CalculationResult(); raimund@3887: } raimund@3887: raimund@3887: private CalculationResult internalCalculate() { raimund@3887: rrenkert@6215: BedDiffYearResult [] results = new BedDiffYearResult[heightIds.length]; raimund@3898: rrenkert@6215: for (int i = 0; i < heightIds.length; i++) { rrenkert@6215: BedHeight [] pair = getHeightPair(heightIds[i], "single"); rrenkert@6215: results[i] = calculateYearDifference(pair); raimund@3887: } rrenkert@6215: return new CalculationResult(results, this); rrenkert@6215: // Currently epochs are handled like single years. To handle epochs rrenkert@6215: // uncomment the follwing code and use an if-clause in the code above. rrenkert@6215: /* raimund@3887: if (yearEpoch.equals("epoch")) { teichmann@6148: BedDiffEpochResult [] results = new BedDiffEpochResult[heightIds.length]; teichmann@6148: teichmann@6148: for (int i = 0; i < heightIds.length; i++) { teichmann@6148: BedHeight[] pair = getHeightPair(heightIds[i], "epoch"); teichmann@6148: results[i] = calculateEpochDifference(pair); raimund@3887: } teichmann@6148: return new CalculationResult(results, this); raimund@3887: } raimund@3887: raimund@3898: return new CalculationResult(); rrenkert@6215: */ raimund@3887: } raimund@3887: felix@6573: /** Get two BedHeights from factory. */ teichmann@6148: private static BedHeight [] getHeightPair(int [] ids, String type) { teichmann@6148: return new BedHeight [] { teichmann@6148: BedHeightFactory.getHeight(type, ids[0], 0), teichmann@6148: BedHeightFactory.getHeight(type, ids[1], 0) teichmann@6148: }; raimund@3887: } raimund@3887: raimund@3887: private BedDiffEpochResult calculateEpochDifference(BedHeight[] pair) { raimund@3887: teichmann@6147: BedHeight bh1 = pair[0]; teichmann@6147: BedHeight bh2 = pair[1]; raimund@3898: teichmann@6147: TDoubleArrayList stations = bh1.getStations(); teichmann@6147: int size = stations.size(); teichmann@6147: teichmann@6147: TDoubleArrayList diffRes = new TDoubleArrayList(size); teichmann@6147: TDoubleArrayList kms = new TDoubleArrayList(size); teichmann@6147: TDoubleArrayList heights1 = new TDoubleArrayList(size); teichmann@6147: TDoubleArrayList heights2 = new TDoubleArrayList(size); teichmann@6147: teichmann@6147: for (int i = 0; i < size; i++) { teichmann@6147: double station = stations.getQuick(i); teichmann@6147: double h1 = bh1.getHeight(station); teichmann@6147: double h2 = bh2.getHeight(station); teichmann@6147: double hDiff = h1 - h2; teichmann@6147: if (!Double.isNaN(hDiff)) { raimund@3887: diffRes.add(hDiff); teichmann@6147: kms.add(station); teichmann@6147: heights1.add(h1); teichmann@6147: heights2.add(h2); raimund@3887: } raimund@3887: } teichmann@6147: Date start = ((BedHeightEpoch)bh1).getStart(); teichmann@6147: Date end = ((BedHeightEpoch)bh2).getEnd(); raimund@3898: return new BedDiffEpochResult(kms, diffRes, heights1, heights2, start, end); raimund@3887: } raimund@3887: raimund@3887: private BedDiffYearResult calculateYearDifference(BedHeight[] pair) { raimund@3887: raimund@3887: BedHeightSingle s1 = (BedHeightSingle)pair[0]; raimund@3887: BedHeightSingle s2 = (BedHeightSingle)pair[1]; teichmann@6147: teichmann@6147: TDoubleArrayList stations = s1.getStations(); teichmann@6147: int size = stations.size(); teichmann@6147: teichmann@6147: TDoubleArrayList diffRes = new TDoubleArrayList(size); teichmann@6147: TDoubleArrayList kms = new TDoubleArrayList(size); teichmann@6147: TDoubleArrayList morphs = new TDoubleArrayList(size); teichmann@6147: TDoubleArrayList absolute = new TDoubleArrayList(size); teichmann@6147: TDoubleArrayList gap = new TDoubleArrayList(size); teichmann@6147: TDoubleArrayList heights1 = new TDoubleArrayList(size); teichmann@6147: TDoubleArrayList heights2 = new TDoubleArrayList(size); teichmann@6147: teichmann@6147: int range = Math.abs(s1.getYear() - s2.getYear()); teichmann@6147: teichmann@6147: for (int i = 0; i < size; i++) { teichmann@6147: double station = stations.getQuick(i); teichmann@6147: double h1 = s1.getHeight(station); teichmann@6147: double h2 = s2.getHeight(station); teichmann@6147: double hDiff = h1 - h2; teichmann@6147: teichmann@6147: if (!Double.isNaN(hDiff)) { raimund@3887: diffRes.add(hDiff); teichmann@6147: kms.add(station); teichmann@6147: teichmann@6147: morphs.add(Math.max( teichmann@6147: s1.getMorphWidth(station), teichmann@6147: s2.getMorphWidth(station))); teichmann@6147: teichmann@6147: gap.add(Math.max( teichmann@6147: s1.getDataGap(station), teichmann@6147: s2.getDataGap(station))); teichmann@6147: teichmann@6147: absolute.add((hDiff / range) * 100d); teichmann@6147: heights1.add(h1); teichmann@6147: heights2.add(h2); raimund@3887: } raimund@3887: } raimund@3898: return new BedDiffYearResult( raimund@3898: kms, raimund@3898: diffRes, raimund@3898: heights1, raimund@3898: heights2, raimund@3898: morphs, raimund@3898: absolute, raimund@3898: gap, raimund@3898: s1.getYear(), felix@6089: s2.getYear(), felix@6089: s1.getName(), felix@6089: s2.getName()); raimund@3887: } raimund@3887: } felix@6948: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :