view artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculation.java @ 8980:b194fa64506a

SINFO - show results themes according to spec, either raw data or floating mean values. Some improvements to error handling and handling of empty results.
author gernotbelger
date Thu, 05 Apr 2018 18:30:34 +0200
parents 45f1ad66560e
children 2ed3824a3d53
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.flowdepth;

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.tkhcalculation.DischargeValuesFinder;
import org.dive4elements.river.artifacts.sinfo.tkhcalculation.TkhCalculator;
import org.dive4elements.river.artifacts.sinfo.tkhcalculation.WaterlevelValuesFinder;
import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsFinder;
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;

class FlowDepthCalculation {

    // private static Logger log = Logger.getLogger(FlowDepthCalculation.class);

    private final CallContext context;

    public FlowDepthCalculation(final CallContext context) {
        this.context = context;
    }

    public CalculationResult calculate(final SINFOArtifact sinfo) {

        final String user = CalculationUtils.findArtifactUser(this.context, sinfo);

        /* access input data */
        final FlowDepthAccess access = new FlowDepthAccess(sinfo);
        final River river = access.getRiver();
        final RiverInfo riverInfo = new RiverInfo(river);

        final Collection<WstSoundingIdPair> diffPairs = access.getDifferencePairs();

        final DoubleRange calcRange = access.getRange();

        final boolean useTkh = access.isUseTransportBodies();

        /* 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 FlowDepthCalculationResults results = new FlowDepthCalculationResults(calcModeLabel, user, riverInfo, calcRange, useTkh);

        for (final WstSoundingIdPair diffPair : diffPairs) {
            final FlowDepthCalculationResult result = calculateResult(calcRange, diffPair, problems, infoProvider, useTkh);
            results.addResult(result, problems);
        }

        return new CalculationResult(results, problems);
    }

    /**
     * Calculates one W-MSH differences pair.
     *
     * @param infoProvider
     */
    private FlowDepthCalculationResult calculateResult(final DoubleRange calcRange, final WstSoundingIdPair diffPair, final Calculation problems,
            final RiverInfoProvider infoProvider, final boolean useTkh) {

        /* access real input data from database */
        final String soundingId = diffPair.getSoundingId();
        final String wstId = diffPair.getWstId();

        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 WKms wstKms = waterlevel.getWkms();

        final String wspLabel = wstKms.getName();
        final String soundingLabel = bedHeight.getInfo().getDescription();
        final String label = String.format("%s - %s", wspLabel, soundingLabel);

        FlowDepthUtils.checkYearDifference(label, waterlevel.getYear(), bedHeight.getInfo().getYear(), 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(wspLabel, wspYear, riverInfoProvider.getReferenceGauge());

        final WaterlevelValuesFinder waterlevelProvider = WaterlevelValuesFinder.fromKms(problems, wstKms);
        final DischargeValuesFinder dischargeProvider = DischargeValuesFinder.fromKms(wstKms);

        final River river = riverInfoProvider.getRiver();
        final TkhCalculator tkhCalculator = TkhCalculator.buildTkhCalculator(useTkh, problems, label, river, calcRange, waterlevelProvider,
                dischargeProvider, bedHeight);

        final FlowDepthCalculator calculator = new FlowDepthCalculator(riverInfoProvider, wspLabel, bedHeight, tkhCalculator);
        return calculator.execute(label, wstInfo, calcRange);
    }
}

http://dive4elements.wald.intevation.org