changeset 3411:0ef83077c93f

FixA: Renamed FixCalculation to FixAnalysisCalculation. flys-artifacts/trunk@5064 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 19 Jul 2012 14:11:11 +0000
parents f382127df48e
children da000d9513f7
files flys-artifacts/ChangeLog flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/FixAnalysisAccess.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisCalculation.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/FixationCompute.java
diffstat 5 files changed, 633 insertions(+), 620 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Thu Jul 19 13:56:11 2012 +0000
+++ b/flys-artifacts/ChangeLog	Thu Jul 19 14:11:11 2012 +0000
@@ -1,3 +1,15 @@
+2012-07-19	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
+
+	* src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java:
+	  Deleted
+
+	* src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisCalculation.java:
+	  Re-added.
+
+	* src/main/java/de/intevation/flys/artifacts/access/FixAnalysisAccess.java,
+	  src/main/java/de/intevation/flys/artifacts/states/fixation/FixationCompute.java:
+	  Adjusted class name usage.
+
 2012-07-19	Christian Lins	<christian.lins@intevation.de>
 
 	* src/main/java/de/intevation/flys/exports/fixings/FixWQCurveGenerator.java,
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/FixAnalysisAccess.java	Thu Jul 19 13:56:11 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/access/FixAnalysisAccess.java	Thu Jul 19 14:11:11 2012 +0000
@@ -1,7 +1,9 @@
 package de.intevation.flys.artifacts.access;
 
 import de.intevation.artifactdatabase.data.StateData;
+
 import de.intevation.flys.artifacts.FLYSArtifact;
+
 import de.intevation.flys.artifacts.model.DateRange;
 
 import java.util.Arrays;
@@ -9,7 +11,6 @@
 
 import org.apache.log4j.Logger;
 
