Mercurial > dive4elements > river
view artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixCalculation.java @ 9479:2b83d3a96703
i18n TODO "benutzerdefiniert" = "custom" fixed
author | gernotbelger |
---|---|
date | Mon, 10 Sep 2018 15:31:55 +0200 |
parents | 9744ce3c3853 |
children |
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.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.dive4elements.artifacts.CallMeta; import org.dive4elements.artifacts.common.utils.StringUtils; import org.dive4elements.river.artifacts.access.FixAccess; import org.dive4elements.river.artifacts.math.fitting.Function; import org.dive4elements.river.artifacts.math.fitting.FunctionFactory; import org.dive4elements.river.artifacts.model.Calculation; import org.dive4elements.river.artifacts.model.CalculationResult; import org.dive4elements.river.artifacts.model.Parameters; import org.dive4elements.river.artifacts.model.fixings.FixingsOverview.IdsFilter; import org.dive4elements.river.utils.DoubleUtil; /** Calculation base class for fix. */ public abstract class FixCalculation extends Calculation { private static final long serialVersionUID = 1L; private static Logger log = Logger.getLogger(FixCalculation.class); private static final String[] STANDARD_COLUMNS = { "km", "chi_sqr", "max_q", "std-dev" }; protected static class FitResult { private final Parameters parameters; private final FixResultColumns resultColumns; public FitResult(final Parameters parameters, final FixResultColumns resultColumns) { this.parameters = parameters; this.resultColumns = resultColumns; } public Parameters getParameters() { return this.parameters; } public FixResultColumns getResultColumns() { return this.resultColumns; } } protected String river; protected double from; protected double to; protected double step; protected boolean preprocessing; protected String function; protected int[] events; protected int qSectorStart; protected int qSectorEnd; public FixCalculation() { } public FixCalculation(final FixAccess access) { final String river = access.getRiverName(); final Double from = access.getLowerKm(); final Double to = access.getUpperKm(); final Double step = access.getStep(); final String function = access.getFunction(); final int[] events = access.getEvents(); final Integer qSectorStart = access.getQSectorStart(); final Integer qSectorEnd = access.getQSectorEnd(); final Boolean preprocessing = access.getPreprocessing(); if (river == null) { addProblem("fix.missing.river"); } if (from == null) { addProblem("fix.missing.from"); } if (to == null) { addProblem("fix.missing.to"); } if (step == null) { addProblem("fix.missing.step"); } if (function == null) { addProblem("fix.missing.function"); } if (events == null || events.length < 1) { addProblem("fix.missing.events"); } if (qSectorStart == null) { addProblem("fix.missing.qstart.sector"); } if (qSectorEnd == null) { addProblem("fix.missing.qend.sector"); } if (preprocessing == null) { addProblem("fix.missing.preprocessing"); } if (!hasProblems()) { this.river = river; this.from = from; this.to = to; this.step = step; this.function = function; this.events = events; this.qSectorStart = qSectorStart; this.qSectorEnd = qSectorEnd; this.preprocessing = preprocessing; } } protected static String toString(final String[] parameterNames, final double[] values) { final StringBuilder sb = new StringBuilder(); for (int i = 0; i < parameterNames.length; ++i) { if (i > 0) sb.append(", "); sb.append(parameterNames[i]).append(": ").append(values[i]); } return sb.toString(); } /** * Create filter to accept only the chosen events. * This factored out out to be overwritten. */ protected FixingColumnFilter createFilter() { return new IdsFilter(this.events); } protected List<FixingColumnWithData> getEventColumns(final FixingsOverview overview, final ColumnCache cc) { final FixingColumnFilter filter = createFilter(); final List<FixingColumn> metas = overview.filter(null, filter); final List<FixingColumnWithData> columns = new ArrayList<>(metas.size()); for (final FixingColumn meta : metas) { final FixingColumnWithData data = cc.getColumn(meta); if (data == null) { addProblem("fix.cannot.load.data"); } else { columns.add(data); } } return columns; } // Fit a function to the given points from fixation. protected final FitResult doFitting(final FixingsOverview overview, final ColumnCache cc, final Function func) { final boolean debug = log.isDebugEnabled(); final FixResultColumns resultColumns = new FixResultColumns(); final List<FixingColumnWithData> eventColumns = getEventColumns(overview, cc); if (eventColumns.size() < 2) { addProblem("fix.too.less.data.columns"); return null; } final String[] parameterNames = func.getParameterNames(); final Parameters results = new Parameters(StringUtils.join(STANDARD_COLUMNS, parameterNames)); boolean invalid = false; final double[] kms = DoubleUtil.explode(this.from, this.to, this.step / 1000.0); if (debug) { log.debug("number of kms: " + kms.length); } final int kmIndex = results.columnIndex("km"); final int chiSqrIndex = results.columnIndex("chi_sqr"); final int maxQIndex = results.columnIndex("max_q"); final int stdDevIndex = results.columnIndex("std-dev"); final int[] parameterIndices = results.columnIndices(parameterNames); int numFailed = 0; for (final double km : kms) { final Fitting fitting = Fitting.fit(resultColumns, km, func, this.preprocessing, eventColumns); if (fitting == null) { log.debug("Fitting for km: " + km + " failed"); ++numFailed; addProblem(km, "fix.fitting.failed"); continue; } final int row = results.newRow(); final double[] values = fitting.getParameters(); results.set(row, kmIndex, km); results.set(row, chiSqrIndex, fitting.getChiSquare()); results.set(row, stdDevIndex, fitting.getStandardDeviation()); results.set(row, maxQIndex, fitting.getMaxQ()); invalid |= results.set(row, parameterIndices, values); if (debug) { log.debug("km: " + km + " " + toString(parameterNames, values)); } } if (debug) { log.debug("success: " + (kms.length - numFailed)); log.debug("failed: " + numFailed); } if (invalid) { addProblem("fix.invalid.values"); results.removeNaNs(); } resultColumns.sortAll(); return new FitResult(results, resultColumns); } public CalculationResult calculate(final CallMeta meta) { final FixingsOverview overview = FixingsOverviewFactory.getOverview(this.river); if (overview == null) { addProblem("fix.no.overview.available"); } final Function func = FunctionFactory.getInstance().getFunction(this.function); if (func == null) { addProblem("fix.invalid.function.name"); } if (hasProblems()) return new CalculationResult(this); return innerCalculate(overview, func, meta); } protected abstract CalculationResult innerCalculate(FixingsOverview overview, Function function, CallMeta meta); }