diff flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFacet.java @ 5831:bd047b71ab37

Repaired internal references
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 12:06:39 +0200
parents flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadFacet.java@4a1bd43e7aa6
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFacet.java	Thu Apr 25 12:06:39 2013 +0200
@@ -0,0 +1,178 @@
+package org.dive4elements.river.artifacts.model.minfo;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+
+import org.dive4elements.river.artifacts.FLYSArtifact;
+
+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.states.DefaultState.ComputeType;
+
+import org.dive4elements.river.model.MeasurementStation;
+
+import org.dive4elements.river.utils.FLYSUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.log4j.Logger;
+
+
+/** Facet to access various sediment loads. */
+public class SedimentLoadFacet
+extends DataFacet
+{
+    /** Very own logger. */
+    private static Logger logger = Logger.getLogger(SedimentLoadFacet.class);
+
+    /** Used as tolerance value when fetching measurement stations. */
+    private static double EPSILON = 1e-5;
+
+
+    public SedimentLoadFacet() {
+    }
+
+    public SedimentLoadFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for sediment load at index: " + index);
+
+        FLYSArtifact flys = (FLYSArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        Object[] data =
+            (SedimentLoadResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
+
+        List<MeasurementStation> allStations = FLYSUtils.getRiver(flys).getMeasurementStations();
+        SedimentLoadResult result = data != null && data.length > index ? (SedimentLoadResult)data[index] : null;
+        if (result == null) {
+            return null;
+        }
+
+        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 (FacetTypes.IS.SEDIMENT_LOAD_NO_FLOAT(this.getName())
+                && 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")) {
+                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*3];
+        values[1] = new double[km.length*3];
+
+        List<double[]> kmWithoutStation = new ArrayList<double[]>();
+
+        // Find station via its station (km).
+        // 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() - entry.getKey()) < EPSILON ||
+                    station.getRange().containsTolerant(entry.getKey())) {
+                    // TODO: In rare cases, two matches can be found.
+                    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;
+                }
+            }
+            // Store points without match for later assessment.
+            if (!matchFound) {
+                logger.warn("measurement without station ("+entry.getKey()+")!");
+            }
+            i++;
+        }
+
+        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
+                    && values[1][x+1] != values[1][x]) {
+                values[0][x] = Double.NaN;
+                values[1][x] = Double.NaN;
+            }
+        }
+
+        return values;
+    }
+
+
+    /** Get data according to type of facet. */
+    private double[][] getLoadData(SedimentLoadResult result) {
+        if (getName().equals(FacetTypes.SEDIMENT_LOAD_SAND))
+            return result.getSandData();
+        else if (getName().equals(FacetTypes.SEDIMENT_LOAD_COARSE))
+            return result.getCoarseData();
+        else if (getName().equals(FacetTypes.SEDIMENT_LOAD_FINEMIDDLE))
+            return result.getFineMiddleData();
+        else if (getName().equals(FacetTypes.SEDIMENT_LOAD_SUSP_SAND))
+            return result.getSuspSandData();
+        else if (getName().equals(FacetTypes.SEDIMENT_LOAD_SUSP_SAND_BED))
+            return result.getSuspSandBedData();
+        else if (getName().equals(FacetTypes.SEDIMENT_LOAD_SUSP_SEDIMENT))
+            return result.getSuspSedimentData();
+        else if (getName().equals(FacetTypes.SEDIMENT_LOAD_TOTAL_LOAD))
+            return result.getTotalLoadData();
+        else if (getName().equals(FacetTypes.SEDIMENT_LOAD_TOTAL))
+            return result.getTotalData();
+        else {
+            logger.error("SedimentLoadFacet " + getName() + " cannot determine data type.");
+            return null;
+        }
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        SedimentLoadFacet copy = new SedimentLoadFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org