-
 public class FixAnalysisAccess
 extends      Access
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisCalculation.java	Thu Jul 19 14:11:11 2012 +0000
@@ -0,0 +1,617 @@
+package de.intevation.flys.artifacts.model.fixings;
+
+import de.intevation.flys.artifacts.access.FixAnalysisAccess;
+
+import de.intevation.flys.artifacts.math.fitting.Function;
+import de.intevation.flys.artifacts.math.fitting.FunctionFactory;
+
+import de.intevation.flys.artifacts.model.Calculation;
+import de.intevation.flys.artifacts.model.CalculationResult;
+import de.intevation.flys.artifacts.model.DateRange;
+import de.intevation.flys.artifacts.model.FixingsColumn;
+import de.intevation.flys.artifacts.model.FixingsColumnFactory;
+
+import de.intevation.flys.artifacts.model.FixingsOverview.AndFilter;
+import de.intevation.flys.artifacts.model.FixingsOverview.DateRangeFilter;
+
+import de.intevation.flys.artifacts.model.FixingsOverview.Fixing.Filter;
+
+import de.intevation.flys.artifacts.model.FixingsOverview.Fixing;
+import de.intevation.flys.artifacts.model.FixingsOverview.IdsFilter;
+import de.intevation.flys.artifacts.model.FixingsOverview.KmFilter;
+import de.intevation.flys.artifacts.model.FixingsOverview.SectorFilter;
+import de.intevation.flys.artifacts.model.FixingsOverview.SectorRangeFilter;
+
+import de.intevation.flys.artifacts.model.FixingsOverview;
+import de.intevation.flys.artifacts.model.FixingsOverviewFactory;
+import de.intevation.flys.artifacts.model.Parameters;
+import de.intevation.flys.artifacts.model.Range;
+
+import de.intevation.flys.utils.DateAverager;
+import de.intevation.flys.utils.DoubleUtil;
+import de.intevation.flys.utils.KMIndex;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
+
+import org.apache.log4j.Logger;
+
+public class FixAnalysisCalculation
+extends      Calculation
+{
+    private static Logger log = Logger.getLogger(FixAnalysisCalculation.class);
+
+    public static final double EPSILON = 1e-4;
+
+    protected String       river;
+    protected double       from;
+    protected double       to;
+    protected double       step;
+    protected boolean      preprocessing;
+    protected String       function;
+    protected int []       events;
+    protected DateRange    referencePeriod;
+    protected DateRange [] analysisPeriods;
+    protected int          qSectorStart;
+    protected int          qSectorEnd;
+
+    public FixAnalysisCalculation() {
+    }
+
+    public FixAnalysisCalculation(FixAnalysisAccess 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();
+        DateRange    referencePeriod = access.getReferencePeriod();
+        DateRange [] analysisPeriods = access.getAnalysisPeriods();
+        Integer      qSectorStart    = access.getQSectorStart();
+        Integer      qSectorEnd      = access.getQSectorEnd();
+        Boolean      preprocessing   = access.getPreprocessing();
+
+        if (river == null) {
+            addProblem("fix.missing.river");
+        }
+
+        if (from == null) {
+            addProblem("fix.missing.from");
+        }
+
+        if (to == null) {
+            addProblem("fix.missing.to");
+        }
+
+        if (step == null) {
+            addProblem("fix.missing.step");
+        }
+
+        if (function == null) {
+            addProblem("fix.missing.function");
+        }
+
+        if (events == null || events.length < 1) {
+            addProblem("fix.missing.events");
+        }
+
+        if (referencePeriod == null) {
+            addProblem("fix.missing.reference.period");
+        }
+
+        if (analysisPeriods == null || analysisPeriods.length < 1) {
+            addProblem("fix.missing.analysis.periods");
+        }
+
+        if (qSectorStart == null) {
+            addProblem("fix.missing.qstart.sector");
+        }
+
+        if (qSectorEnd == null) {
+            addProblem("fix.missing.qend.sector");
+        }
+
+        if (preprocessing == null) {
+            addProblem("fix.missing.preprocessing");
+        }
+
+        if (!hasProblems()) {
+            this.river           = river;
+            this.from            = from;
+            this.to              = to;
+            this.step            = step;
+            this.function        = function;
+            this.events          = events;
+            this.referencePeriod = referencePeriod;
+            this.analysisPeriods = analysisPeriods;
+            this.qSectorStart    = qSectorStart;
+            this.qSectorEnd      = qSectorEnd;
+            this.preprocessing   = preprocessing;
+        }
+    }
+
+    public CalculationResult calculate() {
+
+        boolean debug = log.isDebugEnabled();
+
+        FixingsOverview overview =
+            FixingsOverviewFactory.getOverview(river);
+
+        if (overview == null) {
+            addProblem("fix.no.overview.available");
+        }
+
+        Function func = FunctionFactory.getInstance()
+            .getFunction(function);
+
+        if (func == null) {
+            addProblem("fix.invalid.function.name");
+        }
+
+        if (hasProblems()) {
+            return new CalculationResult(this);
+        }
+
+        final List<Column> eventColumns = getEventColumns(overview);
+
+        if (eventColumns.size() < 2) {
+            addProblem("fix.too.less.data.columns");
+            return new CalculationResult(this);
+        }
+
+        double [] kms = DoubleUtil.explode(from, to, step / 1000.0);
+
+        final double  [] qs = new double[eventColumns.size()];
+        final double  [] ws = new double[qs.length];
+        final boolean [] interpolated = new boolean[ws.length];
+
+        Fitting.QWDFactory qwdFactory = new Fitting.QWDFactory() {
+            @Override
+            public QWD create(double q, double w) {
+                // Check all the event columns for close match
+                // and take the description and the date from meta.
+                for (int i = 0; i < qs.length; ++i) {
+                    if (Math.abs(qs[i]-q) < EPSILON
+                    &&  Math.abs(ws[i]-w) < EPSILON) {
+                        Column column = eventColumns.get(i);
+                        return new QWD(
+                            qs[i], ws[i],
+                            column.getDescription(),
+                            column.getDate(),
+                            interpolated[i],
+                            0d);
+                    }
+                }
+                log.warn("cannot find column for (" + q + ", " + w + ")");
+                return new QWD(q, w);
+            }
+        };
+
+        Fitting fitting = new Fitting(func, qwdFactory, preprocessing);
+
+        String [] parameterNames = func.getParameterNames();
+
+        Parameters results =
+            new Parameters(createColumnNames(parameterNames));
+
+        boolean invalid = false;
+
+        if (debug) {
+            log.debug("number of kms: " + kms.length);
+        }
+
+        KMIndex<QW []>  outliers   = new KMIndex<QW []>();
+        KMIndex<QWD []> referenced = new KMIndex<QWD []>(kms.length);
+
+        int kmIndex             = results.columnIndex("km");
+        int chiSqrIndex         = results.columnIndex("chi_sqr");
+        int maxQIndex           = results.columnIndex("max_q");
+        int stdDevIndex         = results.columnIndex("std-dev");
+        int [] parameterIndices = results.columnIndices(parameterNames);
+
+        int numFailed = 0;
+
+        for (int i = 0; i < kms.length; ++i) {
+            double km = kms[i];
+
+            // Fill Qs and Ws from event columns.
+            for (int j = 0; j < ws.length; ++j) {
+                interpolated[j] = !eventColumns.get(j).getQW(km, qs, ws, j);
+            }
+
+            fitting.reset();
+
+            if (!fitting.fit(qs, ws)) {
+                ++numFailed;
+                addProblem(km, "fix.fitting.failed");
+                continue;
+            }
+
+            referenced.add(km, fitting.referencedToArray());
+
+            if (fitting.hasOutliers()) {
+                outliers.add(km, fitting.outliersToArray());
+            }
+
+            int row = results.newRow();
+            double [] values = fitting.getParameters();
+
+            results.set(row, kmIndex, km);
+            results.set(row, chiSqrIndex, fitting.getChiSquare());
+            results.set(row, stdDevIndex, fitting.getStandardDeviation());
+            results.set(row, maxQIndex,   fitting.getMaxQ());
+            invalid |= results.set(row, parameterIndices, values);
+
+            if (debug) {
+                log.debug("km: "+km+" " + toString(parameterNames, values));
+            }
+        }
+
+        if (debug) {
+            log.debug("success: " + (kms.length - numFailed));
+            log.debug("failed: " + numFailed);
+        }
+
+        if (invalid) {
+            addProblem("fix.invalid.values");
+            results.removeNaNs();
+        }
+
+        KMIndex<AnalysisPeriod []> analysisPeriods =
+            calculateAnalysisPeriods(func, results, overview);
+
+        outliers.sort();
+        referenced.sort();
+        analysisPeriods.sort();
+
+        FixResult fr = new FixResult(
+            results,
+            referenced, outliers,
+            analysisPeriods);
+
+        return new CalculationResult(fr, this);
+    }
+
+    protected String toString(String [] parameterNames, double [] values) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < parameterNames.length; ++i) {
+            if (i > 0) sb.append(", ");
+            sb.append(parameterNames[i]).append(": ").append(values[i]);
+        }
+        return sb.toString();
+    }
+
+    protected List<Column> getEventColumns(FixingsOverview overview) {
+
+        FixingsColumnFactory fcf = FixingsColumnFactory.getInstance();
+
+        IdsFilter ids = new IdsFilter(events);
+        DateRangeFilter rdf = new DateRangeFilter(
+            referencePeriod.getFrom(),
+            referencePeriod.getTo());
+        Filter filter = new AndFilter().add(rdf).add(ids);
+
+        List<Fixing.Column> metas = overview.filter(null, filter);
+
+        List<Column> columns = new ArrayList<Column>(metas.size());
+
+        for (Fixing.Column meta: metas) {
+
+            FixingsColumn data = fcf.getColumnData(meta);
+            if (data == null) {
+                addProblem("fix.cannot.load.data");
+            }
+            else {
+                columns.add(new Column(meta, data));
+            }
+        }
+
+        return columns;
+    }
+
+
+    protected KMIndex<AnalysisPeriod []> calculateAnalysisPeriods(
+        Function        function,
+        Parameters      parameters,
+        FixingsOverview overview
+    ) {
+        Range range = new Range(from, to);
+
+        int kmIndex   = parameters.columnIndex("km");
+        int maxQIndex = parameters.columnIndex("max_q");
+
+        ColumnCache cc = new ColumnCache();
+
+        double [] wq = new double[2];
+
+        int [] parameterIndices =
+            parameters.columnIndices(function.getParameterNames());
+
+        double [] parameterValues = new double[parameterIndices.length];
+
+        DateAverager dateAverager = new DateAverager();
+
+        KMIndex<AnalysisPeriod []> results =
+            new KMIndex<AnalysisPeriod []>(parameters.size());
+
+        IdsFilter idsFilter = new IdsFilter(events);
+
+        for (int row = 0, R = parameters.size(); row < R; ++row) {
+            double km = parameters.get(row, kmIndex);
+            parameters.get(row, parameterIndices, parameterValues);
+
+            // This is the paraterized function for a given km.
+            de.intevation.flys.artifacts.math.Function instance =
+                function.instantiate(parameterValues);
+
+            KmFilter kmFilter = new KmFilter(km);
+
+            ArrayList<AnalysisPeriod> periodResults =
+                new ArrayList<AnalysisPeriod>(analysisPeriods.length);
+
+            for (DateRange analysisPeriod: analysisPeriods) {
+                DateRangeFilter drf = new DateRangeFilter(
+                    analysisPeriod.getFrom(),
+                    analysisPeriod.getTo());
+
+                QWD []    qSectorAverages = new QWD[4];
+                double [] qSectorStdDevs  = new double[4];
+
+                ArrayList<QWD> allQWDs = new ArrayList<QWD>();
+
+                // for all Q sectors.
+                for (int qSector = qSectorStart; qSector < qSectorEnd; ++qSector) {
+
+                    Filter filter = new AndFilter()
+                        .add(kmFilter)
+                        .add(new SectorFilter(qSector))
+                        .add(drf)
+                        .add(idsFilter);
+
+                    List<Fixing.Column> metas = overview.filter(range, filter);
+
+                    if (metas.isEmpty()) {
+                        // No fixings for km and analysis period
+                        continue;
+                    }
+
+                    double sumQ = 0.0;
+                    double sumW = 0.0;
+
+                    StandardDeviation stdDev = new StandardDeviation();
+
+                    List<QWD> qwds = new ArrayList<QWD>(metas.size());
+
+                    dateAverager.clear();
+
+                    for (Fixing.Column meta: metas) {
+                        if (meta.findQSector(km) != qSector) {
+                            // Ignore not matching sectors.
+                            continue;
+                        }
+
+                        Column column = cc.getColumn(meta);
+                        if (column == null || !column.getQW(km, wq)) {
+                            continue;
+                        }
+
+                        double fw = instance.value(wq[1]);
+                        if (Double.isNaN(fw)) {
+                            continue;
+                        }
+
+                        double dw = (wq[0] - fw)*100.0;
+
+                        stdDev.increment(dw);
+
+                        Date date = column.getDate();
+                        String description = column.getDescription();
+
+                        QWD qwd = new QWD(
+                            wq[1], wq[0], description, date, true, dw);
+
+                        qwds.add(qwd);
+
+                        sumW += wq[0];
+                        sumQ += wq[1];
+
+                        dateAverager.add(date);
+                    }
+
+                    // Calulate average per Q sector.
+                    int N = qwds.size();
+                    if (N > 0) {
+                        allQWDs.addAll(qwds);
+                        double avgW = sumW / N;
+                        double avgQ = sumQ / N;
+
+                        double avgFw = instance.value(avgQ);
+                        if (!Double.isNaN(avgFw)) {
+                            double avgDw = (avgW - avgFw)*100.0;
+                            Date avgDate = dateAverager.getAverage();
+
+                            String avgDescription = "avg.deltawt." + qSector;
+
+                            QWD avgQWD = new QWD(
+                                avgQ, avgW, avgDescription, avgDate, true, avgDw);
+
+                            qSectorAverages[qSector] = avgQWD;
+                        }
+                        qSectorStdDevs[qSector] = stdDev.getResult();
+                    }
+                    else {
+                        qSectorStdDevs[qSector] = Double.NaN;
+                    }
+                } // for all Q sectors
+
+                QWD [] aqwds = allQWDs.toArray(new QWD[allQWDs.size()]);
+
+                AnalysisPeriod periodResult = new AnalysisPeriod(
+                    analysisPeriod,
+                    aqwds,
+                    qSectorAverages,
+                    qSectorStdDevs);
+                periodResults.add(periodResult);
+            }
+
+            double maxQ = -Double.MAX_VALUE;
+            for (AnalysisPeriod ap: periodResults) {
+                double q = ap.getMaxQ();
+                if (q > maxQ) {
+                    maxQ = q;
+                }
+            }
+
+            double oldMaxQ = parameters.get(row, maxQIndex);
+            if (oldMaxQ < maxQ) {
+                parameters.set(row, maxQIndex, maxQ);
+            }
+
+            results.add(km, periodResults.toArray(
+                new AnalysisPeriod[periodResults.size()]));
+        }
+
+        return results;
+    }
+
+    /** 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;
+        }
+
+        public Date getDate() {
+            return meta.getStartTime();
+        }
+
+        public String getDescription() {
+            return meta.getDescription();
+        }
+
+        public boolean getQW(
+            double    km,
+            double [] qs,
+            double [] ws,
+            int       index
+        ) {
+            qs[index] = data.getQ(km);
+            return data.getW(km, ws, index);
+        }
+
+        public boolean getQW(double km, double [] wq) {
+            data.getW(km, wq, 0);
+            if (Double.isNaN(wq[0])) return false;
+            wq[1] = data.getQ(km);
+            return !Double.isNaN(wq[1]);
+        }
+    } // class Column
+
+
+    /**
+     * Helper class to find the data belonging to meta info more quickly.
+     */
+    public static class ColumnCache {
+
+        protected Map<Integer, Column> columns;
+
+        public ColumnCache() {
+            columns = new HashMap<Integer, Column>();
+        }
+
+        public Column getColumn(Fixing.Column meta) {
+            Integer key = meta.getId();
+            Column column = columns.get(key);
+            if (column == null) {
+                FixingsColumn data = FixingsColumnFactory
+                    .getInstance()
+                    .getColumnData(meta);
+                if (data != null) {
+                    column = new Column(meta, data);
+                    columns.put(key, column);
+                }
+            }
+            return column;
+        }
+    } // class ColumnCache
+
+    /** Fetch meta and data columns for analysis periods. */
+    protected Column [][] getAnalysisColumns(FixingsOverview overview) {
+
+        boolean debug = log.isDebugEnabled();
+        if (debug) {
+            log.debug("number analysis periods: " + analysisPeriods.length);
+        }
+
+        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.
+            DateRange period = analysisPeriods[i];
+
+            AndFilter filter = new AndFilter();
+
+            DateRangeFilter dateRangeFilter =
+                new DateRangeFilter(period.getFrom(), period.getTo());
+
+            filter.add(dateRangeFilter);
+            filter.add(sectorRangeFilter);
+
+            List<Fixing.Column> metaCols = overview.filter(range, filter);
+
+            if (debug) {
+                log.debug("number of filtered columns: " + metaCols.size());
+            }
+
+            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));
+                }
+            }
+
+            if (debug) {
+                log.debug("failed loading: " + (metaCols.size()-cols.size()));
+            }
+            columns[i] = cols.toArray(new Column[cols.size()]);
+        }
+
+        return columns;
+    }
+
+    protected static String [] createColumnNames(String [] parameters) {
+        String [] result = new String[parameters.length + 4];
+        result[0] = "km";
+        result[1] = "chi_sqr";
+        result[2] = "max_q";
+        result[3] = "std-dev";
+        System.arraycopy(parameters, 0, result, 4, parameters.length);
+        return result;
+    }
+}
+// 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	Thu Jul 19 13:56:11 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,617 +0,0 @@
-package de.intevation.flys.artifacts.model.fixings;
-
-import de.intevation.flys.artifacts.access.FixAnalysisAccess;
-
-import de.intevation.flys.artifacts.math.fitting.Function;
-import de.intevation.flys.artifacts.math.fitting.FunctionFactory;
-
-import de.intevation.flys.artifacts.model.Calculation;
-import de.intevation.flys.artifacts.model.CalculationResult;
-import de.intevation.flys.artifacts.model.DateRange;
-import de.intevation.flys.artifacts.model.FixingsColumn;
-import de.intevation.flys.artifacts.model.FixingsColumnFactory;
-
-import de.intevation.flys.artifacts.model.FixingsOverview.AndFilter;
-import de.intevation.flys.artifacts.model.FixingsOverview.DateRangeFilter;
-
-import de.intevation.flys.artifacts.model.FixingsOverview.Fixing.Filter;
-
-import de.intevation.flys.artifacts.model.FixingsOverview.Fixing;
-import de.intevation.flys.artifacts.model.FixingsOverview.IdsFilter;
-import de.intevation.flys.artifacts.model.FixingsOverview.KmFilter;
-import de.intevation.flys.artifacts.model.FixingsOverview.SectorFilter;
-import de.intevation.flys.artifacts.model.FixingsOverview.SectorRangeFilter;
-
-import de.intevation.flys.artifacts.model.FixingsOverview;
-import de.intevation.flys.artifacts.model.FixingsOverviewFactory;
-import de.intevation.flys.artifacts.model.Parameters;
-import de.intevation.flys.artifacts.model.Range;
-
-import de.intevation.flys.utils.DateAverager;
-import de.intevation.flys.utils.DoubleUtil;
-import de.intevation.flys.utils.KMIndex;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
-
-import org.apache.log4j.Logger;
-
-public class FixCalculation
-extends      Calculation
-{
-    private static Logger log = Logger.getLogger(FixCalculation.class);
-
-    public static final double EPSILON = 1e-4;
-
-    protected String       river;
-    protected double       from;
-    protected double       to;
-    protected double       step;
-    protected boolean      preprocessing;
-    protected String       function;
-    protected int []       events;
-    protected DateRange    referencePeriod;
-    protected DateRange [] analysisPeriods;
-    protected int          qSectorStart;
-    protected int          qSectorEnd;
-
-    public FixCalculation() {
-    }
-
-    public FixCalculation(FixAnalysisAccess 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();
-        DateRange    referencePeriod = access.getReferencePeriod();
-        DateRange [] analysisPeriods = access.getAnalysisPeriods();
-        Integer      qSectorStart    = access.getQSectorStart();
-        Integer      qSectorEnd      = access.getQSectorEnd();
-        Boolean      preprocessing   = access.getPreprocessing();
-
-        if (river == null) {
-            addProblem("fix.missing.river");
-        }
-
-        if (from == null) {
-            addProblem("fix.missing.from");
-        }
-
-        if (to == null) {
-            addProblem("fix.missing.to");
-        }
-
-        if (step == null) {
-            addProblem("fix.missing.step");
-        }
-
-        if (function == null) {
-            addProblem("fix.missing.function");
-        }
-
-        if (events == null || events.length < 1) {
-            addProblem("fix.missing.events");
-        }
-
-        if (referencePeriod == null) {
-            addProblem("fix.missing.reference.period");
-        }
-
-        if (analysisPeriods == null || analysisPeriods.length < 1) {
-            addProblem("fix.missing.analysis.periods");
-        }
-
-        if (qSectorStart == null) {
-            addProblem("fix.missing.qstart.sector");
-        }
-
-        if (qSectorEnd == null) {
-            addProblem("fix.missing.qend.sector");
-        }
-
-        if (preprocessing == null) {
-            addProblem("fix.missing.preprocessing");
-        }
-
-        if (!hasProblems()) {
-            this.river           = river;
-            this.from            = from;
-            this.to              = to;
-            this.step            = step;
-            this.function        = function;
-            this.events          = events;
-            this.referencePeriod = referencePeriod;
-            this.analysisPeriods = analysisPeriods;
-            this.qSectorStart    = qSectorStart;
-            this.qSectorEnd      = qSectorEnd;
-            this.preprocessing   = preprocessing;
-        }
-    }
-
-    public CalculationResult calculate() {
-
-        boolean debug = log.isDebugEnabled();
-
-        FixingsOverview overview =
-            FixingsOverviewFactory.getOverview(river);
-
-        if (overview == null) {
-            addProblem("fix.no.overview.available");
-        }
-
-        Function func = FunctionFactory.getInstance()
-            .getFunction(function);
-
-        if (func == null) {
-            addProblem("fix.invalid.function.name");
-        }
-
-        if (hasProblems()) {
-            return new CalculationResult(this);
-        }
-
-        final List<Column> eventColumns = getEventColumns(overview);
-
-        if (eventColumns.size() < 2) {
-            addProblem("fix.too.less.data.columns");
-            return new CalculationResult(this);
-        }
-
-        double [] kms = DoubleUtil.explode(from, to, step / 1000.0);
-
-        final double  [] qs = new double[eventColumns.size()];
-        final double  [] ws = new double[qs.length];
-        final boolean [] interpolated = new boolean[ws.length];
-
-        Fitting.QWDFactory qwdFactory = new Fitting.QWDFactory() {
-            @Override
-            public QWD create(double q, double w) {
-                // Check all the event columns for close match
-                // and take the description and the date from meta.
-                for (int i = 0; i < qs.length; ++i) {
-                    if (Math.abs(qs[i]-q) < EPSILON
-                    &&  Math.abs(ws[i]-w) < EPSILON) {
-                        Column column = eventColumns.get(i);
-                        return new QWD(
-                            qs[i], ws[i],
-                            column.getDescription(),
-                            column.getDate(),
-                            interpolated[i],
-                            0d);
-                    }
-                }
-                log.warn("cannot find column for (" + q + ", " + w + ")");
-                return new QWD(q, w);
-            }
-        };
-
-        Fitting fitting = new Fitting(func, qwdFactory, preprocessing);
-
-        String [] parameterNames = func.getParameterNames();
-
-        Parameters results =
-            new Parameters(createColumnNames(parameterNames));
-
-        boolean invalid = false;
-
-        if (debug) {
-            log.debug("number of kms: " + kms.length);
-        }
-
-        KMIndex<QW []>  outliers   = new KMIndex<QW []>();
-        KMIndex<QWD []> referenced = new KMIndex<QWD []>(kms.length);
-
-        int kmIndex             = results.columnIndex("km");
-        int chiSqrIndex         = results.columnIndex("chi_sqr");
-        int maxQIndex           = results.columnIndex("max_q");
-        int stdDevIndex         = results.columnIndex("std-dev");
-        int [] parameterIndices = results.columnIndices(parameterNames);
-
-        int numFailed = 0;
-
-        for (int i = 0; i < kms.length; ++i) {
-            double km = kms[i];
-
-            // Fill Qs and Ws from event columns.
-            for (int j = 0; j < ws.length; ++j) {
-                interpolated[j] = !eventColumns.get(j).getQW(km, qs, ws, j);
-            }
-
-            fitting.reset();
-
-            if (!fitting.fit(qs, ws)) {
-                ++numFailed;
-                addProblem(km, "fix.fitting.failed");
-                continue;
-            }
-
-            referenced.add(km, fitting.referencedToArray());
-
-            if (fitting.hasOutliers()) {
-                outliers.add(km, fitting.outliersToArray());
-            }
-
-            int row = results.newRow();
-            double [] values = fitting.getParameters();
-
-            results.set(row, kmIndex, km);
-            results.set(row, chiSqrIndex, fitting.getChiSquare());
-            results.set(row, stdDevIndex, fitting.getStandardDeviation());
-            results.set(row, maxQIndex,   fitting.getMaxQ());
-            invalid |= results.set(row, parameterIndices, values);
-
-            if (debug) {
-                log.debug("km: "+km+" " + toString(parameterNames, values));
-            }
-        }
-
-        if (debug) {
-            log.debug("success: " + (kms.length - numFailed));
-            log.debug("failed: " + numFailed);
-        }
-
-        if (invalid) {
-            addProblem("fix.invalid.values");
-            results.removeNaNs();
-        }
-
-        KMIndex<AnalysisPeriod []> analysisPeriods =
-            calculateAnalysisPeriods(func, results, overview);
-
-        outliers.sort();
-        referenced.sort();
-        analysisPeriods.sort();
-
-        FixResult fr = new FixResult(
-            results,
-            referenced, outliers,
-            analysisPeriods);
-
-        return new CalculationResult(fr, this);
-    }
-
-    protected String toString(String [] parameterNames, double [] values) {
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < parameterNames.length; ++i) {
-            if (i > 0) sb.append(", ");
-            sb.append(parameterNames[i]).append(": ").append(values[i]);
-        }
-        return sb.toString();
-    }
-
-    protected List<Column> getEventColumns(FixingsOverview overview) {
-
-        FixingsColumnFactory fcf = FixingsColumnFactory.getInstance();
-
-        IdsFilter ids = new IdsFilter(events);
-        DateRangeFilter rdf = new DateRangeFilter(
-            referencePeriod.getFrom(),
-            referencePeriod.getTo());
-        Filter filter = new AndFilter().add(rdf).add(ids);
-
-        List<Fixing.Column> metas = overview.filter(null, filter);
-
-        List<Column> columns = new ArrayList<Column>(metas.size());
-
-        for (Fixing.Column meta: metas) {
-
-            FixingsColumn data = fcf.getColumnData(meta);
-            if (data == null) {
-                addProblem("fix.cannot.load.data");
-            }
-            else {
-                columns.add(new Column(meta, data));
-            }
-        }
-
-        return columns;
-    }
-
-
-    protected KMIndex<AnalysisPeriod []> calculateAnalysisPeriods(
-        Function        function,
-        Parameters      parameters,
-        FixingsOverview overview
-    ) {
-        Range range = new Range(from, to);
-
-        int kmIndex   = parameters.columnIndex("km");
-        int maxQIndex = parameters.columnIndex("max_q");
-
-        ColumnCache cc = new ColumnCache();
-
-        double [] wq = new double[2];
-
-        int [] parameterIndices =
-            parameters.columnIndices(function.getParameterNames());
-
-        double [] parameterValues = new double[parameterIndices.length];
-
-        DateAverager dateAverager = new DateAverager();
-
-        KMIndex<AnalysisPeriod []> results =
-            new KMIndex<AnalysisPeriod []>(parameters.size());
-
-        IdsFilter idsFilter = new IdsFilter(events);
-
-        for (int row = 0, R = parameters.size(); row < R; ++row) {
-            double km = parameters.get(row, kmIndex);
-            parameters.get(row, parameterIndices, parameterValues);
-
-            // This is the paraterized function for a given km.
-            de.intevation.flys.artifacts.math.Function instance =
-                function.instantiate(parameterValues);
-
-            KmFilter kmFilter = new KmFilter(km);
-
-            ArrayList<AnalysisPeriod> periodResults =
-                new ArrayList<AnalysisPeriod>(analysisPeriods.length);
-
-            for (DateRange analysisPeriod: analysisPeriods) {
-                DateRangeFilter drf = new DateRangeFilter(
-                    analysisPeriod.getFrom(),
-                    analysisPeriod.getTo());
-
-                QWD []    qSectorAverages = new QWD[4];
-                double [] qSectorStdDevs  = new double[4];
-
-                ArrayList<QWD> allQWDs = new ArrayList<QWD>();
-
-                // for all Q sectors.
-                for (int qSector = qSectorStart; qSector < qSectorEnd; ++qSector) {
-
-                    Filter filter = new AndFilter()
-                        .add(kmFilter)
-                        .add(new SectorFilter(qSector))
-                        .add(drf)
-                        .add(idsFilter);
-
-                    List<Fixing.Column> metas = overview.filter(range, filter);
-
-                    if (metas.isEmpty()) {
-                        // No fixings for km and analysis period
-                        continue;
-                    }
-
-                    double sumQ = 0.0;
-                    double sumW = 0.0;
-
-                    StandardDeviation stdDev = new StandardDeviation();
-
-                    List<QWD> qwds = new ArrayList<QWD>(metas.size());
-
-                    dateAverager.clear();
-
-                    for (Fixing.Column meta: metas) {
-                        if (meta.findQSector(km) != qSector) {
-                            // Ignore not matching sectors.
-                            continue;
-                        }
-
-                        Column column = cc.getColumn(meta);
-                        if (column == null || !column.getQW(km, wq)) {
-                            continue;
-                        }
-
-                        double fw = instance.value(wq[1]);
-                        if (Double.isNaN(fw)) {
-                            continue;
-                        }
-
-                        double dw = (wq[0] - fw)*100.0;
-
-                        stdDev.increment(dw);
-
-                        Date date = column.getDate();
-                        String description = column.getDescription();
-
-                        QWD qwd = new QWD(
-                            wq[1], wq[0], description, date, true, dw);
-
-                        qwds.add(qwd);
-
-                        sumW += wq[0];
-                        sumQ += wq[1];
-
-                        dateAverager.add(date);
-                    }
-
-                    // Calulate average per Q sector.
-                    int N = qwds.size();
-                    if (N > 0) {
-                        allQWDs.addAll(qwds);
-                        double avgW = sumW / N;
-                        double avgQ = sumQ / N;
-
-                        double avgFw = instance.value(avgQ);
-                        if (!Double.isNaN(avgFw)) {
-                            double avgDw = (avgW - avgFw)*100.0;
-                            Date avgDate = dateAverager.getAverage();
-
-                            String avgDescription = "avg.deltawt." + qSector;
-
-                            QWD avgQWD = new QWD(
-                                avgQ, avgW, avgDescription, avgDate, true, avgDw);
-
-                            qSectorAverages[qSector] = avgQWD;
-                        }
-                        qSectorStdDevs[qSector] = stdDev.getResult();
-                    }
-                    else {
-                        qSectorStdDevs[qSector] = Double.NaN;
-                    }
-                } // for all Q sectors
-
-                QWD [] aqwds = allQWDs.toArray(new QWD[allQWDs.size()]);
-
-                AnalysisPeriod periodResult = new AnalysisPeriod(
-                    analysisPeriod,
-                    aqwds,
-                    qSectorAverages,
-                    qSectorStdDevs);
-                periodResults.add(periodResult);
-            }
-
-            double maxQ = -Double.MAX_VALUE;
-            for (AnalysisPeriod ap: periodResults) {
-                double q = ap.getMaxQ();
-                if (q > maxQ) {
-                    maxQ = q;
-                }
-            }
-
-            double oldMaxQ = parameters.get(row, maxQIndex);
-            if (oldMaxQ < maxQ) {
-                parameters.set(row, maxQIndex, maxQ);
-            }
-
-            results.add(km, periodResults.toArray(
-                new AnalysisPeriod[periodResults.size()]));
-        }
-
-        return results;
-    }
-
-    /** 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;
-        }
-
-        public Date getDate() {
-            return meta.getStartTime();
-        }
-
-        public String getDescription() {
-            return meta.getDescription();
-        }
-
-        public boolean getQW(
-            double    km,
-            double [] qs,
-            double [] ws,
-            int       index
-        ) {
-            qs[index] = data.getQ(km);
-            return data.getW(km, ws, index);
-        }
-
-        public boolean getQW(double km, double [] wq) {
-            data.getW(km, wq, 0);
-            if (Double.isNaN(wq[0])) return false;
-            wq[1] = data.getQ(km);
-            return !Double.isNaN(wq[1]);
-        }
-    } // class Column
-
-
-    /**
-     * Helper class to find the data belonging to meta info more quickly.
-     */
-    public static class ColumnCache {
-
-        protected Map<Integer, Column> columns;
-
-        public ColumnCache() {
-            columns = new HashMap<Integer, Column>();
-        }
-
-        public Column getColumn(Fixing.Column meta) {
-            Integer key = meta.getId();
-            Column column = columns.get(key);
-            if (column == null) {
-                FixingsColumn data = FixingsColumnFactory
-                    .getInstance()
-                    .getColumnData(meta);
-                if (data != null) {
-                    column = new Column(meta, data);
-                    columns.put(key, column);
-                }
-            }
-            return column;
-        }
-    } // class ColumnCache
-
-    /** Fetch meta and data columns for analysis periods. */
-    protected Column [][] getAnalysisColumns(FixingsOverview overview) {
-
-        boolean debug = log.isDebugEnabled();
-        if (debug) {
-            log.debug("number analysis periods: " + analysisPeriods.length);
-        }
-
-        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.
-            DateRange period = analysisPeriods[i];
-
-            AndFilter filter = new AndFilter();
-
-            DateRangeFilter dateRangeFilter =
-                new DateRangeFilter(period.getFrom(), period.getTo());
-
-            filter.add(dateRangeFilter);
-            filter.add(sectorRangeFilter);
-
-            List<Fixing.Column> metaCols = overview.filter(range, filter);
-
-            if (debug) {
-                log.debug("number of filtered columns: " + metaCols.size());
-            }
-
-            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));
-                }
-            }
-
-            if (debug) {
-                log.debug("failed loading: " + (metaCols.size()-cols.size()));
-            }
-            columns[i] = cols.toArray(new Column[cols.size()]);
-        }
-
-        return columns;
-    }
-
-    protected static String [] createColumnNames(String [] parameters) {
-        String [] result = new String[parameters.length + 4];
-        result[0] = "km";
-        result[1] = "chi_sqr";
-        result[2] = "max_q";
-        result[3] = "std-dev";
-        System.arraycopy(parameters, 0, result, 4, parameters.length);
-        return result;
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/FixationCompute.java	Thu Jul 19 13:56:11 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/fixation/FixationCompute.java	Thu Jul 19 14:11:11 2012 +0000
@@ -17,7 +17,7 @@
 import de.intevation.flys.artifacts.model.fixings.FixAnalysisEventsFacet;
 import de.intevation.flys.artifacts.model.fixings.FixAnalysisPeriodsFacet;
 import de.intevation.flys.artifacts.model.fixings.FixAvSectorFacet;
-import de.intevation.flys.artifacts.model.fixings.FixCalculation;
+import de.intevation.flys.artifacts.model.fixings.FixAnalysisCalculation;
 import de.intevation.flys.artifacts.model.fixings.FixDerivateFacet;
 import de.intevation.flys.artifacts.model.fixings.FixDeviationFacet;
 import de.intevation.flys.artifacts.model.fixings.FixLongitudinalAnalysisFacet;
@@ -96,7 +96,7 @@
             res = (CalculationResult)old;
         }
         else {
-            FixCalculation calc = new FixCalculation(access);
+            FixAnalysisCalculation calc = new FixAnalysisCalculation(access);
             res = calc.calculate();
         }
 

http://dive4elements.wald.intevation.org