changeset 3552:1df6984628c3

S/Q: Extented the result data model of the S/Q calculation to store the curve coefficients for each iteration step of the outlier elimination. flys-artifacts/trunk@5146 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 27 Jul 2012 12:36:09 +0000 (2012-07-27)
parents e7f1556192b3
children 5da58c5c1517
files flys-artifacts/ChangeLog flys-artifacts/doc/conf/artifacts/minfo.xml flys-artifacts/doc/conf/themes.xml flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Parameters.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Segment.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Fitting.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Outlier.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQCurveFacet.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQFractionResult.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQMeasurementFacet.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierCurveFacet.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierFacet.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierMeasurementFacet.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQRelationCalculation.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/SQRelation.java flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationExporter.java flys-artifacts/src/main/resources/messages.properties flys-artifacts/src/main/resources/messages_de.properties flys-artifacts/src/main/resources/messages_de_DE.properties flys-artifacts/src/main/resources/messages_en.properties
diffstat 21 files changed, 776 insertions(+), 394 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/ChangeLog	Fri Jul 27 12:36:09 2012 +0000
@@ -1,3 +1,62 @@
+2012-07-27	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
+
+	Extented the result data model of the S/Q calculation to
+	store the curve coefficients for each iteration step
+	of the outlier elimination. The starting data set of S/Qs
+	is stored as well.
+
+	TODOs:
+	- Create the new facets as inactive.
+	- Repair the facet to style mapping.
+
+	* doc/conf/themes.xml: Added mappings for new facets.
+
+	* doc/conf/artifacts/minfo.xml: Configured the new facets.
+
+	* src/main/java/de/intevation/flys/exports/sq/SQRelationExporter.java:
+	  Adjusted to new data model.
+
+	* src/main/java/de/intevation/flys/artifacts/states/SQRelation.java:
+	  Generate facets for outlier curves and measurements. Simplified code.
+
+	* src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java:
+	  New facet types for outlier curves and meassurements.
+
+	* src/main/java/de/intevation/flys/artifacts/model/Parameters.java:
+	  New set() method to set an array of values by their names.
+
+	* src/main/java/de/intevation/flys/artifacts/model/Segment.java:
+	  Removed trailing whitespace.
+
+	* src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierFacet.java,
+	  src/main/java/de/intevation/flys/artifacts/model/sq/SQCurveFacet.java,
+	  src/main/java/de/intevation/flys/artifacts/model/sq/SQMeasurementFacet.java:
+	  Adjusted to new data model. Curves are drawn over the whole length of the
+	  starting S/Q dataset.
+
+	* src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierCurveFacet.java:
+	  New. Facet for the curves of the outlier test iterations.
+
+	* src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierMeasurementFacet.java
+	  New. Facet for the meassurement data remainind after outlier test iteration.
+
+	* src/main/java/de/intevation/flys/artifacts/model/sq/SQRelationCalculation.java:
+	  Now creates the new data model.
+
+	* src/main/java/de/intevation/flys/artifacts/model/sq/Fitting.java,
+	  src/main/java/de/intevation/flys/artifacts/model/sq/Outlier.java:
+	  Refactorted to have more control over the data structures to be generated.
+
+	* src/main/java/de/intevation/flys/artifacts/model/sq/SQFractionResult.java:
+	  The new data model to represnt a fraction result. Each outlier test iteration
+	  results in a different iteration object.
+
+	* src/main/resources/messages.properties,
+	  src/main/resources/messages_de_DE.properties,
+	  src/main/resources/messages_en.properties,
+	  src/main/resources/messages_de.properties:
+	  Added i18n strings for new facets.
+
 2012-07-27  Ingo Weinzierl <ingo@intevation.de>
 
 	* src/main/java/de/intevation/flys/artifacts/model/QWDDateRange.java:
--- a/flys-artifacts/doc/conf/artifacts/minfo.xml	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/doc/conf/artifacts/minfo.xml	Fri Jul 27 12:36:09 2012 +0000
@@ -143,6 +143,8 @@
                         <facet name="sq_a_measurement" description="A facet for sq measurements"/>
                         <facet name="sq_a_outlier" description="A facet fo sq outliers"/>
                         <facet name="sq_a_curve" description="A facet for sq curve"/>
+                        <facet name="sq_a_outlier_curve" description="A facet for sq outlier curve"/>
+                        <facet name="sq_a_outlier_measurement" description="A facet for sq outlier measurement"/>
                     </facets>
                 </outputmode>
                 <outputmode name="sq_relation_b" description="output.sq_relation" type="chart">
@@ -150,6 +152,8 @@
                         <facet name="sq_b_measurement" description="A facet for sq measurements"/>
                         <facet name="sq_b_outlier" description="A facet fo sq outliers"/>
                         <facet name="sq_b_curve" description="A facet for sq curve"/>
+                        <facet name="sq_b_outlier_curve" description="A facet for sq outlier curve"/>
+                        <facet name="sq_b_outlier_measurement" description="A facet for sq outlier measurement"/>
                     </facets>
                 </outputmode>
                 <outputmode name="sq_relation_c" description="output.sq_relation" type="chart">
@@ -157,6 +161,8 @@
                         <facet name="sq_c_measurement" description="A facet for sq measurements"/>
                         <facet name="sq_c_outlier" description="A facet fo sq outliers"/>
                         <facet name="sq_c_curve" description="A facet for sq curve"/>
+                        <facet name="sq_c_outlier_curve" description="A facet for sq outlier curve"/>
+                        <facet name="sq_c_outlier_measurement" description="A facet for sq outlier measurement"/>
                     </facets>
                 </outputmode>
                 <outputmode name="sq_relation_d" description="output.sq_relation" type="chart">
@@ -164,6 +170,8 @@
                         <facet name="sq_d_measurement" description="A facet for sq measurements"/>
                         <facet name="sq_d_outlier" description="A facet fo sq outliers"/>
                         <facet name="sq_d_curve" description="A facet for sq curve"/>
+                        <facet name="sq_d_outlier_curve" description="A facet for sq outlier curve"/>
+                        <facet name="sq_d_outlier_measurement" description="A facet for sq outlier measurement"/>
                     </facets>
                 </outputmode>
                 <outputmode name="sq_relation_e" description="output.sq_relation" type="chart">
@@ -171,6 +179,8 @@
                         <facet name="sq_e_measurement" description="A facet for sq measurements"/>
                         <facet name="sq_e_outlier" description="A facet fo sq outliers"/>
                         <facet name="sq_e_curve" description="A facet for sq curve"/>
+                        <facet name="sq_e_outlier_curve" description="A facet for sq outlier curve"/>
+                        <facet name="sq_e_outlier_measurement" description="A facet for sq outlier measurement"/>
                     </facets>
                 </outputmode>
                 <outputmode name="sq_relation_f" description="output.sq_relation" type="chart">
@@ -178,6 +188,8 @@
                         <facet name="sq_f_measurement" description="A facet for sq measurements"/>
                         <facet name="sq_f_outlier" description="A facet fo sq outliers"/>
                         <facet name="sq_f_curve" description="A facet for sq curve"/>
+                        <facet name="sq_f_outlier_curve" description="A facet for sq outlier curve"/>
+                        <facet name="sq_f_outlier_measurement" description="A facet for sq outlier measurement"/>
                     </facets>
                 </outputmode>
                 <outputmode name="sq_overview" description="output.sq_overview" type="overview">
