changeset 8704:93a31cfb18c0

(issue1787) Sort WQ data locally over Q bevor lookup of Qs for given W.
author Tom Gottfried <tom@intevation.de>
date Thu, 23 Apr 2015 19:13:33 +0200
parents e4f9e2316e92
children 682a26e4158b
files artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTable.java
diffstat 2 files changed, 152 insertions(+), 157 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java	Thu Apr 23 19:06:41 2015 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java	Thu Apr 23 19:13:33 2015 +0200
@@ -229,7 +229,7 @@
             log.debug("Determine Q values based on a set of W values.");
             qSel = false;
             ws   = getWs();
-            double [][] qws = getQsForWs(ws);
+            double [][] qws = getQsForWs(ws, report);
             if (qws == null || qws.length == 0) {
                 return error(new WQKms[0], "converting.ws.to.qs.failed");
             }
@@ -661,7 +661,7 @@
      *
      * @return an array of Q values.
      */
-    public double [][] getQsForWs(double[] ws) {
+    public double [][] getQsForWs(double[] ws, Calculation report) {
 
         if (ws == null) {
             log.error("getQsForWs: ws == null");
@@ -708,8 +708,8 @@
                 if (debug) {
                     log.debug("getQsForWs: lookup Q for W: " + w);
                 }
-                // There could bemore than one Q per W.
-                double [] qs = wst.findQsForW(km, w);
+                // There could be more than one Q per W.
+                double [] qs = wst.findQsForW(km, w, report);
                 for (int j = 0; j < qs.length; ++j) {
                     outWs.add(ws[i]);
                     outQs.add(qs[j]);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTable.java	Thu Apr 23 19:06:41 2015 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTable.java	Thu Apr 23 19:13:33 2015 +0200
@@ -202,6 +202,134 @@
         }
 
         /**
+         * Sort Qs and Ws for this Row over Q.
+         */
+        private double[][] getSortedWQ(
+            WstValueTable table,
+            Calculation   errors
+        ) {
+            int W = ws.length;
+
+            if (W < 1) {
+                if (errors != null) {
+                    errors.addProblem(km, "no.ws.found");
+                }
+                return new double[][] {{Double.NaN}, {Double.NaN}};
+            }
+
+            double [] sortedWs = ws;
+            double [] sortedQs = new double[W];
+
+            for (int i=0; i < W; ++i) {
+                double q = table.getQIndex(i, km);
+                if (Double.isNaN(q) && errors != null) {
+                    errors.addProblem(
+                        km, "no.q.found.in.column", i+1);
+                }
+                sortedQs[i] = q;
+            }
+
+            DoubleUtil.sortByFirst(sortedQs, sortedWs);
+
+            return new double[][] { sortedWs, sortedQs };
+        }
+
+        /**
+         * Return an array of Qs and Ws for the given km between
+         * 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);
+
+            if (W < 1) {
+                if (errors != null) {
+                    errors.addProblem("no.ws.found");
+                }
+                return new double[][] {{Double.NaN}, {Double.NaN}};
+            }
+
+            double factor = Linear.factor(km, this.km, other.km);
+
+            double [] sortedQs = new double[W];
+            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);
+
+                if (Double.isNaN(wws) || Double.isNaN(wqs)) {
+                    if (errors != null) {
+                        errors.addProblem(km, "cannot.find.w.or.q");
+                    }
+                }
+
+                sortedWs[i] = wws;
+                sortedQs[i] = wqs;
+            }
+
+            DoubleUtil.sortByFirst(sortedQs, sortedWs);
+
+            return new double[][] { sortedWs, sortedQs };
+        }
+
+        /**
+         * 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;
+
+            double[] sortedQs = sortedWQ[1];
+            double[] sortedWs = sortedWQ[0];
+
+            TDoubleArrayList qs = new TDoubleArrayList();
+
+            if (W > 0 && Math.abs(sortedWs[0]-w) < W_EPSILON) {
+                double q = sortedQs[0];
+                if (!Double.isNaN(q)) {
+                    qs.add(q);
+                }
+            }
+
+            for (int i = 1; i < W; ++i) {
+                double w2 = sortedWs[i];
+                if (Double.isNaN(w2)) {
+                    continue;
+                }
+                if (Math.abs(w2-w) < W_EPSILON) {
+                    double q = sortedQs[i];
+                    if (!Double.isNaN(q)) {
+                        qs.add(q);
+                    }
+                    continue;
+                }
+                double w1 = sortedWs[i-1];
+                if (Double.isNaN(w1)) {
+                    continue;
+                }
+
+                if (w < Math.min(w1, w2) || w > Math.max(w1, w2)) {
+                    continue;
+                }
+
+                double q1 = sortedQs[i-1];
+                double q2 = sortedQs[i];
+                if (Double.isNaN(q1) || Double.isNaN(q2)) {
+                    continue;
+                }
+
+                double q = Linear.linear(w, w1, w2, q1, q2);
+                qs.add(q);
+            }
+
+            return qs.toNativeArray();
+        }
+
+        /**
          * Compare according to place of measurement (km).
          */
         public int compareTo(Row other) {
@@ -256,36 +384,14 @@
             WstValueTable table,
             Calculation   errors
         ) {
-            int W = ws.length;
-
-            if (W < 1) {
-                if (errors != null) {
-                    errors.addProblem(km, "no.ws.found");
-                }
-                return null;
-            }
-
-            double [] splineQs = new double[W];
-            double [] splineWs = new double[W];
-
-            for (int i = 0; i < W; ++i) {
-                double sq = table.getQIndex(i, km);
-                if (Double.isNaN(sq) && errors != null) {
-                    errors.addProblem(
-                        km, "no.q.found.in.column", (i+1));
-                }
-                splineQs[i] = sq;
-                splineWs[i] = ws[i];
-            }
-
-            DoubleUtil.sortByFirst(splineQs, splineWs);
+            double[][] sortedWQ = getSortedWQ(table, errors);
 
             try {
                 SplineInterpolator interpolator = new SplineInterpolator();
                 PolynomialSplineFunction spline =
-                    interpolator.interpolate(splineQs, splineWs);
+                    interpolator.interpolate(sortedWQ[1], sortedWQ[0]);
 
-                return new SplineFunction(spline, splineQs, ws);
+                return new SplineFunction(spline, sortedWQ[1], ws);
             }
             catch (MathIllegalArgumentException miae) {
                 if (errors != null) {
@@ -302,46 +408,15 @@
             WstValueTable table,
             Calculation   errors
         ) {
-            int W = Math.min(ws.length, other.ws.length);
-
-            if (W < 1) {
-                if (errors != null) {
-                    errors.addProblem("no.ws.found");
-                }
-                return null;
-            }
-
-            double factor = Linear.factor(km, this.km, other.km);
-
-            double [] splineQs = new double[W];
-            double [] splineWs = new double[W];
-
-            for (int i = 0; i < W; ++i) {
-                double wws = Linear.weight(factor, ws[i], other.ws[i]);
-                double wqs = Linear.weight(
-                    factor,
-                    table.getQIndex(i, km),
-                    table.getQIndex(i, other.km));
-
-                if (Double.isNaN(wws) || Double.isNaN(wqs)) {
-                    if (errors != null) {
-                        errors.addProblem(km, "cannot.find.w.or.q");
-                    }
-                }
-
-                splineWs[i] = wws;
-                splineQs[i] = wqs;
-            }
-
-            DoubleUtil.sortByFirst(splineQs, splineWs);
+            double[][] sortedWQ = getSortedWQ(other, km, table, errors);
 
             SplineInterpolator interpolator = new SplineInterpolator();
 
             try {
                 PolynomialSplineFunction spline =
-                    interpolator.interpolate(splineQs, splineWs);
+                    interpolator.interpolate(sortedWQ[1], sortedWQ[0]);
 
-                return new SplineFunction(spline, splineQs, splineWs);
+                return new SplineFunction(spline, sortedWQ[1], sortedWQ[0]);
             }
             catch (MathIllegalArgumentException miae) {
                 if (errors != null) {
@@ -414,104 +489,24 @@
             return Linear.weight(kmWeight, tw, ow);
         }
 
-        public double [] findQsForW(double w, WstValueTable table) {
-
-            TDoubleArrayList qs = new TDoubleArrayList();
-
-            if (ws.length > 0 && Math.abs(ws[0]-w) < W_EPSILON) {
-                double q = table.getQIndex(0, km);
-                if (!Double.isNaN(q)) {
-                    qs.add(q);
-                }
-            }
-
-            for (int i = 1; i < ws.length; ++i) {
-                double w2 = ws[i];
-                if (Double.isNaN(w2)) {
-                    continue;
-                }
-                if (Math.abs(w2-w) < W_EPSILON) {
-                    double q = table.getQIndex(i, km);
-                    if (!Double.isNaN(q)) {
-                        qs.add(q);
-                    }
-                    continue;
-                }
-                double w1 = ws[i-1];
-                if (Double.isNaN(w1)) {
-                    continue;
-                }
-
-                if (w < Math.min(w1, w2) || w > Math.max(w1, w2)) {
-                    continue;
-                }
-
-                double q1 = table.getQIndex(i-1, km);
-                double q2 = table.getQIndex(i,   km);
-                if (Double.isNaN(q1) || Double.isNaN(q2)) {
-                    continue;
-                }
-
-                double q = Linear.linear(w, w1, w2, q1, q2);
-                qs.add(q);
-            }
-
-            return qs.toNativeArray();
+        public double [] findQsForW(
+            double        w,
+            WstValueTable table,
+            Calculation   errors
+        ) {
+            log.debug("Find Qs for given W at tabulated km " + km);
+            return findQsForW(w, getSortedWQ(table, errors));
         }
 
         public double [] findQsForW(
             Row           other,
             double        w,
             double        km,
-            WstValueTable table
+            WstValueTable table,
+            Calculation   errors
         ) {
-            TDoubleArrayList qs = new TDoubleArrayList();
-
-            double factor = Linear.factor(km, this.km, other.km);
-
-            if (ws.length > 0) {
-                double wt = Linear.weight(factor, ws[0], other.ws[0]);
-                if (Math.abs(wt-w) < W_EPSILON) {
-                    double q = table.getQIndex(0, km);
-                    if (!Double.isNaN(q)) {
-                        qs.add(q);
-                    }
-                }
-            }
-
-            for (int i = 1; i < ws.length; ++i) {
-                double w2 = Linear.weight(factor, ws[i], other.ws[i]);
-                if (Double.isNaN(w2)) {
-                    continue;
-                }
-                if (Math.abs(w2-w) < W_EPSILON) {
-                    double q = table.getQIndex(i, km);
-                    if (!Double.isNaN(q)) {
-                        qs.add(q);
-                    }
-                    continue;
-                }
-
-                double w1 = Linear.weight(factor, ws[i-1], other.ws[i-1]);
-                if (Double.isNaN(w1)) {
-                    continue;
-                }
-
-                if (w < Math.min(w1, w2) || w > Math.max(w1, w2)) {
-                    continue;
-                }
-
-                double q1 = table.getQIndex(i-1, km);
-                double q2 = table.getQIndex(i,   km);
-                if (Double.isNaN(q1) || Double.isNaN(q2)) {
-                    continue;
-                }
-
-                double q = Linear.linear(w, w1, w2, q1, q2);
-                qs.add(q);
-            }
-
-            return qs.toNativeArray();
+            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) {
@@ -1008,12 +1003,12 @@
         return new double [][] {qs, ws};
     }
 
-    public double [] findQsForW(double km, double w) {
+    public double [] findQsForW(double km, double w, Calculation errors) {
 
         int rowIndex = Collections.binarySearch(rows, new Row(km));
 
         if (rowIndex >= 0) {
-            return rows.get(rowIndex).findQsForW(w, this);
+            return rows.get(rowIndex).findQsForW(w, this, errors);
         }
 
         rowIndex = -rowIndex - 1;
@@ -1027,7 +1022,7 @@
         Row r1 = rows.get(rowIndex-1);
         Row r2 = rows.get(rowIndex);
 
-        return r1.findQsForW(r2, w, km, this);
+        return r1.findQsForW(r2, w, km, this, errors);
     }
 
     protected SplineFunction createSpline(double km, Calculation errors) {

http://dive4elements.wald.intevation.org