# HG changeset patch # User Felix Wolfsteller # Date 1365670376 -7200 # Node ID 5231e6b849ce4df2497e7af40efdf40db7a4b0d5 # Parent 2e420f65c5e0954cfb0511c34332ab0135f7d73e issue1077: Handle overlapping measurement station ranges, refactored Generator, Allow gaps in graph (not sorting, living with NaNs). diff -r 2e420f65c5e0 -r 5231e6b849ce flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadFacet.java --- 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 sortedStarts = new ArrayList(); // Filter stations according to type. List stations = new ArrayList(); 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 sortData = new TreeMap(); + 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 kmWithoutStation = new ArrayList(); // 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 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; } diff -r 2e420f65c5e0 -r 5231e6b849ce flys-artifacts/src/main/java/de/intevation/flys/exports/minfo/SedimentLoadLSGenerator.java --- 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); } } - }