--- a/flys-artifacts/doc/conf/themes.xml	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/doc/conf/themes.xml	Fri Jul 27 12:36:09 2012 +0000
@@ -140,21 +140,33 @@
         <mapping from="sq_a_measurement" to="SQMeasurements"/>
         <mapping from="sq_a_outlier" to="SQOutliers"/>
         <mapping from="sq_a_curve" to="SQCurve"/>
+        <mapping from="sq_a_outlier_curve" to="SQCurve"/>
+        <mapping from="sq_a_outlier_measurement" to="SQMeasurements"/>
         <mapping from="sq_b_measurement" to="SQMeasurements"/>
         <mapping from="sq_b_outlier" to="SQOutliers"/>
         <mapping from="sq_b_curve" to="SQCurve"/>
+        <mapping from="sq_b_outlier_curve" to="SQCurve"/>
+        <mapping from="sq_b_outlier_measurement" to="SQMeasurements"/>
         <mapping from="sq_c_measurement" to="SQMeasurements"/>
         <mapping from="sq_c_outlier" to="SQOutliers"/>
         <mapping from="sq_c_curve" to="SQCurve"/>
+        <mapping from="sq_c_outlier_curve" to="SQCurve"/>
+        <mapping from="sq_c_outlier_measurement" to="SQMeasurements"/>
         <mapping from="sq_d_measurement" to="SQMeasurements"/>
         <mapping from="sq_d_outlier" to="SQOutliers"/>
         <mapping from="sq_d_curve" to="SQCurve"/>
+        <mapping from="sq_d_outlier_curve" to="SQCurve"/>
+        <mapping from="sq_d_outlier_measurement" to="SQMeasurements"/>
         <mapping from="sq_e_measurement" to="SQMeasurements"/>
         <mapping from="sq_e_outlier" to="SQOutliers"/>
         <mapping from="sq_e_curve" to="SQCurve"/>
+        <mapping from="sq_e_outlier_curve" to="SQCurve"/>
+        <mapping from="sq_e_outlier_measurement" to="SQMeasurements"/>
         <mapping from="sq_f_measurement" to="SQMeasurements"/>
         <mapping from="sq_f_outlier" to="SQOutliers"/>
         <mapping from="sq_f_curve" to="SQCurve"/>
+        <mapping from="sq_f_outlier_curve" to="SQCurve"/>
+        <mapping from="sq_f_outlier_measurement" to="SQMeasurements"/>
         <mapping from="fix_sector_average_wq_0" to="FixingSectorAverageWQ0"/>
         <mapping from="fix_sector_average_wq_1" to="FixingSectorAverageWQ1"/>
         <mapping from="fix_sector_average_wq_2" to="FixingSectorAverageWQ2"/>
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java	Fri Jul 27 12:36:09 2012 +0000
@@ -54,7 +54,14 @@
                 || type.equals(SQ_C_CURVE)
                 || type.equals(SQ_D_CURVE)
                 || type.equals(SQ_E_CURVE)
-                || type.equals(SQ_F_CURVE))
+                || type.equals(SQ_F_CURVE)
+                || type.equals(SQ_A_OUTLIER_CURVE)
+                || type.equals(SQ_B_OUTLIER_CURVE)
+                || type.equals(SQ_C_OUTLIER_CURVE)
+                || type.equals(SQ_D_OUTLIER_CURVE)
+                || type.equals(SQ_E_OUTLIER_CURVE)
+                || type.equals(SQ_F_OUTLIER_CURVE)
+                )
             {
                 return true;
             }
@@ -67,7 +74,14 @@
                 || type.equals(SQ_C_MEASUREMENT)
                 || type.equals(SQ_D_MEASUREMENT)
                 || type.equals(SQ_E_MEASUREMENT)
-                || type.equals(SQ_F_MEASUREMENT))
+                || type.equals(SQ_F_MEASUREMENT)
+                || type.equals(SQ_A_OUTLIER_MEASUREMENT)
+                || type.equals(SQ_B_OUTLIER_MEASUREMENT)
+                || type.equals(SQ_C_OUTLIER_MEASUREMENT)
+                || type.equals(SQ_D_OUTLIER_MEASUREMENT)
+                || type.equals(SQ_E_OUTLIER_MEASUREMENT)
+                || type.equals(SQ_F_OUTLIER_MEASUREMENT)
+                )
             {
                 return true;
             }
@@ -204,26 +218,38 @@
     String SQ_A_CURVE       = "sq_a_curve";
     String SQ_A_MEASUREMENT = "sq_a_measurement";
     String SQ_A_OUTLIER     = "sq_a_outlier";
+    String SQ_A_OUTLIER_CURVE = "sq_a_outlier_curve";
+    String SQ_A_OUTLIER_MEASUREMENT = "sq_a_outlier_measurement";
 
     String SQ_B_CURVE       = "sq_b_curve";
     String SQ_B_MEASUREMENT = "sq_b_measurement";
     String SQ_B_OUTLIER     = "sq_b_outlier";
+    String SQ_B_OUTLIER_CURVE  = "sq_b_outlier_curve";
+    String SQ_B_OUTLIER_MEASUREMENT  = "sq_b_outlier_measurement";
 
     String SQ_C_CURVE       = "sq_c_curve";
     String SQ_C_MEASUREMENT = "sq_c_measurement";
     String SQ_C_OUTLIER     = "sq_c_outlier";
+    String SQ_C_OUTLIER_CURVE = "sq_c_outlier_curve";
+    String SQ_C_OUTLIER_MEASUREMENT = "sq_c_outlier_measurement";
 
     String SQ_D_CURVE       = "sq_d_curve";
     String SQ_D_MEASUREMENT = "sq_d_measurement";
     String SQ_D_OUTLIER     = "sq_d_outlier";
+    String SQ_D_OUTLIER_CURVE = "sq_d_outlier_curve";
+    String SQ_D_OUTLIER_MEASUREMENT = "sq_d_outlier_measurement";
 
     String SQ_E_CURVE       = "sq_e_curve";
     String SQ_E_MEASUREMENT = "sq_e_measurement";
     String SQ_E_OUTLIER     = "sq_e_outlier";
+    String SQ_E_OUTLIER_CURVE = "sq_e_outlier_curve";
+    String SQ_E_OUTLIER_MEASUREMENT = "sq_e_outlier_curve_measurement";
 
     String SQ_F_CURVE       = "sq_f_curve";
     String SQ_F_MEASUREMENT = "sq_f_measurement";
     String SQ_F_OUTLIER     = "sq_f_outlier";
+    String SQ_F_OUTLIER_CURVE = "sq_f_outlier_curve";
+    String SQ_F_OUTLIER_MEASUREMENT = "sq_f_outlier_measurement";
 
     String RELATIVE_POINT = "relativepoint";
 
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Parameters.java	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Parameters.java	Fri Jul 27 12:36:09 2012 +0000
@@ -97,6 +97,20 @@
         return invalid;
     }
 
+    public boolean set(int row, String [] names, double [] values) {
+        boolean success = true;
+        for (int i = 0; i < names.length; ++i) {
+            int idx = columnIndex(names[i]);
+            if (idx >= 0) {
+                columns[idx].setQuick(row, values[i]);
+            }
+            else {
+                success = false;
+            }
+        }
+        return success;
+    }
+
     public int size() {
         return columns[0].size();
     }
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Segment.java	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Segment.java	Fri Jul 27 12:36:09 2012 +0000
@@ -56,7 +56,7 @@
     }
 
     public boolean inside(double km) {
-        return from < to 
+        return from < to
             ? km >= from && km <= to
             : km >= to   && km <= from;
     }
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Fitting.java	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Fitting.java	Fri Jul 27 12:36:09 2012 +0000
@@ -15,27 +15,42 @@
 import org.apache.log4j.Logger;
 
 public class Fitting
