diff flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java @ 2744:c1f2e792704a

FixA: Calculate Delta W/t, too. flys-artifacts/trunk@4479 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 23 May 2012 18:27:45 +0000
parents a441be7f1589
children cbb513a8f548
line wrap: on
line diff
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java	Wed May 23 13:48:20 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java	Wed May 23 18:27:45 2012 +0000
@@ -13,13 +13,19 @@
 import de.intevation.flys.artifacts.model.FixingsOverviewFactory;
 import de.intevation.flys.artifacts.model.Parameters;
 
+import de.intevation.flys.artifacts.model.FixingsOverview.Range;
 import de.intevation.flys.artifacts.model.FixingsOverview.Fixing;
 import de.intevation.flys.artifacts.model.FixingsOverview.IdFilter;
+import de.intevation.flys.artifacts.model.FixingsOverview.Fixing.Filter;
+import de.intevation.flys.artifacts.model.FixingsOverview.AndFilter;
+import de.intevation.flys.artifacts.model.FixingsOverview.DateRangeFilter;
+import de.intevation.flys.artifacts.model.FixingsOverview.SectorRangeFilter;
 
 import de.intevation.flys.utils.DoubleUtil;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Date;
 
 import org.apache.commons.math.MathException;
 
@@ -34,25 +40,31 @@
 {
     private static Logger logger = Logger.getLogger(FixCalculation.class);
 
-    protected String  river;
-    protected double  from;
-    protected double  to;
-    protected double  step;
-    protected boolean preprocessing;
-    protected String  function;
-    protected int []  events;
+    protected String    river;
+    protected double    from;
+    protected double    to;
+    protected double    step;
+    protected boolean   preprocessing;
+    protected String    function;
+    protected int []    events;
+    protected long [][] analysisPeriods;
+    protected int       qSectorStart;
+    protected int       qSectorEnd;
 
     public FixCalculation() {
     }
 
     public FixCalculation(FixationArtifactAccess access) {
 
-        String river    = access.getRiver();
-        Double from     = access.getFrom();
-        Double to       = access.getTo();
-        Double step     = access.getStep();
-        String function = access.getFunction();
-        int [] events   = access.getEvents();
+        String    river           = access.getRiver();
+        Double    from            = access.getFrom();
+        Double    to              = access.getTo();
+        Double    step            = access.getStep();
+        String    function        = access.getFunction();
+        int []    events          = access.getEvents();
+        long [][] analysisPeriods = access.getAnalysisPeriods();
+        Integer   qSectorStart    = access.getQSectorStart();
+        Integer   qSectorEnd      = access.getQSectorEnd();
 
         if (river == null) {
             // TODO: i18n
@@ -84,13 +96,31 @@
             addProblem("fix.missing.events");
         }
 
+        if (analysisPeriods == null || analysisPeriods.length < 1) {
+            // TODO: i18n
+            addProblem("fix.missing.analysis.periods");
+        }
+
+        if (qSectorStart == null) {
+            // TODO: i18n
+            addProblem("fix.missing.qstart.sector");
+        }
+
+        if (qSectorEnd == null) {
+            // TODO: i18n
+            addProblem("fix.missing.qend.sector");
+        }
+
         if (!hasProblems()) {
-            this.river    = river;
-            this.from     = from;
-            this.to       = to;
-            this.step     = step;
-            this.function = function;
-            this.events   = events;
+            this.river           = river;
+            this.from            = from;
+            this.to              = to;
+            this.step            = step;
+            this.function        = function;
+            this.events          = events;
+            this.analysisPeriods = analysisPeriods;
+            this.qSectorStart    = qSectorStart;
+            this.qSectorEnd      = qSectorEnd;
         }
     }
 
@@ -192,8 +222,141 @@
             results.removeNaNs();
         }
 
