# HG changeset patch # User mschaefer # Date 1535014660 -7200 # Node ID fd6621f47a72b5deab6100a67570a6ea83d7b9fd # Parent 7e1fb8d0cb0da8673cbd2a635ddf938e0c32fe80 Bundu bzws density calculation completed diff -r 7e1fb8d0cb0d -r fd6621f47a72 artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/BunduResultType.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/BunduResultType.java Wed Aug 22 19:12:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/BunduResultType.java Thu Aug 23 10:57:40 2018 +0200 @@ -404,7 +404,7 @@ } }; - public static final BunduResultType missStationRangeFrom = new BunduResultType(I18NStrings.UNIT_KM, "bundu.export.bezugswst.csv.meta.miss.mass.km_from") { + public static final BunduResultType missStationRangeFrom = new BunduResultType(I18NStrings.UNIT_KM, "bundu.export.bezugswst.csv.meta.miss.km_from") { private static final long serialVersionUID = 1L; @@ -420,7 +420,7 @@ } }; - public static final BunduResultType missStationRangeTo = new BunduResultType(I18NStrings.UNIT_KM, "bundu.export.bezugswst.csv.meta.miss.mass.km_to") { + public static final BunduResultType missStationRangeTo = new BunduResultType(I18NStrings.UNIT_KM, "bundu.export.bezugswst.csv.meta.miss.km_to") { private static final long serialVersionUID = 1L; diff -r 7e1fb8d0cb0d -r fd6621f47a72 artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BedQualityCalculator.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BedQualityCalculator.java Wed Aug 22 19:12:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BedQualityCalculator.java Thu Aug 23 10:57:40 2018 +0200 @@ -11,10 +11,14 @@ package org.dive4elements.river.artifacts.bundu.bezugswst; import java.util.Date; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.TreeMap; import org.dive4elements.artifacts.CallContext; import org.dive4elements.river.artifacts.access.BedQualityAccess; import org.dive4elements.river.artifacts.bundu.BUNDUArtifact; +import org.dive4elements.river.artifacts.math.Linear; import org.dive4elements.river.artifacts.model.Calculation; import org.dive4elements.river.artifacts.model.Calculation.Problem; import org.dive4elements.river.artifacts.model.CalculationResult; @@ -35,16 +39,19 @@ private final BUNDUArtifact bundu; + private final NavigableMap densities; public BedQualityCalculator(final CallContext context, final BUNDUArtifact bundu) { this.context = context; this.bundu = bundu; + this.densities = new TreeMap<>(); } + /** * Calculates the river bed sublayer densities for an array of kms and a time period of measurements */ - public double[][] execute(final Calculation problems, final River river, final double[] kms, final Date startDay, final Date endDay) { + public void execute(final Calculation problems, final River river, final double[] kms, final Date startDay, final Date endDay) { final BedQualityCalculation bqCalc = new BedQualityCalculation(); final BedQualityAccess access = createBqAccess(kms[0], kms[kms.length - 1], startDay, endDay); final CalculationResult bqCalcResult = bqCalc.calculate(access); @@ -55,7 +62,52 @@ final BedQualityResult[] results = (BedQualityResult[]) bqCalcResult.getData(); final BedQualityResult result = results[0]; final BedQualityResultValue bqResValue = result.getValue("density", "sublayer"); - return bqResValue.getDataInterpolated(kms); + final double[][] kmdensities = bqResValue.getDataInterpolated(kms); + this.densities.clear(); + for (int i = 0; i <= kmdensities[0].length - 1; i++) + this.densities.put(Double.valueOf(kmdensities[0][i]), Double.valueOf(kmdensities[1][i])); + } + + /** + * Searches the density of a station in the active calculation result + */ + public double getDensity(final double station) { + return interpolateDensity(station); + } + + /** + * Searches and interpolates a density value for a km + */ + private double interpolateDensity(final double km) { + + if (this.densities.containsKey(km)) { + final Double value = this.densities.get(km); + return (value == null) ? Double.NaN : value.doubleValue(); + } + + final Entry floorEntry = this.densities.floorEntry(km); + final Entry ceilingEntry = this.densities.ceilingEntry(km); + + if ((floorEntry == null) || (ceilingEntry == null)) + return Double.NaN; + + final double floorKm = floorEntry.getKey().doubleValue(); + final double ceilKm = ceilingEntry.getKey().doubleValue(); + + // report once if the interpolation distance exceeds 1000m + // if ((Math.abs(floorKm - ceilKm) > MAX_DISTANCE_KM) && (this.problems != null)) { + // this.problems.addProblem(km, "linearInterpolator.maxdistance", MAX_DISTANCE_KM * 1000); + // this.problems = null; + // return Double.NaN; + // } + + final Double floorHeight = floorEntry.getValue(); + final Double ceilingHeight = ceilingEntry.getValue(); + + if (floorHeight == null || ceilingHeight == null) + return Double.NaN; + + return Linear.linear(km, floorKm, ceilKm, floorHeight, ceilingHeight); } /** diff -r 7e1fb8d0cb0d -r fd6621f47a72 artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java Wed Aug 22 19:12:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java Thu Aug 23 10:57:40 2018 +0200 @@ -38,6 +38,7 @@ import org.dive4elements.river.exports.WaterlevelDescriptionBuilder; import org.dive4elements.river.model.BedHeightValueType; import org.dive4elements.river.model.River; +import org.dive4elements.river.utils.DoubleUtil; import org.dive4elements.river.utils.Formatter; class BezugswstCalculation { @@ -120,14 +121,8 @@ // Compute the missing volumes if (access.isCalculateMissingValue()) { computeMissingVolumes(problems); - final BedQualityCalculator bqCalculator = new BedQualityCalculator(this.context, bunduartifact); - final double[] kms = new double[] { this.missKmFrom.doubleValue(), this.missKmTo.doubleValue() }; - final Calendar endDay = Calendar.getInstance(); - endDay.set(access.getBezugsJahr().intValue(), 11, 31); - final Calendar startDay = Calendar.getInstance(); - startDay.set(endDay.get(Calendar.YEAR) - 20, 0, 1); - // TODO final double[][] kmDensities = bqCalculator.execute(problems, river, kms, startDay.getTime(), endDay.getTime()); - computeMissingMasses(problems); + final BedQualityCalculator bqCalculator = computeDensities(problems, bunduartifact, access, river); + computeMissingMasses(problems, bqCalculator); } // Add the result to the results collection @@ -388,15 +383,33 @@ } /** + * Create a density calculator and compute the densities of the missing volume km range and time period according to the + * reference year + */ + private BedQualityCalculator computeDensities(final Calculation problems, final BUNDUArtifact bunduartifact, final BunduAccess access, final River river) { + final BedQualityCalculator bqCalculator = new BedQualityCalculator(this.context, bunduartifact); + // REMARK 10km tolerance at start and end to enable interpolation there + final double[] kms = DoubleUtil.explode(access.getMissingVolFrom().doubleValue() - 10.0, access.getMissingVolTo().doubleValue() + 10.0, + access.getStep().doubleValue() / 1000); + final Calendar endDay = Calendar.getInstance(); + endDay.set(access.getBezugsJahr().intValue(), 11, 31); + final Calendar startDay = Calendar.getInstance(); + // TODO Spezialregelung für den Rhein (bis 1999, 2000 bis 2009, ab 2010) + startDay.set(endDay.get(Calendar.YEAR) - 20, 0, 1); + bqCalculator.execute(problems, river, kms, startDay.getTime(), endDay.getTime()); + return bqCalculator; + } + + /** * Computes the missing masses */ - private void computeMissingMasses(final Calculation problems) { + private void computeMissingMasses(final Calculation problems, final BedQualityCalculator densityFinder) { for (final ResultRow row : this.rows) { @SuppressWarnings("unchecked") final List volumes = (List) row.getValue(BunduResultType.missVolumeFields); if ((volumes == null) || Double.isNaN(volumes.get(0))) continue; - final double density = getDensity(row.getDoubleValue(GeneralResultType.station)); + final double density = getDensity(row.getDoubleValue(GeneralResultType.station), densityFinder); final List masses = new ArrayList<>(); double kmTotal = 0.0; for (int j = BedHeightValueType.FIELD_FIRST_INDEX; j <= BedHeightValueType.FIELD_LAST_INDEX; j++) { @@ -470,8 +483,11 @@ return missRows; } - private double getDensity(final double km) { - return 1.73; // TODO + /** + * Gets the density of a km from the densities calculation + */ + private double getDensity(final double km, final BedQualityCalculator densityFinder) { + return densityFinder.getDensity(km); } /** diff -r 7e1fb8d0cb0d -r fd6621f47a72 artifacts/src/main/java/org/dive4elements/river/utils/Formatter.java --- a/artifacts/src/main/java/org/dive4elements/river/utils/Formatter.java Wed Aug 22 19:12:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/utils/Formatter.java Thu Aug 23 10:57:40 2018 +0200 @@ -449,7 +449,7 @@ } public static NumberFormat getCurrencyFormat(final CallContext context) { - final NumberFormat nf = getFormatter(context.getMeta(), 0, 0); + final NumberFormat nf = getFormatter(context.getMeta(), 2, 2); nf.setGroupingUsed(true); return nf; }