view artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixRealizingCalculation.java @ 9415:9744ce3c3853

Rework of fixanalysis computation and dWt and WQ facets. Got rid of strange remapping and bitshifting code by explicitely saving the column information and using it in the facets. The facets also put the valid station range into their xml-metadata
author gernotbelger
date Thu, 16 Aug 2018 16:27:53 +0200
parents ddcd52d239cd
children 2b83d3a96703
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
 * Software engineering by Intevation GmbH
 *
 * 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.model.fixings;

import java.util.List;

import org.dive4elements.river.artifacts.access.FixRealizingAccess;
import org.dive4elements.river.artifacts.math.fitting.Function;
import org.dive4elements.river.artifacts.model.CalculationResult;
import org.dive4elements.river.artifacts.model.Parameters;
import org.dive4elements.river.artifacts.model.RiverFactory;
import org.dive4elements.river.artifacts.model.Segment;
import org.dive4elements.river.artifacts.model.WQKms;
import org.dive4elements.river.model.River;

/** Calculation for FixRealize (german: ausgel. WSPL). */
public class FixRealizingCalculation extends FixCalculation {
    private static final long serialVersionUID = 1L;

    protected boolean isQ;

    protected List<Segment> segments;

    public FixRealizingCalculation() {
    }

    public FixRealizingCalculation(final FixRealizingAccess access) {
        super(access);

        final Boolean isQ = access.isQ();
        final List<Segment> segments = access.getSegments();

        if (isQ == null) {
            addProblem("fix.realize.missing.is.q");
        }

        if (segments == null || segments.isEmpty()) {
            addProblem("fix.realize.missing.segments");
        }

        final River r = RiverFactory.getRiver(this.river);

        if (r == null) {
            addProblem("fix.no.such.river");
        }

        if (!hasProblems()) {
            this.isQ = isQ;
            this.segments = segments;

            // Convert from W to Q
            Segment.setReferencePointConvertQ(segments, r, isQ, this);
        }
    }

    @Override
    protected CalculationResult innerCalculate(final FixingsOverview overview, final Function func) {
        final ColumnCache cc = new ColumnCache();
        final FitResult fitResult = doFitting(overview, cc, func);

        if (fitResult == null) {
            return new CalculationResult(this);
        }

        Segment segment = this.segments.get(0);
        final int numResults = segment.numValues();

        final WQKms[] results = new WQKms[numResults];
        for (int i = 0; i < results.length; ++i) {
            results[i] = new WQKms();
        }

        final Parameters parameters = fitResult.getParameters();

        final int kmIndex = parameters.columnIndex("km");
        final int[] parameterIndices = parameters.columnIndices(func.getParameterNames());

        final double[] parameterValues = new double[parameterIndices.length];

        for (int row = 0, R = parameters.size(); row < R; ++row) {
            final double km = parameters.get(row, kmIndex);

            if (!segment.inside(km)) {
                Segment nextSeg = null;
                for (final Segment seg : this.segments) {
                    if (seg.inside(km)) {
                        nextSeg = seg;
                        break;
                    }
                }
                if (nextSeg == null) {
                    addProblem(km, "fix.cannot.find.segment");
                    continue;
                }
                segment = nextSeg;
            }

            parameters.get(row, parameterIndices, parameterValues);

            final org.dive4elements.river.artifacts.math.Function instance = func.instantiate(parameterValues);

            final double[] values = segment.getValues();
            for (int i = 0; i < numResults; ++i) {
                final double q = values[i];
                final double w = instance.value(q);

                if (Double.isNaN(w)) {
                    addProblem(km, "fix.cannot.calculate.function", q);
                } else {
                    results[i].add(w, q, km);
                }
            }
        }

        // Name the curves.
        for (int i = 0; i < results.length; ++i)
            results[i].setName(createName(i));

        final FixRealizingResult frr = new FixRealizingResult(parameters, fitResult.getResultColumns(), results);

        return new CalculationResult(frr, this);
    }

    // TODO: issue1109/2
    protected String createName(final int index) {
        // TODO: i18n
        final StringBuilder sb = new StringBuilder(this.isQ ? "Q" : "W");
        sb.append(" benutzerdefiniert (");
        for (int i = 0, N = this.segments.size(); i < N; ++i) {
            if (i > 0) {
                sb.append("; ");
            }
            final Segment segment = this.segments.get(i);
            final double[] backup = segment.getBackup();
            final double[] values = segment.getValues();
            sb.append((backup != null ? backup : values)[index]);
        }
        sb.append(')');
        return sb.toString();
    }
}

http://dive4elements.wald.intevation.org