# HG changeset patch # User Tom Gottfried # Date 1429809213 -7200 # Node ID 93a31cfb18c04c712adbc514f5f4921664fbd432 # Parent e4f9e2316e92813f819e4761036f8d177ea287b0 (issue1787) Sort WQ data locally over Q bevor lookup of Qs for given W. diff -r e4f9e2316e92 -r 93a31cfb18c0 artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java --- 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]); diff -r e4f9e2316e92 -r 93a31cfb18c0 artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTable.java --- 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) {