mschaefer@9450: /** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde mschaefer@9450: * Software engineering by mschaefer@9450: * Björnsen Beratende Ingenieure GmbH mschaefer@9450: * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt mschaefer@9450: * mschaefer@9450: * This file is Free Software under the GNU AGPL (>=v3) mschaefer@9450: * and comes with ABSOLUTELY NO WARRANTY! Check out the mschaefer@9450: * documentation coming with Dive4Elements River for details. mschaefer@9450: */ mschaefer@9450: mschaefer@9450: package org.dive4elements.river.artifacts.bundu.bezugswst; mschaefer@9450: mschaefer@9450: import java.util.Date; mschaefer@9451: import java.util.Map.Entry; mschaefer@9451: import java.util.NavigableMap; mschaefer@9451: import java.util.TreeMap; mschaefer@9450: mschaefer@9450: import org.dive4elements.artifacts.CallContext; mschaefer@9450: import org.dive4elements.river.artifacts.access.BedQualityAccess; mschaefer@9450: import org.dive4elements.river.artifacts.bundu.BUNDUArtifact; mschaefer@9451: import org.dive4elements.river.artifacts.math.Linear; mschaefer@9450: import org.dive4elements.river.artifacts.model.Calculation; mschaefer@9450: import org.dive4elements.river.artifacts.model.Calculation.Problem; mschaefer@9450: import org.dive4elements.river.artifacts.model.CalculationResult; mschaefer@9450: import org.dive4elements.river.artifacts.model.minfo.BedQualityCalculation; mschaefer@9450: import org.dive4elements.river.artifacts.model.minfo.BedQualityResult; mschaefer@9450: import org.dive4elements.river.artifacts.model.minfo.BedQualityResultValue; mschaefer@9450: import org.dive4elements.river.model.River; mschaefer@9450: mschaefer@9450: /** mschaefer@9450: * Calculator for bed quality parameters in a km range and time period, wrapping the minfo BedQualityCalculation mschaefer@9450: * mschaefer@9450: * @author Matthias Schäfer mschaefer@9450: * mschaefer@9450: */ mschaefer@9450: public class BedQualityCalculator { mschaefer@9450: mschaefer@9450: private final CallContext context; mschaefer@9450: mschaefer@9450: private final BUNDUArtifact bundu; mschaefer@9450: mschaefer@9451: private final NavigableMap densities; mschaefer@9450: mschaefer@9450: public BedQualityCalculator(final CallContext context, final BUNDUArtifact bundu) { mschaefer@9450: this.context = context; mschaefer@9450: this.bundu = bundu; mschaefer@9451: this.densities = new TreeMap<>(); mschaefer@9450: } mschaefer@9450: mschaefer@9451: mschaefer@9450: /** mschaefer@9450: * Calculates the river bed sublayer densities for an array of kms and a time period of measurements mschaefer@9450: */ mschaefer@9451: public void execute(final Calculation problems, final River river, final double[] kms, final Date startDay, final Date endDay) { mschaefer@9450: final BedQualityCalculation bqCalc = new BedQualityCalculation(); mschaefer@9450: final BedQualityAccess access = createBqAccess(kms[0], kms[kms.length - 1], startDay, endDay); mschaefer@9450: final CalculationResult bqCalcResult = bqCalc.calculate(access); mschaefer@9450: if (bqCalcResult.getReport().getProblems() != null) { mschaefer@9450: for (final Problem problem : bqCalcResult.getReport().getProblems()) mschaefer@9450: problems.addProblem(problem); mschaefer@9450: } mschaefer@9450: final BedQualityResult[] results = (BedQualityResult[]) bqCalcResult.getData(); mschaefer@9450: final BedQualityResult result = results[0]; mschaefer@9450: final BedQualityResultValue bqResValue = result.getValue("density", "sublayer"); mschaefer@9451: final double[][] kmdensities = bqResValue.getDataInterpolated(kms); mschaefer@9451: this.densities.clear(); mschaefer@9451: for (int i = 0; i <= kmdensities[0].length - 1; i++) mschaefer@9451: this.densities.put(Double.valueOf(kmdensities[0][i]), Double.valueOf(kmdensities[1][i])); mschaefer@9451: } mschaefer@9451: mschaefer@9451: /** mschaefer@9451: * Searches the density of a station in the active calculation result mschaefer@9451: */ mschaefer@9451: public double getDensity(final double station) { mschaefer@9451: return interpolateDensity(station); mschaefer@9451: } mschaefer@9451: mschaefer@9451: /** mschaefer@9451: * Searches and interpolates a density value for a km mschaefer@9451: */ mschaefer@9451: private double interpolateDensity(final double km) { mschaefer@9451: mschaefer@9451: if (this.densities.containsKey(km)) { mschaefer@9451: final Double value = this.densities.get(km); mschaefer@9451: return (value == null) ? Double.NaN : value.doubleValue(); mschaefer@9451: } mschaefer@9451: mschaefer@9451: final Entry floorEntry = this.densities.floorEntry(km); mschaefer@9451: final Entry ceilingEntry = this.densities.ceilingEntry(km); mschaefer@9451: mschaefer@9451: if ((floorEntry == null) || (ceilingEntry == null)) mschaefer@9451: return Double.NaN; mschaefer@9451: mschaefer@9451: final double floorKm = floorEntry.getKey().doubleValue(); mschaefer@9451: final double ceilKm = ceilingEntry.getKey().doubleValue(); mschaefer@9451: mschaefer@9451: // report once if the interpolation distance exceeds 1000m mschaefer@9451: // if ((Math.abs(floorKm - ceilKm) > MAX_DISTANCE_KM) && (this.problems != null)) { mschaefer@9451: // this.problems.addProblem(km, "linearInterpolator.maxdistance", MAX_DISTANCE_KM * 1000); mschaefer@9451: // this.problems = null; mschaefer@9451: // return Double.NaN; mschaefer@9451: // } mschaefer@9451: mschaefer@9451: final Double floorHeight = floorEntry.getValue(); mschaefer@9451: final Double ceilingHeight = ceilingEntry.getValue(); mschaefer@9451: mschaefer@9451: if (floorHeight == null || ceilingHeight == null) mschaefer@9451: return Double.NaN; mschaefer@9451: mschaefer@9451: return Linear.linear(km, floorKm, ceilKm, floorHeight, ceilingHeight); mschaefer@9450: } mschaefer@9450: mschaefer@9450: /** mschaefer@9450: * Creates an access object for the bed quality calculation mschaefer@9450: */ mschaefer@9450: private BedQualityAccess createBqAccess(final double fromKm, final double toKm, final Date startDay, final Date endDay) { mschaefer@9450: final BunduMinfoArtifactWrapper minfo = new BunduMinfoArtifactWrapper(this.bundu, startDay, endDay); mschaefer@9450: return new BedQualityAccess(minfo, this.context); mschaefer@9450: } mschaefer@9450: }