-        // TODO: Calculate Delta W/t, too.
-        return new CalculationResult(results, this);
+        // Calculate Delta W/t
+        List<DeltaWT> deltaWTs = calculateDeltaWTs(
+            func,
+            overview,
+            results);
+
+        // TODO: Add km indexed structure for deltaWTs
+
+        return new CalculationResult(deltaWTs, this);
+    }
+
+    public List<DeltaWT> calculateDeltaWTs(
+        Function        function,
+        FixingsOverview overview,
+        Parameters      results
+    ) {
+        List<DeltaWT> deltaWTs = new ArrayList<DeltaWT>();
+
+        Column [][] analysisColumns = getAnalysisColumns(overview);
+
+        int [] parameterIndices = 
+            results.columnIndices(function.getParameterNames());
+
+        double [] parameterValues =
+            new double[parameterIndices.length];
+
+        double [] ow = new double[1];
+
+        for (int i = 0, N = results.size(); i < N; ++i) {
+            double km = results.get(i, "km");
+            results.get(i, parameterIndices, parameterValues);
+
+            // This is the paraterized function for a given km.
+            de.intevation.flys.artifacts.math.Function instance =
+                function.instantiate(parameterValues);
+
+            // Evaluate all columns for all analysis periods.
+            for (int j = 0; j < analysisColumns.length; ++j) {
+                Column [] periodColumns = analysisColumns[j];
+
+                for (int k = 0; k < periodColumns.length; ++k) {
+                    Column pc = periodColumns[k];
+
+                    // Q from real data.
+                    double q = pc.data.getQ(km);
+                    if (Double.isNaN(q)) {
+                        continue;
+                    }
+
+                    // Calculate W from function.
+                    double nw = instance.value(q);
+                    if (Double.isNaN(nw)) {
+                        continue;
+                    }
+
+                    // W from real data.
+                    pc.data.getW(km, ow);
+
+                    if (Double.isNaN(ow[0])) {
+                        continue;
+                    }
+
+                    double deltaW = ow[0] - nw;
+
+                    DeltaWT deltaWT = new DeltaWT(
+                        deltaW,
+                        pc.meta.getStartTime(),
+                        pc.meta.getDescription());
+
+                    deltaWTs.add(deltaWT);
+                }
+            }
+        }
+
+        return deltaWTs;
+    }
+
+    /** Helper class to bundle the meta information of a column 
+     *  and the real data.
+     */
+    protected static class Column {
+
+        protected Fixing.Column meta;
+        protected FixingsColumn data;
+
+        public Column() {
+        }
+
+        public Column(Fixing.Column meta, FixingsColumn data) {
+            this.meta = meta;
+            this.data = data;
+        }
+    } // class Column
+
+    /** Fetch meta and data columns for analysis periods. */
+    protected Column [][] getAnalysisColumns(FixingsOverview overview) {
+
+        Column columns [][] = new Column[analysisPeriods.length][];
+
+        Range range = new Range(from, to);
+        SectorRangeFilter sectorRangeFilter =
+            new SectorRangeFilter(qSectorStart, qSectorEnd);
+
+        FixingsColumnFactory fcf = FixingsColumnFactory.getInstance();
+
+        for (int i = 0; i < columns.length; ++i) {
+
+            // Construct filter for period.
+            long [] period = analysisPeriods[i];
+
+            AndFilter filter = new AndFilter();
+
+            DateRangeFilter dateRangeFilter =
+                new DateRangeFilter(
+                    new Date(period[0]),
+                    new Date(period[1]));
+
+            filter.add(dateRangeFilter);
+            filter.add(sectorRangeFilter);
+
+            List<Fixing.Column> metaCols = overview.filter(range, filter);
+
+            ArrayList<Column> cols = new ArrayList<Column>(metaCols.size());
+
+            // Only use columns which have data.
+            for (Fixing.Column meta: metaCols) {
+                FixingsColumn data = fcf.getColumnData(meta);
+                if (data != null) {
+                    cols.add(new Column(meta, data));
+                }
+            }
+            columns[i] = cols.toArray(new Column[cols.size()]);
+        }
+
+        return columns;
     }
 
     protected static String [] createColumnNames(String [] parameters) {

http://dive4elements.wald.intevation.org