+implements   Outlier.Callback
 {
     private static Logger log = Logger.getLogger(Fitting.class);
 
+    public interface Callback {
+
+        void afterIteration(
+            double [] parameters,
+            SQ []     measurements,
+            SQ []     outliers,
+            double    standardDeviation,
+            double    chiSqr);
+    } // interfacte
+
     protected Function function;
 
-    protected double [] parameters;
+    protected double [] coeffs;
 
-    protected double stdDevFactor;
+    protected de.intevation.flys.artifacts.math.Function instance;
+
+    protected List<SQ> remainings;
+    protected List<SQ> outliers;
 
     protected double standardDeviation;
-
+    protected double stdDevFactor;
     protected double chiSqr;
 
-    protected SQ [] remaining;
-
-    protected List<SQ []> outliers;
+    protected Callback callback;
 
     public Fitting() {
+        remainings = new ArrayList<SQ>();
+        outliers   = new ArrayList<SQ>();
     }
 
     public Fitting(Function function, double stdDevFactor) {
+        this();
         this.function     = function;
         this.stdDevFactor = stdDevFactor;
     }
@@ -48,14 +63,6 @@
         this.function = function;
     }
 
-    public double [] getParameters() {
-        return parameters;
-    }
-
-    public void setParameters(double [] parameters) {
-        this.parameters = parameters;
-    }
-
     public double getStdDevFactor() {
         return stdDevFactor;
     }
@@ -64,45 +71,66 @@
         this.stdDevFactor = stdDevFactor;
     }
 
