changeset 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 10e6400d4166
children b63017afbca8
files flys-artifacts/ChangeLog flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Function.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsOverview.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Parameters.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/DeltaWT.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FitResult.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java
diffstat 7 files changed, 340 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Wed May 23 13:48:20 2012 +0000
+++ b/flys-artifacts/ChangeLog	Wed May 23 18:27:45 2012 +0000
@@ -14,6 +14,26 @@
 
 2012-05-23  Raimund Renkert <raimund.renkert@intevation.de>
 
+	* src/main/java/de/intevation/flys/artifacts/math/fitting/Function.java:
+	  Allow instantiation of a function with concrete parameters.
+
+	* src/main/java/de/intevation/flys/artifacts/model/Parameters.java:
+	  Enable indexed access to parameter names.
+
+	* src/main/java/de/intevation/flys/artifacts/model/fixings/FitResult.java:
+	  New. Bundles the results of the fitting.
+
+	* src/main/java/de/intevation/flys/artifacts/model/fixings/DeltaWT.java:
+	  New. Stores results of Delta W/t calcs.
+
+	* src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java:
+	  Calculate Delta W/t s, too.
+
+	* src/main/java/de/intevation/flys/artifacts/model/FixingsOverview.java:
+	  Make component filters ('and', 'or') more easy to construct.
+
+2012-05-23  Raimund Renkert <raimund.renkert@intevation.de>
+
 	* src/main/java/de/intevation/flys/artifacts/context/FLYSContextFactory.java,
 	  src/main/java/de/intevation/flys/themes/ThemeFactory.java:
 	  Improved startup performance.
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Function.java	Wed May 23 13:48:20 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/fitting/Function.java	Wed May 23 18:27:45 2012 +0000
@@ -1,5 +1,7 @@
 package de.intevation.flys.artifacts.math.fitting;
 
+import org.apache.commons.math.FunctionEvaluationException;
+
 import org.apache.commons.math.optimization.fitting.ParametricRealFunction;
 
 import de.intevation.flys.utils.DoubleUtil;
@@ -53,5 +55,22 @@
     public double [] getInitialGuess() {
         return initialGuess;
     }
+
+    public de.intevation.flys.artifacts.math.Function instantiate(
+        final double [] parameters
+    ) {
+        return new de.intevation.flys.artifacts.math.Function() {
+
+            @Override
+            public double value(double x) {
+                try {
+                    return Function.this.value(x, parameters);
+                }
+                catch (FunctionEvaluationException fee) {
+                    return Double.NaN;
+                }
+            }
+        };
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsOverview.java	Wed May 23 13:48:20 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsOverview.java	Wed May 23 18:27:45 2012 +0000
@@ -748,13 +748,24 @@
     public static abstract class ComponentFilter implements Fixing.Filter {
         protected List<Fixing.Filter> children;
 
+        public ComponentFilter() {
+            children = new ArrayList<Fixing.Filter>();
+        }
+
         public ComponentFilter(List<Fixing.Filter> children) {
             this.children = children;
         }
+
+        public void add(Fixing.Filter filter) {
+            children.add(filter);
+        }
     } // class ComponentFilter
 
     public static class OrFilter extends ComponentFilter {
 
+        public OrFilter() {
+        }
+
         public OrFilter(List<Fixing.Filter> children) {
             super(children);
         }
@@ -772,6 +783,9 @@
 
     public static class AndFilter extends ComponentFilter {
 
+        public AndFilter() {
+        }
+
         public AndFilter(List<Fixing.Filter> children) {
             super(children);
         }
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Parameters.java	Wed May 23 13:48:20 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Parameters.java	Wed May 23 18:27:45 2012 +0000
@@ -77,5 +77,22 @@
     public void removeNaNs() {
         W.removeNaNs(columns);
     }
+
+    public int [] columnIndices(String [] columns) {
+        int [] indices = new int[columns.length];
+        for (int i = 0; i < columns.length; ++i) {
+            indices[i] = columnIndex(columns[i]);
+        }
+        return indices;
+    }
+
+    public void get(int row, int [] columnIndices, double [] values) {
+        for (int i = 0; i < columnIndices.length; ++i) {
+            int index = columnIndices[i];
+            values[i] = index >= 0 && index < columns.length
+                ? columns[index].getQuick(row)
+                : Double.NaN;
+        }
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/DeltaWT.java	Wed May 23 18:27:45 2012 +0000
@@ -0,0 +1,47 @@
+package de.intevation.flys.artifacts.model.fixings;
+
+import java.io.Serializable;
+
+import java.util.Date;
+
+public class DeltaWT
+implements   Serializable
+{
+    protected double deltaW;
+    protected Date   date;
+    protected String description;
+
+    public DeltaWT() {
+    }
+
+    public DeltaWT(double deltaW, Date date, String description) {
+        this.deltaW      = deltaW;
+        this.date        = date;
+        this.description = description;
+    }
+
+    public double getDeltaW() {
+        return deltaW;
+    }
+
+    public void setDeltaW(double deltaW) {
+        this.deltaW = deltaW;
+    }
+
+    public Date getDate() {
+        return date;
+    }
+
+    public void setDate(Date date) {
+        this.date = date;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FitResult.java	Wed May 23 18:27:45 2012 +0000
@@ -0,0 +1,39 @@
+package de.intevation.flys.artifacts.model.fixings;
+
+import de.intevation.flys.artifacts.model.Parameters;
+
+import java.io.Serializable;
+
+import java.util.List;
+
+public class FitResult
+implements   Serializable
+{
+    protected Parameters    parameters;
+    protected List<DeltaWT> deltaWTs;
+
+    public FitResult() {
+    }
+
+    public FitResult(Parameters parameters, List<DeltaWT> deltaWTs) {
+        this.parameters = parameters;
+        this.deltaWTs   = deltaWTs;
+    }
+
+    public Parameters getParameters() {
+        return parameters;
+    }
+
+    public void setParameters(Parameters parameters) {
+        this.parameters = parameters;
+    }
+
+    public List<DeltaWT> getDeltaWTs() {
+        return deltaWTs;
+    }
+
+    public void setDeltaWTs(List<DeltaWT> deltaWTs) {
+        this.deltaWTs = deltaWTs;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- 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