[PATCH 2 of 2] Improved flood duration curve calculation as specified by BfG
Wald Commits
scm-commit at wald.intevation.org
Tue Jul 24 07:32:24 CEST 2018
# HG changeset patch
# User mschaefer
# Date 1532366406 -7200
# Node ID bcbae86ce7b3d36ae5684210bf7337b9f8e4d1db
# Parent 9b16f58c62a78a496d4d346fc3522d7d0535aaf6
Improved flood duration curve calculation as specified by BfG
diff -r 9b16f58c62a7 -r bcbae86ce7b3 artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTable.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTable.java Mon Jul 23 19:18:11 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTable.java Mon Jul 23 19:20:06 2018 +0200
@@ -8,31 +8,25 @@
package org.dive4elements.river.artifacts.model;
+import static org.dive4elements.river.backend.utils.EpsilonComparator.CMP;
+
import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.math.ArgumentOutsideDomainException;
+import org.apache.commons.math.analysis.interpolation.SplineInterpolator;
+import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
+import org.apache.commons.math.exception.MathIllegalArgumentException;
+import org.apache.log4j.Logger;
+import org.dive4elements.river.artifacts.math.Function;
import org.dive4elements.river.artifacts.math.Linear;
-import org.dive4elements.river.artifacts.math.Function;
import org.dive4elements.river.utils.DoubleUtil;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Collections;
-
-import org.apache.log4j.Logger;
-
-import org.apache.commons.math.analysis.interpolation.SplineInterpolator;
-
-import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
-
-import org.apache.commons.math.ArgumentOutsideDomainException;
-
-import org.apache.commons.math.exception.MathIllegalArgumentException;
-
import gnu.trove.TDoubleArrayList;
-import static org.dive4elements.river.backend.utils.EpsilonComparator.CMP;
-
/**
* W, Q and km data from database 'wsts' spiced with interpolation algorithms.
*/
@@ -60,23 +54,23 @@
public Column() {
}
- public Column(String name) {
+ public Column(final String name) {
this.name = name;
}
public String getName() {
- return name;
+ return this.name;
}
- public void setName(String name) {
+ public void setName(final String name) {
this.name = name;
}
public QRangeTree getQRangeTree() {
- return qRangeTree;
+ return this.qRangeTree;
}
- public void setQRangeTree(QRangeTree qRangeTree) {
+ public void setQRangeTree(final QRangeTree qRangeTree) {
this.qRangeTree = qRangeTree;
}
} // class Column
@@ -92,12 +86,12 @@
public QPosition() {
}
- public QPosition(int index, double weight) {
+ public QPosition(final int index, final double weight) {
this.index = index;
this.weight = weight;
}
- public QPosition set(int index, double weight) {
+ public QPosition set(final int index, final double weight) {
this.index = index;
this.weight = weight;
return this;
@@ -112,38 +106,38 @@
public double [] splineWs;
public SplineFunction(
- PolynomialSplineFunction spline,
- double [] splineQs,
- double [] splineWs
- ) {
+ final PolynomialSplineFunction spline,
+ final double [] splineQs,
+ final double [] splineWs
+ ) {
this.spline = spline;
this.splineQs = splineQs;
this.splineWs = splineWs;
}
public double [][] sample(
- int numSamples,
- double km,
- Calculation errors
- ) {
- double minQ = getQMin();
- double maxQ = getQMax();
+ final int numSamples,
+ final double km,
+ final Calculation errors
+ ) {
+ final double minQ = getQMin();
+ final double maxQ = getQMax();
- double [] outWs = new double[numSamples];
- double [] outQs = new double[numSamples];
+ final double [] outWs = new double[numSamples];
+ final double [] outQs = new double[numSamples];
Arrays.fill(outWs, Double.NaN);
Arrays.fill(outQs, Double.NaN);
- double stepWidth = (maxQ - minQ)/numSamples;
+ final double stepWidth = (maxQ - minQ)/numSamples;
try {
double q = minQ;
for (int i = 0; i < outWs.length; ++i, q += stepWidth) {
- outWs[i] = spline.value(outQs[i] = q);
+ outWs[i] = this.spline.value(outQs[i] = q);
}
}
- catch (ArgumentOutsideDomainException aode) {
+ catch (final ArgumentOutsideDomainException aode) {
if (errors != null) {
errors.addProblem(km, "spline.interpolation.failed");
}
@@ -154,26 +148,26 @@
}
public double getQMin() {
- return Math.min(splineQs[0], splineQs[splineQs.length-1]);
+ return Math.min(this.splineQs[0], this.splineQs[this.splineQs.length-1]);
}
public double getQMax() {
- return Math.max(splineQs[0], splineQs[splineQs.length-1]);
+ return Math.max(this.splineQs[0], this.splineQs[this.splineQs.length-1]);
}
/** Constructs a continues index between the columns to Qs. */
public PolynomialSplineFunction createIndexQRelation() {
- double [] indices = new double[splineQs.length];
+ final double [] indices = new double[this.splineQs.length];
for (int i = 0; i < indices.length; ++i) {
indices[i] = i;
}
try {
- SplineInterpolator interpolator = new SplineInterpolator();
- return interpolator.interpolate(indices, splineQs);
+ final SplineInterpolator interpolator = new SplineInterpolator();
+ return interpolator.interpolate(indices, this.splineQs);
}
- catch (MathIllegalArgumentException miae) {
+ catch (final MathIllegalArgumentException miae) {
// Ignore me!
}
return null;
@@ -192,11 +186,11 @@
public Row() {
}
- public Row(double km) {
+ public Row(final double km) {
this.km = km;
}
- public Row(double km, double [] ws) {
+ public Row(final double km, final double [] ws) {
this(km);
this.ws = ws;
}
@@ -205,26 +199,26 @@
* Sort Qs and Ws for this Row over Q.
*/
private double[][] getSortedWQ(
- WstValueTable table,
- Calculation errors
- ) {
- int W = ws.length;
+ final WstValueTable table,
+ final Calculation errors
+ ) {
+ final int W = this.ws.length;
if (W < 1) {
if (errors != null) {
- errors.addProblem(km, "no.ws.found");
+ errors.addProblem(this.km, "no.ws.found");
}
return new double[][] {{Double.NaN}, {Double.NaN}};
}
- double [] sortedWs = ws;
- double [] sortedQs = new double[W];
+ final double [] sortedWs = this.ws;
+ final double [] sortedQs = new double[W];
for (int i=0; i < W; ++i) {
- double q = table.getQIndex(i, km);
+ final double q = table.getQIndex(i, this.km);
if (Double.isNaN(q) && errors != null) {
errors.addProblem(
- km, "no.q.found.in.column", i+1);
+ this.km, "no.q.found.in.column", i+1);
}
sortedQs[i] = q;
}
@@ -239,12 +233,12 @@
* this Row and another, sorted over Q.
*/
private double[][] getSortedWQ(
- Row other,
- double km,
- WstValueTable table,
- Calculation errors
- ) {
- int W = Math.min(ws.length, other.ws.length);
+ final Row other,
+ final double km,
+ final WstValueTable table,
+ final Calculation errors
+ ) {
+ final int W = Math.min(this.ws.length, other.ws.length);
if (W < 1) {
if (errors != null) {
@@ -253,14 +247,14 @@
return new double[][] {{Double.NaN}, {Double.NaN}};
}
- double factor = Linear.factor(km, this.km, other.km);
+ final double factor = Linear.factor(km, this.km, other.km);
- double [] sortedQs = new double[W];
- double [] sortedWs = new double[W];
+ final double [] sortedQs = new double[W];
+ final double [] sortedWs = new double[W];
for (int i = 0; i < W; ++i) {
- double wws = Linear.weight(factor, ws[i], other.ws[i]);
- double wqs = table.getQIndex(i, km);
+ final double wws = Linear.weight(factor, this.ws[i], other.ws[i]);
+ final double wqs = table.getQIndex(i, km);
if (Double.isNaN(wws) || Double.isNaN(wqs)) {
if (errors != null) {
@@ -280,34 +274,34 @@
/**
* Find Qs matching w in an array of Qs and Ws sorted over Q.
*/
- private double[] findQsForW(double w, double[][] sortedWQ) {
- int W = sortedWQ[0].length;
+ private double[] findQsForW(final double w, final double[][] sortedWQ) {
+ final int W = sortedWQ[0].length;
- double[] sortedQs = sortedWQ[1];
- double[] sortedWs = sortedWQ[0];
+ final double[] sortedQs = sortedWQ[1];
+ final double[] sortedWs = sortedWQ[0];
- TDoubleArrayList qs = new TDoubleArrayList();
+ final TDoubleArrayList qs = new TDoubleArrayList();
if (W > 0 && Math.abs(sortedWs[0]-w) < W_EPSILON) {
- double q = sortedQs[0];
+ final double q = sortedQs[0];
if (!Double.isNaN(q)) {
qs.add(q);
}
}
for (int i = 1; i < W; ++i) {
- double w2 = sortedWs[i];
+ final double w2 = sortedWs[i];
if (Double.isNaN(w2)) {
continue;
}
if (Math.abs(w2-w) < W_EPSILON) {
- double q = sortedQs[i];
+ final double q = sortedQs[i];
if (!Double.isNaN(q)) {
qs.add(q);
}
continue;
}
- double w1 = sortedWs[i-1];
+ final double w1 = sortedWs[i-1];
if (Double.isNaN(w1)) {
continue;
}
@@ -316,13 +310,13 @@
continue;
}
- double q1 = sortedQs[i-1];
- double q2 = sortedQs[i];
+ final double q1 = sortedQs[i-1];
+ final double q2 = sortedQs[i];
if (Double.isNaN(q1) || Double.isNaN(q2)) {
continue;
}
- double q = Linear.linear(w, w1, w2, q1, q2);
+ final double q = Linear.linear(w, w1, w2, q1, q2);
qs.add(q);
}
@@ -332,8 +326,9 @@
/**
* Compare according to place of measurement (km).
*/
- public int compareTo(Row other) {
- return CMP.compare(km, other.km);
+ @Override
+ public int compareTo(final Row other) {
+ return CMP.compare(this.km, other.km);
}
/**
@@ -344,25 +339,25 @@
* @param table Table of which to use data for interpolation.
*/
public void interpolateW(
- Row other,
- double km,
- double [] iqs,
- double [] ows,
- WstValueTable table,
- Calculation errors
- ) {
- double kmWeight = Linear.factor(km, this.km, other.km);
+ final Row other,
+ final double km,
+ final double [] iqs,
+ final double [] ows,
+ final WstValueTable table,
+ final Calculation errors
+ ) {
+ final double kmWeight = Linear.factor(km, this.km, other.km);
- QPosition qPosition = new QPosition();
+ final QPosition qPosition = new QPosition();
for (int i = 0; i < iqs.length; ++i) {
if (table.getQPosition(km, iqs[i], qPosition) != null) {
- double wt = getW(qPosition);
- double wo = other.getW(qPosition);
+ final double wt = getW(qPosition);
+ final double wo = other.getW(qPosition);
if (Double.isNaN(wt) || Double.isNaN(wo)) {
if (errors != null) {
errors.addProblem(
- km, "cannot.find.w.for.q", iqs[i]);
+ km, "cannot.find.w.for.q", iqs[i]);
}
ows[i] = Double.NaN;
}
@@ -381,21 +376,21 @@
public SplineFunction createSpline(
- WstValueTable table,
- Calculation errors
- ) {
- double[][] sortedWQ = getSortedWQ(table, errors);
+ final WstValueTable table,
+ final Calculation errors
+ ) {
+ final double[][] sortedWQ = getSortedWQ(table, errors);
try {
- SplineInterpolator interpolator = new SplineInterpolator();
- PolynomialSplineFunction spline =
- interpolator.interpolate(sortedWQ[1], sortedWQ[0]);
+ final SplineInterpolator interpolator = new SplineInterpolator();
+ final PolynomialSplineFunction spline =
+ interpolator.interpolate(sortedWQ[1], sortedWQ[0]);
- return new SplineFunction(spline, sortedWQ[1], ws);
+ return new SplineFunction(spline, sortedWQ[1], this.ws);
}
- catch (MathIllegalArgumentException miae) {
+ catch (final MathIllegalArgumentException miae) {
if (errors != null) {
- errors.addProblem(km, "spline.creation.failed");
+ errors.addProblem(this.km, "spline.creation.failed");
}
log.error("spline creation failed", miae);
}
@@ -403,22 +398,22 @@
}
public SplineFunction createSpline(
- Row other,
- double km,
- WstValueTable table,
- Calculation errors
- ) {
- double[][] sortedWQ = getSortedWQ(other, km, table, errors);
+ final Row other,
+ final double km,
+ final WstValueTable table,
+ final Calculation errors
+ ) {
+ final double[][] sortedWQ = getSortedWQ(other, km, table, errors);
- SplineInterpolator interpolator = new SplineInterpolator();
+ final SplineInterpolator interpolator = new SplineInterpolator();
try {
- PolynomialSplineFunction spline =
- interpolator.interpolate(sortedWQ[1], sortedWQ[0]);
+ final PolynomialSplineFunction spline =
+ interpolator.interpolate(sortedWQ[1], sortedWQ[0]);
return new SplineFunction(spline, sortedWQ[1], sortedWQ[0]);
}
- catch (MathIllegalArgumentException miae) {
+ catch (final MathIllegalArgumentException miae) {
if (errors != null) {
errors.addProblem(km, "spline.creation.failed");
}
@@ -429,60 +424,60 @@
}
public double [][] interpolateWQ(
- Row other,
- double km,
- int steps,
- WstValueTable table,
- Calculation errors
- ) {
- SplineFunction sf = createSpline(other, km, table, errors);
+ final Row other,
+ final double km,
+ final int steps,
+ final WstValueTable table,
+ final Calculation errors
+ ) {
+ final SplineFunction sf = createSpline(other, km, table, errors);
return sf != null
- ? sf.sample(steps, km, errors)
- : new double[2][0];
+ ? sf.sample(steps, km, errors)
+ : new double[2][0];
}
public double [][] interpolateWQ(
- int steps,
- WstValueTable table,
- Calculation errors
- ) {
- SplineFunction sf = createSpline(table, errors);
+ final int steps,
+ final WstValueTable table,
+ final Calculation errors
+ ) {
+ final SplineFunction sf = createSpline(table, errors);
return sf != null
- ? sf.sample(steps, km, errors)
- : new double[2][0];
+ ? sf.sample(steps, this.km, errors)
+ : new double[2][0];
}
- public double getW(QPosition qPosition) {
- int index = qPosition.index;
- double weight = qPosition.weight;
+ public double getW(final QPosition qPosition) {
+ final int index = qPosition.index;
+ final double weight = qPosition.weight;
return weight == 1.0
- ? ws[index]
- : Linear.weight(weight, ws[index-1], ws[index]);
+ ? this.ws[index]
+ : Linear.weight(weight, this.ws[index-1], this.ws[index]);
}
public double getW(
- Row other,
- double km,
- QPosition qPosition
- ) {
- double kmWeight = Linear.factor(km, this.km, other.km);
+ final Row other,
+ final double km,
+ final QPosition qPosition
+ ) {
+ final double kmWeight = Linear.factor(km, this.km, other.km);
- int index = qPosition.index;
- double weight = qPosition.weight;
+ final int index = qPosition.index;
+ final double weight = qPosition.weight;
double tw, ow;
if (weight == 1.0) {
- tw = ws[index];
+ tw = this.ws[index];
ow = other.ws[index];
}
else {
- tw = Linear.weight(weight, ws[index-1], ws[index]);
+ tw = Linear.weight(weight, this.ws[index-1], this.ws[index]);
ow = Linear.weight(weight, other.ws[index-1], other.ws[index]);
}
@@ -490,30 +485,30 @@
}
public double [] findQsForW(
- double w,
- WstValueTable table,
- Calculation errors
- ) {
- log.debug("Find Qs for given W at tabulated km " + km);
+ final double w,
+ final WstValueTable table,
+ final Calculation errors
+ ) {
+ log.debug("Find Qs for given W at tabulated km " + this.km);
return findQsForW(w, getSortedWQ(table, errors));
}
public double [] findQsForW(
- Row other,
- double w,
- double km,
- WstValueTable table,
- Calculation errors
- ) {
+ final Row other,
+ final double w,
+ final double km,
+ final WstValueTable table,
+ final Calculation errors
+ ) {
log.debug("Find Qs for given W at non-tabulated km " + km);
return findQsForW(w, getSortedWQ(other, km, table, errors));
}
- public double [] getMinMaxW(double [] result) {
+ public double [] getMinMaxW(final double [] result) {
double minW = Double.MAX_VALUE;
double maxW = -Double.MAX_VALUE;
- for (int i = 0; i < ws.length; ++i) {
- double w = ws[i];
+ for (int i = 0; i < this.ws.length; ++i) {
+ final double w = this.ws[i];
if (w < minW) minW = w;
if (w > maxW) maxW = w;
}
@@ -522,10 +517,10 @@
return result;
}
- public double [] getMinMaxW(Row other, double km, double [] result) {
- double [] m1 = this .getMinMaxW(new double [2]);
- double [] m2 = other.getMinMaxW(new double [2]);
- double factor = Linear.factor(km, this.km, other.km);
+ public double [] getMinMaxW(final Row other, final double km, final double [] result) {
+ final double [] m1 = this .getMinMaxW(new double [2]);
+ final double [] m2 = other.getMinMaxW(new double [2]);
+ final double factor = Linear.factor(km, this.km, other.km);
result[0] = Linear.weight(factor, m1[0], m2[0]);
result[1] = Linear.weight(factor, m1[1], m2[1]);
return result;
@@ -539,10 +534,10 @@
protected Column [] columns;
public WstValueTable() {
- rows = new ArrayList<Row>();
+ this.rows = new ArrayList<>();
}
- public WstValueTable(Column [] columns) {
+ public WstValueTable(final Column [] columns) {
this();
this.columns = columns;
}
@@ -551,13 +546,13 @@
* @param columns The WST-columns.
* @param rows A list of Rows that must be sorted by km.
*/
- public WstValueTable(Column [] columns, List<Row> rows) {
+ public WstValueTable(final Column [] columns, final List<Row> rows) {
this.columns = columns;
this.rows = rows;
}
public Column [] getColumns() {
- return columns;
+ return this.columns;
}
/**
@@ -565,7 +560,7 @@
* @param qs Given Q values.
* @param ws output parameter.
*/
- public double [] interpolateW(double km, double [] qs, double [] ws) {
+ public double [] interpolateW(final double km, final double [] qs, final double [] ws) {
return interpolateW(km, qs, ws, null);
}
@@ -575,17 +570,17 @@
* @return output parameter ws.
*/
public double [] interpolateW(
- double km,
- double [] qs,
- double [] ws,
- Calculation errors
- ) {
- int rowIndex = Collections.binarySearch(rows, new Row(km));
+ final double km,
+ final double [] qs,
+ final double [] ws,
+ final Calculation errors
+ ) {
+ int rowIndex = Collections.binarySearch(this.rows, new Row(km));
- QPosition qPosition = new QPosition();
+ final QPosition qPosition = new QPosition();
if (rowIndex >= 0) { // direct row match
- Row row = rows.get(rowIndex);
+ final Row row = this.rows.get(rowIndex);
for (int i = 0; i < qs.length; ++i) {
if (getQPosition(km, qs[i], qPosition) == null) {
if (errors != null) {
@@ -595,9 +590,9 @@
}
else {
if (Double.isNaN(ws[i] = row.getW(qPosition))
- && errors != null) {
+ && errors != null) {
errors.addProblem(
- km, "cannot.find.w.for.q", qs[i]);
+ km, "cannot.find.w.for.q", qs[i]);
}
}
}
@@ -605,7 +600,7 @@
else { // needs bilinear interpolation
rowIndex = -rowIndex -1;
- if (rowIndex < 1 || rowIndex >= rows.size()) {
+ if (rowIndex < 1 || rowIndex >= this.rows.size()) {
// do not extrapolate
Arrays.fill(ws, Double.NaN);
if (errors != null) {
@@ -613,8 +608,8 @@
}
}
else {
- Row r1 = rows.get(rowIndex-1);
- Row r2 = rows.get(rowIndex);
+ final Row r1 = this.rows.get(rowIndex-1);
+ final Row r2 = this.rows.get(rowIndex);
r1.interpolateW(r2, km, qs, ws, this, errors);
}
}
@@ -622,16 +617,46 @@
return ws;
}
- public double [] getMinMaxQ(double km) {
+ /**
+ * Interpolates a W for a km using a Q column position
+ */
+ public double interpolateW(final double km, final QPosition qPosition, final Calculation errors) {
+
+ int rowIndex = Collections.binarySearch(this.rows, new Row(km));
+
+ if (rowIndex >= 0) { // direct row match
+ final Row row = this.rows.get(rowIndex);
+ return row.getW(qPosition);
+ }
+ else { // needs bilinear interpolation
+ rowIndex = -rowIndex - 1;
+ if ((rowIndex <= 0) || (rowIndex >= this.rows.size()))
+ return Double.NaN;
+ else {
+ final Row r1 = this.rows.get(rowIndex - 1);
+ final Row r2 = this.rows.get(rowIndex);
+ final double w1 = r1.getW(qPosition);
+ final double w2 = r2.getW(qPosition);
+ if (Double.isNaN(w1) || Double.isNaN(w2))
+ return Double.NaN;
+ else {
+ final double kmWeight = Linear.factor(km, r1.km, r2.km);
+ return Linear.weight(kmWeight, w1, w2);
+ }
+ }
+ }
+ }
+
+ public double [] getMinMaxQ(final double km) {
return getMinMaxQ(km, new double [2]);
}
- public double [] getMinMaxQ(double km, double [] result) {
+ public double [] getMinMaxQ(final double km, final double [] result) {
double minQ = Double.MAX_VALUE;
double maxQ = -Double.MAX_VALUE;
- for (int i = 0; i < columns.length; ++i) {
- double q = columns[i].getQRangeTree().findQ(km);
+ for (int i = 0; i < this.columns.length; ++i) {
+ final double q = this.columns[i].getQRangeTree().findQ(km);
if (!Double.isNaN(q)) {
if (q < minQ) minQ = q;
if (q > maxQ) maxQ = q;
@@ -648,13 +673,13 @@
}
public double [] getMinMaxQ(double from, double to, double step) {
- double [] result = new double[2];
+ final double [] result = new double[2];
double minQ = Double.MAX_VALUE;
double maxQ = -Double.MAX_VALUE;
if (from > to) {
- double tmp = from;
+ final double tmp = from;
from = to;
to = tmp;
}
@@ -677,42 +702,42 @@
}
return minQ < Double.MAX_VALUE
- ? new double [] { minQ, maxQ }
- : null;
+ ? new double [] { minQ, maxQ }
+ : null;
}
- public double [] getMinMaxW(double km) {
+ public double [] getMinMaxW(final double km) {
return getMinMaxW(km, new double [2]);
}
- public double [] getMinMaxW(double km, double [] result) {
- int rowIndex = Collections.binarySearch(rows, new Row(km));
+ public double [] getMinMaxW(final double km, final double [] result) {
+ int rowIndex = Collections.binarySearch(this.rows, new Row(km));
if (rowIndex >= 0) {
- return rows.get(rowIndex).getMinMaxW(result);
+ return this.rows.get(rowIndex).getMinMaxW(result);
}
rowIndex = -rowIndex -1;
- if (rowIndex < 1 || rowIndex >= rows.size()) {
+ if (rowIndex < 1 || rowIndex >= this.rows.size()) {
// do not extrapolate
return null;
}
- Row r1 = rows.get(rowIndex-1);
- Row r2 = rows.get(rowIndex);
+ final Row r1 = this.rows.get(rowIndex-1);
+ final Row r2 = this.rows.get(rowIndex);
return r1.getMinMaxW(r2, km, result);
}
public double [] getMinMaxW(double from, double to, double step) {
- double [] result = new double[2];
+ final double [] result = new double[2];
double minW = Double.MAX_VALUE;
double maxW = -Double.MAX_VALUE;
if (from > to) {
- double tmp = from;
+ final double tmp = from;
from = to;
to = tmp;
}
@@ -735,14 +760,14 @@
}
return minW < Double.MAX_VALUE
- ? new double [] { minW, maxW }
- : null;
+ ? new double [] { minW, maxW }
+ : null;
}
/**
* Interpolate W and Q values at a given km.
*/
- public double [][] interpolateWQ(double km) {
+ public double [][] interpolateWQ(final double km) {
return interpolateWQ(km, null);
}
@@ -753,7 +778,7 @@
*
* @return double double array, first index Ws, second Qs.
*/
- public double [][] interpolateWQ(double km, Calculation errors) {
+ public double [][] interpolateWQ(final double km, final Calculation errors) {
return interpolateWQ(km, DEFAULT_Q_STEPS, errors);
}
@@ -762,20 +787,20 @@
* Interpolate W and Q values at a given km.
*/
public double [][] interpolateWQ(
- double km,
- int steps,
- Calculation errors
- ) {
- int rowIndex = Collections.binarySearch(rows, new Row(km));
+ final double km,
+ final int steps,
+ final Calculation errors
+ ) {
+ int rowIndex = Collections.binarySearch(this.rows, new Row(km));
if (rowIndex >= 0) { // direct row match
- Row row = rows.get(rowIndex);
+ final Row row = this.rows.get(rowIndex);
return row.interpolateWQ(steps, this, errors);
}
rowIndex = -rowIndex -1;
- if (rowIndex < 1 || rowIndex >= rows.size()) {
+ if (rowIndex < 1 || rowIndex >= this.rows.size()) {
// do not extrapolate
if (errors != null) {
errors.addProblem(km, "km.not.found");
@@ -783,19 +808,19 @@
return new double[2][0];
}
- Row r1 = rows.get(rowIndex-1);
- Row r2 = rows.get(rowIndex);
+ final Row r1 = this.rows.get(rowIndex-1);
+ final Row r2 = this.rows.get(rowIndex);
return r1.interpolateWQ(r2, km, steps, this, errors);
}
public boolean interpolate(
- double km,
- double [] out,
- QPosition qPosition,
- Function qFunction
- ) {
- int R1 = rows.size()-1;
+ final double km,
+ final double [] out,
+ final QPosition qPosition,
+ final Function qFunction
+ ) {
+ final int R1 = this.rows.size()-1;
out[1] = qFunction.value(getQ(qPosition, km));
@@ -803,16 +828,16 @@
return false;
}
- QPosition nPosition = new QPosition();
+ final QPosition nPosition = new QPosition();
if (getQPosition(km, out[1], nPosition) == null) {
return false;
}
- int rowIndex = Collections.binarySearch(rows, new Row(km));
+ int rowIndex = Collections.binarySearch(this.rows, new Row(km));
if (rowIndex >= 0) {
// direct row match
- out[0] = rows.get(rowIndex).getW(nPosition);
+ out[0] = this.rows.get(rowIndex).getW(nPosition);
return !Double.isNaN(out[0]);
}
@@ -823,8 +848,8 @@
return false;
}
- Row r1 = rows.get(rowIndex-1);
- Row r2 = rows.get(rowIndex);
+ final Row r1 = this.rows.get(rowIndex-1);
+ final Row r2 = this.rows.get(rowIndex);
out[0] = r1.getW(r2, km, nPosition);
return !Double.isNaN(out[0]);
@@ -842,15 +867,15 @@
* @param errors calculation object to store errors.
*/
public QPosition interpolate(
- double q,
- double referenceKm,
- double [] kms,
- double [] ws,
- double [] qs,
- Calculation errors
- ) {
+ final double q,
+ final double referenceKm,
+ final double [] kms,
+ final double [] ws,
+ final double [] qs,
+ final Calculation errors
+ ) {
return interpolate(
- q, referenceKm, kms, ws, qs, 0, kms.length, errors);
+ q, referenceKm, kms, ws, qs, 0, kms.length, errors);
}
/**
@@ -860,16 +885,16 @@
* @param qs [out] looked up qs for kms.
*/
public QPosition interpolate(
- double q,
- double referenceKm,
- double [] kms,
- double [] ws,
- double [] qs,
- int startIndex,
- int length,
- Calculation errors
- ) {
- QPosition qPosition = getQPosition(referenceKm, q);
+ final double q,
+ final double referenceKm,
+ final double [] kms,
+ final double [] ws,
+ final double [] qs,
+ final int startIndex,
+ final int length,
+ final Calculation errors
+ ) {
+ final QPosition qPosition = getQPosition(referenceKm, q);
if (qPosition == null) {
// we cannot locate q at km
@@ -881,9 +906,9 @@
return null;
}
- Row kmKey = new Row();
+ final Row kmKey = new Row();
- int R1 = rows.size()-1;
+ final int R1 = this.rows.size()-1;
for (int i = startIndex, end = startIndex+length; i < end; ++i) {
@@ -896,12 +921,12 @@
}
kmKey.km = kms[i];
- int rowIndex = Collections.binarySearch(rows, kmKey);
+ int rowIndex = Collections.binarySearch(this.rows, kmKey);
if (rowIndex >= 0) {
// direct row match
- if (Double.isNaN(ws[i] = rows.get(rowIndex).getW(qPosition))
- && errors != null) {
+ if (Double.isNaN(ws[i] = this.rows.get(rowIndex).getW(qPosition))
+ && errors != null) {
errors.addProblem(kms[i], "cannot.find.w.for.q", q);
}
continue;
@@ -917,11 +942,11 @@
ws[i] = Double.NaN;
continue;
}
- Row r1 = rows.get(rowIndex-1);
- Row r2 = rows.get(rowIndex);
+ final Row r1 = this.rows.get(rowIndex-1);
+ final Row r2 = this.rows.get(rowIndex);
if (Double.isNaN(ws[i] = r1.getW(r2, kms[i], qPosition))
- && errors != null) {
+ && errors != null) {
errors.addProblem(kms[i], "cannot.find.w.for.q", q);
}
}
@@ -939,14 +964,14 @@
*
* @return Linearly interpolated w, NaN if one of the given rows was null.
*/
- public static double linearW(double km, Row row1, Row row2, int col) {
+ public static double linearW(final double km, final Row row1, final Row row2, final int col) {
if (row1 == null || row2 == null) {
return Double.NaN;
}
return Linear.linear(km,
- row1.km, row2.km,
- row1.ws[col], row2.ws[col]);
+ row1.km, row2.km,
+ row1.ws[col], row2.ws[col]);
}
/**
@@ -955,27 +980,27 @@
* @param km position (km) at which to interpolate/lookup.
* @return [[q0, q1, .. qx] , [w0, w1, .. wx]] (can contain NaNs)
*/
- public double [][] interpolateWQColumnwise(double km) {
+ public double [][] interpolateWQColumnwise(final double km) {
log.debug("WstValueTable.interpolateWQColumnwise");
- double [] qs = new double[columns.length];
- double [] ws = new double[columns.length];
+ final double [] qs = new double[this.columns.length];
+ final double [] ws = new double[this.columns.length];
// Find out row from where we will start searching.
- int rowIndex = Collections.binarySearch(rows, new Row(km));
+ int rowIndex = Collections.binarySearch(this.rows, new Row(km));
if (rowIndex < 0) {
rowIndex = -rowIndex -1;
}
// TODO Beyond definition, we could stop more clever.
- if (rowIndex >= rows.size()) {
- rowIndex = rows.size() -1;
+ if (rowIndex >= this.rows.size()) {
+ rowIndex = this.rows.size() -1;
}
- Row startRow = rows.get(rowIndex);
+ final Row startRow = this.rows.get(rowIndex);
- for (int col = 0; col < columns.length; col++) {
- qs[col] = columns[col].getQRangeTree().findQ(km);
+ for (int col = 0; col < this.columns.length; col++) {
+ qs[col] = this.columns[col].getQRangeTree().findQ(km);
if (startRow.km == km && !Double.isNaN(startRow.ws[col])) {
// Great. W is defined at km.
ws[col] = startRow.ws[col];
@@ -986,18 +1011,18 @@
Row rowBefore = null;
Row rowAfter = null;
for (int before = rowIndex -1; before >= 0; before--) {
- if (!Double.isNaN(rows.get(before).ws[col])) {
- rowBefore = rows.get(before);
+ if (!Double.isNaN(this.rows.get(before).ws[col])) {
+ rowBefore = this.rows.get(before);
break;
}
}
if (rowBefore != null) {
- for (int after = rowIndex, R = rows.size();
- after < R;
- after++
- ) {
- if (!Double.isNaN(rows.get(after).ws[col])) {
- rowAfter = rows.get(after);
+ for (int after = rowIndex, R = this.rows.size();
+ after < R;
+ after++
+ ) {
+ if (!Double.isNaN(this.rows.get(after).ws[col])) {
+ rowAfter = this.rows.get(after);
break;
}
}
@@ -1009,34 +1034,34 @@
return new double [][] {qs, ws};
}
- public double [] findQsForW(double km, double w, Calculation errors) {
+ public double [] findQsForW(final double km, final double w, final Calculation errors) {
- int rowIndex = Collections.binarySearch(rows, new Row(km));
+ int rowIndex = Collections.binarySearch(this.rows, new Row(km));
if (rowIndex >= 0) {
- return rows.get(rowIndex).findQsForW(w, this, errors);
+ return this.rows.get(rowIndex).findQsForW(w, this, errors);
}
rowIndex = -rowIndex - 1;
- if (rowIndex < 1 || rowIndex >= rows.size()) {
+ if (rowIndex < 1 || rowIndex >= this.rows.size()) {
// Do not extrapolate.
return new double[0];
}
// Needs bilinear interpolation.
- Row r1 = rows.get(rowIndex-1);
- Row r2 = rows.get(rowIndex);
+ final Row r1 = this.rows.get(rowIndex-1);
+ final Row r2 = this.rows.get(rowIndex);
return r1.findQsForW(r2, w, km, this, errors);
}
- protected SplineFunction createSpline(double km, Calculation errors) {
+ protected SplineFunction createSpline(final double km, final Calculation errors) {
- int rowIndex = Collections.binarySearch(rows, new Row(km));
+ int rowIndex = Collections.binarySearch(this.rows, new Row(km));
if (rowIndex >= 0) {
- SplineFunction sf = rows.get(rowIndex).createSpline(this, errors);
+ final SplineFunction sf = this.rows.get(rowIndex).createSpline(this, errors);
if (sf == null && errors != null) {
errors.addProblem(km, "cannot.create.wq.relation");
}
@@ -1045,7 +1070,7 @@
rowIndex = -rowIndex - 1;
- if (rowIndex < 1 || rowIndex >= rows.size()) {
+ if (rowIndex < 1 || rowIndex >= this.rows.size()) {
// Do not extrapolate.
if (errors != null) {
errors.addProblem(km, "km.not.found");
@@ -1054,10 +1079,10 @@
}
// Needs bilinear interpolation.
- Row r1 = rows.get(rowIndex-1);
- Row r2 = rows.get(rowIndex);
+ final Row r1 = this.rows.get(rowIndex-1);
+ final Row r2 = this.rows.get(rowIndex);
- SplineFunction sf = r1.createSpline(r2, km, this, errors);
+ final SplineFunction sf = r1.createSpline(r2, km, this, errors);
if (sf == null && errors != null) {
errors.addProblem(km, "cannot.create.wq.relation");
}
@@ -1067,10 +1092,10 @@
/** 'Bezugslinienverfahren' */
public double [][] relateWs(
- double km1,
- double km2,
- Calculation errors
- ) {
+ final double km1,
+ final double km2,
+ final Calculation errors
+ ) {
return relateWs(km1, km2, RELATE_WS_SAMPLES, errors);
}
@@ -1079,14 +1104,14 @@
boolean hasErrors;
Calculation errors;
- ErrorHandler(Calculation errors) {
+ ErrorHandler(final Calculation errors) {
this.errors = errors;
}
- void error(double km, String key, Object ... args) {
- if (errors != null && !hasErrors) {
- hasErrors = true;
- errors.addProblem(km, key, args);
+ void error(final double km, final String key, final Object ... args) {
+ if (this.errors != null && !this.hasErrors) {
+ this.hasErrors = true;
+ this.errors.addProblem(km, key, args);
}
}
} // class ErrorHandler
@@ -1097,22 +1122,22 @@
* the start km is always the same.
*/
public double [][] relateWs(
- double km1,
- double km2,
- int numSamples,
- Calculation errors
- ) {
- SplineFunction sf1 = createSpline(km1, errors);
+ final double km1,
+ final double km2,
+ final int numSamples,
+ final Calculation errors
+ ) {
+ final SplineFunction sf1 = createSpline(km1, errors);
if (sf1 == null) {
return new double[2][0];
}
- SplineFunction sf2 = createSpline(km2, errors);
+ final SplineFunction sf2 = createSpline(km2, errors);
if (sf2 == null) {
return new double[2][0];
}
- PolynomialSplineFunction iQ1 = sf1.createIndexQRelation();
+ final PolynomialSplineFunction iQ1 = sf1.createIndexQRelation();
if (iQ1 == null) {
if (errors != null) {
errors.addProblem(km1, "cannot.create.index.q.relation");
@@ -1120,7 +1145,7 @@
return new double[2][0];
}
- PolynomialSplineFunction iQ2 = sf2.createIndexQRelation();
+ final PolynomialSplineFunction iQ2 = sf2.createIndexQRelation();
if (iQ2 == null) {
if (errors != null) {
errors.addProblem(km2, "cannot.create.index.q.relation");
@@ -1128,18 +1153,18 @@
return new double[2][0];
}
- int N = Math.min(sf1.splineQs.length, sf2.splineQs.length);
- double stepWidth = N/(double)numSamples;
+ final int N = Math.min(sf1.splineQs.length, sf2.splineQs.length);
+ final double stepWidth = N/(double)numSamples;
- PolynomialSplineFunction qW1 = sf1.spline;
- PolynomialSplineFunction qW2 = sf2.spline;
+ final PolynomialSplineFunction qW1 = sf1.spline;
+ final PolynomialSplineFunction qW2 = sf2.spline;
- TDoubleArrayList ws1 = new TDoubleArrayList(numSamples);
- TDoubleArrayList ws2 = new TDoubleArrayList(numSamples);
- TDoubleArrayList qs1 = new TDoubleArrayList(numSamples);
- TDoubleArrayList qs2 = new TDoubleArrayList(numSamples);
+ final TDoubleArrayList ws1 = new TDoubleArrayList(numSamples);
+ final TDoubleArrayList ws2 = new TDoubleArrayList(numSamples);
+ final TDoubleArrayList qs1 = new TDoubleArrayList(numSamples);
+ final TDoubleArrayList qs2 = new TDoubleArrayList(numSamples);
- ErrorHandler err = new ErrorHandler(errors);
+ final ErrorHandler err = new ErrorHandler(errors);
int i = 0;
for (double p = 0d; p <= N-1; p += stepWidth, ++i) {
@@ -1148,7 +1173,7 @@
try {
q1 = iQ1.value(p);
}
- catch (ArgumentOutsideDomainException aode) {
+ catch (final ArgumentOutsideDomainException aode) {
err.error(km1, "w.w.qkm1.failed", p);
continue;
}
@@ -1157,7 +1182,7 @@
try {
w1 = qW1.value(q1);
}
- catch (ArgumentOutsideDomainException aode) {
+ catch (final ArgumentOutsideDomainException aode) {
err.error(km1, "w.w.wkm1.failed", q1, p);
continue;
}
@@ -1166,7 +1191,7 @@
try {
q2 = iQ2.value(p);
}
- catch (ArgumentOutsideDomainException aode) {
+ catch (final ArgumentOutsideDomainException aode) {
err.error(km2, "w.w.qkm2.failed", p);
continue;
}
@@ -1175,7 +1200,7 @@
try {
w2 = qW2.value(q2);
}
- catch (ArgumentOutsideDomainException aode) {
+ catch (final ArgumentOutsideDomainException aode) {
err.error(km2, "w.w.wkm2.failed", q2, p);
continue;
}
@@ -1193,24 +1218,24 @@
qs2.toNativeArray() };
}
- public QPosition getQPosition(double km, double q) {
+ public QPosition getQPosition(final double km, final double q) {
return getQPosition(km, q, new QPosition());
}
- public QPosition getQPosition(double km, double q, QPosition qPosition) {
+ public QPosition getQPosition(final double km, final double q, final QPosition qPosition) {
- if (columns.length == 0) {
+ if (this.columns.length == 0) {
return null;
}
- double qLast = columns[0].getQRangeTree().findQ(km);
+ double qLast = this.columns[0].getQRangeTree().findQ(km);
if (Math.abs(qLast - q) < 0.00001) {
return qPosition.set(0, 1d);
}
- for (int i = 1; i < columns.length; ++i) {
- double qCurrent = columns[i].getQRangeTree().findQ(km);
+ for (int i = 1; i < this.columns.length; ++i) {
+ final double qCurrent = this.columns[i].getQRangeTree().findQ(km);
if (Math.abs(qCurrent - q) < 0.00001) {
return qPosition.set(i, 1d);
}
@@ -1220,7 +1245,7 @@
else { qMin = qCurrent; qMax = qLast; }
if (q > qMin && q < qMax) {
- double weight = Linear.factor(q, qLast, qCurrent);
+ final double weight = Linear.factor(q, qLast, qCurrent);
return qPosition.set(i, weight);
}
qLast = qCurrent;
@@ -1229,53 +1254,53 @@
return null;
}
- public double getQIndex(int index, double km) {
- return columns[index].getQRangeTree().findQ(km);
+ public double getQIndex(final int index, final double km) {
+ return this.columns[index].getQRangeTree().findQ(km);
}
- public double getQ(QPosition qPosition, double km) {
- int index = qPosition.index;
- double weight = qPosition.weight;
+ public double getQ(final QPosition qPosition, final double km) {
+ final int index = qPosition.index;
+ final double weight = qPosition.weight;
if (weight == 1d) {
- return columns[index].getQRangeTree().findQ(km);
+ return this.columns[index].getQRangeTree().findQ(km);
}
- double q1 = columns[index-1].getQRangeTree().findQ(km);
- double q2 = columns[index ].getQRangeTree().findQ(km);
+ final double q1 = this.columns[index-1].getQRangeTree().findQ(km);
+ final double q2 = this.columns[index ].getQRangeTree().findQ(km);
return Linear.weight(weight, q1, q2);
}
- public double [][] interpolateTabulated(double km) {
- return interpolateTabulated(km, new double[2][columns.length]);
+ public double [][] interpolateTabulated(final double km) {
+ return interpolateTabulated(km, new double[2][this.columns.length]);
}
- public double [][] interpolateTabulated(double km, double [][] result) {
+ public double [][] interpolateTabulated(final double km, final double [][] result) {
- int rowIndex = Collections.binarySearch(rows, new Row(km));
+ int rowIndex = Collections.binarySearch(this.rows, new Row(km));
if (rowIndex >= 0) {
// Direct hit -> copy ws.
- Row row = rows.get(rowIndex);
+ final Row row = this.rows.get(rowIndex);
System.arraycopy(
- row.ws, 0, result[0], 0,
- Math.min(row.ws.length, result[0].length));
+ row.ws, 0, result[0], 0,
+ Math.min(row.ws.length, result[0].length));
}
else {
rowIndex = -rowIndex -1;
- if (rowIndex < 1 || rowIndex >= rows.size()) {
+ if (rowIndex < 1 || rowIndex >= this.rows.size()) {
// Out of bounds.
return null;
}
// Interpolate ws.
- Row r1 = rows.get(rowIndex-1);
- Row r2 = rows.get(rowIndex);
- double factor = Linear.factor(km, r1.km, r2.km);
+ final Row r1 = this.rows.get(rowIndex-1);
+ final Row r2 = this.rows.get(rowIndex);
+ final double factor = Linear.factor(km, r1.km, r2.km);
Linear.weight(factor, r1.ws, r2.ws, result[0]);
}
- double [] qs = result[1];
- for (int i = Math.min(qs.length, columns.length)-1; i >= 0; --i) {
- qs[i] = columns[i].getQRangeTree().findQ(km);
+ final double [] qs = result[1];
+ for (int i = Math.min(qs.length, this.columns.length)-1; i >= 0; --i) {
+ qs[i] = this.columns[i].getQRangeTree().findQ(km);
}
return result;
}
@@ -1283,7 +1308,7 @@
/** True if no QRange is given or Q equals zero. */
public boolean hasEmptyQ() {
- for (Column column: columns) {
+ for (final Column column: this.columns) {
if (column.getQRangeTree() == null) {
return true;
}
@@ -1294,7 +1319,7 @@
}
}
- if (columns.length == 0) {
+ if (this.columns.length == 0) {
log.warn("No columns in WstValueTable.");
}
@@ -1303,10 +1328,10 @@
/** Find ranges that are between km1 and km2 (inclusive?) */
- public List<Range> findSegments(double km1, double km2) {
- return columns.length != 0
- ? columns[columns.length-1].getQRangeTree().findSegments(km1, km2)
- : Collections.<Range>emptyList();
+ public List<Range> findSegments(final double km1, final double km2) {
+ return this.columns.length != 0
+ ? this.columns[this.columns.length-1].getQRangeTree().findSegments(km1, km2)
+ : Collections.<Range>emptyList();
}
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
diff -r 9b16f58c62a7 -r bcbae86ce7b3 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java Mon Jul 23 19:18:11 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java Mon Jul 23 19:20:06 2018 +0200
@@ -66,8 +66,8 @@
/**
* Calculate the infrastructures flood duration result rows
*/
- public void execute(final Calculation problems, final String label, final DoubleRange calcRange,
- final RiversideChoiceKey riverside, final WINFOArtifact winfo, final FloodDurationCalculationResults results) {
+ public void execute(final Calculation problems, final String label, final DoubleRange calcRange, final RiversideChoiceKey riverside,
+ final WINFOArtifact winfo, final FloodDurationCalculationResults results) {
// Find all gauges of the calc range, and create the duration finders
final Map<Gauge, GaugeDurationValuesFinder> durFinders = new HashMap<>();
@@ -91,20 +91,23 @@
addInfrastructures(allStations, secondBank, infras);
final double[] stationsSorted = sortStations(allStations.keySet());
- // Calculate W and Q for all stations and the selected discharge states
- // TODO Geht das schneller, wenn man WstValueTable statt WINFOArtifact.computeWaterlevelData nutzt?
- final WQKms[] wqkmsArray = calculateWaterlevels(winfo, stationsSorted, problems);
+ // Calculate W and Q for all stations and the selected discharge states/waterlevels
+ final WQKms[] wqkmsArray = calculateWsts(winfo, stationsSorted, problems);
- // Determine discharge state labels of the main values
- updateMainValueLabels(wqkmsArray, winfo, problems);
+ // Determine discharge state labels of the waterlevels
+ updateWstLabels(wqkmsArray, winfo, problems);
- // Load base wst table (river).wst - first run takes long time, then it's cached
+ final Map<Gauge, List<Double>> gaugeWstDurations = new HashMap<>();
+ calcGaugeWstDurations(winfo, new ArrayList<>(durFinders.keySet()), gaugeWstDurations, durFinders);
+
+ // Load base wst table (river).wst
+ // (should be in cache since already used in calculateWaterlevels (winfo.computeWaterlevelData)
final WstValueTable wst = WstValueTableFactory.getTable(this.riverInfoProvider.getRiver());
- // Calculate the durations and create the result rows
+ // Create the result rows, and calculate and add the flood durations etc.
for (int i = 0; i <= stationsSorted.length - 1; i++) {
final Gauge gauge = this.riverInfoProvider.getGauge(stationsSorted[i], true);
- final ResultRow row = createRow(stationsSorted[i], gauge, firstGauge, wqkmsArray, durFinders.get(gauge), i);
+ final ResultRow row = createRow(stationsSorted[i], gauge, firstGauge, wqkmsArray, gaugeWstDurations.get(gauge), i);
if (allStations.containsKey(stationsSorted[i]) && (allStations.get(stationsSorted[i]) != null))
calculateInfrastructure(row, gauge, allStations.get(stationsSorted[i]), wst, durFinders);
this.rows.add(row);
@@ -115,50 +118,39 @@
}
}
- //// Create a finder for Q in the {river}.wst km-w-q table
- // final WQBaseTableFinder wqFinder = WQBaseTableFinder.loadValues(this.riverInfoProvider.getRiver(),
- //// calcRange.getMinimumDouble(),
- // calcRange.getMaximumDouble(), problems);
- //
- //// Calculate the durations and create the result rows
- // for (int i = 0; i <= stationsSorted.length - 1; i++) {
- // final Gauge gauge = this.riverInfoProvider.getGauge(stationsSorted[i], true);
- // final ResultRow row = createRow(stationsSorted[i], gauge, firstGauge, wqkmsArray, durFinders.get(gauge), i);
- // if (allStations.containsKey(stationsSorted[i]) && (allStations.get(stationsSorted[i]) != null))
- // calculateInfrastructure(row, gauge, allStations.get(stationsSorted[i]), wqFinder, durFinders);
- // this.rows.add(row);
- // if (secondBank.containsKey(stationsSorted[i])) {
- // final ResultRow row2 = ResultRow.create(row);
- // calculateInfrastructure(row2, gauge, secondBank.get(stationsSorted[i]), wqFinder, durFinders);
- // this.rows.add(row2);
- // }
- // }
+ // Get the labels of the selected waterlevels
+ final String[] wstLabels = new String[wqkmsArray.length];
+ for (int i = 0; i <= wqkmsArray.length - 1; i++)
+ wstLabels[i] = wqkmsArray[i].getName();
- final String[] mainValueLabels = new String[wqkmsArray.length];
- for (int i = 0; i <= wqkmsArray.length - 1; i++)
- mainValueLabels[i] = wqkmsArray[i].getName();
- results.addResult(new FloodDurationCalculationResult(label, mainValueLabels, this.rows), problems);
+ results.addResult(new FloodDurationCalculationResult(label, wstLabels, this.rows), problems);
}
/**
* Calculates the duration curve for a station
+ * (other than the version 3.2.1 W-Info Dauerlinie the wst column positions
+ * are taken from the Q values of the gauge's Q-D-table)
*/
public WQDay calcWQDays(final Calculation problems, final double station, final WINFOArtifact winfo) {
- // Same processing as in W-Info DurationCurveState
- winfo.addStringData("ld_locations", Double.toString(station));
- final CalculationResult res = winfo.getDurationCurveData();
- final WQDay underflow = (WQDay) res.getData();
- // Transform underflow days into overflow days and re-sort
- final int[] days = new int[underflow.getWs().length];
- final double[] ws = new double[days.length];
- final double[] qs = new double[days.length];
- for (int i = 0, j = days.length - 1; i <= days.length - 1; i++, j--) {
- days[j] = 365 - underflow.getDay(i);
- ws[j] = underflow.getW(i);
- qs[j] = underflow.getQ(i);
+ final WstValueTable wst = WstValueTableFactory.getTable(this.riverInfoProvider.getRiver());
+ final Gauge gauge = this.riverInfoProvider.getRiver().determineGaugeByPosition(station);
+ final Object[] obj = gauge.fetchDurationCurveData();
+ final int[] udays = (int[]) obj[0];
+ final double[] qs = (double[]) obj[1];
+ final int[] odays = new int[udays.length];
+ final double[] oqs = new double[udays.length];
+ final double[] ows = new double[udays.length];
+ for (int i = 0, j = udays.length - 1; i <= udays.length - 1; i++, j--) {
+ odays[j] = 365 - udays[i];
+ oqs[j] = qs[i];
+ final QPosition qpos = wst.getQPosition(gauge.getStation().doubleValue(), qs[i]);
+ if (qpos != null)
+ ows[j] = wst.interpolateW(station, qpos, problems);
+ else
+ ows[j] = Double.NaN;
}
- return new WQDay(days, ws, qs);
+ return new WQDay(odays, ows, oqs);
}
/**
@@ -341,9 +333,8 @@
/**
* Calculates an array of w-q-longitudinal sections for all artifact W/Q options
*/
- private WQKms[] calculateWaterlevels(final WINFOArtifact winfo, final double[] stations, final Calculation problems) {
- // REMARK aus TkhCalculation - move to WinfoArtifactWrapper?
- // TODO das ist ziemlich langsam - durch den WQBaseTableFinder ersetzen? (vorher W-Optionen in Q umrechnen)
+ private WQKms[] calculateWsts(final WINFOArtifact winfo, final double[] stations, final Calculation problems) {
+ // First run may take long, further runs are faster since WstValueTable is in cache then
// (So funktioniert computeWaterlevelData wohl:
// Es sucht die Spalte(n) zum Bezugspegel-Q in der W-Q-Tabelle ({river}.wst in Wst etc.),
// interpoliert die horizontale Tabellenposition (Q) und dann die vertikale Tabellenposition der station;
@@ -352,36 +343,35 @@
// interpoliert;
// bei Vorgabe eines W auf freier Strecke wird wohl vorher noch die .wst-Interpolation eingesetzt, um das Q zu bekommen.
- final CalculationResult waterlevelData = winfo.computeWaterlevelData(stations);
+ final CalculationResult wstsData = winfo.computeWaterlevelData(stations);
/* copy all problems */
- final Calculation winfoProblems = waterlevelData.getReport();
+ final Calculation winfoProblems = wstsData.getReport();
final List<Problem> problems2 = winfoProblems.getProblems();
if (problems2 != null) {
for (final Problem problem : problems2) {
problems.addProblem(problem);
}
}
- return (WQKms[]) waterlevelData.getData();
+ return (WQKms[]) wstsData.getData();
}
/**
* Determines the waterlevel/discharge state labels for the selected Q or W values and sets them in the WQKms array
*/
- private void updateMainValueLabels(final WQKms[] wqkmsArray, final WINFOArtifact winfo, final Calculation problems) {
+ private void updateWstLabels(final WQKms[] wqkmsArray, final WINFOArtifact winfo, final Calculation problems) {
for (int i = 0; i <= wqkmsArray.length - 1; i++)
wqkmsArray[i].setName(buildWQDescription(wqkmsArray[i], winfo));
}
/**
- *
- * @param wqkms
- * @param descBuilder
- * @return
+ * Builds the description label of a waterlevel
*/
private String buildWQDescription(final WQKms wqkms, final WINFOArtifact winfo) {
+
final WaterlevelDescriptionBuilder descBuilder = new WaterlevelDescriptionBuilder(winfo, this.context);
+ // TODO Zwischen numerischem Q-Wert und Dauerzahl-Hauptwert (0..364) unterscheiden
final String description = descBuilder.getDesc(wqkms);
if (!description.isEmpty() && Character.isDigit(description.charAt(0))) {
if (winfo.isQ())
@@ -394,10 +384,32 @@
}
/**
+ * Calculates the flood durations of the Qs of the waterlevels/discharge states for a map of gauges
+ */
+ private void calcGaugeWstDurations(final WINFOArtifact winfo, final List<Gauge> gauges, final Map<Gauge, List<Double>> gaugeWstDurations,
+ final Map<Gauge, GaugeDurationValuesFinder> durFinders) {
+
+ final double[] gaugeKms = new double[gauges.size()];
+ for (int i = 0; i <= gauges.size() - 1; i++) {
+ gaugeKms[i] = gauges.get(i).getStation().doubleValue();
+ gaugeWstDurations.put(gauges.get(i), new ArrayList<Double>());
+ }
+ final CalculationResult wstsData = winfo.computeWaterlevelData(gaugeKms);
+ final WQKms[] wsts = (WQKms[]) wstsData.getData();
+ for (int i = 0; i <= gauges.size() - 1; i++) {
+ final GaugeDurationValuesFinder durFinder = durFinders.get(gauges.get(i));
+ for (int j = 0; j <= wsts.length - 1; j++) {
+ final double d = durFinder.getDuration(wsts[j].getQ(i));
+ gaugeWstDurations.get(gauges.get(i)).add(Double.valueOf(underflowDaysToOverflowDays(d)));
+ }
+ }
+ }
+
+ /**
* Create a result row for a station and its gauge, and add w-q-values as selected
*/
private ResultRow createRow(final Double station, final Gauge gauge, final Gauge firstGauge, final WQKms[] wqkmsArray,
- final GaugeDurationValuesFinder durationFinder, final int kmIndex) {
+ final List<Double> gaugeDurations, final int kmIndex) {
final ResultRow row = ResultRow.create();
row.putValue(GeneralResultType.station, station);
@@ -410,39 +422,22 @@
final String location = this.riverInfoProvider.getLocation(station);
row.putValue(SInfoResultType.location, location);
- final List<DurationWaterlevel> waterlevels = new ArrayList<>(wqkmsArray.length);
+ final List<DurationWaterlevel> wsts = new ArrayList<>(wqkmsArray.length);
- for (final WQKms wqKms : wqkmsArray) {
- assert (wqKms.getKm(kmIndex) == station.doubleValue());
+ for (int i = 0; i <= wqkmsArray.length - 1; i++) {
+ assert (wqkmsArray[i].getKm(kmIndex) == station.doubleValue());
- final int overflowDays = (int) Math.round(underflowDaysToOverflowDays(durationFinder.getDuration(wqKms.getQ(kmIndex))));
+ final int overflowDays = (int) Math.round(gaugeDurations.get(i));
- final DurationWaterlevel dw = new DurationWaterlevel(wqKms.getW(kmIndex), overflowDays, wqKms.getQ(kmIndex), wqKms.getName());
- waterlevels.add(dw);
+ final DurationWaterlevel dw = new DurationWaterlevel(wqkmsArray[i].getW(kmIndex), overflowDays, wqkmsArray[i].getQ(kmIndex),
+ wqkmsArray[i].getName());
+ wsts.add(dw);
}
- row.putValue(SInfoResultType.customMultiRowColWaterlevel, waterlevels);
+ row.putValue(SInfoResultType.customMultiRowColWaterlevel, wsts);
return row;
}
- /// **
- // * Calculate the result row fields for one infrastructure - gives wrong duration numbers where Q changes within the
- /// gauge range
- // */
- // private void calculateInfrastructure(final ResultRow row, final Gauge gauge, final InfrastructureValue
- /// infrastructure, final WQBaseTableFinder wqFinder,
- // final Map<Gauge, GaugeDurationValuesFinder> durFinders) {
- //
- // final double q = wqFinder.getDischarge(infrastructure.getStation(), infrastructure.getHeight());
- // final double qOut = Double.isInfinite(q) ? Double.NaN : q;
- // final double dur = underflowDaysToOverflowDays(durFinders.get(gauge).getDuration(q));
- // row.putValue(SInfoResultType.riverside, infrastructure.getAttributeKey());
- // row.putValue(SInfoResultType.floodDuration, dur);
- // row.putValue(SInfoResultType.floodDischarge, qOut);
- // row.putValue(SInfoResultType.infrastructureHeight, infrastructure.getHeight());
- // row.putValue(SInfoResultType.infrastructuretype, infrastructure.getInfrastructure().getType().getName());
- // }
-
/**
* Calculate the result row fields for one infrastructure
*/
@@ -454,17 +449,16 @@
final double[] qs = wst.findQsForW(infrastructure.getStation().doubleValue(), infrastructure.getHeight().doubleValue(), problems);
// TODO Fehlerbehandlung (kein Q gefunden)
final double q = (qs.length >= 1) ? qs[0] : Double.NaN;
- final double qOut = Double.isInfinite(q) ? Double.NaN : q;
- // Determine the relative column position of the Q
+ // Determine the relative column position of the Q of the infrastructure height
final QPosition qPos = wst.getQPosition(infrastructure.getStation().doubleValue(), q);
// Get the Q for the found column position for the station of the gauge
final double qGauge = wst.getQ(qPos, gauge.getStation().doubleValue());
// Interpolate the Q-D-table of the gauge
final double dur = underflowDaysToOverflowDays(durFinders.get(gauge).getDuration(qGauge));
- // Set result row
+ // Set the result row
row.putValue(SInfoResultType.riverside, infrastructure.getAttributeKey());
row.putValue(SInfoResultType.floodDuration, dur);
- row.putValue(SInfoResultType.floodDischarge, qOut);
+ row.putValue(SInfoResultType.floodDischarge, q);
row.putValue(SInfoResultType.infrastructureHeight, infrastructure.getHeight());
row.putValue(SInfoResultType.infrastructuretype, infrastructure.getInfrastructure().getType().getName());
}
More information about the Dive4Elements-commits
mailing list