Mercurial > dive4elements > river
view artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepthminmax/FlowDepthMinMaxCalculation.java @ 8993:0adc6d04de95
SInfo - FlowDepthMinMax: choosing bed heights, not bed height min and max separately
author | gernotbelger |
---|---|
date | Wed, 11 Apr 2018 14:09:13 +0200 |
parents | b194fa64506a |
children | d5802f22e4f5 |
line wrap: on
line source
/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde * Software engineering by * Björnsen Beratende Ingenieure GmbH * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt * * This file is Free Software under the GNU AGPL (>=v3) * and comes with ABSOLUTELY NO WARRANTY! Check out the * documentation coming with Dive4Elements River for details. */ package org.dive4elements.river.artifacts.sinfo.flowdepthminmax; import java.util.ArrayList; import java.util.Collection; import org.apache.commons.lang.math.DoubleRange; import org.dive4elements.artifacts.CallContext; import org.dive4elements.river.artifacts.model.Calculation; import org.dive4elements.river.artifacts.model.CalculationResult; import org.dive4elements.river.artifacts.model.WKms; import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.artifacts.sinfo.SINFOArtifact; import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider; import org.dive4elements.river.artifacts.sinfo.common.SInfoResultRow; import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType; import org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthUtils; import org.dive4elements.river.artifacts.sinfo.flowdepth.WstSoundingIdPair; import org.dive4elements.river.artifacts.sinfo.tkhcalculation.DischargeValuesFinder; import org.dive4elements.river.artifacts.sinfo.tkhcalculation.WaterlevelValuesFinder; import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsFinder; 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.artifacts.states.WaterlevelFetcher; import org.dive4elements.river.model.River; /** * @author Gernot Belger */ final class FlowDepthMinMaxCalculation { private final CallContext context; public FlowDepthMinMaxCalculation(final CallContext context) { this.context = context; } public CalculationResult calculate(final SINFOArtifact sinfo) { final String user = CalculationUtils.findArtifactUser(this.context, sinfo); /* access input data */ final FlowDepthMinMaxAccess access = new FlowDepthMinMaxAccess(sinfo); final River river = access.getRiver(); final RiverInfo riverInfo = new RiverInfo(river); final Collection<WstSoundingIdPair> minMaxPairs = access.getMinMaxPairs(); final DoubleRange calcRange = access.getRange(); /* calculate results for each diff pair */ final Calculation problems = new Calculation(); final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange); final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name()); final FlowDepthMinMaxCalculationResults results = new FlowDepthMinMaxCalculationResults(calcModeLabel, user, riverInfo, calcRange); for (final WstSoundingIdPair minMaxPair : minMaxPairs) { final FlowDepthMinMaxCalculationResult result = calculateResult(calcRange, minMaxPair, problems, infoProvider); results.addResult(result, problems); } return new CalculationResult(results, problems); } /** * Calculates one W-MSH differences pair. * * @param infoProvider */ private FlowDepthMinMaxCalculationResult calculateResult(final DoubleRange calcRange, final WstSoundingIdPair minMaxPair, final Calculation problems, final RiverInfoProvider infoProvider) { /* access real input data from database */ final String wstId = minMaxPair.getWstId(); final String soundingId = minMaxPair.getSoundingId(); final BedHeightsFinder bedHeight = BedHeightsFinder.forId(this.context, soundingId, calcRange, problems); if (bedHeight == null) return null; /* REMARK: fetch ALL wst kms, because we want to determine the original reference gauge */ final WaterlevelData waterlevel = new WaterlevelFetcher().findWaterlevel(this.context, wstId, calcRange, problems); if (waterlevel == null) return null; final String label = createLabel(waterlevel, bedHeight); final WKms wstKms = waterlevel.getWkms(); final BedHeightInfo bedHeightInfo = bedHeight.getInfo(); final int soundingYear = bedHeightInfo.getYear(); FlowDepthUtils.checkYearDifference(label, waterlevel.getYear(), soundingYear, problems); /* re-determine the reference gauge, in the same way as the WaterlevelArtifact would do it */ final RiverInfoProvider riverInfoProvider = infoProvider.forWaterlevel(waterlevel); final int wspYear = waterlevel.getYear(); final WstInfo wstInfo = new WstInfo(waterlevel.getName(), wspYear, riverInfoProvider.getReferenceGauge()); final WaterlevelValuesFinder waterlevelProvider = WaterlevelValuesFinder.fromKms(problems, wstKms); final DischargeValuesFinder dischargeProvider = DischargeValuesFinder.fromKms(wstKms); final String waterlevelLabel = waterlevel.getName(); final String soundingLabel = bedHeightInfo.getDescription(); /* real calculation loop */ final Collection<SInfoResultRow> rows = new ArrayList<>(); final Collection<Double> stations = bedHeight.getStations(); for (final double station : stations) { if (calcRange.containsDouble(station)) { final double wst = waterlevelProvider.getWaterlevel(station); final double discharge = dischargeProvider.getDischarge(station); final double minBedHeightValue = bedHeight.getMinBedHeight(station); final double maxBedHeightValue = bedHeight.getMaxBedHeight(station); final double meanBedHeight = bedHeight.getMeanBedHeight(station); final double minFlowDepth = wst - maxBedHeightValue; final double maxFlowDepth = wst - minBedHeightValue; // REMARK: access the location once only during calculation final String location = riverInfoProvider.getLocation(station); // REMARK: access the gauge once only during calculation final String gaugeLabel = riverInfoProvider.findGauge(station); /* ignore invalid lines */ if (Double.isNaN(wst) || Double.isNaN(minBedHeightValue) || Double.isNaN(maxBedHeightValue)) continue; final SInfoResultRow row = SInfoResultRow.create().// putValue(SInfoResultType.station, station). // putValue(SInfoResultType.flowdepthmin, minFlowDepth). // putValue(SInfoResultType.flowdepthmax, maxFlowDepth). // putValue(SInfoResultType.waterlevel, wst). // putValue(SInfoResultType.discharge, discharge). // putValue(SInfoResultType.waterlevelLabel, waterlevelLabel). // putValue(SInfoResultType.gaugeLabel, gaugeLabel). // putValue(SInfoResultType.meanBedHeight, meanBedHeight). // putValue(SInfoResultType.soundingLabel, soundingLabel). // putValue(SInfoResultType.location, location); rows.add(row); } } return new FlowDepthMinMaxCalculationResult(label, wstInfo, bedHeightInfo, rows); } private String createLabel(final WaterlevelData waterlevel, final BedHeightsFinder bedHeight) { return new StringBuilder(waterlevel.getName()). // append(" - "). // append(bedHeight.getInfo().getDescription()). // toString(); } }