-    public double getStandardDeviation() {
-        return standardDeviation;
+    @Override
+    public void initialize(Iterator<SQ> good) throws MathException {
+
+        LevenbergMarquardtOptimizer lmo =
+            new LevenbergMarquardtOptimizer();
+
+        CurveFitter cf = new CurveFitter(lmo);
+        while (good.hasNext()) {
+            SQ sq = good.next();
+            cf.addObservedPoint(sq.getQ(), sq.getS());
+        }
+
+        coeffs = cf.fit(
+            function, function.getInitialGuess());
+
+        instance = function.instantiate(coeffs);
+
+        chiSqr = lmo.getChiSquare();
+
     }
 
-    public void setStandardDeviation(double standardDeviation) {
+    @Override
+    public double eval(SQ sq) {
+        double s = instance.value(sq.q);
+        return sq.s - s;
+    }
+
+    @Override
+    public void outlier(SQ sq) {
+        outliers.add(sq);
+    }
+
+    @Override
+    public void remaining(SQ sq) {
+        remainings.add(sq);
+    }
+
+    @Override
+    public void standardDeviation(double standardDeviation) {
         this.standardDeviation = standardDeviation;
     }
 
-    public double getChiSqr() {
-        return chiSqr;
-    }
-
-    public void setChiSqr(double chiSqr) {
-        this.chiSqr = chiSqr;
-    }
-
-    public SQ [] getRemaining() {
-        return remaining;
-    }
-
-    public void setRemaining(SQ [] remaining) {
-        this.remaining = remaining;
-    }
-
-    public List<SQ []> getOutliers() {
-        return outliers;
-    }
-
-    public void setOutliers(List<SQ []> outliers) {
-        this.outliers = outliers;
-    }
-
-    public void reset() {
-        outliers          = null;
-        remaining         = null;
-        parameters        = null;
-        standardDeviation = 0d;
-        standardDeviation = 0d;
-        chiSqr            = 0d;
+    @Override
+    public void iterationFinished() {
+        if (log.isDebugEnabled()) {
+            log.debug("iterationFinished ----");
+            log.debug(" num remainings: " + remainings.size());
+            log.debug(" num outliers: " + outliers.size());
+            log.debug(" standardDeviation: " + standardDeviation);
+            log.debug(" Chi^2: " + chiSqr);
+            log.debug("---- iterationFinished");
+        }
+        callback.afterIteration(
+            coeffs,
+            remainings.toArray(new SQ[remainings.size()]),
+            outliers.toArray(new SQ[outliers.size()]),
+            standardDeviation,
+            chiSqr);
+        remainings.clear();
+        outliers.clear();
     }
 
     protected static final List<SQ> onlyValid(List<SQ> sqs) {
@@ -118,7 +146,7 @@
         return good;
     }
 
-    public boolean fit(List<SQ> sqs) {
+    public boolean fit(List<SQ> sqs, Callback callback) {
 
         sqs = onlyValid(sqs);
 
@@ -127,94 +155,10 @@
             return false;
         }
 
-        final LevenbergMarquardtOptimizer lmo =
-            new LevenbergMarquardtOptimizer();
-
-        CurveFitter cf = new CurveFitter(lmo);
-
-        for (SQ sq: sqs) {
-            cf.addObservedPoint(sq.getQ(), sq.getS());
-        }
-
-        try {
-            parameters = cf.fit(function, function.getInitialGuess());
-        }
-        catch (MathException me) {
-            log.warn(me);
-            return false;
-        }
-
-        chiSqr = lmo.getChiSquare();
-
-        final de.intevation.flys.artifacts.math.Function [] instance = {
-            function.instantiate(parameters)
-        };
+        this.callback = callback;
 
         try {
-            remaining = Outlier.detectOutliers(
-                new Outlier.Callback() {
-
-                    List<List<SQ>> outliers =
-                        new ArrayList<List<SQ>>();
-
-                    int currentIteration;
-
-                    @Override
-                    public double eval(SQ sq) {
-                        double s = instance[0].value(sq.q);
-                        return s - sq.s;
-                    }
-
-                    @Override
-                    public void iteration(int i) {
-                        currentIteration = i;
-                    }
-
-                    @Override
-                    public void outlier(SQ sq) {
-                        if (currentIteration > outliers.size()) {
-                            outliers.add(new ArrayList<SQ>(2));
-                        }
-                        outliers.get(currentIteration-1).add(sq);
-                    }
-
-                    @Override
-                    public void standardDeviation(double stdDev) {
-                        setStandardDeviation(stdDev);
-                    }
-
-                    @Override
-                    public void reinitialize(Iterator<SQ> good)
-                    throws MathException
-                    {
-                        CurveFitter cf = new CurveFitter(lmo);
-                        while (good.hasNext()) {
-                            SQ sq = good.next();
-                            cf.addObservedPoint(sq.getQ(), sq.getS());
-                        }
-
-                        parameters = cf.fit(
-                            function, function.getInitialGuess());
-
-                        instance[0] = function.instantiate(parameters);
-
-                        chiSqr = lmo.getChiSquare();
-                    }
-
-                    @Override
-                    public void finished() {
-                        List<SQ []> result =
-                            new ArrayList<SQ []>(outliers.size());
-
-                        for (List<SQ> ols: outliers) {
-                            result.add(ols.toArray(new SQ[ols.size()]));
-                        }
-
-                        setOutliers(result);
-                    }
-                },
-                sqs,
-                stdDevFactor);
+            Outlier.detectOutliers(this, sqs, stdDevFactor);
         }
         catch (MathException me) {
             log.warn(me);
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Outlier.java	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Outlier.java	Fri Jul 27 12:36:09 2012 +0000
@@ -8,23 +8,27 @@
 
 import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
 
+import org.apache.log4j.Logger;
+
 public class Outlier
 {
+    private static Logger log = Logger.getLogger(Outlier.class);
+
     public static final int MAX_ITERATIONS = 1000;
 
     public interface Callback {
 
+        void initialize(Iterator<SQ> good) throws MathException;
+
         double eval(SQ sq);
 
-        void iteration(int i);
-
         void outlier(SQ sq);
 
+        void remaining(SQ sq);
+
         void standardDeviation(double stdDev);
 
-        void reinitialize(Iterator<SQ> good) throws MathException;
-
-        void finished();
+        void iterationFinished();
 
     } // interface Callback
 
@@ -37,13 +41,19 @@
         }
     } // class EvalSQ
 
-    public static SQ [] detectOutliers(
+    public static void detectOutliers(
         Callback callback,
         List<SQ> sqs,
         double   stdDevFactor
     )
     throws MathException
     {
+        boolean debug = log.isDebugEnabled();
+
+        if (debug) {
+            log.debug("stdDevFactor: " + stdDevFactor);
+        }
+
         List<EvalSQ> data = new ArrayList<EvalSQ>(sqs.size());
 
         for (SQ sq: sqs) {
@@ -52,7 +62,9 @@
 
         List<EvalSQ> good = new ArrayList<EvalSQ>(sqs.size());
 
-        for (int i = 1; i <= MAX_ITERATIONS && data.size() > 2; ++i) {
+        for (int i = 0; i < MAX_ITERATIONS && data.size() > 2; ++i) {
+
+            callback.initialize(asSQIterator(data));
 
             StandardDeviation stdDev = new StandardDeviation();
 
@@ -66,38 +78,35 @@
 
             double accepted = stdDevFactor * sd;
 
-            callback.iteration(i);
+            if (debug) {
+                log.debug("accepted: " + accepted);
+            }
 
             for (EvalSQ esq: data) {
+                if (debug) {
+                    log.debug(" value: " + Math.abs(esq.value));
+                }
+
                 if (Math.abs(esq.value) > accepted) {
                     callback.outlier(esq.sq);
                 }
                 else {
+                    callback.remaining(esq.sq);
                     good.add(esq);
                 }
             }
 
+            callback.iterationFinished();
+
             if (good.size() == data.size()) {
                 break;
             }
 
-            callback.reinitialize(asSQIterator(good));
-
             List<EvalSQ> tmp = good;
             good = data;
             data = tmp;
             good.clear();
         }
-
-        callback.finished();
-
-        SQ [] result = new SQ[good.size()];
-
-        for (int i = 0; i < result.length; ++i) {
-            result[i] = good.get(i).sq;
-        }
-
-        return result;
     }
 
     protected static Iterator<SQ> asSQIterator(List<EvalSQ> esqs) {
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQCurveFacet.java	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQCurveFacet.java	Fri Jul 27 12:36:09 2012 +0000
@@ -53,41 +53,42 @@
     public Object getData(Artifact artifact, CallContext context) {
         log.debug("SQCurveFacet.getData");
 
-        if (artifact instanceof FLYSArtifact) {
-            FLYSArtifact flys = (FLYSArtifact) artifact;
-
-            CalculationResult res = (CalculationResult) flys.compute(
-                context, ComputeType.ADVANCE, false);
-
-            SQResult[]       results = (SQResult[]) res.getData();
-            SQFractionResult result  = results[index].getFraction(fractionIdx);
-
-            Function func = FunctionFactory.getInstance().getFunction(FUNCTION);
-            String[] paramNames = func.getParameterNames();
-
-            Parameters params = result.getParameters();
-
-            if (params == null) {
-                log.debug("no parameters found");
-                return null;
-            }
-
-            double[]   coeffs = params.get(0, paramNames);
-
-            if (log.isDebugEnabled()) {
-                for (int i = 0, N = paramNames.length; i < N; i++) {
-                    log.debug("retrieved parameter " + paramNames[i] +
-                              " = " + coeffs[i]);
-                }
-            }
-
-            de.intevation.flys.artifacts.math.Function mf =
-                func.instantiate(coeffs);
-
-            return new SQFunction(mf, result.getMinQ(), result.getMaxQ());
+        if (!(artifact instanceof FLYSArtifact)) {
+            return null;
         }
 
-        return null;
+        FLYSArtifact flys = (FLYSArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(
+            context, ComputeType.ADVANCE, false);
+
+        SQResult[]       results = (SQResult[]) res.getData();
+        SQFractionResult result  = results[index].getFraction(fractionIdx);
+
+        Parameters params = result.getParameters();
+
+        if (params == null) {
+            log.debug("no parameters found");
+            return null;
+        }
+
+        Function func = FunctionFactory.getInstance().getFunction(FUNCTION);
+        String[] paramNames = func.getParameterNames();
+
+        double [] coeffs = params.get(0, paramNames);
+
+        if (log.isDebugEnabled()) {
+            for (int i = 0, N = paramNames.length; i < N; i++) {
+                log.debug("retrieved parameter " + paramNames[i] +
+                          " = " + coeffs[i]);
+            }
+        }
+
+        de.intevation.flys.artifacts.math.Function mf =
+            func.instantiate(coeffs);
+
+        double [] extent = result.getQExtent();
+        return new SQFunction(mf, extent[0], extent[1]);
     }
 
 
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQFractionResult.java	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQFractionResult.java	Fri Jul 27 12:36:09 2012 +0000
@@ -6,110 +6,161 @@
 
 import java.util.List;
 
-public class SQFractionResult implements Serializable {
+public class SQFractionResult
+implements   Serializable
+{
+    public static class Iteration
+    implements          Serializable
+    {
+        protected Parameters parameters;
+        protected SQ []      measurements;
+        protected SQ []      outliers;
 
-    protected Parameters parameters;
-    protected SQ[]       measurements;
-    protected List<SQ[]> outliers;
+        public Iteration() {
+        }
+
+        public Iteration(
+            Parameters parameters,
+            SQ []      measurements,
+            SQ []      outliers
+        ) {
+            this.parameters   = parameters;
+            this.measurements = measurements;
+            this.outliers     = outliers;
+        }
+
+        public Parameters getParameters() {
+            return parameters;
+        }
+
+        public void setParameters(Parameters parameters) {
+            this.parameters = parameters;
+        }
+
+        public SQ [] getMeasurements() {
+            return measurements;
+        }
+
+        public void setMeasurements(SQ [] measurements) {
+            this.measurements = measurements;
+        }
+
+        public SQ [] getOutliers() {
+            return outliers;
+        }
+
+        public void setOutliers(SQ [] outliers) {
+            this.outliers = outliers;
+        }
+
+        public boolean isValid() {
+            return parameters   != null
+                && measurements != null
+                && outliers     != null;
+        }
+
+        public int numOutliers() {
+            return outliers != null
+                ? outliers.length
+                : 0;
+        }
+
+        public int numMeasurements() {
+            return measurements != null
+                ? measurements.length
+                : 0;
+        }
+    } // class Iteration
+
+    protected SQ []           measurements;
+    protected List<Iteration> iterations;
 
     public SQFractionResult() {
     }
 
     public SQFractionResult(
-        Parameters parameters,
-        SQ[]       measurements,
-        List<SQ[]> outliers
+        SQ []           measurements,
+        List<Iteration> iterations
     ) {
-        this.parameters   = parameters;
         this.measurements = measurements;
-        this.outliers     = outliers;
+        this.iterations   = iterations;
     }
 
-    public boolean isValid() {
-        return parameters   != null
-            && measurements != null
-            && outliers     != null;
-    }
-
-    public Parameters getParameters() {
-        return parameters;
-    }
-
-    public void setParameters(Parameters parameters) {
-        this.parameters = parameters;
-    }
-
-
-    public SQ[] getMeasurements() {
+    public SQ [] getMeasurements() {
         return measurements;
     }
 
-    public void setMeasurements(SQ[] measurements) {
+    public void setMeasurements(SQ [] measurements) {
         this.measurements = measurements;
     }
 
-
-    public List<SQ[]> getOutliers() {
-        return outliers;
-    }
-
-    public void setOutliers(List<SQ[]> outliers) {
-        this.outliers = outliers;
+    public List<Iteration> getIterations() {
+        return iterations;
     }
 
-
-    public int getOutliersCount() {
-        return outliers != null
-            ? outliers.size()
-            : 0;
+    public void setIterations(List<Iteration> iterations) {
+        this.iterations = iterations;
     }
 
+    public double [] getQExtent() {
+        return getQExtent(new double[2]);
+    }
 
-    public SQ[] getOutliers(int idx) {
-        if (outliers != null && idx >= 0 && idx < outliers.size()) {
-            return outliers.get(idx);
+    public double [] getQExtent(double extent[]) {
+        extent[0] =  Double.MAX_VALUE;
+        extent[1] = -Double.MIN_VALUE;
+
+        for (SQ sq: measurements) {
+            double q = sq.getQ();
+            if (q < extent[0]) extent[0] = q;
+            if (q > extent[1]) extent[1] = q;
         }
 
-        return null;
+        return extent;
     }
 
-    public void addOutliers(SQ[] outliers) {
-        this.outliers.add(outliers);
+    public int numIterations() {
+        return iterations != null ? iterations.size() : 0;
     }
 
-    public int getTotalCount() {
+    public Parameters getParameters() {
+        return iterations != null && !iterations.isEmpty()
+            ? iterations.get(iterations.size()-1).getParameters()
+            : null;
+    }
+
+    public SQ [] getOutliers(int index) {
+        return index >= 0 && index < iterations.size()
+            ? iterations.get(index).getOutliers()
+            : null;
+    }
+
+    public Parameters getParameters(int index) {
+        return index >= 0 && index < iterations.size()
+            ? iterations.get(index).getParameters()
+            : null;
+    }
+
+    public SQ [] getMeasurements(int index) {
+        return index >= 0 && index < iterations.size()
+            ? iterations.get(index).getMeasurements()
+            : null;
+    }
+
+    public int totalNumOutliers() {
+        int sum = 0;
+        if (iterations != null) {
+            for (Iteration iteration: iterations) {
+                sum += iteration.numOutliers();
+            }
+        }
+        return sum;
+    }
+
+    public int numMeasurements() {
         return measurements != null
             ? measurements.length
             : 0;
     }
-
-    public double getMinQ() {
-        double min = Double.MAX_VALUE;
-
-        for (SQ sq: measurements) {
-            double q = sq.getQ();
-
-            if (q < min) {
-                min = q;
-            }
-        }
-
-        return min;
-    }
-
-
-    public double getMaxQ() {
-        double max = -Double.MAX_VALUE;
-
-        for (SQ sq: measurements) {
-            double q = sq.getQ();
-
-            if (q > max) {
-                max = q;
-            }
-        }
-
-        return max;
-    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQMeasurementFacet.java	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQMeasurementFacet.java	Fri Jul 27 12:36:09 2012 +0000
@@ -46,19 +46,19 @@
     public Object getData(Artifact artifact, CallContext context) {
         log.debug("SQMeasurementFacet.getData");
 
-        if (artifact instanceof FLYSArtifact) {
-            FLYSArtifact flys = (FLYSArtifact) artifact;
-
-            CalculationResult res = (CalculationResult) flys.compute(
-                context, ComputeType.ADVANCE, false);
-
-            SQResult[]       result  = (SQResult[]) res.getData();
-            SQFractionResult fResult = result[index].getFraction(fractionIdx);
-
-            return fResult.getMeasurements();
+        if (!(artifact instanceof FLYSArtifact)) {
+            return null;
         }
 
-        return null;
+        FLYSArtifact flys = (FLYSArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(
+            context, ComputeType.ADVANCE, false);
+
+        SQResult[]       result  = (SQResult[]) res.getData();
+        SQFractionResult fResult = result[index].getFraction(fractionIdx);
+
+        return fResult.getMeasurements();
     }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierCurveFacet.java	Fri Jul 27 12:36:09 2012 +0000
@@ -0,0 +1,102 @@
+package de.intevation.flys.artifacts.model.sq;
+
+import de.intevation.artifactdatabase.state.Facet;
+
+import de.intevation.artifacts.Artifact;
+import de.intevation.artifacts.CallContext;
+
+import de.intevation.flys.artifacts.FLYSArtifact;
+
+import de.intevation.flys.artifacts.math.fitting.Function;
+import de.intevation.flys.artifacts.math.fitting.FunctionFactory;
+
+import de.intevation.flys.artifacts.model.CalculationResult;
+import de.intevation.flys.artifacts.model.DataFacet;
+import de.intevation.flys.artifacts.model.FacetTypes;
+import de.intevation.flys.artifacts.model.Parameters;
+
+import de.intevation.flys.artifacts.states.DefaultState.ComputeType;
+
+import org.apache.log4j.Logger;
+
+public class SQOutlierCurveFacet
+extends      DataFacet
+implements   FacetTypes
+{
+    private static final Logger log =
+        Logger.getLogger(SQOutlierCurveFacet.class);
+
+    public static final String FUNCTION = "sq-pow";
+
+    public static final int BITMASK_ITERATION = (1 << 16) - 1;
+
+    private int fractionIdx;
+
+    public SQOutlierCurveFacet() {
+    }
+
+    public SQOutlierCurveFacet(
+        int    idx,
+        int    fractionIdx,
+        String name,
+        String description,
+        String hash,
+        String stateId
+    ) {
+        super(idx, name, description, ComputeType.ADVANCE, hash, stateId);
+        this.fractionIdx = fractionIdx;
+    }
+
+
+    @Override
+    public Object getData(Artifact artifact, CallContext context) {
+        log.debug("SQOutlierCurveFacet.getData");
+
+        if (!(artifact instanceof FLYSArtifact)) {
+            return null;
+        }
+
+        FLYSArtifact flys = (FLYSArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(
+            context, ComputeType.ADVANCE, false);
+
+        int idx  = this.index >> 16;
+        int iter = this.index & BITMASK_ITERATION;
+
+        SQResult[]       results = (SQResult[]) res.getData();
+        SQFractionResult result  = results[idx].getFraction(fractionIdx);
+
+        Parameters params = result.getParameters(iter);
+
+        if (params == null) {
+            return null;
+        }
+
+        Function func = FunctionFactory.getInstance().getFunction(FUNCTION);
+        String [] paramNames = func.getParameterNames();
+
+        double [] coeffs = params.get(0, paramNames);
+
+        if (log.isDebugEnabled()) {
+            for (int i = 0; i < paramNames.length; i++) {
+                log.debug("retrieved parameter " + paramNames[i] +
+                          " = " + coeffs[i]);
+            }
+        }
+
+        de.intevation.flys.artifacts.math.Function mf =
+            func.instantiate(coeffs);
+
+        double [] extent = result.getQExtent();
+        return new SQFunction(mf, extent[0], extent[1]);
+    }
+
+    @Override
+    public Facet deepCopy() {
+        SQOutlierCurveFacet copy = new SQOutlierCurveFacet();
+        copy.set(this);
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierFacet.java	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierFacet.java	Fri Jul 27 12:36:09 2012 +0000
@@ -1,17 +1,17 @@
 package de.intevation.flys.artifacts.model.sq;
 
-import org.apache.log4j.Logger;
-
 import de.intevation.artifacts.Artifact;
 import de.intevation.artifacts.CallContext;
 
 import de.intevation.flys.artifacts.FLYSArtifact;
+
 import de.intevation.flys.artifacts.model.CalculationResult;
 import de.intevation.flys.artifacts.model.DataFacet;
 import de.intevation.flys.artifacts.model.FacetTypes;
 
 import de.intevation.flys.artifacts.states.DefaultState.ComputeType;
 
+import org.apache.log4j.Logger;
 
 /**
  * Facet to show the curve in a sq relation.
@@ -24,14 +24,11 @@
 
     public static final int BITMASK_ITERATION = (1 << 16) - 1;
 
-
     private int fractionIdx;
 
-
     public SQOutlierFacet() {
     }
 
-
     public SQOutlierFacet(
         int    idx,
         int    fractionIdx,
@@ -49,39 +46,43 @@
     public Object getData(Artifact artifact, CallContext context) {
         log.debug("SQOutlierFacet.getData");
 
-        if (artifact instanceof FLYSArtifact) {
-            FLYSArtifact flys = (FLYSArtifact) artifact;
-
-            CalculationResult res = (CalculationResult) flys.compute(
-                context, ComputeType.ADVANCE, false);
-
-            int idx  = this.index >> 16;
-            int iter = this.index & BITMASK_ITERATION;
-
-            if (log.isDebugEnabled()) {
-                log.debug("Fetch data for index : " + this.index);
-                log.debug("  > index:       " + idx);
-                log.debug("  > fraction:    " + fractionIdx);
-                log.debug("  > iteration:   " + iter);
-            }
-
-            SQResult[]       result  = (SQResult[]) res.getData();
-            SQFractionResult fResult = result[idx].getFraction(fractionIdx);
-
-            if (fResult == null) {
-                log.warn("No SQFractionResult at " + idx + "|" + fractionIdx);
-            }
-            else if (log.isDebugEnabled()) {
-                SQ[] outliers = fResult.getOutliers(iter);
-                int  num      = outliers != null ? outliers.length : 0;
-
-                log.debug("Found " + num + " outliers for iteration " + iter);
-            }
-
-            return fResult.getOutliers(iter);
+        if (!(artifact instanceof FLYSArtifact)) {
+            return null;
         }
 
-        return null;
+        FLYSArtifact flys = (FLYSArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(
+            context, ComputeType.ADVANCE, false);
+
+        int idx  = this.index >> 16;
+        int iter = this.index & BITMASK_ITERATION;
+
+        boolean debug = log.isDebugEnabled();
+
+        if (debug) {
+            log.debug("Fetch data for index : " + this.index);
+            log.debug("  > index:       " + idx);
+            log.debug("  > fraction:    " + fractionIdx);
+            log.debug("  > iteration:   " + iter);
+        }
+
+        SQResult[]       result  = (SQResult[]) res.getData();
+        SQFractionResult fResult = result[idx].getFraction(fractionIdx);
+
+        if (fResult == null) {
+            log.warn("No SQFractionResult at " + idx + "|" + fractionIdx);
+            return null;
+        }
+
+        SQ [] outliers = fResult.getOutliers(iter);
+
+        if (debug) {
+            int num = outliers != null ? outliers.length : 0;
+            log.debug("Found " + num + " outliers for iteration " + iter);
+        }
+
+        return outliers;
     }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQOutlierMeasurementFacet.java	Fri Jul 27 12:36:09 2012 +0000
@@ -0,0 +1,73 @@
+package de.intevation.flys.artifacts.model.sq;
+
+import de.intevation.artifactdatabase.state.Facet;
+
+import de.intevation.artifacts.Artifact;
+import de.intevation.artifacts.CallContext;
+
+import de.intevation.flys.artifacts.FLYSArtifact;
+
+import de.intevation.flys.artifacts.model.CalculationResult;
+import de.intevation.flys.artifacts.model.DataFacet;
+import de.intevation.flys.artifacts.model.FacetTypes;
+
+import de.intevation.flys.artifacts.states.DefaultState.ComputeType;
+
+import org.apache.log4j.Logger;
+
+public class SQOutlierMeasurementFacet
+extends      DataFacet
+implements   FacetTypes
+{
+    private static final Logger log =
+        Logger.getLogger(SQOutlierMeasurementFacet.class);
+
+    private int fractionIdx;
+
+    public static final int BITMASK_ITERATION = (1 << 16) - 1;
+
+    public SQOutlierMeasurementFacet() {
+    }
+
+    public SQOutlierMeasurementFacet(
+        int    idx,
+        int    fractionIdx,
+        String name,
+        String description,
+        String hash,
+        String stateId
+    ) {
+        super(idx, name, description, ComputeType.ADVANCE, hash, stateId);
+        this.fractionIdx = fractionIdx;
+    }
+
+    @Override
+    public Object getData(Artifact artifact, CallContext context) {
+        log.debug("SQOutlierMeasurementFacet.getData");
+
+        if (!(artifact instanceof FLYSArtifact)) {
+            return null;
+        }
+
+        FLYSArtifact flys = (FLYSArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(
+            context, ComputeType.ADVANCE, false);
+
+        int idx  = this.index >> 16;
+        int iter = this.index & BITMASK_ITERATION;
+
+        SQResult[]       result  = (SQResult[]) res.getData();
+        SQFractionResult fResult = result[idx].getFraction(fractionIdx);
+
+        return fResult.getMeasurements(iter);
+    }
+
+    @Override
+    public Facet deepCopy() {
+        SQOutlierMeasurementFacet copy = new SQOutlierMeasurementFacet();
+        copy.set(this);
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQRelationCalculation.java	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SQRelationCalculation.java	Fri Jul 27 12:36:09 2012 +0000
@@ -12,6 +12,7 @@
 
 import de.intevation.flys.backend.SedDBSessionHolder;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.log4j.Logger;
@@ -35,7 +36,7 @@
 
         String    river    = access.getRiver();
         Double    location = access.getLocation();
-        DateRange period  = access.getPeriod();
+        DateRange period   = access.getPeriod();
         Double    outliers = access.getOutliers();
 
         //river = "Rhein";
@@ -99,13 +100,10 @@
             addProblem("sq.missing.sq.function");
         }
 
-
         String [] parameterNames = function.getParameterNames();
 
-        Fitting fitting = new Fitting(function, outliers);
-
-            Measurements measurements =
-                MeasurementFactory.getMeasurements(river, location, period);
+        Measurements measurements =
+            MeasurementFactory.getMeasurements(river, location, period);
 
         SQFractionResult [] fractionResults =
             new SQFractionResult[SQResult.NUMBER_FRACTIONS];
@@ -115,27 +113,20 @@
 
             SQFractionResult fractionResult;
 
-            if (!fitting.fit(sqs)) {
+            List<SQFractionResult.Iteration> iterations =
+                doFitting(function, sqs);
+
+            if (iterations == null) {
                 // TODO: i18n
                 addProblem("sq.fitting.failed." + i);
                 fractionResult = new SQFractionResult();
             }
             else {
-                Parameters parameters = createParameters(parameterNames);
-                int row = parameters.newRow();
-                double [] coeffs = fitting.getParameters();
-                for (int j = 0; j < parameterNames.length; ++j) {
-                    parameters.set(row, parameterNames[j], coeffs[j]);
-                }
-                parameters.set(row, "chi_sqr", fitting.getChiSqr());
-                parameters.set(row, "std_dev", fitting.getStandardDeviation());
+                fractionResult = new SQFractionResult(
+                    sqs.toArray(new SQ[sqs.size()]),
+                    iterations);
+            }
 
-                fractionResult = new SQFractionResult(
-                    parameters,
-                    fitting.getRemaining(),
-                    fitting.getOutliers());
-            }
-            fitting.reset();
             fractionResults[i] = fractionResult;
         }
 
@@ -144,13 +135,55 @@
             this);
     }
 
-    public static final Parameters createParameters(String [] names) {
+    protected List<SQFractionResult.Iteration> doFitting(
+        final Function function,
+        List<SQ> sqs
+    ) {
+        final List<SQFractionResult.Iteration> iterations =
+            new ArrayList<SQFractionResult.Iteration>();
 
+        boolean success = new Fitting(function, outliers).fit(
+            sqs,
+            new Fitting.Callback() {
+                @Override
+                public void afterIteration(
+                    double [] coeffs,
+                    SQ []     measurements,
+                    SQ []     outliers,
+                    double    standardDeviation,
+                    double    chiSqr
+                ) {
+                    Parameters parameters = createParameters(
+                        function.getParameterNames(),
+                        coeffs,
+                        standardDeviation,
+                        chiSqr);
+                    iterations.add(new SQFractionResult.Iteration(
+                        parameters,
+                        measurements,
+                        outliers));
+                }
+            });
+
+        return success ? iterations : null;
+    }
+
+    public static final Parameters createParameters(
+        String [] names,
+        double [] values,
+        double    standardDeviation,
+        double    chiSqr
+    ) {
         String [] columns = new String[names.length + 2];
         columns[0] = "chi_sqr";
         columns[1] = "std_dev";
         System.arraycopy(names, 0, columns, 2, names.length);
-        return new Parameters(columns);
+        Parameters parameters = new Parameters(columns);
+        int row = parameters.newRow();
+        parameters.set(row, names, values);
+        parameters.set(row, "chi_sqr", chiSqr);
+        parameters.set(row, "std_dev", standardDeviation);
+        return parameters;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/SQRelation.java	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/SQRelation.java	Fri Jul 27 12:36:09 2012 +0000
@@ -16,10 +16,12 @@
 import de.intevation.flys.artifacts.model.sq.SQCurveFacet;
 import de.intevation.flys.artifacts.model.sq.SQFractionResult;
 import de.intevation.flys.artifacts.model.sq.SQMeasurementFacet;
+import de.intevation.flys.artifacts.model.sq.SQOutlierCurveFacet;
 import de.intevation.flys.artifacts.model.sq.SQOutlierFacet;
+import de.intevation.flys.artifacts.model.sq.SQOutlierMeasurementFacet;
+import de.intevation.flys.artifacts.model.sq.SQOverviewFacet;
 import de.intevation.flys.artifacts.model.sq.SQRelationCalculation;
 import de.intevation.flys.artifacts.model.sq.SQResult;
-import de.intevation.flys.artifacts.model.sq.SQOverviewFacet;
 
 import de.intevation.flys.artifacts.resources.Resources;
 
@@ -44,6 +46,11 @@
     public static final String I18N_FACET_OUTLIERS =
         "facet.sq_relation.outliers";
 
+    public static final String I18N_FACET_OUTLIER_CURVE =
+        "facet.sq_relation.outlier.curve";
+
+    public static final String I18N_FACET_OUTLIER_MEASUREMENT =
+        "facet.sq_relation.outlier.measurement";
 
     public SQRelation() {
     }
@@ -94,6 +101,8 @@
         SQResult[]  sqr,
         String      hash
     ) {
+        boolean debug = log.isDebugEnabled();
+
         CallMeta meta    = context.getMeta();
         String   stateId = getID();
         for (int i = 0; i < 6; i++) {
@@ -112,7 +121,7 @@
         }
         for (int res = 0, n = sqr.length; res < n; res++) {
 
-            for (int i = 0; i < 6; i++) {
+            for (int i = 0; i < SQResult.NUMBER_FRACTIONS; i++) {
                 SQFractionResult result = sqr[res].getFraction(i);
 
                 if (result == null) {
@@ -120,19 +129,6 @@
                     continue;
                 }
 
-                container.add(new SQMeasurementFacet(
-                    res,
-                    i,
-                    getFractionFacetname(1, i),
-                    Resources.getMsg(
-                        meta,
-                        I18N_FACET_MEASUREMENTS,
-                        I18N_FACET_MEASUREMENTS
-                    ),
-                    hash,
-                    stateId
-                ));
-
                 container.add(new SQCurveFacet(
                     res,
                     i,
@@ -146,12 +142,15 @@
                     stateId
                 ));
 
-                for (int j = 0, C = result.getOutliersCount(); j < C; j++) {
+                for (int j = 0, C = result.numIterations()-1; j < C; j++) {
+
+                    Object [] round = new Object [] { j + 1 };
+
                     int index = res;
                     index     = index << 16;
                     index     = index + j;
 
-                    if (log.isDebugEnabled()) {
+                    if (debug) {
                         log.debug("new outliers facet (index=" +index+ ")");
                         log.debug("   result index = " + res);
                         log.debug("   fraction idx = " + i);
@@ -166,51 +165,83 @@
                             meta,
                             I18N_FACET_OUTLIERS,
                             I18N_FACET_OUTLIERS,
-                            new Object[] { j }
+                            round
                         ),
                         hash,
                         stateId
                     ));
-                }
-            }
+
+                    container.add(new SQOutlierCurveFacet(
+                        index,
+                        i,
+                        getFractionFacetname(3, i),
+                        Resources.getMsg(
+                            meta,
+                            I18N_FACET_OUTLIER_CURVE,
+                            I18N_FACET_OUTLIER_CURVE,
+                            round
+                        ),
+                        hash,
+                        stateId
+                    ));
+
+                    container.add(new SQOutlierMeasurementFacet(
+                        index,
+                        i,
+                        getFractionFacetname(4, i),
+                        Resources.getMsg(
+                            meta,
+                            I18N_FACET_OUTLIER_MEASUREMENT,
+                            I18N_FACET_OUTLIER_MEASUREMENT,
+                            round
+                        ),
+                        hash,
+                        stateId
+                    ));
+                } // for all outliers
+
+                container.add(new SQMeasurementFacet(
+                    res,
+                    i,
+                    getFractionFacetname(1, i),
+                    Resources.getMsg(
+                        meta,
+                        I18N_FACET_MEASUREMENTS,
+                        I18N_FACET_MEASUREMENTS
+                    ),
+                    hash,
+                    stateId
+                ));
+            } // for all fractions
+        } // for all results
+    }
+
+    public static final String [][] FACET_NAMES = {
+        { SQ_A_CURVE, SQ_B_CURVE, SQ_C_CURVE,
+          SQ_D_CURVE, SQ_E_CURVE, SQ_F_CURVE
+        },
+        { SQ_A_MEASUREMENT, SQ_B_MEASUREMENT, SQ_C_MEASUREMENT,
+          SQ_D_MEASUREMENT, SQ_E_MEASUREMENT, SQ_F_MEASUREMENT
+        },
+        { SQ_A_OUTLIER, SQ_B_OUTLIER, SQ_C_OUTLIER,
+          SQ_D_OUTLIER, SQ_E_OUTLIER, SQ_F_OUTLIER
+        },
+        { SQ_A_OUTLIER_CURVE, SQ_B_OUTLIER_CURVE, SQ_C_OUTLIER_CURVE,
+          SQ_D_OUTLIER_CURVE, SQ_E_OUTLIER_CURVE, SQ_F_OUTLIER_CURVE
+        },
+        { SQ_A_OUTLIER_MEASUREMENT, SQ_B_OUTLIER_MEASUREMENT,
+          SQ_C_OUTLIER_MEASUREMENT, SQ_D_OUTLIER_MEASUREMENT,
+          SQ_E_OUTLIER_MEASUREMENT, SQ_F_OUTLIER_MEASUREMENT
         }
-    }
+    };
 
 
-    protected String getFractionFacetname(int type, int fractionIdx) {
-        log.debug("getFractionFacetname(): " + type + " | " + fractionIdx);
-
-        switch (type) {
-            case 0:
-                switch (fractionIdx) {
-                    case 0: return SQ_A_CURVE;
-                    case 1: return SQ_B_CURVE;
-                    case 2: return SQ_C_CURVE;
-                    case 3: return SQ_D_CURVE;
-                    case 4: return SQ_E_CURVE;
-                    case 5: return SQ_F_CURVE;
-                }
-            case 1:
-                switch (fractionIdx) {
-                    case 0: return SQ_A_MEASUREMENT;
-                    case 1: return SQ_B_MEASUREMENT;
-                    case 2: return SQ_C_MEASUREMENT;
-                    case 3: return SQ_D_MEASUREMENT;
-                    case 4: return SQ_E_MEASUREMENT;
-                    case 5: return SQ_F_MEASUREMENT;
-                }
-            case 2:
-                switch (fractionIdx) {
-                    case 0: return SQ_A_OUTLIER;
-                    case 1: return SQ_B_OUTLIER;
-                    case 2: return SQ_C_OUTLIER;
-                    case 3: return SQ_D_OUTLIER;
-                    case 4: return SQ_E_OUTLIER;
-                    case 5: return SQ_F_OUTLIER;
-                }
+    protected static String getFractionFacetname(int type, int idx) {
+        if (log.isDebugEnabled()) {
+            log.debug("getFractionFacetname(): " + type + " | " + idx);
         }
-
-        return null;
+        type %= FACET_NAMES.length;
+        return FACET_NAMES[type][idx % FACET_NAMES[type].length];
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationExporter.java	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/sq/SQRelationExporter.java	Fri Jul 27 12:36:09 2012 +0000
@@ -120,20 +120,26 @@
     protected void data2CSV(CSVWriter writer, SQResult result) {
         logger.debug("data2CSV");
 
+        // TODO: i18n
         String km = String.valueOf(result.getKm());
 
         for (int i = 0; i < SQResult.NUMBER_FRACTIONS; ++i) {
             SQFractionResult fraction = result.getFraction(i);
-            if (!fraction.isValid()) {
+
+            String name = result.getFractionName(i);
+
+            Parameters parameters = fraction.getParameters();
+
+            if (parameters == null) {
                 continue;
             }
-            String name = result.getFractionName(i);
-            Parameters parameters = fraction.getParameters();
+
             double a  = parameters.getValue(0, "a");
             double b  = parameters.getValue(0, "b");
             double sd = Math.sqrt(parameters.getValue(0, "std_dev"));
-            int    t  = fraction.getTotalCount();
-            int    o  = fraction.getOutliersCount();
+            int    o  = fraction.totalNumOutliers();
+            int    t  = fraction.numMeasurements() + o;
+
             writer.writeNext(new String[] {
                 km,
                 name,
--- a/flys-artifacts/src/main/resources/messages.properties	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/resources/messages.properties	Fri Jul 27 12:36:09 2012 +0000
@@ -161,6 +161,8 @@
 facet.sq_relation.curve = Potenziell (Geschiebedaten)
 facet.sq_relation.measurements = Geschiebedaten
 facet.sq_relation.outliers = Ausrei\u00dfer Durchgang {0}
+facet.sq_relation.outlier.curve = Potenziell Durchgang {0}
+facet.sq_relation.outlier.measurement = Geschiebedaten Durchgang {0}
 
 facet.longitudinal_section.annotations = POIs
 facet.discharge_curves.mainvalues.q = Q (main values)
--- a/flys-artifacts/src/main/resources/messages_de.properties	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/resources/messages_de.properties	Fri Jul 27 12:36:09 2012 +0000
@@ -161,6 +161,8 @@
 facet.sq_relation.curve = Potenziell (Geschiebedaten)
 facet.sq_relation.measurements = Geschiebedaten
 facet.sq_relation.outliers = Ausrei\u00dfer Durchgang {0}
+facet.sq_relation.outlier.curve = Potenziell Durchgang {0}
+facet.sq_relation.outlier.measurement = Geschiebedaten Durchgang {0}
 
 facet.longitudinal_section.annotations = Streckenfavoriten
 facet.discharge_curves.mainvalues.q = Q (Haupt- und Extremwerte)
--- a/flys-artifacts/src/main/resources/messages_de_DE.properties	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/resources/messages_de_DE.properties	Fri Jul 27 12:36:09 2012 +0000
@@ -159,6 +159,8 @@
 facet.sq_relation.curve = Potenziell (Geschiebedaten)
 facet.sq_relation.measurements = Geschiebedaten
 facet.sq_relation.outliers = Ausrei\u00dfer Durchgang {0}
+facet.sq_relation.outlier.curve = Potenziell Durchgang {0}
+facet.sq_relation.outlier.measurement = Geschiebedaten Durchgang {0}
 
 facet.longitudinal_section.annotations = Streckenfavoriten
 facet.discharge_curves.mainvalues.q = Q (Haupt- und Extremwerte)
--- a/flys-artifacts/src/main/resources/messages_en.properties	Fri Jul 27 08:36:24 2012 +0000
+++ b/flys-artifacts/src/main/resources/messages_en.properties	Fri Jul 27 12:36:09 2012 +0000
@@ -163,6 +163,8 @@
 facet.sq_relation.curve = Potenziell (Geschiebedaten)
 facet.sq_relation.measurements = Geschiebedaten
 facet.sq_relation.outliers = Ausrei\u00dfer Durchgang {0}
+facet.sq_relation.outlier.curve = Potenziell Durchgang {0}
+facet.sq_relation.outlier.measurement = Geschiebedaten Durchgang {0}
 
 facet.longitudinal_section.annotations = POIs
 facet.discharge_curves.mainvalues.q = Q (main values)

http://dive4elements.wald.intevation.org