changeset 8125:f01c65261963

(issue1448) Add WIP SedimentLoadDataFacet and use it in calculation. The unit handling is currently just a stub
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 25 Aug 2014 15:56:09 +0200
parents 2c21fd1ade39
children 353f93d5d9f7
files artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadDataFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadDataResult.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadDataCalculate.java
diffstat 3 files changed, 98 insertions(+), 157 deletions(-) [+]
line wrap: on
line diff
--- 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<MeasurementStation> 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<Double> sortedStarts = new ArrayList<Double>();
-        // Filter stations according to type.
-        List<MeasurementStation> stations = new ArrayList<MeasurementStation>();
-        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<Double>(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<Double, Double> sortedKmLoad = new TreeMap<Double,Double>();
-
-        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<Double, Double> 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;
     }
 }
--- 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<Fraction> fractions;
--- 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);
 
         */
 

http://dive4elements.wald.intevation.org