Mercurial > dive4elements > river
diff artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java @ 9394:439699ff9b2d
Added U-Info iota (prev. salix) calculation for historical scenario
author | mschaefer |
---|---|
date | Fri, 10 Aug 2018 17:31:46 +0200 |
parents | 2da486c7c05f |
children | 6e7094368e97 |
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java Fri Aug 10 17:07:30 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java Fri Aug 10 17:31:46 2018 +0200 @@ -10,6 +10,7 @@ package org.dive4elements.river.artifacts.uinfo.salix; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.NavigableMap; import java.util.TreeMap; @@ -22,26 +23,39 @@ import org.dive4elements.river.artifacts.model.CalculationResult; import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider; +import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsFinder; +import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsUtils; +import org.dive4elements.river.artifacts.sinfo.tkhstate.DefaultBedHeights; import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils; import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; import org.dive4elements.river.artifacts.uinfo.UINFOArtifact; import org.dive4elements.river.artifacts.uinfo.salix.SalixLineAccess.ScenarioType; +import org.dive4elements.river.model.BedHeight; import org.dive4elements.river.model.River; +import org.dive4elements.river.utils.Formatter; /** + * Calculation of a iota (former salix) longitudinal section, optionally with a delta scenario + * * @author Domenico Nardi Tironi + * @author Matthias Schäfer * */ final class SalixLineCalculation { private final CallContext context; + private Calculation problems; + public SalixLineCalculation(final CallContext context) { this.context = context; } + /** + * Calculates the iota longitudinal section and delta scenario of a uinfo artifact + */ public CalculationResult calculate(final UINFOArtifact uinfo) { - final Calculation problems = new Calculation(); + this.problems = new Calculation(); final String calcModeLabel = Resources.getMsg(this.context.getMeta(), uinfo.getCalculationMode().name()); final String user = CalculationUtils.findArtifactUser(this.context, uinfo); @@ -62,14 +76,14 @@ final SalixLineCalculator calculator = new SalixLineCalculator(riverInfoProvider); final NavigableMap<Double, List<Double>> rangeScenarios = buildRangeScenarios(accessSalix); - calculator.execute(problems, uinfo, rangeScenarios, scenarioType, buildScenarioLabels(accessSalix), buildPartialRangeString(accessSalix), + calculator.execute(this.problems, uinfo, rangeScenarios, scenarioType, buildScenarioLabels(accessSalix), buildPartialRangeString(accessSalix), buildAdditionalString(accessSalix), results); - return new CalculationResult(results, problems); + return new CalculationResult(results, this.problems); } /** - * Build a map of delta-Ws by from-km for the selected scenario + * Builds a map of delta-Ws by from-km for the selected scenario */ private NavigableMap<Double, List<Double>> buildRangeScenarios(final SalixLineAccess access) { final NavigableMap<Double, List<Double>> rangeScenarios = new TreeMap<>(); @@ -78,8 +92,8 @@ access.getRegionalScenarioIntegers()); else if (access.getScenario() == ScenarioType.SUPRAREGIONAL) fillRangeScenarios(rangeScenarios, access.getSupraRegionalString()); - // TODO else if (access.getScenario().equals(ScenarioType.HISTORICAL.getKey())) - // historisches Szenario aus MSH etc. + else if (access.getScenario() == ScenarioType.HISTORICAL) + fillRangeScenarios(rangeScenarios, access, access.getFromPart().doubleValue(), access.getToPart().doubleValue(), access.getBedHeightId()); else fillRangeScenarios(rangeScenarios, access); @@ -87,23 +101,23 @@ } /** - * Fill a map of delta-Ws with only one 0-delta for the whole calc range (no scenario) + * Fills a map of delta-Ws with only one 0-delta for the whole calc range (no scenario) */ private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final RangeAccess calcRange) { final List<Double> nulls = new ArrayList<>(); - nulls.add(0.0); + nulls.add(null); rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls); } /** - * Fill a map of delta-Ws by km-range from the regional scenario input data + * Fills a map of delta-Ws by km-range from the regional scenario input data */ - private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final RangeAccess calcRange, final double partFrom, - final double partTo, final int[] deltaWs) { + private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final RangeAccess calcRange, + final double partFrom, final double partTo, final int[] deltaWs) { final List<Double> nulls = new ArrayList<>(); final List<Double> dwsm = new ArrayList<>(); for (int i = 0; i <= deltaWs.length - 1; i++) { - nulls.add(0.0); + nulls.add(null); dwsm.add(deltaWs[i] / 100.0); } rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls); @@ -112,20 +126,65 @@ } /** - * Fill a map of delta-Ws by km-range from the supraregional scenario input data + * Fills a map of delta-Ws by km-range from the supraregional scenario input data * (the zones input by the user cover the calc range completely) */ private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final String zones) { final List<SalixZone> parts = SalixZone.parse(zones); for (final SalixZone part : parts) { final List<Double> dwsm = new ArrayList<>(); - dwsm.add(part.getDwsplValue() / 100.0); + if (part.getDwsplValue() == 0) + dwsm.add(null); + else + dwsm.add(part.getDwsplValue() / 100.0); rangeScenarios.put(Double.valueOf(part.getFromKm().doubleValue() - 0.0001), dwsm); } } /** - * Build the list of delta-w labels for the scenario type + * Fetches historical and reference bed heights and fills a map of delta-MSHs for all fetched stations in the calc range + */ + private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final RangeAccess calcRange, + final double partFrom, final double partTo, final int historicalBedHeightId) { + + // Find relevant default bed-heights + final River river = calcRange.getRiver(); + final List<BedHeight> defaultBedHeights = new DefaultBedHeights(river).getBedHeights(this.problems); + if (defaultBedHeights.isEmpty()) + return; + final DoubleRange scenarioRange = new DoubleRange(partFrom, partTo); + final Collection<BedHeightsFinder> allFinders = BedHeightsFinder.createTkhBedHeights(this.problems, scenarioRange, defaultBedHeights); + final Collection<BedHeightsFinder> currentFinders = new ArrayList<>(allFinders); + + // Add historical bed-heights + final BedHeightsFinder historicalFinder = BedHeightsFinder.forId(this.problems, historicalBedHeightId, scenarioRange); + allFinders.add(historicalFinder); + final Collection<Double> stations = BedHeightsUtils.extractStationCollection(allFinders, true); + final List<Double> nulls = new ArrayList<>(); + nulls.add(null); + rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls); + for (final Double station : stations) { + rangeScenarios.put(station, new ArrayList<Double>()); + rangeScenarios.get(station).add(Double.valueOf(bedHeightDifference(station.doubleValue(), currentFinders, historicalFinder))); + } + rangeScenarios.put(Double.valueOf(partTo + 0.0001), nulls); + } + + /** + * Gets the difference of a historical bed height against a current one for a station + */ + private double bedHeightDifference(final double station, final Collection<BedHeightsFinder> currentFinders, final BedHeightsFinder historicalFinder) { + double currentMSH = Double.NaN; + for (final BedHeightsFinder bhf : currentFinders) { + currentMSH = bhf.getMeanBedHeight(station); + if (!Double.isNaN(currentMSH)) + break; + } + return Formatter.roundFlowDepth(historicalFinder.getMeanBedHeight(station)).subtract(Formatter.roundFlowDepth(currentMSH)).doubleValue(); + } + + /** + * Builds the list of delta-w labels for the scenario type */ private String[] buildScenarioLabels(final SalixLineAccess access) { final List<String> labels = new ArrayList<>(); @@ -142,7 +201,7 @@ } /** - * Build the km range string for the scenario type + * Builds the km range string for the scenario type */ private String buildPartialRangeString(final SalixLineAccess access) { if ((access.getScenario() == ScenarioType.REGIONAL) || (access.getScenario() == ScenarioType.HISTORICAL)) { @@ -166,7 +225,7 @@ } /** - * Build the delta w or time string for the scenario type + * Builds the delta w or time string for the scenario type */ private String buildAdditionalString(final SalixLineAccess access) { if (access.getScenario() == ScenarioType.REGIONAL) {