# HG changeset patch # User Andre Heinecke # Date 1408974969 -7200 # Node ID f01c65261963b1eaf5f8f29bb167951277afc046 # Parent 2c21fd1ade39f75992f11b45d7474638039ff526 (issue1448) Add WIP SedimentLoadDataFacet and use it in calculation. The unit handling is currently just a stub diff -r 2c21fd1ade39 -r f01c65261963 artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadDataFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadDataFacet.java Mon Aug 25 12:18:35 2014 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadDataFacet.java Mon Aug 25 15:56:09 2014 +0200 @@ -23,13 +23,18 @@ import org.dive4elements.artifacts.Artifact; import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.artifacts.D4EArtifact; import org.dive4elements.river.artifacts.model.CalculationResult; import org.dive4elements.river.artifacts.model.DataFacet; import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadDataResult; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadDataResult.Fraction; + import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; import org.dive4elements.river.model.MeasurementStation; @@ -53,148 +58,66 @@ /** Very own logger. */ private static Logger logger = Logger.getLogger(SedimentLoadDataFacet.class); - /** Used as tolerance value when fetching measurement stations. */ - private static double EPSILON = 1e-5; + private static final String BASE_NAME = "sedimentload"; + public String fraction; public SedimentLoadDataFacet() { } - public SedimentLoadDataFacet(int idx, String name, String description, - ComputeType type, String stateId, String hash) { - super(idx, name, description, type, hash, stateId); - this.metaData.put("X", "chart.longitudinal.section.xaxis.label"); - this.metaData.put("Y", ""); + public SedimentLoadDataFacet(int idx, String fraction_name, String unit, + ComputeType type, String stateId, String hash, CallContext context) { + super(idx, /*name*/"", ""/*description*/, type, hash, stateId); + + this.fraction = fraction_name; + + String typeUnit; /* Gnah someone should unify unit strings,... */ + String i18nUnit; + if (unit != null && unit.equals("m3/a")) { + typeUnit = "m3a"; + i18nUnit = "m\u00b3/a"; + } else { + typeUnit = "ta"; + i18nUnit = "t/a"; + } + + name = BASE_NAME + "." + typeUnit + "." + fraction_name; + + CallMeta meta = context.getMeta(); + description = Resources.getMsg( + meta, + "facet.sedimentload." + fraction_name, + "Error: please add l10n for facet.sedimentload." + fraction_name, + new Object[] { i18nUnit }); + + /* Is this necessary? */ + metaData.put("X", "chart.longitudinal.section.xaxis.label"); + metaData.put("Y", ""); } @Override public Object getData(Artifact artifact, CallContext context) { - logger.debug("Get data for sediment load at index: " + index); + logger.debug("Get data for sediment load with fraction: " + fraction); D4EArtifact flys = (D4EArtifact) artifact; - CalculationResult res = (CalculationResult) flys.compute(context, hash, - stateId, type, false); + CalculationResult res = (CalculationResult) flys.compute(context, hash, stateId, type, false); + Object payload = res.getData(); - Object[] data = - (SedimentLoadResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS - - List allStations = RiverUtils.getRiver(flys).getMeasurementStations(); - SedimentLoadResult result = data != null && data.length > index ? (SedimentLoadResult)data[index] : null; - if (result == null) { - return null; + if (!(payload instanceof SedimentLoadDataResult)) { + logger.error("Invalid result!"); } - // These complicated calculations were necessary because - // SedimentLoad/Fraction did not contain the ranges of the given - // values. Since this changed, the code is somewhat obsolete, but stable. - // For an example of easier calculation, see the "total" part below. + SedimentLoadDataResult sdResult = (SedimentLoadDataResult) payload; - List sortedStarts = new ArrayList(); - // Filter stations according to type. - List stations = new ArrayList(); - for (MeasurementStation station: allStations) { - if (station.getRange() == null || station.getMeasurementType() == null) { - continue; - } - if (this.getName().contains("susp_sediment") - && station.getMeasurementType().equals("Schwebstoff")) { - stations.add(station); - sortedStarts.add(station.getStation()); - } - else if (!this.getName().contains("susp_sediment") - && station.getMeasurementType().equals("Geschiebe")) { - stations.add(station); - sortedStarts.add(station.getStation()); - } - } - Collections.sort(sortedStarts); - - // Handle sediment load differently, as it respects already - // the ranges that were added to SedimentLoad/Fraction. - if (getName().equals(FacetTypes.SEDIMENT_LOAD_TA_TOTAL) - ||getName().equals(FacetTypes.SEDIMENT_LOAD_M3A_TOTAL)) { - SedimentLoadLSData load = result.getLoad(); - TDoubleArrayList xPos = new TDoubleArrayList(); - TDoubleArrayList yPos = new TDoubleArrayList(); - double lastX = -1d; - for (double km: new TreeSet(load.getKms())) { - SedimentLoadFraction fraction = load.getFraction(km); - if (fraction.getTotal() != 0) { - if (Math.abs(lastX-km) >= EPSILON) { - xPos.add(Double.NaN); - yPos.add(Double.NaN); - } - xPos.add(km); - yPos.add(fraction.getTotal()); - xPos.add(fraction.getTotalRange().getEnd()); - yPos.add(fraction.getTotal()); - lastX = fraction.getTotalRange().getEnd(); - } - } - return new double[][] {xPos.toNativeArray(), yPos.toNativeArray()}; + Fraction frac = sdResult.getFractionByName(fraction); + if (frac == null) { + logger.warn("No result for: " + fraction); } - // Access data according to type (except total - see above). - double[][] sd = getLoadData(result); - - // Sort by km. - TreeMap sortedKmLoad = new TreeMap(); - - double[] km = sd[0]; - double[] load = sd[1]; - - // Build map of km->load, but directly exclude the ones which do - // not match against a measurements station ranges start. - for (int i = 0 ; i < km.length; i++) { - for (MeasurementStation station: stations) { - if (Math.abs(station.getStation() - km[i]) <= EPSILON) { - sortedKmLoad.put(km[i], load[i]); - continue; - } - } - } - - // [0] -> x, [1] -> y - double[][] values = new double[2][]; - values[0] = new double[sortedKmLoad.size()*3]; - values[1] = new double[sortedKmLoad.size()*3]; + return frac.getData(); - // Find station via its station (km). - // TODO use a binarySearch instead of linear absdiff approach - int i = 0; - for (Map.Entry kmLoad: sortedKmLoad.entrySet()) { - boolean matchFound = false; - for (int k = 0, S = stations.size(); k < S; k++) { - MeasurementStation station = stations.get(k); - if (Math.abs(station.getStation() - kmLoad.getKey()) < EPSILON) { - // Value has been taken at measurement station. - values[0][i*3] = station.getRange().getA().doubleValue() + EPSILON; - values[1][i*3] = kmLoad.getValue(); - double endValue = 0d; - // Valid until next measurements stations begin of range, - // or end of current range if last value. - if (k+2 <= S) { - endValue = stations.get(k+1).getRange().getA().doubleValue(); - } - else { - endValue = station.getRange().getB().doubleValue(); - } - values[0][i*3+1] = endValue; - values[1][i*3+1] = kmLoad.getValue(); - values[0][i*3+2] = endValue; - values[1][i*3+2] = kmLoad.getValue(); - matchFound = true; - break; - } - } - // Store points without match for later assessment. - if (!matchFound) { - logger.warn("measurement without station ("+kmLoad.getKey()+")!"); - } - i++; - } - + /* Are gaps neccessary now? for (int x = 0; x < values[0].length-1; x++) { // Introduce gaps where no data in measurement station. if (Math.abs(values[0][x+1] - values[0][x]) > 3*EPSILON @@ -204,33 +127,7 @@ } } - return values; - } - - - /** Get data according to type of facet. */ - private double[][] getLoadData(SedimentLoadResult result) { - String name = getName(); - if (FacetTypes.IS.SEDIMENT_LOAD_SAND(name)) - return result.getSandData(); - else if (FacetTypes.IS.SEDIMENT_LOAD_COARSE(name)) - return result.getCoarseData(); - else if (FacetTypes.IS.SEDIMENT_LOAD_FINEMIDDLE(name)) - return result.getFineMiddleData(); - else if (FacetTypes.IS.SEDIMENT_LOAD_SUSP_SAND(name)) - return result.getSuspSandData(); - else if (FacetTypes.IS.SEDIMENT_LOAD_SUSP_SAND_BED(name)) - return result.getSuspSandBedData(); - else if (FacetTypes.IS.SEDIMENT_LOAD_SUSP_SEDIMENT(name)) - return result.getSuspSedimentData(); - else if (FacetTypes.IS.SEDIMENT_LOAD_TOTAL_LOAD(name)) - return result.getTotalLoadData(); - else if (FacetTypes.IS.SEDIMENT_LOAD_TOTAL(name)) - return result.getTotalData(); - else { - logger.error("SedimentLoadDataFacet " + name + " cannot determine data type."); - return null; - } + return values; */ } /** Copy deeply. */ @@ -241,6 +138,7 @@ copy.type = type; copy.hash = hash; copy.stateId = stateId; + copy.fraction = fraction; return copy; } } diff -r 2c21fd1ade39 -r f01c65261963 artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadDataResult.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadDataResult.java Mon Aug 25 12:18:35 2014 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadDataResult.java Mon Aug 25 15:56:09 2014 +0200 @@ -17,6 +17,7 @@ public static class Fraction implements Serializable { private String name; + private String unit; private double [][] data; public Fraction() { @@ -25,6 +26,7 @@ public Fraction(String name, double [][] data) { this.name = name; this.data = data; + this.unit = "ta"; // TODO take from calculation } public String getName() { @@ -43,6 +45,14 @@ this.data = data; } + public String getUnit() { + return unit; + } + + public void setUnit(String unit) { + this.unit = unit; + } + } // class Fraction private List fractions; diff -r 2c21fd1ade39 -r f01c65261963 artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadDataCalculate.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadDataCalculate.java Mon Aug 25 12:18:35 2014 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadDataCalculate.java Mon Aug 25 15:56:09 2014 +0200 @@ -28,7 +28,9 @@ import org.dive4elements.river.artifacts.model.minfo.SedimentLoadLSData; import org.dive4elements.river.artifacts.model.minfo.SedimentLoadFacet; import org.dive4elements.river.artifacts.model.minfo.SedimentLoadFactory; -import org.dive4elements.river.artifacts.model.minfo.SedimentLoadResult; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadDataResult; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadDataResult.Fraction; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadDataFacet; import org.dive4elements.river.artifacts.model.minfo.SedimentLoadUnknownFacet; import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.artifacts.states.DefaultState; @@ -42,7 +44,7 @@ private static final long serialVersionUID = 1L; private static final Logger logger = Logger - .getLogger(SedimentLoadCalculate.class); + .getLogger(SedimentLoadDataCalculate.class); public static final String I18N_FACET_SEDIMENTLOAD_COARSE = "facet.sedimentload.coarse"; public static final String I18N_FACET_SEDIMENTLOAD_SAND = "facet.sedimentload.sand"; @@ -143,10 +145,45 @@ ? (CalculationResult) old : new SedimentLoadDataCalculation().calculate(access); - if (facets == null || res == null) { + SedimentLoadDataResult sdRes; + + if (res == null) { + logger.error ("No calculation result."); + } + + Object raw = res.getData(); + if (raw == null) { + logger.warn("No result data."); return res; } + if (raw instanceof SedimentLoadDataResult) { + sdRes = (SedimentLoadDataResult) raw; + } else if (raw instanceof SedimentLoadDataCalculation) { + SedimentLoadDataCalculation calc = (SedimentLoadDataCalculation) raw; + logger.warn ("Problems : " + calc.problemsToString()); + return calc; + } else { + logger.error ("Unknown result"); + return null; + } + + int i = 0; + for (Fraction fract: sdRes.getFractions()) { + logger.debug("Adding facet for fraction: " + fract.getName()); + newFacets.add(new SedimentLoadDataFacet(i++, fract.getName(), + fract.getUnit(), ComputeType.ADVANCE, id, hash, context)); + } + + newFacets.add( + new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); + + if (facets != null) { + facets.addAll(newFacets); + } else { + facets = newFacets; + } + /* XXX: THIS IS ALL BROKEN SedimentLoadResult[] results = (SedimentLoadResult[]) res.getData(); @@ -189,10 +226,6 @@ hash)); } - newFacets.add( - new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); - - facets.addAll(newFacets); */