Mercurial > dive4elements > river
diff artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/TkhCalculation.java @ 8942:11bf13cf0463
Minor changes to tkh calculation. Loading default bed heights form config file.
author | gernotbelger |
---|---|
date | Fri, 09 Mar 2018 18:47:06 +0100 |
parents | 9c02733a1b3c |
children | 5d5d482da3e9 |
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/TkhCalculation.java Wed Mar 07 17:36:04 2018 +0100 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/TkhCalculation.java Fri Mar 09 18:47:06 2018 +0100 @@ -11,9 +11,14 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import org.apache.commons.lang.math.DoubleRange; +import org.apache.commons.lang.math.NumberRange; import org.dive4elements.artifacts.CallContext; import org.dive4elements.river.artifacts.WINFOArtifact; import org.dive4elements.river.artifacts.model.Calculation; @@ -26,11 +31,13 @@ import org.dive4elements.river.artifacts.sinfo.tkhcalculation.DischargeValuesFinder; import org.dive4elements.river.artifacts.sinfo.tkhcalculation.Tkh; import org.dive4elements.river.artifacts.sinfo.tkhcalculation.TkhCalculator; +import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo; import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils; import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; import org.dive4elements.river.artifacts.sinfo.util.WstInfo; import org.dive4elements.river.artifacts.states.WaterlevelData; import org.dive4elements.river.exports.WaterlevelDescriptionBuilder; +import org.dive4elements.river.model.BedHeight; import org.dive4elements.river.model.River; /** @@ -55,7 +62,8 @@ final Calculation problems = new Calculation(); /* find relevant bed-heights */ - final Collection<BedHeightsFinder> bedHeights = BedHeightsFinder.createTkhBedHeights(river, problems, calcRange); + final List<BedHeight> defaultBedHeights = new DefaultBedHeights(river).getBedHeights(problems); + final Collection<BedHeightsFinder> bedHeights = BedHeightsFinder.createTkhBedHeights(calcRange, defaultBedHeights); /* misuse winfo-artifact to calculate waterlevels in the same way */ final WINFOArtifact winfo = new WinfoArtifactWrapper(sinfo); @@ -118,46 +126,77 @@ final WstInfo wstInfo = new WstInfo(wstLabel, wspYear, riverInfoProvider.getReferenceGauge()); + /* build tkh calculators per bedheight */ + final Map<NumberRange, TkhCalculator> calculatorsByRanges = buildCalculators(calcRange, wkms, bedHeights, problems, riverInfoProvider, wstLabel); + if (calculatorsByRanges.isEmpty()) { + /* there should already be some problems, so just abort */ + return null; + } + final Collection<TkhResultRow> rows = new ArrayList<>(); - /* - * for each separate bed height dataset we do the calculation and put everything into one result, bed heights must not - * overlap accordingly - */ + /* using wst-kms as basis, because we know that they are generated wst's with a fixed km-step */ + // FIXME: das führt dazu, das aktuell die Sohlhöhen beliebig linear interpolierrt werden. ist das immer richtig? z.b. + // bei großen abständen? + + final int size = wkms.size(); + for (int i = 0; i < size; i++) { + + final double station = wkms.getKm(i); + final double wst = wkms.getW(i); + + /* find the right calculator (i.e. bedheigh) depending on station, there should only be one maximal */ + final TkhCalculator tkhCalculator = findCalculator(calculatorsByRanges, station); + if (tkhCalculator == null) + continue; + + final Tkh tkh = tkhCalculator.getTkh(station, wst); + + final String description = descBuilder.getDesc(wkms); + final String gaugeLabel = riverInfoProvider.findGauge(station); + final String location = riverInfoProvider.getLocation(station); + + rows.add(new TkhResultRow(tkh, description, gaugeLabel, location)); + } + + return new TkhCalculationResult(wstLabel, wstInfo, true, rows); + } + + private TkhCalculator findCalculator(final Map<NumberRange, TkhCalculator> calculators, final double station) { + + // REMAKR: linear search at this point, put we expect the number of bed heights to be very small (1-2 items) + final Set<Entry<NumberRange, TkhCalculator>> x = calculators.entrySet(); + for (final Entry<NumberRange, TkhCalculator> entry : x) { + final NumberRange range = entry.getKey(); + // FIXME: check if we need comparison with a tolerance + if (range.containsDouble(station)) + return entry.getValue(); + } + + return null; + } + + private Map<NumberRange, TkhCalculator> buildCalculators(final DoubleRange calcRange, final WQKms wkms, final Collection<BedHeightsFinder> bedHeights, + final Calculation problems, final RiverInfoProvider riverInfoProvider, final String wstLabel) { + final Map<NumberRange, TkhCalculator> calculatorByRanges = new HashMap<>(); for (final BedHeightsFinder bedHeightsProvider : bedHeights) { + final BedHeightInfo info = bedHeightsProvider.getInfo(); + + final NumberRange range = new NumberRange(info.getFrom(), info.getTo()); + final DischargeValuesFinder dischargeProvider = DischargeValuesFinder.fromKms(wkms); /* initialize tkh calculator */ final TkhCalculator tkhCalculator = TkhCalculator.buildTkhCalculator(true, this.context, problems, wstLabel, riverInfoProvider.getRiver(), - calcRange, - dischargeProvider, bedHeightsProvider); - if (tkhCalculator == null) { - /* just abort, problems have already been updated by buildTkhCalculator() */ - return null; - } - - /* using wst-kms as basis, because we know that they are generated wst's with a fixed km-step */ - - // FIXME: das führt dazu, das aktuell die Sohlhöhen beliebig linear interpolierrt werden. ist das immer richtig? z.b. - // bei großen abständen? + calcRange, dischargeProvider, bedHeightsProvider); - final int size = wkms.size(); - for (int i = 0; i < size; i++) { - - final double station = wkms.getKm(i); - final double wst = wkms.getW(i); - - final Tkh tkh = tkhCalculator.getTkh(station, wst); - - final String description = descBuilder.getDesc(wkms); - final String gaugeLabel = riverInfoProvider.findGauge(station); - final String location = riverInfoProvider.getLocation(station); - - rows.add(new TkhResultRow(tkh, description, gaugeLabel, location)); + if (tkhCalculator != null) { + /* just ignore null ones, problems have already been updated by buildTkhCalculator() */ + calculatorByRanges.put(range, tkhCalculator); } } - return new TkhCalculationResult(wstLabel, wstInfo, true, rows); + return calculatorByRanges; } } \ No newline at end of file