changeset 5653:5231e6b849ce

issue1077: Handle overlapping measurement station ranges, refactored Generator, Allow gaps in graph (not sorting, living with NaNs).
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Thu, 11 Apr 2013 10:52:56 +0200
parents 2e420f65c5e0
children c5854dc8d6a1
files flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadFacet.java flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/SedimentLoadLSGenerator.java
diffstat 2 files changed, 72 insertions(+), 134 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadFacet.java	Thu Apr 11 10:14:18 2013 +0200
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadFacet.java	Thu Apr 11 10:52:56 2013 +0200
@@ -3,7 +3,12 @@
 import org.apache.log4j.Logger;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
 
 import de.intevation.artifactdatabase.state.Facet;
 import de.intevation.artifacts.Artifact;
@@ -54,6 +59,7 @@
             return null;
         }
 
+        List<Double> sortedStarts = new ArrayList<Double>();
         // Filter stations according to type.
         List<MeasurementStation> stations = new ArrayList<MeasurementStation>();
         for (MeasurementStation station: allStations) {
@@ -61,43 +67,88 @@
                 continue;
             }
             if (FacetTypes.IS.SEDIMENT_LOAD_NO_FLOAT(this.getName())
-                && station.getMeasurementType().equals("Geschiebe"))
+                && station.getMeasurementType().equals("Geschiebe")) {
                 stations.add(station);
+                sortedStarts.add(station.getStation());
+            }
             else if (!FacetTypes.IS.SEDIMENT_LOAD_NO_FLOAT(this.getName())
-                && station.getMeasurementType().equals("Schwebstoff"))
+                && station.getMeasurementType().equals("Schwebstoff")) {
                 stations.add(station);
+                sortedStarts.add(station.getStation());
+            }
         }
+        Collections.sort(sortedStarts);
 
         // Access data according to type.
         double[][] sd = getLoadData(result);
 
+        // Sort by km.
+        TreeMap<Double, Double> sortData = new TreeMap<Double,Double>();
+
         double[] km   = sd[0];
         double[] load = sd[1];
 
+        for (int i = 0 ; i < km.length; i++) {
+            sortData.put(km[i], load[i]);
+        }
+
         double[][] values = new double[2][];
-        values[0] = new double[km.length*2];
-        values[1] = new double[km.length*2];
+        values[0] = new double[km.length*3];
+        values[1] = new double[km.length*3];
+
+        List<double[]> kmWithoutStation = new ArrayList<double[]>();
 
         // Find station via its station (km).
-        // TODO what to do with gaps in measurement stations.
-        for (int i = 0; i < km.length; i++) {
+        // TODO use a binarySearch instead of linear absdiff approach
+        int i = 0;
+        for (Map.Entry<Double, Double> entry: sortData.entrySet()) {
             boolean matchFound = false;
+            // For now, ignore overlaps like (B> next A)
             for (MeasurementStation station: stations) {
-                if (Math.abs(station.getStation() - km[i]) < EPSILON) {
-                    values[0][i*2] = station.getRange().getA().doubleValue();
-                    values[1][i*2] = load[i];
-                    values[0][i*2+1] = station.getRange().getB().doubleValue();
-                    values[1][i*2+1] = load[i];
+                if (Math.abs(station.getStation() - entry.getKey()) < EPSILON) {
+                    values[0][i*3] = station.getRange().getA().doubleValue() + EPSILON;
+                    values[1][i*3] = entry.getValue();
+                    values[0][i*3+1] = station.getRange().getB().doubleValue() - EPSILON;
+                    values[1][i*3+1] = entry.getValue();
+                    values[0][i*3+2] = station.getRange().getB().doubleValue();
+                    values[1][i*3+2] = entry.getValue();
                     matchFound = true;
                 }
             }
-            // For now, add point if no matching measurement station found.
+            // Store points without match for later assessment.
             if (!matchFound) {
-                values[0][i*2] = km[i];
-                values[1][i*2] = load[i];
-                logger.debug("No measurement station for km " + km[i]);
+                kmWithoutStation.add(new double[] {entry.getKey(), entry.getValue(), i});
+            }
+            i++;
+        }
+
+        // Find fitting measurement stations for values without match.
+        for (double misses[]: kmWithoutStation) {
+             int idc = Math.abs(Collections.binarySearch(sortedStarts, misses[0]));
+             double locationA = sortedStarts.get(idc-2);
+             double locationB = sortedStarts.get(idc-1);
+             values[0][(int)misses[2]*3] = locationA + EPSILON;
+             values[1][(int)misses[2]*3] = misses[1];
+             values[0][(int)misses[2]*3+1] = locationB - EPSILON;
+             values[1][(int)misses[2]*3+1] = misses[1];
+             values[0][(int)misses[2]*3+2] = locationB ;
+             values[1][(int)misses[2]*3+2] = misses[1];
+        }
+
+
+        for (int x = 0; x < values[0].length-1; x++) {
+            // Correct measurement stationo overlap.
+            if (values[0][x] > values[0][x+1]) {
+                values[0][x+1] = values[0][x] + EPSILON;
+            }
+            // Introduce gaps where no data in measurement station.
+            if (Math.abs(values[0][x+1] - values[0][x]) > 3*EPSILON
+                    && values[1][x+1] != values[1][x]) {
+                values[0][x] = Double.NaN;
+                values[1][x] = Double.NaN;
             }
         }
+
         return values;
     }
 
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/SedimentLoadLSGenerator.java	Thu Apr 11 10:14:18 2013 +0200
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/SedimentLoadLSGenerator.java	Thu Apr 11 10:52:56 2013 +0200
@@ -126,57 +126,8 @@
             context.putContextValue("startkm", bounds.getLower());
             context.putContextValue("endkm", bounds.getUpper());
         }
