[PATCH] (issue1755) Interpolate BedQuality Results
Wald Commits
scm-commit at wald.intevation.org
Mon Mar 16 15:36:42 CET 2015
# HG changeset patch
# User Andre Heinecke <andre.heinecke at intevation.de>
# Date 1426516598 -3600
# Node ID 073ea4bcea589d70a59280e64fb0bf009a830275
# Parent d9f038b8e2cec5fd33fbe99a40195b42307b28e8
(issue1755) Interpolate BedQuality Results
This adds an interpolation function to each various bedQuality result class.
Imho this is ok as the interpolation function can be seen as part of the result.
The interpolation function is initalized on first use and can be accessed through
get.*Interpol functions.
diff -r d9f038b8e2ce -r 073ea4bcea58 artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterResult.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterResult.java Mon Mar 16 14:37:30 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterResult.java Mon Mar 16 15:36:38 2015 +0100
@@ -8,8 +8,13 @@
package org.dive4elements.river.artifacts.model.minfo;
+import org.dive4elements.river.utils.DoubleUtil;
+
import gnu.trove.TDoubleArrayList;
+import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
+
+import org.apache.commons.math.ArgumentOutsideDomainException;
public class BedDiameterResult
extends BedQualityDiameterResult
@@ -17,6 +22,11 @@
protected TDoubleArrayList diameterCap;
protected TDoubleArrayList diameterSub;
+ protected PolynomialSplineFunction interpolSub;
+ protected PolynomialSplineFunction interpolCap;
+ protected boolean nonInterpolSub;
+ protected boolean nonInterpolCap;
+
public BedDiameterResult (
String type,
TDoubleArrayList diameterCap,
@@ -26,6 +36,10 @@
super(type, km);
this.diameterCap = diameterCap;
this.diameterSub = diameterSub;
+ interpolSub = null;
+ nonInterpolSub = false;
+ interpolCap = null;
+ nonInterpolCap = false;
}
public double getDiameterCap(int ndx) {
@@ -49,6 +63,25 @@
return Double.NaN;
}
+ public double getDiameterCapInterpol(double km) {
+ if (nonInterpolCap) {
+ return Double.NaN;
+ }
+ if (interpolCap == null) {
+ interpolCap = DoubleUtil.getLinearInterpolator(kms, diameterCap);
+ if (interpolCap == null) {
+ nonInterpolCap = true;
+ return Double.NaN;
+ }
+ }
+ try {
+ return interpolCap.value(km);
+ } catch (ArgumentOutsideDomainException e) {
+ /* This is expected for many results. */
+ return Double.NaN;
+ }
+ }
+
public double getDiameterSub(double km) {
if (kms.indexOf(km) >= 0) {
return diameterSub.get(kms.indexOf(km));
@@ -56,6 +89,25 @@
return Double.NaN;
}
+ public double getDiameterSubInterpol(double km) {
+ if (nonInterpolSub) {
+ return Double.NaN;
+ }
+ if (interpolSub == null) {
+ interpolSub = DoubleUtil.getLinearInterpolator(kms, diameterSub);
+ if (interpolSub == null) {
+ nonInterpolSub = true;
+ return Double.NaN;
+ }
+ }
+ try {
+ return interpolSub.value(km);
+ } catch (ArgumentOutsideDomainException e) {
+ /* This is expected for many results. */
+ return Double.NaN;
+ }
+ }
+
public double[][] getDiameterCapData() {
return new double[][] {
kms.toNativeArray(),
diff -r d9f038b8e2ce -r 073ea4bcea58 artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedParametersResult.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedParametersResult.java Mon Mar 16 14:37:30 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedParametersResult.java Mon Mar 16 15:36:38 2015 +0100
@@ -9,6 +9,9 @@
package org.dive4elements.river.artifacts.model.minfo;
import gnu.trove.TDoubleArrayList;
+import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
+import org.dive4elements.river.utils.DoubleUtil;
+import org.apache.commons.math.ArgumentOutsideDomainException;
import java.io.Serializable;
@@ -22,6 +25,16 @@
protected TDoubleArrayList loadDensitySub;
protected TDoubleArrayList kms;
+ protected PolynomialSplineFunction interpolPoroSub;
+ protected PolynomialSplineFunction interpolPoroCap;
+ protected PolynomialSplineFunction interpolDensSub;
+ protected PolynomialSplineFunction interpolDensCap;
+
+ protected boolean nonInterpolPoroSub;
+ protected boolean nonInterpolPoroCap;
+ protected boolean nonInterpolDensSub;
+ protected boolean nonInterpolDensCap;
+
public BedParametersResult() {
}
@@ -38,6 +51,16 @@
this.porositySub = porositySub;
this.loadDensityCap = densityCap;
this.loadDensitySub = densitySub;
+
+ PolynomialSplineFunction interpolPoroSub = null;
+ PolynomialSplineFunction interpolPoroCap = null;
+ PolynomialSplineFunction interpolDensSub = null;
+ PolynomialSplineFunction interpolDensCap = null;
+
+ nonInterpolPoroSub = false;
+ nonInterpolPoroCap = false;
+ nonInterpolDensSub = false;
+ nonInterpolDensCap = false;
}
public double getPorosityCap(int ndx) {
@@ -111,4 +134,81 @@
loadDensitySub.toNativeArray()
};
}
+
+ public double getPorositySubInterpol(double km) {
+ if (nonInterpolPoroSub) {
+ return Double.NaN;
+ }
+ if (interpolPoroSub == null) {
+ interpolPoroSub = DoubleUtil.getLinearInterpolator(kms, porositySub);
+ if (interpolPoroSub == null) {
+ nonInterpolPoroSub = true;
+ return Double.NaN;
+ }
+ }
+ try {
+ return interpolPoroSub.value(km);
+ } catch (ArgumentOutsideDomainException e) {
+ /* This is expected for many results. */
+ return Double.NaN;
+ }
+ }
+
+ public double getPorosityCapInterpol(double km) {
+ if (nonInterpolPoroCap) {
+ return Double.NaN;
+ }
+ if (interpolPoroCap == null) {
+ interpolPoroCap = DoubleUtil.getLinearInterpolator(kms, porosityCap);
+ if (interpolPoroCap == null) {
+ nonInterpolPoroCap = true;
+ return Double.NaN;
+ }
+ }
+ try {
+ return interpolPoroCap.value(km);
+ } catch (ArgumentOutsideDomainException e) {
+ /* This is expected for many results. */
+ return Double.NaN;
+ }
+ }
+
+ public double getDensitySubInterpol(double km) {
+ if (nonInterpolDensSub) {
+ return Double.NaN;
+ }
+ if (interpolDensSub == null) {
+ interpolDensSub = DoubleUtil.getLinearInterpolator(kms, loadDensitySub);
+ if (interpolDensSub == null) {
+ nonInterpolDensSub = true;
+ return Double.NaN;
+ }
+ }
+ try {
+ return interpolDensSub.value(km);
+ } catch (ArgumentOutsideDomainException e) {
+ /* This is expected for many results. */
+ return Double.NaN;
+ }
+ }
+
+ public double getDensityCapInterpol(double km) {
+ if (nonInterpolDensCap) {
+ return Double.NaN;
+ }
+ if (interpolDensCap == null) {
+ interpolDensCap = DoubleUtil.getLinearInterpolator(kms, loadDensityCap);
+ if (interpolDensCap == null) {
+ nonInterpolDensCap = true;
+ return Double.NaN;
+ }
+ }
+ try {
+ return interpolDensCap.value(km);
+ } catch (ArgumentOutsideDomainException e) {
+ /* This is expected for many results. */
+ return Double.NaN;
+ }
+ }
+
}
diff -r d9f038b8e2ce -r 073ea4bcea58 artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterResult.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterResult.java Mon Mar 16 14:37:30 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterResult.java Mon Mar 16 15:36:38 2015 +0100
@@ -9,13 +9,22 @@
package org.dive4elements.river.artifacts.model.minfo;
import org.dive4elements.river.artifacts.model.DateRange;
+import org.dive4elements.river.utils.DoubleUtil;
+
import gnu.trove.TDoubleArrayList;
+import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
+
+import org.apache.commons.math.ArgumentOutsideDomainException;
public class BedloadDiameterResult
extends BedQualityDiameterResult
{
protected TDoubleArrayList diameter;
+ protected PolynomialSplineFunction interpol;
+
+ /** Set to true if this result can't be interpolated.*/
+ protected boolean nonInterpolResult;
public BedloadDiameterResult(
String type,
@@ -25,6 +34,8 @@
) {
super (type, km);
this.diameter = diameter;
+ interpol = null;
+ nonInterpolResult = false;
}
public double getDiameter(int ndx) {
@@ -41,6 +52,25 @@
return Double.NaN;
}
+ public double getDiameterInterpol(double km) {
+ if (nonInterpolResult) {
+ return Double.NaN;
+ }
+ if (interpol == null) {
+ interpol = DoubleUtil.getLinearInterpolator(kms, diameter);
+ if (interpol == null) {
+ nonInterpolResult = true;
+ return Double.NaN;
+ }
+ }
+ try {
+ return interpol.value(km);
+ } catch (ArgumentOutsideDomainException e) {
+ /* This is expected for many results. */
+ return Double.NaN;
+ }
+ }
+
public double[][] getDiameterData() {
return new double[][] {
kms.toNativeArray(),
diff -r d9f038b8e2ce -r 073ea4bcea58 artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityExporter.java
--- a/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityExporter.java Mon Mar 16 14:37:30 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityExporter.java Mon Mar 16 15:36:38 2015 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+/* Copyright (C) 2011, 2012, 2013, 2015 by Bundesanstalt für Gewässerkunde
* Software engineering by Intevation GmbH
*
* This file is Free Software under the GNU AGPL (>=v3)
@@ -29,6 +29,9 @@
import org.dive4elements.river.exports.AbstractExporter;
import org.dive4elements.river.utils.Formatter;
+import org.dive4elements.river.artifacts.access.RangeAccess;
+import org.dive4elements.river.artifacts.D4EArtifact;
+
public class BedQualityExporter
extends AbstractExporter
@@ -59,43 +62,16 @@
results = new BedQualityResult[0];
}
- /** Populate param kms with kms from param beds and loads, return it. */
- private TDoubleArrayList populateKmList(BedDiameterResult[] beds,
- BedloadDiameterResult[] loads,
- TDoubleArrayList kms) {
- for (int j = 0; j < beds.length; j++) {
- TDoubleArrayList bkms = beds[j].getKms();
- for (int k = 0, K = bkms.size(); k < K; k++) {
- double km = bkms.get(k);
- if (!kms.contains(km)) { // XXX: O(N^2)
- kms.add(km);
- }
- }
- }
- for (int j = 0; j < loads.length; j++) {
- TDoubleArrayList lkms = loads[j].getKms();
- for (int k = 0, L = lkms.size(); k < L; k++) {
- double km = lkms.get(k);
- if (!kms.contains(km)) { // XXX: O(N^2)
- kms.add(km);
- }
- }
- }
- return kms;
- }
-
/** Create double[] containing the data for rows in csv. */
private List<double[]> createDataRows() {
- // Calculate how many columns and rows we need.
- TDoubleArrayList kms = new TDoubleArrayList();
+
+ double[] kms = new RangeAccess((D4EArtifact) master).getKmSteps();
int cols = 1;
for (BedQualityResult result : results) {
BedDiameterResult[] beds = result.getBedResults();
BedloadDiameterResult[] loads = result.getBedloadResults();
- kms = populateKmList(beds, loads, kms);
-
cols += beds.length * 2;
if (beds.length > 0) {
cols += 4;
@@ -103,22 +79,21 @@
cols += loads.length;
}
- kms.sort();
-
- List<double[]> rows = new ArrayList<double[]>(kms.size());
- for (int i = 0, K = kms.size(); i < K; i++) {
+ List<double[]> rows = new ArrayList<double[]>(kms.length);
+ for (double km: kms) {
double[] row = new double[cols];
- double km = kms.get(i);
row[0] = km;
for (int j = 0; j < results.length; j++) {
+
BedloadDiameterResult[] loads = results[j].getBedloadResults();
for(int k = 0; k < loads.length; k++) {
// k + 1: shift km column.
// j* loads.length: shift periods.
row[(k + 1) + (j * loads.length)] =
- loads[k].getDiameter(km);
+ loads[k].getDiameterInterpol(km);
}
+
BedDiameterResult[] beds = results[j].getBedResults();
if (beds.length == 0) {
continue;
@@ -128,17 +103,18 @@
// j * beds.length * 2: shift periods.
// loads.length * results.length: shift bed load columns.
int ndx = (k * 2 + 1) + (j * beds.length * 2) + (loads.length * results.length);
- row[ndx] = beds[k].getDiameterCap(km);
- row[ndx + 1] = beds[k].getDiameterSub(km);
+ row[ndx] = beds[k].getDiameterCapInterpol(km);
+ row[ndx + 1] = beds[k].getDiameterSubInterpol(km);
}
+
BedParametersResult[] params = results[j].getParameters();
for(int k = 0; k < params.length; k++) {
// loads.length + (beds.lenght * 2) * (j + 1): shift bed and bedload columns.
int ndx = 1 + (loads.length + (beds.length * 2) * (j + 1));
- row[ndx] = params[k].getLoadDensityCap(km);
- row[ndx + 1] = params[k].getLoadDensitySub(km);
- row[ndx + 2] = params[k].getPorosityCap(km);
- row[ndx + 3] = params[k].getPorositySub(km);
+ row[ndx] = params[k].getDensityCapInterpol(km);
+ row[ndx + 1] = params[k].getDensitySubInterpol(km);
+ row[ndx + 2] = params[k].getPorosityCapInterpol(km);
+ row[ndx + 3] = params[k].getPorositySubInterpol(km);
}
}
rows.add(row);
@@ -149,7 +125,6 @@
@Override
protected void writeCSVData(CSVWriter writer) throws IOException {
- // TODO Auto-generated method stub
writeCSVHeader(writer);
NumberFormat nf = Formatter.getFormatter(context, 1, 3);
@@ -177,7 +152,6 @@
@Override
protected void addData(Object data) {
- // TODO Auto-generated method stub
log.debug("addData()");
if (!(data instanceof CalculationResult)) {
log.warn("Invalid data type.");
diff -r d9f038b8e2ce -r 073ea4bcea58 artifacts/src/main/java/org/dive4elements/river/utils/DoubleUtil.java
--- a/artifacts/src/main/java/org/dive4elements/river/utils/DoubleUtil.java Mon Mar 16 14:37:30 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/utils/DoubleUtil.java Mon Mar 16 15:36:38 2015 +0100
@@ -10,6 +10,13 @@
import org.dive4elements.river.artifacts.math.Linear;
+import org.apache.commons.math.analysis.interpolation.LinearInterpolator;
+import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
+
+import org.apache.commons.math.exception.DimensionMismatchException;
+import org.apache.commons.math.exception.NumberIsTooSmallException;
+import org.apache.commons.math.exception.NonMonotonousSequenceException;
+
import gnu.trove.TDoubleArrayList;
import java.util.Arrays;
@@ -305,5 +312,23 @@
}
}
}
+
+ /** Convieniance function for results to get an interpolator.
+ * This is basically a static wrapper to for LinearInterpolator.interpolate
+ * with error handling. Returns null on error.*/
+ public static PolynomialSplineFunction getLinearInterpolator(TDoubleArrayList x, TDoubleArrayList y) {
+ LinearInterpolator lpol = new LinearInterpolator();
+ try {
+ return lpol.interpolate(x.toNativeArray(), y.toNativeArray());
+ } catch (DimensionMismatchException e) {
+ log.error("KMs and Result values have different sizes. Failed to interpolate: " +
+ e.getMessage());
+ } catch (NonMonotonousSequenceException e) {
+ log.error("KMs are not monotonous. Failed to interpolate: " + e.getMessage());
+ } catch (NumberIsTooSmallException e) {
+ log.error("Result is to small. Failed to interpolate: " + e.getMessage());
+ }
+ return null;
+ }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
More information about the Dive4Elements-commits
mailing list