changeset 6875:437856cec419

FixA: Fixed reference events mapping. TODO: Same for analysis periods.
author Sascha L. Teichmann <teichmann@intevation.de>
date Tue, 20 Aug 2013 19:24:26 +0200
parents d9dfa52f69eb
children a071f0a80883
files artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisCalculation.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisResult.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixCalculation.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixReferenceEventsFacet.java
diffstat 4 files changed, 124 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisCalculation.java	Tue Aug 20 11:20:25 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisCalculation.java	Tue Aug 20 19:24:26 2013 +0200
@@ -101,6 +101,11 @@
             fitResult.getOutliers(),
             analysisPeriods);
 
+        // Workaraound to deal with same dates in data set
+        far.makeReferenceEventsDatesUnique();
+
+        far.remapReferenceIndicesToRank();
+
         return new CalculationResult(far, this);
     }
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisResult.java	Tue Aug 20 11:20:25 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisResult.java	Tue Aug 20 19:24:26 2013 +0200
@@ -8,10 +8,17 @@
 
 package org.dive4elements.river.artifacts.model.fixings;
 
+import gnu.trove.TIntIntHashMap;
+import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TLongHashSet;
+
 import java.util.Collection;
 import java.util.Date;
+import java.util.TreeMap;
 import java.util.TreeSet;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.dive4elements.river.artifacts.model.Parameters;
 
 import org.dive4elements.river.utils.KMIndex;
@@ -19,6 +26,9 @@
 public class FixAnalysisResult
 extends      FixResult
 {
+    private static final Log log =
+        LogFactory.getLog(FixAnalysisResult.class);
+
     protected KMIndex<AnalysisPeriod []> analysisPeriods;
 
     public FixAnalysisResult() {
@@ -60,15 +70,103 @@
         return dates;
     }
 
+    // TODO Refactor to be more general to be used for analysis periods, too.
+    public void makeReferenceEventsDatesUnique() {
+        TLongHashSet times   = new TLongHashSet();
+
+        TIntObjectHashMap already = new TIntObjectHashMap();
+
+        boolean debug = log.isDebugEnabled();
+
+        for (KMIndex.Entry<QWD []> entry: referenced) {
+            for (QWD value: entry.getValue()) {
+                // Map same index to same new value
+                if (already.containsKey(value.index)) {
+                    value.date = (Date)already.get(value.index);
+                    continue;
+                }
+                long time = value.date.getTime();
+                if (!times.add(time)) { // same found before
+                    if (debug) {
+                        log.debug("Found date collision for: " + value.date);
+                    }
+                    do {
+                        time += 30L*1000L; // Add 30secs
+                    }
+                    while (!times.add(time));
+                    Date newDate = new Date(time);
+                    already.put(value.index, newDate);
+                    // write back modified time
+                    value.date = newDate;
+                }
+                else {
+                    already.put(value.index, value.date);
+                }
+            }
+        }
+    }
+
+    public Collection<Integer> getReferenceEventsIndices() {
+        TreeMap<Date, Integer> dates = new TreeMap<Date, Integer>();
+        for (KMIndex.Entry<QWD []> entry: referenced) {
+            for (QWD value: entry.getValue()) {
+                dates.put(value.date, value.index);
+            }
+        }
+        return dates.values();
+    }
+
+    public void remapReferenceIndicesToRank() {
+        Collection<Integer> referenceIndices = getReferenceEventsIndices();
+        int index = 0;
+        TIntIntHashMap map = new TIntIntHashMap();
+        boolean debug = log.isDebugEnabled();
+        for (Integer refId: referenceIndices) {
+            if (debug) {
+                log.debug("map " + refId + " -> " + index);
+            }
+            map.put(refId, index);
+            ++index;
+        }
+
+        // Two passes: If there are shared references do not
+        // remap them twice. In the first pass all indices are
+        // mapped to negative values (assuming the original data
+        // is all positive). If a negative value is found ignore
+        // it because it was remapped before.
+
+        for (KMIndex.Entry<QWD []> entry: referenced) {
+            for (QWD value: entry.getValue()) {
+                if (value.index >= 0) {
+                    if (map.containsKey(value.index)) {
+                        value.index = -(map.get(value.index) + 1);
+                    }
+                    else {
+                        log.warn("Could not remap index: " + value.index);
+                    }
+                }
+            }
+        }
+
+        // In the second pass all indices are turned to positive
+        // values again.
+        for (KMIndex.Entry<QWD []> entry: referenced) {
+            for (QWD value: entry.getValue()) {
+                if (value.index < 0) {
+                    value.index = -(value.index + 1);
+                }
+            }
+        }
+    }
+
     public Collection<Date> getAnalysisEventsDates(int analysisPeriod) {
         TreeSet<Date> dates = new TreeSet<Date>();
         for (KMIndex.Entry<AnalysisPeriod []> entry: analysisPeriods) {
             QWD [] qwds = entry.getValue()[analysisPeriod].getQWDs();
-            if (qwds == null) {
-                continue;
-            }
-            for (int i = 0; i < qwds.length; i++) {
-                dates.add(qwds[i].date);
+            if (qwds != null) {
+                for (QWD qwd: qwds) {
+                    dates.add(qwd.date);
+                }
             }
         }
         return dates;
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixCalculation.java	Tue Aug 20 11:20:25 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixCalculation.java	Tue Aug 20 19:24:26 2013 +0200
@@ -114,6 +114,10 @@
             return index;
         }
 
+        public int getId() {
+            return meta.getId();
+        }
+
         public boolean getQW(
             double    km,
             double [] qs,
@@ -313,7 +317,7 @@
                             column.getDate(),
                             interpolated[i],
                             0d,
-                            column.getIndex());
+                            column.getId()); // Use database id here
                     }
                 }
                 log.warn("cannot find column for (" + q + ", " + w + ")");
@@ -364,7 +368,9 @@
                 continue;
             }
 
-            referenced.add(km, fitting.referencedToArray());
+            QWD [] refs = fitting.referencedToArray();
+
+            referenced.add(km, refs);
 
             if (fitting.hasOutliers()) {
                 outliers.add(km, fitting.outliersToArray());
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixReferenceEventsFacet.java	Tue Aug 20 11:20:25 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixReferenceEventsFacet.java	Tue Aug 20 19:24:26 2013 +0200
@@ -82,19 +82,15 @@
 
         KMIndex<QWD []> kmQWs = result.getReferenced();
         KMIndex.Entry<QWD []> kmQWsEntry = kmQWs.binarySearch(currentKm);
-
-        if (kmQWsEntry == null) {
-            return null;
+        if (kmQWsEntry != null) {
+            int ndx = index & 255;
+            for (QWD qwd: kmQWsEntry.getValue()) {
+                if (qwd.getIndex() == ndx) {
+                    return qwd;
+                }
+            }
         }
-
-        // The lower eight bits contain the index of the point.
-        int ndx = index & 255;
-        QWD [] qwds = kmQWsEntry.getValue();
-        if (ndx >= qwds.length) {
-            logger.error("index too large: " + ndx + " " + qwds.length);
-            return null;
-        }
-        return qwds[ndx];
+        return null;
     }
 
 

http://dive4elements.wald.intevation.org