comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadFacet.java @ 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 4feda81c38bc
children 5bb179d4fd5f
comparison
equal deleted inserted replaced
5652:2e420f65c5e0 5653:5231e6b849ce
1 package de.intevation.flys.artifacts.model.minfo; 1 package de.intevation.flys.artifacts.model.minfo;
2 2
3 import org.apache.log4j.Logger; 3 import org.apache.log4j.Logger;
4 4
5 import java.util.ArrayList; 5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.Collections;
8 import java.util.Comparator;
6 import java.util.List; 9 import java.util.List;
10 import java.util.Map;
11 import java.util.TreeMap;
7 12
8 import de.intevation.artifactdatabase.state.Facet; 13 import de.intevation.artifactdatabase.state.Facet;
9 import de.intevation.artifacts.Artifact; 14 import de.intevation.artifacts.Artifact;
10 import de.intevation.artifacts.CallContext; 15 import de.intevation.artifacts.CallContext;
11 import de.intevation.flys.artifacts.FLYSArtifact; 16 import de.intevation.flys.artifacts.FLYSArtifact;
52 SedimentLoadResult result = data != null && data.length > index ? (SedimentLoadResult)data[index] : null; 57 SedimentLoadResult result = data != null && data.length > index ? (SedimentLoadResult)data[index] : null;
53 if (result == null) { 58 if (result == null) {
54 return null; 59 return null;
55 } 60 }
56 61
62 List<Double> sortedStarts = new ArrayList<Double>();
57 // Filter stations according to type. 63 // Filter stations according to type.
58 List<MeasurementStation> stations = new ArrayList<MeasurementStation>(); 64 List<MeasurementStation> stations = new ArrayList<MeasurementStation>();
59 for (MeasurementStation station: allStations) { 65 for (MeasurementStation station: allStations) {
60 if (station.getRange() == null || station.getMeasurementType() == null) { 66 if (station.getRange() == null || station.getMeasurementType() == null) {
61 continue; 67 continue;
62 } 68 }
63 if (FacetTypes.IS.SEDIMENT_LOAD_NO_FLOAT(this.getName()) 69 if (FacetTypes.IS.SEDIMENT_LOAD_NO_FLOAT(this.getName())
64 && station.getMeasurementType().equals("Geschiebe")) 70 && station.getMeasurementType().equals("Geschiebe")) {
65 stations.add(station); 71 stations.add(station);
72 sortedStarts.add(station.getStation());
73 }
66 else if (!FacetTypes.IS.SEDIMENT_LOAD_NO_FLOAT(this.getName()) 74 else if (!FacetTypes.IS.SEDIMENT_LOAD_NO_FLOAT(this.getName())
67 && station.getMeasurementType().equals("Schwebstoff")) 75 && station.getMeasurementType().equals("Schwebstoff")) {
68 stations.add(station); 76 stations.add(station);
77 sortedStarts.add(station.getStation());
78 }
69 } 79 }
80 Collections.sort(sortedStarts);
70 81
71 // Access data according to type. 82 // Access data according to type.
72 double[][] sd = getLoadData(result); 83 double[][] sd = getLoadData(result);
73 84
85 // Sort by km.
86 TreeMap<Double, Double> sortData = new TreeMap<Double,Double>();
87
74 double[] km = sd[0]; 88 double[] km = sd[0];
75 double[] load = sd[1]; 89 double[] load = sd[1];
76 90
91 for (int i = 0 ; i < km.length; i++) {
92 sortData.put(km[i], load[i]);
93 }
94
77 double[][] values = new double[2][]; 95 double[][] values = new double[2][];
78 values[0] = new double[km.length*2]; 96 values[0] = new double[km.length*3];
79 values[1] = new double[km.length*2]; 97 values[1] = new double[km.length*3];
98
99 List<double[]> kmWithoutStation = new ArrayList<double[]>();
80 100
81 // Find station via its station (km). 101 // Find station via its station (km).
82 // TODO what to do with gaps in measurement stations. 102 // TODO use a binarySearch instead of linear absdiff approach
83 for (int i = 0; i < km.length; i++) { 103 int i = 0;
104 for (Map.Entry<Double, Double> entry: sortData.entrySet()) {
84 boolean matchFound = false; 105 boolean matchFound = false;
106 // For now, ignore overlaps like (B> next A)
85 for (MeasurementStation station: stations) { 107 for (MeasurementStation station: stations) {
86 if (Math.abs(station.getStation() - km[i]) < EPSILON) { 108 if (Math.abs(station.getStation() - entry.getKey()) < EPSILON) {
87 values[0][i*2] = station.getRange().getA().doubleValue(); 109 values[0][i*3] = station.getRange().getA().doubleValue() + EPSILON;
88 values[1][i*2] = load[i]; 110 values[1][i*3] = entry.getValue();
89 values[0][i*2+1] = station.getRange().getB().doubleValue(); 111 values[0][i*3+1] = station.getRange().getB().doubleValue() - EPSILON;
90 values[1][i*2+1] = load[i]; 112 values[1][i*3+1] = entry.getValue();
113 values[0][i*3+2] = station.getRange().getB().doubleValue();
114 values[1][i*3+2] = entry.getValue();
91 matchFound = true; 115 matchFound = true;
92 } 116 }
93 } 117 }
94 // For now, add point if no matching measurement station found. 118 // Store points without match for later assessment.
95 if (!matchFound) { 119 if (!matchFound) {
96 values[0][i*2] = km[i]; 120 kmWithoutStation.add(new double[] {entry.getKey(), entry.getValue(), i});
97 values[1][i*2] = load[i]; 121 }
98 logger.debug("No measurement station for km " + km[i]); 122 i++;
123 }
124
125 // Find fitting measurement stations for values without match.
126 for (double misses[]: kmWithoutStation) {
127 int idc = Math.abs(Collections.binarySearch(sortedStarts, misses[0]));
128 double locationA = sortedStarts.get(idc-2);
129 double locationB = sortedStarts.get(idc-1);
130 values[0][(int)misses[2]*3] = locationA + EPSILON;
131 values[1][(int)misses[2]*3] = misses[1];
132 values[0][(int)misses[2]*3+1] = locationB - EPSILON;
133 values[1][(int)misses[2]*3+1] = misses[1];
134 values[0][(int)misses[2]*3+2] = locationB ;
135 values[1][(int)misses[2]*3+2] = misses[1];
136 }
137
138
139 for (int x = 0; x < values[0].length-1; x++) {
140 // Correct measurement stationo overlap.
141 if (values[0][x] > values[0][x+1]) {
142 values[0][x+1] = values[0][x] + EPSILON;
143 }
144 // Introduce gaps where no data in measurement station.
145 if (Math.abs(values[0][x+1] - values[0][x]) > 3*EPSILON
146 && values[1][x+1] != values[1][x]) {
147 values[0][x] = Double.NaN;
148 values[1][x] = Double.NaN;
99 } 149 }
100 } 150 }
151
101 return values; 152 return values;
102 } 153 }
103 154
104 155
105 /** Get data according to type of facet. */ 156 /** Get data according to type of facet. */

http://dive4elements.wald.intevation.org