-        if (name.equals(SEDIMENT_LOAD_COARSE)) {
-            doSedimentLoadCoarseOut(
-                (double[][]) bundle.getData(context),
-                bundle,
-                attr,
-                visible);
-        }
-        else if (name.equals(SEDIMENT_LOAD_SAND)) {
-            doSedimentLoadSandOut(
-                (double[][]) bundle.getData(context),
-                bundle,
-                attr,
-                visible);
-        }
-        else if (name.equals(SEDIMENT_LOAD_FINEMIDDLE)) {
-            doSedimentLoadFineMiddleOut(
-                (double[][]) bundle.getData(context),
-                bundle,
-                attr,
-                visible);
-        }
-        else if (name.equals(SEDIMENT_LOAD_SUSP_SAND)) {
-            doSedimentLoadSuspSandOut(
-                (double[][]) bundle.getData(context),
-                bundle,
-                attr,
-                visible);
-        }
-        else if (name.equals(SEDIMENT_LOAD_SUSP_SAND_BED)) {
-            doSedimentLoadSuspSandBedOut(
-                (double[][]) bundle.getData(context),
-                bundle,
-                attr,
-                visible);
-        }
-        else if (name.equals(SEDIMENT_LOAD_SUSP_SEDIMENT)) {
-            doSedimentLoadSuspSedimentOut(
-                (double[][]) bundle.getData(context),
-                bundle,
-                attr,
-                visible);
-        }
-        else if (name.equals(SEDIMENT_LOAD_TOTAL_LOAD)) {
-            doSedimentLoadTotalLoadOut(
-                (double[][]) bundle.getData(context),
-                bundle,
-                attr,
-                visible);
-        }
-        else if (name.equals(SEDIMENT_LOAD_TOTAL)) {
-            doSedimentLoadTotalOut(
+        if (FacetTypes.IS.SEDIMENT_LOAD(SEDIMENT_LOAD_COARSE)) {
+            doSedimentLoadOut(
                 (double[][]) bundle.getData(context),
                 bundle,
                 attr,
@@ -290,75 +241,12 @@
         return label;
     }
 
-    // TODO all double[][] eating *Out() can be subsumed.
-    protected void doSedimentLoadCoarseOut(double[][] data,
-        ArtifactAndFacet aandf, Document theme, boolean visible) {
-
-        XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme);
-        StyledSeriesBuilder.addPoints(series, data, true);
-
-        addAxisSeries(series, YAXIS.L.idx, visible);
-    }
-
-    protected void doSedimentLoadSandOut(double[][] data,
-        ArtifactAndFacet aandf, Document theme, boolean visible) {
-
-        XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme);
-        StyledSeriesBuilder.addPoints(series, data, true);
-
-        addAxisSeries(series, YAXIS.L.idx, visible);
-    }
-
-    protected void doSedimentLoadFineMiddleOut(double[][] data,
-        ArtifactAndFacet aandf, Document theme, boolean visible) {
-
-        XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme);
-        StyledSeriesBuilder.addPoints(series, data, true);
-
-        addAxisSeries(series, YAXIS.L.idx, visible);
-    }
-
-    protected void doSedimentLoadSuspSandOut(double[][] data,
+    protected void doSedimentLoadOut(double[][] data,
         ArtifactAndFacet aandf, Document theme, boolean visible) {
 
-        XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme);
-        StyledSeriesBuilder.addPoints(series, data, true);
-
-        addAxisSeries(series, YAXIS.L.idx, visible);
-    }
-
-    protected void doSedimentLoadSuspSandBedOut(double[][] data,
-        ArtifactAndFacet aandf, Document theme, boolean visible) {
-
-        XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme);
-        StyledSeriesBuilder.addPoints(series, data, true);
-
-        addAxisSeries(series, YAXIS.L.idx, visible);
-    }
-
-    protected void doSedimentLoadSuspSedimentOut(double[][] data,
-        ArtifactAndFacet aandf, Document theme, boolean visible) {
-
-        XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme);
-        StyledSeriesBuilder.addPoints(series, data, true);
-
-        addAxisSeries(series, YAXIS.L.idx, visible);
-    }
-
-    protected void doSedimentLoadTotalLoadOut(double[][] data,
-        ArtifactAndFacet aandf, Document theme, boolean visible) {
-
-        XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme);
-        StyledSeriesBuilder.addPoints(series, data, true);
-
-        addAxisSeries(series, YAXIS.L.idx, visible);
-    }
-
-    protected void doSedimentLoadTotalOut(double[][] data,
-        ArtifactAndFacet aandf, Document theme, boolean visible) {
-
-        XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme);
-        StyledSeriesBuilder.addPoints(series, data, true);
+        // Allow for gaps (NaNs).
+        XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), false, theme);
+        StyledSeriesBuilder.addPoints(series, data, false);
 
         addAxisSeries(series, YAXIS.L.idx, visible);
     }
@@ -436,5 +324,4 @@
             setInverted(true);
         }
     }
-
 }

http://dive4elements.wald.intevation.org