changeset 6855:8d98e1825846

Merged backout of changes for 1440 (gap-detection in bedquality).
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Mon, 19 Aug 2013 10:55:52 +0200
parents 9e81ed565095 (diff) aa14ae10a853 (current diff)
children fbbba09ac6a8
files artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityGenerator.java
diffstat 58 files changed, 1191 insertions(+), 342 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/doc/conf/artifacts/winfo.xml	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/doc/conf/artifacts/winfo.xml	Mon Aug 19 10:55:52 2013 +0200
@@ -326,6 +326,8 @@
                         <facet name="computed_discharge_curve.mainvalues.w" description="facet.computed_discharge_curve.mainvalues.w"/>
                         <facet name="discharge_curve.curve" description="facet.discharge_curve.curve"/>
                         <facet name="heightmarks_points" description="facet.other.wqkms"/>
+                        <facet name="other.wqkms.w" description="facet.other.wqkms"/>
+                        <facet name="other.wqkms.q" description="facet.other.wqkms"/>
                         <facet name="other.wqkms" description="facet.other.wqkms"/>
                         <facet name="other.wq"    description="Point-like data like fixations"/>
                         <facet name="other.wkms"  description="Point-like data like fixations"/>
@@ -382,6 +384,8 @@
                 </outputmode>
                 <outputmode name="waterlevel_export" description="output.waterlevel_export" mime-type="text/plain" type="export">
                   <facets>
+                    <!-- include other.wqkms.w to be able to include official lines (issue1384) -->
+                    <facet name="other.wqkms.w" description="W-Type of data" />
                     <facet name="csv" description="facet.waterlevel_export.csv" />
                     <facet name="wst" description="facet.waterlevel_export.wst" />
                     <facet name="pdf" description="facet.waterlevel_export.pdf" />
@@ -638,6 +642,7 @@
                 </outputmode>
                 <outputmode name="historical_discharge_wq" description="output.historical_discharge_wq.description" mime-type="image/png" type="chart">
                     <facets>
+                        <facet name="discharge_curve.curve"/>
                         <facet name="historical_discharge.wq.q"/>
                         <facet name="historical_discharge.wq.w"/>
                         <facet name="historical_discharge.wq.curve"/>
Binary file artifacts/doc/conf/jasper/sqrelation.jasper has changed
Binary file artifacts/doc/conf/jasper/sqrelation_en.jasper has changed
--- a/artifacts/doc/conf/mapserver/barrier_lines_class.vm	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/doc/conf/mapserver/barrier_lines_class.vm	Mon Aug 19 10:55:52 2013 +0200
@@ -1,6 +1,6 @@
 CLASS
     NAME "Damm"
-    EXPRESSION ("[TYP]"="Damm")
+    EXPRESSION /damm/i
     STYLE
         SIZE 5
         OUTLINECOLOR "#008000"
@@ -8,7 +8,7 @@
 END
 CLASS
     NAME "Rohr 1"
-    EXPRESSION ("[TYP]"="Rohr 1")
+    EXPRESSION /rohr.1/i
     STYLE
         SIZE 5
         OUTLINECOLOR "#800080"
@@ -16,7 +16,7 @@
 END
 CLASS
     NAME "Rohr 2"
-    EXPRESSION ("[TYP]"="Rohr 2")
+    EXPRESSION /rohr.2/i
     STYLE
         SIZE 5
         OUTLINECOLOR "#808080"
@@ -24,7 +24,7 @@
 END
 CLASS
     NAME "Graben"
-    EXPRESSION ("[TYP]"="Graben")
+    EXPRESSION /graben/i
     STYLE
         SIZE 5
         OUTLINECOLOR "#800000"
@@ -32,7 +32,7 @@
 END
 CLASS
     NAME "Ringdeich"
-    EXPRESSION ("[TYP]"="Ringdeich")
+    EXPRESSION /ringdeich/i
     STYLE
         SIZE 5
         OUTLINECOLOR "#800000"
--- a/artifacts/doc/conf/mapserver/barrier_polygons_class.vm	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/doc/conf/mapserver/barrier_polygons_class.vm	Mon Aug 19 10:55:52 2013 +0200
@@ -1,6 +1,6 @@
 CLASS
     NAME "Ringdeich"
-    EXPRESSION ("[TYP]"="Ringdeich")
+    EXPRESSION /ringdeich/i
     STYLE
         SIZE 5
         OUTLINECOLOR "#FF8000"
--- a/artifacts/doc/conf/mapserver/shapefile_layer.vm	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/doc/conf/mapserver/shapefile_layer.vm	Mon Aug 19 10:55:52 2013 +0200
@@ -21,6 +21,8 @@
             "wms_group_title" "$LAYER.getGroupTitle()"
         #end
     END
+    
+    CLASSITEM "TYP"
 
     #if ( !$LAYER.getStyle() )
         #if ( $LAYER.getGroupTitle() )
--- a/artifacts/doc/conf/meta-data.xml	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/doc/conf/meta-data.xml	Mon Aug 19 10:55:52 2013 +0200
@@ -353,6 +353,7 @@
                     <dc:when test="$out = 'longitudinal_section'">
                       <dc:call-macro name="longitudinal"/>
                       <dc:call-macro name="differences"/>
+                      <dc:call-macro name="bedheight_differences"/>
                     </dc:when>
                     <dc:when test="$out = 'discharge_longitudinal_section'">
                       <dc:call-macro name="longitudinal"/>
@@ -401,6 +402,7 @@
                     <dc:when test="$out = 'bedheight_middle'">
                       <dc:call-macro name="waterlevels-discharge"/>
                       <dc:call-macro name="differenceable-fix"/>
+                      <dc:call-macro name="differences"/>
                     </dc:when>
                     <dc:when test="$out = 'floodmap-hws'">
                       <dc:call-macro name="floodmap-hws-user"/>
@@ -485,22 +487,23 @@
 
 
     <dc:macro name="historical_discharge_curve">
+      <dc:variable name="refgauge" type="number" expr="$reference_gauge"/>
       <dc:context>
         <dc:statement>
           SELECT g.id   AS gauge_id,
-                 g.name AS gauge_name,
-                 dt.id AS dt_id,
-                 t.start_time AS start_time,
-                 t.stop_time AS stop_time,
-                 dt.description AS desc,
-                 dt.bfg_id AS bfg_id
+          g.name AS gauge_name,
+          dt.id AS dt_id,
+          t.start_time AS start_time,
+          t.stop_time AS stop_time,
+          dt.description AS desc,
+          dt.bfg_id AS bfg_id
           FROM gauges g
           JOIN discharge_tables dt ON g.id = dt.gauge_id
           LEFT JOIN time_intervals t ON dt.time_interval_id = t.id
           WHERE g.river_id = ${river_id}
           AND dt.kind &lt;&gt; 0
-          AND g.station = ${fromkm}
-          AND g.station = ${tokm}
+          AND ((g.station = ${fromkm} AND g.station = ${tokm})
+          OR g.official_number = ${refgauge})
           ORDER BY start_time
         </dc:statement>
         <dc:if test="dc:has-result()">
@@ -508,9 +511,6 @@
             <dc:group expr="$gauge_name">
               <dc:for-each>
                 <dc:variable name="combined_desc" expr="concat($bfg_id, ' ', dc:date-format('dd.MM.yyyy', $start_time), ' - ', dc:date-format('dd.MM.yyyy', $stop_time))"/>
-                <dc:message>
-                  Hallo ANDRE23 {dc:dump-variables()}
-                </dc:message>
                 <histdis name="{$combined_desc}"
                   description="{$combined_desc}"
                   factory="gaugedischarge" target_out="{$out}"
@@ -1337,17 +1337,14 @@
           LEFT JOIN time_intervals t ON dt.time_interval_id = t.id
           WHERE g.river_id = ${river_id}
           AND dt.kind = 0
-          AND g.station = ${fromkm}
-          AND g.station = ${tokm}
+          AND ((g.station = ${fromkm} AND g.station = ${tokm})
+          OR g.official_number = ${refgauge})
         </dc:statement>
         <dc:if test="dc:has-result()">
-          <current_gauge>
-            <dc:for-each>
-              <gauge name="{$gauge_name} ({dc:date-format('dd.MM.yyyy', $start_time)})"
-                factory="gaugedischarge" target_out="{$out}"
-                ids="{$gauge_name}"/>
-            </dc:for-each>
-          </current_gauge>
+          <dc:for-each>
+            <current_gauge factory="gaugedischarge" target_out="{$out}"
+              ids="{$gauge_name}"/>
+          </dc:for-each>
         </dc:if>
       </dc:context>
     </dc:macro>
--- a/artifacts/doc/conf/themes.xml	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/doc/conf/themes.xml	Mon Aug 19 10:55:52 2013 +0200
@@ -273,6 +273,7 @@
         <mapping from="fix_analysis_events_wq" to="FixingAnalysisEventsWQ" />
         <mapping from="fix_outlier" to="FixingOutlier" />
         <mapping from="fix_wq_curve" to="FixingWQCurve" />
+        <mapping from="fix_wq_ls" to="FixingCalculatedPoint" />
         <mapping from="fix_reference_events_wq" to="FixingReferenceEvents" />
         <mapping from="fix_sector_average_dwt_0" to="FixingDeltaWtAverage0" />
         <mapping from="fix_sector_average_dwt_1" to="FixingDeltaWtAverage1" />
--- a/artifacts/doc/conf/themes/default.xml	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/doc/conf/themes/default.xml	Mon Aug 19 10:55:52 2013 +0200
@@ -1459,6 +1459,20 @@
         </fields>
     </theme>
 
+    <theme name="FixingCalculatedPoint">
+        <inherits>
+            <inherit from="FixPoints" />
+        </inherits>
+        <fields>
+            <field name="pointcolor" type="Color" display="Punktfarbe"
+                default="0, 0, 0" />
+            <field name="pointsize" type="int" display="Punktdicke"
+                default="5"/>
+            <field name="showpointlabel" type="boolean"
+                display="Punktbeschriftung anzeigen" default="false"/>
+        </fields>
+    </theme>
+
     <theme name="FixingWQCurve">
         <inherits>
             <inherit from="FixLines" />
@@ -1561,9 +1575,21 @@
         </fields>
     </theme>
 
+    <theme name="FixingDeltaWtAverage">
+        <inherits>
+            <inherit from="FixLines" />
+        </inherits>
+        <fields>
+            <field name="showpointlabel" type="boolean"
+                display="Punktbeschriftung anzeigen" default="false" hints="hidden"/>
+            <field name="showlinelabel" type="boolean"
+                display="Beschriftung anzeigen" default="true" />
+        </fields>
+    </theme>
+
     <theme name="FixingDeltaWtAverage0">
         <inherits>
-            <inherit from="FixLines" />
+            <inherit from="FixingDeltaWtAverage" />
         </inherits>
         <fields>
             <field name="linecolor" type="Color" display="Linienfarbe"
@@ -1573,7 +1599,7 @@
 
     <theme name="FixingDeltaWtAverage1">
         <inherits>
-            <inherit from="FixLines" />
+            <inherit from="FixingDeltaWtAverage" />
         </inherits>
         <fields>
             <field name="linecolor" type="Color" display="Linienfarbe"
@@ -1583,7 +1609,7 @@
 
     <theme name="FixingDeltaWtAverage2">
         <inherits>
-            <inherit from="FixLines" />
+            <inherit from="FixingDeltaWtAverage" />
         </inherits>
         <fields>
             <field name="linecolor" type="Color" display="Linienfarbe"
@@ -1593,7 +1619,7 @@
 
     <theme name="FixingDeltaWtAverage3">
         <inherits>
-            <inherit from="FixLines" />
+            <inherit from="FixingDeltaWtAverage" />
         </inherits>
         <fields>
             <field name="linecolor" type="Color" display="Linienfarbe"
--- a/artifacts/doc/conf/themes/second.xml	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/doc/conf/themes/second.xml	Mon Aug 19 10:55:52 2013 +0200
@@ -14,6 +14,20 @@
         </fields>
     </theme>
 
+    <theme name="MainValuesQVerticalText">
+        <inherits>
+            <inherit from="Lines" />
+        </inherits>
+        <fields>
+            <field name="linecolor" type="Color" display="Farbe"
+                default="200, 0, 15" />
+            <field name="textorientation" type="boolean" display="Textausrichtung"
+                default="false" />
+            <field name="showlinelabel" type="boolean"
+                display="Linienbeschriftung anzeigen" default="false" hints="hidden" />
+        </fields>
+    </theme>
+
     <theme name="MainValuesW">
         <inherits>
             <inherit from="Lines" />
@@ -28,20 +42,6 @@
         </fields>
     </theme>
 
-    <theme name="MainValuesQVerticalText">
-        <inherits>
-            <inherit from="Lines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Farbe"
-                default="200, 0, 15" />
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="false" />
-            <field name="showlinelabel" type="boolean"
-                display="Linienbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
     <theme name="RelativePoint">
         <inherits>
             <inherit from="Points" />
@@ -843,7 +843,7 @@
             <field name="showlines" type="boolean" display="Linie anzeigen"
                 default="true" />
             <field name="linesize" type="int" display="Liniendicke"
-                default="2" />
+                default="1" />
             <field name="linetype" type="Dash" display="Linienart"
                 default="10" />
             <field name="linecolor" type="Color" display="Linienfarbe"
@@ -1459,6 +1459,20 @@
         </fields>
     </theme>
 
+    <theme name="FixingCalculatedPoint">
+        <inherits>
+            <inherit from="FixPoints" />
+        </inherits>
+        <fields>
+            <field name="pointcolor" type="Color" display="Punktfarbe"
+                default="0, 0, 0" />
+            <field name="pointsize" type="int" display="Punktdicke"
+                default="5"/>
+            <field name="showpointlabel" type="boolean"
+                display="Punktbeschriftung anzeigen" default="false"/>
+        </fields>
+    </theme>
+
     <theme name="FixingWQCurve">
         <inherits>
             <inherit from="FixLines" />
@@ -1561,9 +1575,21 @@
         </fields>
     </theme>
 
+    <theme name="FixingDeltaWtAverage">
+        <inherits>
+            <inherit from="FixLines" />
+        </inherits>
+        <fields>
+            <field name="showpointlabel" type="boolean"
+                display="Punktbeschriftung anzeigen" default="false" hints="hidden"/>
+            <field name="showlinelabel" type="boolean"
+                display="Beschriftung anzeigen" default="true" />
+        </fields>
+    </theme>
+
     <theme name="FixingDeltaWtAverage0">
         <inherits>
-            <inherit from="FixLines" />
+            <inherit from="FixingDeltaWtAverage" />
         </inherits>
         <fields>
             <field name="linecolor" type="Color" display="Linienfarbe"
@@ -1573,7 +1599,7 @@
 
     <theme name="FixingDeltaWtAverage1">
         <inherits>
-            <inherit from="FixLines" />
+            <inherit from="FixingDeltaWtAverage" />
         </inherits>
         <fields>
             <field name="linecolor" type="Color" display="Linienfarbe"
@@ -1583,7 +1609,7 @@
 
     <theme name="FixingDeltaWtAverage2">
         <inherits>
-            <inherit from="FixLines" />
+            <inherit from="FixingDeltaWtAverage" />
         </inherits>
         <fields>
             <field name="linecolor" type="Color" display="Linienfarbe"
@@ -1593,7 +1619,7 @@
 
     <theme name="FixingDeltaWtAverage3">
         <inherits>
-            <inherit from="FixLines" />
+            <inherit from="FixingDeltaWtAverage" />
         </inherits>
         <fields>
             <field name="linecolor" type="Color" display="Linienfarbe"
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Datacage.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Datacage.java	Mon Aug 19 10:55:52 2013 +0200
@@ -896,8 +896,8 @@
             @Override
             public boolean doIt() throws SQLException {
                 prepareStatement(SQL_UPDATE_ARTIFACT_STATE);
-                stmnt.setInt(1, artifactId);
-                stmnt.setString(2, artifact.getCurrentStateId());
+                stmnt.setString(1, artifact.getCurrentStateId());
+                stmnt.setInt(2, artifactId);
                 stmnt.execute();
                 conn.commit();
                 return true;
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java	Mon Aug 19 10:55:52 2013 +0200
@@ -37,6 +37,7 @@
     private long []   timerange;
     private double [] values;
     private Long      officialGaugeNumber;
+    private String    riverName;
 
 
     public Calculation6(HistoricalDischargeAccess access) {
@@ -45,6 +46,7 @@
         double [] vs = mode != null && mode == EvaluationMode.W
             ? access.getWs()
             : access.getQs();
+        riverName = access.getRiver();
 
         Long officialGaugeNumber = access.getOfficialGaugeNumber();
 
@@ -98,7 +100,8 @@
             return null;
         }
 
-        Gauge gauge = Gauge.getGaugeByOfficialNumber(officialGaugeNumber);
+        Gauge gauge = Gauge.getGaugeByOfficialNumber(officialGaugeNumber,
+                riverName);
         if (gauge == null) {
             // TODO: i18n
             return error("hist.discharge.gauge.not.found");
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsOverview.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsOverview.java	Mon Aug 19 10:55:52 2013 +0200
@@ -28,8 +28,10 @@
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import org.dive4elements.river.utils.BatchLoader;
 
-/** Generate Fixings Table chart. */
+
+/** Generate Fixings Table overview data structure to be stored in cache. */
 public class FixingsOverview
 implements   Serializable
 {
@@ -56,39 +58,154 @@
         "WHERE" +
         "    river_id = :river_id AND kind = 2";
 
-    /** All columns from given wst. */
-    public static final String SQL_FIXING_COLUMNS =
-        "SELECT" +
-        "    wc.id         AS wst_column_id," +
-        "    ti.start_time AS start_time," +
-        "    wc.name       AS name " +
-        "FROM wst_columns wc" +
-        "    JOIN time_intervals ti ON wc.time_interval_id = ti.id " +
-        "WHERE" +
-        "    wc.wst_id = :wst_id " +
-        "ORDER BY position";
+    public static final String SQL_FIXING_COLUMNS_BATCH =
+        "SELECT " +
+            "wc.wst_id     AS wst_id," +
+            "wc.id         AS wst_column_id," +
+            "ti.start_time AS start_time," +
+            "wc.name       AS name " +
+        "FROM wst_columns wc " +
+            "JOIN time_intervals ti ON wc.time_interval_id = ti.id " +
+        "WHERE " +
+            "wc.wst_id IN ($IDS) " +
+        "ORDER BY wc.wst_id, position";
 
-    public static final String SQL_FIXING_COLUMN_Q_RANGES =
-        "SELECT" +
-        "    wqr.q AS q," +
-        "    r.a   AS start_km," +
-        "    r.b   AS stop_km " +
-        "FROM wst_column_q_ranges wcqr" +
-        "    JOIN wst_q_ranges wqr ON wcqr.wst_q_range_id = wqr.id" +
-        "    JOIN ranges       r   ON wqr.range_id        = r.id " +
-        "WHERE" +
-        "    wcqr.wst_column_id = :column_id " +
-        "ORDER BY r.a";
+    public static final String SQL_FIXING_COLUMN_Q_RANGES_BATCH =
+        "SELECT " +
+            "wcqr.wst_column_id AS wst_column_id," +
+            "wqr.q              AS q," +
+            "r.a                AS start_km," +
+            "r.b                AS stop_km " +
+        "FROM wst_column_q_ranges wcqr " +
+            "JOIN wst_q_ranges wqr ON wcqr.wst_q_range_id = wqr.id " +
+            "JOIN ranges       r   ON wqr.range_id        = r.id " +
+        "WHERE " +
+            "wcqr.wst_column_id IN ($IDS) " +
+        "ORDER BY wcqr.wst_column_id, r.a";
 
-    public static final String SQL_FIXING_COLUMN_KM_RANGE =
-        "SELECT" +
-        "    MIN(position) AS start_km," +
-        "    MAX(position) AS stop_km " +
-        "FROM" +
-        "    wst_column_values " +
-        "WHERE" +
-        "    wst_column_id = :column_id";
+    public static final String SQL_FIXING_COLUMN_KM_RANGE_BATCH =
+        "SELECT " +
+            "wst_column_id," +
+            "MIN(position) AS start_km," +
+            "MAX(position) AS stop_km " +
+        "FROM " +
+            "wst_column_values " +
+        "WHERE " +
+            "wst_column_id IN ($IDS) " +
+        "GROUP BY wst_column_id";
 
+    public static final class KMRangeLoader extends BatchLoader<double []> {
+
+        public KMRangeLoader(List<Integer> columns, Session session) {
+            super(columns, session, SQL_FIXING_COLUMN_KM_RANGE_BATCH);
+        }
+
+        @Override
+        protected void fill(SQLQuery query) {
+            query
+                .addScalar("wst_column_id", StandardBasicTypes.INTEGER)
+                .addScalar("start_km",      StandardBasicTypes.DOUBLE)
+                .addScalar("stop_km",       StandardBasicTypes.DOUBLE);
+
+            List<Object []> ranges = query.list();
+            for (Object [] r: ranges) {
+                Integer cid = (Integer)r[0];
+                double [] vs = new double [] { (Double)r[1], (Double)r[2] };
+                cache(cid, vs);
+            }
+        }
+    } // class KMRangeLoader
+
+    public static final class ColumnQRangeLoader extends BatchLoader<List<double []>> {
+
+        public ColumnQRangeLoader(List<Integer> columns, Session session) {
+            super(columns, session, SQL_FIXING_COLUMN_Q_RANGES_BATCH);
+        }
+
+        @Override
+        protected void fill(SQLQuery query) {
+            query
+                .addScalar("wst_column_id", StandardBasicTypes.INTEGER)
+                .addScalar("q",             StandardBasicTypes.DOUBLE)
+                .addScalar("start_km",      StandardBasicTypes.DOUBLE)
+                .addScalar("stop_km",       StandardBasicTypes.DOUBLE);
+
+            int lastId = Integer.MIN_VALUE;
+            List<double []> column = new ArrayList<double []>();
+
+            List<Object []> ranges = query.list();
+            for (Object [] r: ranges) {
+                int cid = (Integer)r[0];
+
+                if (cid != lastId && !column.isEmpty()) {
+                    cache(lastId, column);
+                    column = new ArrayList<double []>();
+                }
+                column.add(new double [] {
+                    (Double)r[1],
+                    (Double)r[2],
+                    (Double)r[3]
+                });
+
+                lastId = cid;
+            }
+
+            if (!column.isEmpty()) {
+                cache(lastId, column);
+            }
+        }
+    } // class ColumnQRangeLoader
+
+    /** Helper class to store data from batching fixing columns. */
+    private static final class FixColumn {
+        int    columnId;
+        Date   startTime;
+        String name;
+
+        FixColumn(int columnId, Date startTime, String name) {
+            this.columnId  = columnId;
+            this.startTime = startTime;
+            this.name      = name;
+        }
+    } // class FixColumn
+
+    public static final class FixColumnLoader extends BatchLoader<List<FixColumn>> {
+
+        public FixColumnLoader(List<Integer> columns, Session session) {
+            super(columns, session, SQL_FIXING_COLUMNS_BATCH);
+        }
+
+        @Override
+        protected void fill(SQLQuery query) {
+            query
+                .addScalar("wst_id",        StandardBasicTypes.INTEGER)
+                .addScalar("wst_column_id", StandardBasicTypes.INTEGER)
+                .addScalar("start_time",    StandardBasicTypes.DATE)
+                .addScalar("name",          StandardBasicTypes.STRING);
+
+            int lastId = Integer.MIN_VALUE;
+            List<FixColumn> cols = new ArrayList<FixColumn>();
+
+            List<Object []> columns = query.list();
+            for (Object [] c: columns) {
+                int wid = (Integer)c[0];
+
+                if (wid != lastId && !cols.isEmpty()) {
+                    cache(lastId, cols);
+                    cols = new ArrayList<FixColumn>();
+                }
+                cols.add(new FixColumn(
+                    (Integer)c[1],
+                    (Date)   c[2],
+                    (String) c[3]));
+
+                lastId = wid;
+            }
+            if (!cols.isEmpty()) {
+                cache(lastId, cols);
+            }
+        }
+    } // class FixColumnLoader
 
     public static class QRange extends Range {
 
@@ -255,34 +372,35 @@
                 } // for all Q ranges
             }
 
-            public void loadKmRange(SQLQuery query) {
-                query.setInteger("column_id", columnId);
-
-                List<Object []> kms = query.list();
+            public void loadKmRange(KMRangeLoader loader) {
 
-                if (kms.isEmpty()) {
+                double [] range = loader.get(columnId);
+
+                if (range == null) {
                     log.warn("No km range for column " + columnId + ".");
+                    return;
                 }
-                else {
-                    Object [] obj = kms.get(0);
-                    start = (Double)obj[0];
-                    end   = (Double)obj[1];
-                }
+                start = range[0];
+                end   = range[1];
             }
 
             public void loadQRanges(
-                SQLQuery    query,
-                GaugeFinder gaugeFinder
+                ColumnQRangeLoader loader,
+                GaugeFinder        gaugeFinder
             ) {
-                query.setInteger("column_id", columnId);
-                List<Object []> list = query.list();
+                List<double []> qrs = loader.get(columnId);
+                if (qrs == null) {
+                    log.warn("No q ranges found for column " + columnId);
+                    return;
+                }
 
-                List<QRange> qRanges = new ArrayList<QRange>(list.size());
+                List<QRange> qRanges = new ArrayList<QRange>(qrs.size());
 
-                for (Object [] row: list) {
-                    double q     = (Double)row[0];
-                    double start = (Double)row[1];
-                    double end   = (Double)row[2];
+                for (double [] qr: qrs) {
+                    double q     = qr[0];
+                    double start = qr[1];
+                    double end   = qr[2];
+
                     QRange qRange = new QRange(start, end, q);
                     if (qRange.clip(this)) {
                         qRanges.add(qRange);
@@ -314,20 +432,26 @@
             columns = new ArrayList<Column>();
         }
 
-        public void loadColumns(SQLQuery query) {
-            query.setInteger("wst_id", wstId);
-            List<Object []> list = query.list();
-            for (Object [] row: list) {
-                int    columnId  = (Integer)row[0];
-                Date   startTime = (Date)   row[1];
-                String name      = (String) row[2];
-                columns.add(new Column(columnId, startTime, name));
+        public void allColumnIds(List<Integer> cIds) {
+            for (Column column: columns) {
+                cIds.add(column.columnId);
             }
         }
 
-        public void loadColumnsKmRange(SQLQuery query) {
+        public void loadColumns(FixColumnLoader loader) {
+            List<FixColumn> fcs = loader.get(wstId);
+            if (fcs == null) {
+                log.warn("No columns for wst " + wstId);
+                return;
+            }
+            for (FixColumn fc: fcs) {
+                columns.add(new Column(fc.columnId, fc.startTime, fc.name));
+            }
+        }
+
+        public void loadColumnsKmRange(KMRangeLoader loader) {
             for (Column column: columns) {
-                column.loadKmRange(query);
+                column.loadKmRange(loader);
             }
         }
 
@@ -338,11 +462,11 @@
         }
 
         public void loadColumnsQRanges(
-            SQLQuery    query,
-            GaugeFinder gaugeFinder
+            ColumnQRangeLoader loader,
+            GaugeFinder        gaugeFinder
         ) {
             for (Column column: columns) {
-                column.loadQRanges(query, gaugeFinder);
+                column.loadQRanges(loader, gaugeFinder);
             }
         }
 
@@ -427,23 +551,40 @@
     }
 
     protected void loadFixingsColumns(Session session) {
-        SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMNS)
-            .addScalar("wst_column_id", StandardBasicTypes.INTEGER)
-            .addScalar("start_time",    StandardBasicTypes.DATE)
-            .addScalar("name",          StandardBasicTypes.STRING);
+
+        FixColumnLoader loader = new FixColumnLoader(
+            allFixingIds(),
+            session);
 
         for (Fixing fixing: fixings) {
-            fixing.loadColumns(query);
+            fixing.loadColumns(loader);
         }
     }
 
+    protected List<Integer> allFixingIds() {
+        List<Integer> ids = new ArrayList<Integer>(fixings.size());
+        for (Fixing fixing: fixings) {
+            ids.add(fixing.getId());
+        }
+        return ids;
+    }
+
+    protected List<Integer> allColumnIds() {
+        List<Integer> cIds = new ArrayList<Integer>();
+        for (Fixing fixing: fixings) {
+            fixing.allColumnIds(cIds);
+        }
+        return cIds;
+    }
+
     protected void loadFixingsColumnsKmRange(Session session) {
-        SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_KM_RANGE)
-            .addScalar("start_km", StandardBasicTypes.DOUBLE)
-            .addScalar("stop_km",  StandardBasicTypes.DOUBLE);
+
+        KMRangeLoader loader = new KMRangeLoader(
+            allColumnIds(),
+            session);
 
         for (Fixing fixing: fixings) {
-            fixing.loadColumnsKmRange(query);
+            fixing.loadColumnsKmRange(loader);
         }
     }
 
@@ -451,13 +592,13 @@
         Session     session,
         GaugeFinder gaugeFinder
     ) {
-        SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_Q_RANGES)
-            .addScalar("q",        StandardBasicTypes.DOUBLE)
-            .addScalar("start_km", StandardBasicTypes.DOUBLE)
-            .addScalar("stop_km",  StandardBasicTypes.DOUBLE);
+
+        ColumnQRangeLoader loader = new ColumnQRangeLoader(
+            allColumnIds(),
+            session);
 
         for (Fixing fixing: fixings) {
-            fixing.loadColumnsQRanges(query, gaugeFinder);
+            fixing.loadColumnsQRanges(loader, gaugeFinder);
         }
     }
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurementFactory.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurementFactory.java	Mon Aug 19 10:55:52 2013 +0200
@@ -97,6 +97,7 @@
         private QualityMeasurementResultTransformer() {
         }
 
+        /** tuples is a row. */
         @Override
         public Object transformTuple(Object[] tuple, String[] aliases) {
             Map<String, Double> map = new HashMap<String, Double>();
@@ -175,6 +176,7 @@
         return new QualityMeasurements(query.list());
     }
 
+    /** Get all measurements. */
     public static QualityMeasurements getBedMeasurements(
         String river,
         double from,
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFactory.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFactory.java	Mon Aug 19 10:55:52 2013 +0200
@@ -395,19 +395,24 @@
             sqlQuery.setString("grain", "total");
             List<Object []> results = sqlQuery.list();
             SedimentLoad load = new SedimentLoad();
-            Object[] row = results.get(0);
-            load = new SedimentLoad(
-                    (String) row[0],
-                    (Date) row[1],
-                    null,
-                    false,
-                    (String) row[4]);
-            getValues("coarse", sqlQuery, load, floatStations);
-            getValues("fine_middle", sqlQuery, load, floatStations);
-            getValues("sand", sqlQuery, load, floatStations);
-            getValues("suspended_sediment", sqlQuery, load, suspStations);
-            getValues("susp_sand_bed", sqlQuery, load, floatStations);
-            getValues("susp_sand", sqlQuery, load, floatStations);
+            if (results.isEmpty()) {
+                log.warn("Empty result for year calculation.");
+            }
+            else {
+                Object[] row = results.get(0);
+                load = new SedimentLoad(
+                        (String) row[0],
+                        (Date) row[1],
+                        null,
+                        false,
+                        (String) row[4]);
+            }
+            load = getValues("coarse", sqlQuery, load, floatStations);
+            load = getValues("fine_middle", sqlQuery, load, floatStations);
+            load = getValues("sand", sqlQuery, load, floatStations);
+            load = getValues("suspended_sediment", sqlQuery, load, suspStations);
+            load = getValues("susp_sand_bed", sqlQuery, load, floatStations);
+            load = getValues("susp_sand", sqlQuery, load, floatStations);
 
             return load;
         }
@@ -628,6 +633,7 @@
 
     /**
      * Return sediment loads with 'unknown' fraction type.
+     * @param river Name of the river
      * @param unit Restrict result set to those of given unit.
      * @param type Type like year, epoch, off_epoch
      */
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java	Mon Aug 19 10:55:52 2013 +0200
@@ -8,8 +8,8 @@
 
 package org.dive4elements.river.artifacts.model.sq;
 
+import org.dive4elements.artifacts.common.utils.StringUtils;
 import org.dive4elements.river.artifacts.math.fitting.Function;
-import org.dive4elements.river.artifacts.math.fitting.Linear;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -18,9 +18,8 @@
 
 import org.apache.commons.math.optimization.fitting.CurveFitter;
 
-import org.apache.commons.math.optimization.general.AbstractLeastSquaresOptimizer;
-import org.apache.commons.math.optimization.general.GaussNewtonOptimizer;
 import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer;
+import org.apache.commons.math.stat.regression.SimpleRegression;
 
 import org.apache.log4j.Logger;
 
@@ -54,13 +53,15 @@
 
     protected Callback callback;
 
+    protected SQ.View sqView;
+
     public Fitting() {
     }
 
-    public Fitting(Function function, double stdDevFactor) {
-        this();
+    public Fitting(Function function, double stdDevFactor, SQ.View sqView) {
         this.function     = function;
         this.stdDevFactor = stdDevFactor;
+        this.sqView       = sqView;
     }
 
     public Function getFunction() {
@@ -82,57 +83,84 @@
     @Override
     public void initialize(List<SQ> sqs) throws MathException {
 
-        AbstractLeastSquaresOptimizer optimizer = getOptimizer();
+        if (USE_NON_LINEAR_FITTING
+        || function.getParameterNames().length != 2) {
+            nonLinearFitting(sqs);
+        }
+        else {
+            linearFitting(sqs);
+        }
+    }
+
+    protected void linearFitting(List<SQ> sqs) {
+        coeffs   = linearRegression(sqs);
+        instance = function.instantiate(coeffs);
+    }
+
+    protected double [] linearRegression(List<SQ> sqs) {
+
+        String [] pns = function.getParameterNames();
+        double [] result = new double[pns.length];
+
+        if (sqs.size() < 2) {
+            log.debug("not enough points");
+            return result;
+        }
+
+        SimpleRegression reg = new SimpleRegression();
+
+        for (SQ sq: sqs) {
+            double s = sqView.getS(sq);
+            double q = sqView.getQ(sq);
+            reg.addData(q, s);
+        }
+
+        double m = reg.getIntercept();
+        double b = reg.getSlope();
+
+        if (log.isDebugEnabled()) {
+            log.debug("m: " + m);
+            log.debug("b: " + b);
+        }
+
+        int mIdx = StringUtils.indexOf("m", pns);
+        int bIdx = StringUtils.indexOf("b", pns);
+
+        if (mIdx == -1 || bIdx == -1) {
+            log.error("index not found: " + mIdx + " " + bIdx);
+            return result;
+        }
+
+        result[bIdx] = m;
+        result[mIdx] = b;
+
+        return result;
+    }
+
+
+    protected void nonLinearFitting(List<SQ> sqs) throws MathException {
+
+        LevenbergMarquardtOptimizer optimizer =
+            new LevenbergMarquardtOptimizer();
 
         CurveFitter cf = new CurveFitter(optimizer);
-        double [] values = new double[2];
+
         for (SQ sq: sqs) {
-            values[0] = sq.getQ();
-            values[1] = sq.getS();
-            transformInputValues(values);
-            cf.addObservedPoint(values[0], values[1]);
+            cf.addObservedPoint(sqView.getQ(sq), sqView.getS(sq));
         }
 
         coeffs = cf.fit(
             function, function.getInitialGuess());
 
-        transformCoeffsBack(coeffs);
-
         instance = function.instantiate(coeffs);
 
         chiSqr = optimizer.getChiSquare();
     }
 
-    protected Function getFunction(Function function) {
-        return USE_NON_LINEAR_FITTING
-            ? function
-            : Linear.INSTANCE;
-    }
-
-    protected void transformInputValues(double [] values) {
-        if (!USE_NON_LINEAR_FITTING) {
-            for (int i = 0; i < values.length; ++i) {
-                values[i] = Math.log(values[i]);
-            }
-        }
-    }
-
-    protected AbstractLeastSquaresOptimizer getOptimizer() {
-        return USE_NON_LINEAR_FITTING
-            ? new LevenbergMarquardtOptimizer()
-            : new GaussNewtonOptimizer(false);
-    }
-
-    protected void transformCoeffsBack(double [] coeffs) {
-        if (!USE_NON_LINEAR_FITTING && coeffs.length > 0) {
-            coeffs[0] = Math.exp(coeffs[0]);
-        }
-    }
-
     @Override
     public double eval(SQ sq) {
-        double s = instance.value(sq.q);
-        return sq.s - s;
+        double s = instance.value(sqView.getQ(sq));
+        return sqView.getS(sq) - s;
     }
 
     @Override
@@ -157,28 +185,15 @@
             chiSqr);
     }
 
-    protected static final List<SQ> onlyValid(List<SQ> sqs) {
-
-        List<SQ> good = new ArrayList<SQ>(sqs.size());
-
-        for (SQ sq: sqs) {
-            if (sq.isValid()) {
-                good.add(sq);
-            }
-        }
-
-        return good;
-    }
-
-    public boolean fit(List<SQ> sqs, String method, Callback callback) {
-
-        sqs = onlyValid(sqs);
+    public boolean fit(List<SQ> sqs, String  method, Callback callback) {
 
         if (sqs.size() < 2) {
             log.warn("Too less points for fitting.");
             return false;
         }
 
+        sqs = new ArrayList<SQ>(sqs);
+
         this.callback = callback;
 
         try {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/LogSQ.java	Mon Aug 19 10:55:52 2013 +0200
@@ -0,0 +1,68 @@
+/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.artifacts.model.sq;
+
+public class LogSQ extends SQ {
+
+    public static final View LOG_SQ_VIEW = new View() {
+        @Override
+        public double getS(SQ sq) {
+            return ((LogSQ)sq).getLogS();
+        }
+
+        @Override
+        public double getQ(SQ sq) {
+            return ((LogSQ)sq).getLogQ();
+        }
+    };
+
+    public static final Factory LOG_SQ_FACTORY = new Factory() {
+        @Override
+        public SQ createSQ(double s, double q) {
+            return new LogSQ(s, q);
+        }
+    };
+
+    protected double logS;
+    protected double logQ;
+
+    protected boolean logTrans;
+
+    public LogSQ() {
+    }
+
+    public LogSQ(double s, double q) {
+        super(s, q);
+    }
+
+    /** important: We cannot process negative s/q. */
+    @Override
+    public boolean isValid() {
+        return super.isValid() && s > 0d && q > 0d;
+    }
+
+    protected void ensureLogTrans() {
+        if (!logTrans) {
+            logTrans = true;
+            logS = Math.log(s);
+            logQ = Math.log(q);
+        }
+    }
+
+    public double getLogS() {
+        ensureLogTrans();
+        return logS;
+    }
+
+    public double getLogQ() {
+        ensureLogTrans();
+        return logQ;
+    }
+}
+
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/MeasurementFactory.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/MeasurementFactory.java	Mon Aug 19 10:55:52 2013 +0200
@@ -190,9 +190,10 @@
     }
 
     public static Measurements getMeasurements(
-        String    river,
-        double    location,
-        DateRange dateRange
+        String     river,
+        double     location,
+        DateRange  dateRange,
+        SQ.Factory sqFactory
     ) {
         Session session = SedDBSessionHolder.HOLDER.get();
         try {
@@ -202,7 +203,7 @@
             List<Measurement> accumulated = loadFractions(
                 session, river, location, dateRange);
 
-            return new Measurements(totals, accumulated);
+            return new Measurements(totals, accumulated, sqFactory);
         }
         finally {
             session.close();
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurements.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurements.java	Mon Aug 19 10:55:52 2013 +0200
@@ -66,13 +66,17 @@
     protected List<Measurement> measuments;
     protected List<Measurement> accumulated;
 
+    protected SQ.Factory sqFactory;
+
     public Measurements() {
     }
 
     public Measurements(
         List<Measurement> measuments,
-        List<Measurement> accumulated
+        List<Measurement> accumulated,
+        SQ.Factory        sqFactory
     ) {
+        this.sqFactory = sqFactory;
         if (log.isDebugEnabled()) {
             log.debug("number of measuments: " + measuments.size());
             log.debug("number of accumulated: " + accumulated.size());
@@ -81,14 +85,14 @@
         this.accumulated = accumulated;
     }
 
-    public static List<SQ> extractSQ(
+    public List<SQ> extractSQ(
         List<Measurement> measuments,
         SExtractor extractor
     ) {
         List<SQ> result = new ArrayList<SQ>(measuments.size());
         int invalid = 0;
         for (Measurement measument: measuments) {
-            SQ sq = new SQ(extractor.getS(measument), measument.Q());
+            SQ sq = sqFactory.createSQ(extractor.getS(measument), measument.Q());
             if (sq.isValid()) {
                 result.add(sq);
             }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQ.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQ.java	Mon Aug 19 10:55:52 2013 +0200
@@ -11,8 +11,37 @@
 import java.io.Serializable;
 
 
+/** Represents S/Q pairs. They are immutable! */
 public class SQ implements Serializable {
 
+    public interface Factory {
+        SQ createSQ(double s, double q);
+    }
+
+    public static final Factory SQ_FACTORY = new Factory() {
+        @Override
+        public SQ createSQ(double s, double q) {
+            return new SQ(s, q);
+        }
+    };
+
+    public interface View {
+        double getS(SQ sq);
+        double getQ(SQ sq);
+    }
+
+    public static final View SQ_VIEW = new View() {
+        @Override
+        public double getS(SQ sq) {
+            return sq.getS();
+        }
+
+        @Override
+        public double getQ(SQ sq) {
+            return sq.getQ();
+        }
+    };
+
     protected double s;
     protected double q;
 
@@ -29,19 +58,10 @@
         return s;
     }
 
-    public void setS(double s) {
-        this.s = s;
-    }
-
-
     public double getQ() {
         return q;
     }
 
-    public void setQ(double q) {
-        this.q = q;
-    }
-
     public boolean isValid() {
         return !Double.isNaN(s) && !Double.isNaN(q);
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationCalculation.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationCalculation.java	Mon Aug 19 10:55:52 2013 +0200
@@ -8,6 +8,7 @@
 
 package org.dive4elements.river.artifacts.model.sq;
 
+import org.dive4elements.artifacts.common.utils.StringUtils;
 import org.dive4elements.river.artifacts.access.SQRelationAccess;
 
 import org.dive4elements.river.artifacts.math.fitting.Function;
@@ -21,6 +22,7 @@
 import org.dive4elements.river.backend.SedDBSessionHolder;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import org.apache.log4j.Logger;
@@ -30,7 +32,20 @@
     private static final Logger log =
         Logger.getLogger(SQRelationCalculation.class);
 
-    public static final String SQ_FUNCTION_NAME = "sq-pow";
+    public static final boolean NON_LINEAR_FITTING =
+        Boolean.getBoolean("minfo.sq.calcution.non.linear.fitting");
+
+    public static final String SQ_POW_FUNCTION_NAME = "sq-pow";
+    public static final String SQ_LIN_FUNCTION_NAME = "linear";
+
+    public static final String [] EXTRA_PARAMETERS = {
+        "chi_sqr",
+        "std_dev",
+        "max_q",
+        "c_ferguson",
+        "c_duan",
+        "r2"
+    };
 
     protected String    river;
     protected double    location;
@@ -49,8 +64,6 @@
         Double    outliers = access.getOutliers();
         String    method   = access.getOutlierMethod();
 
-        //river = "Rhein";
-
         if (river == null) {
             // TODO: i18n
             addProblem("sq.missing.river");
@@ -102,31 +115,95 @@
         }
     }
 
+    public interface TransformCoeffs {
+        double [] transform(double [] coeffs);
+    }
+
+    public static final TransformCoeffs IDENTITY_TRANS =
+        new TransformCoeffs() {
+            @Override
+            public double [] transform(double [] coeffs) {
+                return coeffs;
+            }
+        };
+
+    public static final TransformCoeffs LINEAR_TRANS =
+        new TransformCoeffs() {
+            @Override
+            public double [] transform(double [] coeffs) {
+                log.debug("before transform: " + Arrays.toString(coeffs));
+                if (coeffs.length == 2) {
+                    coeffs = new double [] { Math.exp(coeffs[1]), coeffs[0] };
+                }
+                log.debug("after transform: " + Arrays.toString(coeffs));
+                return coeffs;
+            }
+        };
+
     protected CalculationResult internalCalculate() {
 
-        Function function = FunctionFactory
+        Function powFunction = FunctionFactory
             .getInstance()
-            .getFunction(SQ_FUNCTION_NAME);
+            .getFunction(SQ_POW_FUNCTION_NAME);
 
-        if (function == null) {
-            log.error("No '" + SQ_FUNCTION_NAME + "' function found.");
+        if (powFunction == null) {
+            log.error("No '" + SQ_POW_FUNCTION_NAME + "' function found.");
             // TODO: i18n
             addProblem("sq.missing.sq.function");
+            return new CalculationResult(new SQResult[0], this);
+        }
+
+        Function         function;
+        SQ.View          sqView;
+        SQ.Factory       sqFactory;
+        ParameterCreator pc;
+
+        if (NON_LINEAR_FITTING) {
+            log.debug("Use non linear fitting.");
+            sqView    = SQ.SQ_VIEW;
+            sqFactory = SQ.SQ_FACTORY;
+            function  = powFunction;
+            pc = new ParameterCreator(
+                powFunction.getParameterNames(),
+                powFunction.getParameterNames(),
+                powFunction,
+                sqView);
+        }
+        else {
+            log.debug("Use linear fitting.");
+            sqView    = LogSQ.LOG_SQ_VIEW;
+            sqFactory = LogSQ.LOG_SQ_FACTORY;
+            function  = FunctionFactory
+                .getInstance()
+                .getFunction(SQ_LIN_FUNCTION_NAME);
+            if (function == null) {
+                log.error("No '" + SQ_LIN_FUNCTION_NAME + "' function found.");
+                // TODO: i18n
+                addProblem("sq.missing.sq.function");
+                return new CalculationResult(new SQResult[0], this);
+            }
+            pc = new LinearParameterCreator(
+                powFunction.getParameterNames(),
+                function.getParameterNames(),
+                function,
+                sqView);
         }
 
         Measurements measurements =
-            MeasurementFactory.getMeasurements(river, location, period);
+            MeasurementFactory.getMeasurements(
+                river, location, period, sqFactory);
 
         SQFractionResult [] fractionResults =
             new SQFractionResult[SQResult.NUMBER_FRACTIONS];
 
+
         for (int i = 0; i < fractionResults.length; ++i) {
             List<SQ> sqs = measurements.getSQs(i);
 
             SQFractionResult fractionResult;
 
             List<SQFractionResult.Iteration> iterations =
-                doFitting(function, sqs);
+                doFitting(function, sqs, sqView, pc);
 
             if (iterations == null) {
                 // TODO: i18n
@@ -148,13 +225,15 @@
     }
 
     protected List<SQFractionResult.Iteration> doFitting(
-        final Function function,
-        List<SQ> sqs
+        final Function         function,
+        List<SQ>               sqs,
+        SQ.View                sqView,
+        final ParameterCreator pc
     ) {
         final List<SQFractionResult.Iteration> iterations =
             new ArrayList<SQFractionResult.Iteration>();
 
-        boolean success = new Fitting(function, outliers).fit(
+        boolean success = new Fitting(function, outliers, sqView).fit(
             sqs,
             method,
             new Fitting.Callback() {
@@ -166,11 +245,11 @@
                     double    standardDeviation,
                     double    chiSqr
                 ) {
-                    Parameters parameters = createParameters(
-                        function.getParameterNames(),
+                    Parameters parameters = pc.createParameters(
                         coeffs,
                         standardDeviation,
-                        chiSqr);
+                        chiSqr,
+                        measurements);
                     iterations.add(new SQFractionResult.Iteration(
                         parameters,
                         measurements,
@@ -181,22 +260,178 @@
         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);
-        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;
+    public static class ParameterCreator {
+
+        protected String [] origNames;
+        protected String [] proxyNames;
+
+        protected Function  function;
+        protected SQ.View   view;
+
+        public ParameterCreator(
+            String [] origNames,
+            String [] proxyNames,
+            Function  function,
+            SQ.View   view
+        ) {
+            this.origNames  = origNames;
+            this.proxyNames = proxyNames;
+            this.function   = function;
+            this.view       = view;
+        }
+
+        protected double [] transformCoeffs(double [] coeffs) {
+            return coeffs;
+        }
+
+        private static double maxQ(SQ [] sqs) {
+            double max = -Double.MAX_VALUE;
+            for (SQ sq: sqs) {
+                double q = sq.getQ(); // Don't use view here!
+                if (q > max) {
+                    max = q;
+                }
+            }
+            return Math.max(0d, max);
+        }
+
+        private double cFerguson(
+            org.dive4elements.river.artifacts.math.Function instance,
+            SQ [] sqs
+        ) {
+            double sqrSum = 0d;
+
+            for (SQ sq: sqs) {
+                double s = view.getS(sq);
+                double q = view.getQ(sq);
+                double diffS = s - instance.value(q);
+                sqrSum += diffS*diffS;
+            }
+
+            return Math.exp(0.5d * sqrSum/(sqs.length-2));
+        }
+
+        private double cDuan(
+            org.dive4elements.river.artifacts.math.Function instance,
+            SQ [] sqs
+        ) {
+            double sum = 0d;
+
+            for (SQ sq: sqs) {
+                double s = view.getS(sq);
+                double q = view.getQ(sq);
+                double diffS = s - instance.value(q);
+                sum += Math.exp(diffS);
+            }
+            return sum / sqs.length;
+        }
+
+        private double r2(
+            org.dive4elements.river.artifacts.math.Function instance,
+            SQ [] sqs
+        ) {
+            double xm = 0;
+            double ym = 0;
+            for (SQ sq: sqs) {
+                double s  = view.getS(sq);
+                double q  = view.getQ(sq);
+                double fs = instance.value(q);
+                xm += s;
+                ym += fs;
+            }
+            xm /= sqs.length;
+            ym /= sqs.length;
+
+            double mixXY = 0d;
+            double sumX = 0d;
+            double sumY = 0d;
+
+            for (SQ sq: sqs) {
+                double s  = view.getS(sq);
+                double q  = view.getQ(sq);
+                double fs = instance.value(q);
+
+                double xDiff = xm - s;
+                double yDiff = ym - fs;
+
+                mixXY += xDiff*yDiff;
+
+                sumX += xDiff*xDiff;
+                sumY += yDiff*yDiff;
+            }
+
+            double r = mixXY/Math.sqrt(sumX*sumY);
+            return r*r;
+        }
+
+
+        public Parameters createParameters(
+            double [] coeffs,
+            double    standardDeviation,
+            double    chiSqr,
+            SQ []     measurements
+        ) {
+            String [] columns = StringUtils.join(EXTRA_PARAMETERS, origNames);
+
+            Parameters parameters = new Parameters(columns);
+            int row = parameters.newRow();
+            parameters.set(row, origNames, transformCoeffs(coeffs));
+            parameters.set(row, "chi_sqr", chiSqr);
+            parameters.set(row, "std_dev", standardDeviation);
+            parameters.set(row, "max_q", maxQ(measurements));
+
+            // We need to instantiate the function to calculate
+            // the remaining values.
+            org.dive4elements.river.artifacts.math.Function f =
+                function.instantiate(coeffs);
+
+            parameters.set(row, "c_ferguson", cFerguson(f, measurements));
+            parameters.set(row, "c_duan", cDuan(f, measurements));
+            parameters.set(row, "r2", r2(f, measurements));
+
+            return parameters;
+        }
+    }
+
+    /** We need to transform the coeffs back to the original function. */
+    public static class LinearParameterCreator extends ParameterCreator {
+
+        public LinearParameterCreator(
+            String [] origNames,
+            String [] proxyNames,
+            Function  function,
+            SQ.View   view
+        ) {
+            super(origNames, proxyNames, function, view);
+        }
+
+        @Override
+        protected double [] transformCoeffs(double [] coeffs) {
+
+            int bP = StringUtils.indexOf("m", proxyNames);
+            int mP = StringUtils.indexOf("b", proxyNames);
+
+            int aO = StringUtils.indexOf("a", origNames);
+            int bO = StringUtils.indexOf("b", origNames);
+
+            if (bP == -1 || mP == -1 || aO == -1 || bO == -1) {
+                log.error("index not found: "
+                    + bP + " " + mP + " " 
+                    + aO + " " + bO);
+                return coeffs;
+            }
+
+            double [] ncoeffs = (double [])coeffs.clone();
+            ncoeffs[aO] = Math.exp(coeffs[mP]);
+            ncoeffs[bO] = coeffs[bP];
+
+            if (log.isDebugEnabled()) {
+                log.debug("before transform: " + Arrays.toString(coeffs));
+                log.debug("after transform: " + Arrays.toString(ncoeffs));
+            }
+
+            return ncoeffs;
+        }
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationJRDataSource.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationJRDataSource.java	Mon Aug 19 10:55:52 2013 +0200
@@ -86,12 +86,24 @@
             value = data.get(index)[3];
         }
         else if ("total".equals(fieldName)) {
-            value = data.get(index)[4];
+            value = data.get(index)[7];
         }
         else if ("out".equals(fieldName)) {
+            value = data.get(index)[8];
+        }
+        else if ("sd".equals(fieldName)) {
+            value = data.get(index)[4];
+        }
+        else if ("qmax".equals(fieldName)) {
             value = data.get(index)[5];
         }
-        else if ("variance".equals(fieldName)) {
+        else if ("cferg".equals(fieldName)) {
+            value = data.get(index)[10];
+        }
+        else if ("cduan".equals(fieldName)) {
+            value = data.get(index)[9];
+        }
+        else if ("r2".equals(fieldName)) {
             value = data.get(index)[6];
         }
         return value;
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeInfoService.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeInfoService.java	Mon Aug 19 10:55:52 2013 +0200
@@ -40,6 +40,8 @@
 
     public static final String GAUGE_XPATH = "/art:gauge/text()";
 
+    public static final String RIVER_NAME_XPATH = "/art:gauge/art:river/text()";
+
     public DischargeInfoService() {
     }
 
@@ -58,30 +60,39 @@
         String gaugeNumber = XMLUtils.xpathString(
             data, GAUGE_XPATH, ArtifactNamespaceContext.INSTANCE);
 
+        String river = XMLUtils.xpathString(
+            data, RIVER_NAME_XPATH, ArtifactNamespaceContext.INSTANCE);
+
         if (gaugeNumber == null ||
            (gaugeNumber = gaugeNumber.trim()).length() == 0) {
             logger.warn("No gauge specified. Cannot return discharge info.");
             return XMLUtils.newDocument();
         }
 
-        logger.debug("Getting discharge for gauge: " + gaugeNumber);
+        logger.debug("Getting discharge for gauge: " + gaugeNumber + " at river: " + river);
 
         long gn;
         try {
             gn = Long.parseLong(gaugeNumber);
         }
         catch (NumberFormatException nfe) {
-            logger.warn("Invalid gauge number. Cannot return discharg info.");
+            logger.warn("Invalid gauge number. Cannot return discharge info.");
             return XMLUtils.newDocument();
         }
 
-        Gauge gauge = Gauge.getGaugeByOfficialNumber(gn);
+        Gauge gauge;
+        if (river == null || river.isEmpty()) {
+            gauge = Gauge.getGaugeByOfficialNumber(gn);
+        } else {
+            gauge = Gauge.getGaugeByOfficialNumber(gn, river);
+        }
+
         if (gauge == null) {
             logger.warn("No such gauge found.");
             return XMLUtils.newDocument();
         }
 
-        logger.debug("Found gauge: " + gauge.getName());
+        logger.debug("Found gauge: " + gauge.getName() + " id: " + gauge.getId());
 
         return buildDocument(gauge);
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeDischargeState.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeDischargeState.java	Mon Aug 19 10:55:52 2013 +0200
@@ -10,6 +10,8 @@
 
 import java.util.List;
 
+import java.text.DateFormat;
+
 import org.apache.log4j.Logger;
 
 import org.dive4elements.artifacts.CallMeta;
@@ -31,7 +33,10 @@
 import org.dive4elements.river.artifacts.resources.Resources;
 
 import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.DischargeTable;
+import org.dive4elements.river.model.TimeInterval;
 
+import org.dive4elements.river.utils.Formatter;
 
 /**
  * The only state for an GaugeDischargeState (River and km known).
@@ -64,9 +69,18 @@
         }
 
         Gauge gauge = artifact.getGauge();
+        DischargeTable mdt = gauge.fetchMasterDischargeTable();
+        TimeInterval validity = mdt.getTimeInterval();
+        DateFormat df = Formatter.getDateFormatter(meta, "dd.MM.yyyy");
+        String start = validity.getStartTime() != null ?
+                         df.format(validity.getStartTime()) : "Unknown";
+        String stop = validity.getStopTime() != null ?
+                          df.format(validity.getStopTime()) : "";
+
         Object[] args = new Object[] {
             gauge.getName(),
-            gauge.getStation()
+            start,
+            stop
         };
 
         String name = Resources.getMsg(
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeTimerangeState.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeTimerangeState.java	Mon Aug 19 10:55:52 2013 +0200
@@ -67,7 +67,8 @@
             }
         }
 
-        logger.warn("Could not determine time range for gauge: " + gauge);
+        logger.warn("Could not determine time range for gauge: " + gauge.getName()
+                + " id: " + gauge.getId());
 
         return null;
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixAnalysisCompute.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixAnalysisCompute.java	Mon Aug 19 10:55:52 2013 +0200
@@ -9,8 +9,11 @@
 package org.dive4elements.river.artifacts.states.fixation;
 
 import java.text.DateFormat;
+import java.util.Collection;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.log4j.Logger;
 
@@ -41,6 +44,7 @@
 import org.dive4elements.river.artifacts.model.fixings.FixWQCurveFacet;
 import org.dive4elements.river.artifacts.resources.Resources;
 import org.dive4elements.river.artifacts.states.DefaultState;
+import org.dive4elements.river.utils.Formatter;
 import org.dive4elements.river.utils.IdGenerator;
 
 /**
@@ -76,8 +80,6 @@
         "fix.hq5"
     };
 
-    // TODO Why does this happen here? In other cases its implemented in the
-    //      respective artifact, not State.
     static {
         // Active/deactivate facets.
         FacetActivity.Registry.getInstance().register(
@@ -171,15 +173,15 @@
         int qsS = access.getQSectorStart();
         int qsE = access.getQSectorEnd();
 
-        // TODO: i18n
-        DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
+        DateFormat df = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyyy");
+        DateFormat lf = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyy'T'HH:mm");
 
         DateRange [] periods = access.getAnalysisPeriods();
 
         for (int i = 0; i < periods.length; i++) {
             DateRange period = periods[i];
             String startDate = df.format(period.getFrom());
-            String endDate = df.format(period.getTo());
+            String endDate   = df.format(period.getTo());
 
             for (int j = qsS; j <= qsE; j++) {
 
@@ -233,19 +235,22 @@
                                  I18N_ANALYSIS,
                                  I18N_ANALYSIS);
 
+            Collection<Date> aeds = fr.getAnalysisEventsDates(i);
+            UniqueDateFormatter cf = new UniqueDateFormatter(df, lf, aeds);
+
             int k = 0;
-            for (Date d: fr.getAnalysisEventsDates(i)) {
+            for (Date d: aeds) {
                 int anaNdx = i << 8;
                 anaNdx = anaNdx | k;
                 facets.add(new FixAnalysisEventsFacet(anaNdx,
                     FIX_ANALYSIS_EVENTS_DWT,
-                    eventDesc + (i+1) + " - " + df.format(d)));
+                    eventDesc + (i+1) + " - " + cf.format(d)));
                 facets.add(new FixLongitudinalAnalysisFacet(anaNdx,
                     FIX_ANALYSIS_EVENTS_LS,
-                    eventDesc + (i+1) + " - " + df.format(d)));
+                    eventDesc + (i+1) + " - " + cf.format(d)));
                 facets.add(new FixAnalysisEventsFacet(anaNdx,
                     FIX_ANALYSIS_EVENTS_WQ,
-                    eventDesc + (i+1) +" - " + df.format(d)));
+                    eventDesc + (i+1) +" - " + cf.format(d)));
                 k++;
             }
         }
@@ -259,27 +264,29 @@
                 I18N_REFERENCEDEVIATION,
                 I18N_REFERENCEDEVIATION);
 
+        Collection<Date> reds = fr.getReferenceEventsDates();
+        UniqueDateFormatter cf = new UniqueDateFormatter(df, lf, reds);
+
         int i = 0;
-        for (Date d: fr.getReferenceEventsDates()) {
+        for (Date d: reds) {
             int refNdx = idg.next() << 8;
             refNdx |=  i;
             facets.add(new FixReferenceEventsFacet(refNdx,
                 FIX_REFERENCE_EVENTS_DWT,
-                i18n_ref + " - " + df.format(d)));
+                i18n_ref + " - " + cf.format(d)));
             refNdx = idg.next() << 8;
             refNdx = refNdx | i;
             facets.add(new FixLongitudinalReferenceFacet(refNdx,
                 FIX_REFERENCE_EVENTS_LS,
-                i18n_ref + " - " + df.format(d)));
+                i18n_ref + " - " + cf.format(d)));
             refNdx = idg.next() << 8;
             refNdx |= i;
             facets.add(new FixReferenceEventsFacet(refNdx,
                 FIX_REFERENCE_EVENTS_WQ,
-                i18n_ref + " - " + df.format(d)));
+                i18n_ref + " - " + cf.format(d)));
             i++;
         }
 
-
         facets.add(new FixLongitudinalDeviationFacet(idg.next(),
             FIX_DEVIATION_LS,
             i18n_dev));
@@ -333,5 +340,46 @@
                 I18N_DEVIATION)));
         return res;
     }
+
+    /** Little hack to format dates unique if they collide. */
+    private static class UniqueDateFormatter {
+
+        private DateFormat df;
+        private DateFormat lf;
+        private Map<String, int[]> collisions;
+
+        UniqueDateFormatter(
+            DateFormat df,
+            DateFormat lf,
+            Collection<Date> dates
+        ) {
+            this.df = df;
+            this.lf = lf;
+            collisions = build(dates);
+        }
+
+        private Map<String, int []> build(Collection<Date> dates) {
+            Map<String, int []> collisions = new HashMap<String, int[]>();
+            for (Date d: dates) {
+                String s = df.format(d);
+                int [] count = collisions.get(s);
+                if (count == null) {
+                    collisions.put(s, count = new int[1]);
+                }
+                if (++count[0] > 1) {
+                    log.debug("date collsion found: " + d);
+                }
+            }
+            return collisions;
+        }
+
+        String format(Date date) {
+            String s = df.format(date);
+            int [] count = collisions.get(s);
+            return count == null || count[0] < 2
+                ? s
+                : lf.format(date);
+        }
+    } // class UniqueDateFormatter
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferencesState.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferencesState.java	Mon Aug 19 10:55:52 2013 +0200
@@ -127,9 +127,7 @@
                 newFacets.add(new BedDiffYearFacet(
                     idx,
                     BED_DIFFERENCE_MORPH_WIDTH,
-                    createBedDiffMorphDescription(
-                        meta,
-                        (BedDiffYearResult)results[idx]),
+                    createBedDiffMorphDescription(meta),
                     ComputeType.ADVANCE,
                     stateId,
                     hash));
@@ -342,12 +340,9 @@
     }
 
     protected String createBedDiffMorphDescription(
-        CallMeta meta,
-        BedDiffYearResult result) {
-        String range = result.getStart() + " - " + result.getEnd();
-
+        CallMeta meta) {
         return Resources.getMsg(meta, I18N_FACET_BED_DIFF_MORPH,
-            I18N_FACET_BED_DIFF_MORPH, new Object[] { range });
+            I18N_FACET_BED_DIFF_MORPH);
     }
 
     protected String createBedDiffAbsoluteDescription(
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java	Mon Aug 19 10:55:52 2013 +0200
@@ -104,6 +104,7 @@
      * Create Y (range) axis for given index, here with a special axis
      * that depends on other axis (does translation and scaling for
      * special case at gauge in cm).
+     * @return A NumberAxis, possibly scaled.
      */
     @Override
     protected NumberAxis createYAxis(int index) {
@@ -176,7 +177,9 @@
                 mainValues,
                 artifactFacet, attr, visible);
         }
-        else if (name.equals(STATIC_WKMS_INTERPOL) || name.equals(HEIGHTMARKS_POINTS)) {
+        else if (STATIC_WKMS_INTERPOL.equals(name) ||
+            HEIGHTMARKS_POINTS.equals(name) ||
+            STATIC_WQKMS_W.equals(name)) {
             doWAnnotations(
                 artifactFacet.getData(context),
                 artifactFacet,
@@ -212,16 +215,16 @@
 
     /**
      * Add WQ Data to plot.
-     * @param wqkms data as double[][]
+     * @param wq data as double[][]
      */
     protected void doWQOut(
-        Object           wqkms,
+        Object           wq,
         ArtifactAndFacet aaf,
         Document         theme,
         boolean          visible
     ) {
         logger.debug("ComputedDischargeCurveGenerator: doWQOut");
-        double [][] data = (double [][]) wqkms;
+        double [][] data = (double [][]) wq;
 
         XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme);
         StyledSeriesBuilder.addPoints(series, data, true);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeWQCurveGenerator.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeWQCurveGenerator.java	Mon Aug 19 10:55:52 2013 +0200
@@ -124,7 +124,9 @@
                 artifactFacet.getData(context),
                 artifactFacet.getFacetDescription(), theme, visible);
         }
-        else if (name.equals(HISTORICAL_DISCHARGE_WQ_CURVE)) {
+        else if (name.equals(HISTORICAL_DISCHARGE_WQ_CURVE) ||
+                 name.equals(DISCHARGE_CURVE) ||
+                 name.equals(GAUGE_DISCHARGE_CURVE)) {
             doHistoricalDischargeCurveOut(
                 (D4EArtifact) artifactFacet.getArtifact(),
                 artifactFacet.getData(context),
--- a/artifacts/src/main/java/org/dive4elements/river/exports/MapGenerator.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/MapGenerator.java	Mon Aug 19 10:55:52 2013 +0200
@@ -120,9 +120,11 @@
                 setInitialExtent(extent);
                 createWSPLGENLayer(flys, wms, attr);
             }
-            else if (FLOODMAP_USERSHAPE.equals(name)) {
-                createUserShapeLayer(flys, wms);
-            }
+            // FIXME: Already generated by HWSBarrierState
+            // wms has a wrong SRID which would break that layer
+            //else if (FLOODMAP_USERSHAPE.equals(name)) {
+            //    createUserShapeLayer(flys, wms);
+            //}
             else {
                 logger.debug("doOut: createDatabaseLayer for facet name: " + name);
                 createDatabaseLayer(flys, wms, attr);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/StyledSeriesBuilder.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/StyledSeriesBuilder.java	Mon Aug 19 10:55:52 2013 +0200
@@ -49,6 +49,7 @@
      *                 the NaNs lead to gaps in graph.
      * @param distance if two consecutive entries in points[0] are more
      *                 than distance apart, create a NaN value to skip in display.
+     *                 Still, create a line segment.
      */
     public static void addPoints(XYSeries series, double[][] points, boolean skipNANs, double distance) {
         if (points == null || points.length <= 1) {
@@ -64,6 +65,11 @@
             }
             // Create gap if distance >= distance.
             if (i != 0 && Math.abs(xPoints[i-1] - xPoints[i]) >= distance) {
+                // Create at least a small segment for last point.
+                if (!Double.isNaN(yPoints[i-1])) {
+                    series.add(xPoints[i-1]+0.99d*(distance)/2.d, yPoints[i-1], false);
+                }
+
                 if (!Double.isNaN(yPoints[i-1]) && !Double.isNaN(yPoints[i])) {
                     series.add((xPoints[i-1]+xPoints[i])/2.d, Double.NaN, false);
                 }
--- a/artifacts/src/main/java/org/dive4elements/river/exports/SyncNumberAxis.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/SyncNumberAxis.java	Mon Aug 19 10:55:52 2013 +0200
@@ -18,6 +18,7 @@
 /**
  * Axis which is to be registered with other axis and tries
  * to clone its range. The cloned range is transformed.
+ * Keeps in sync via AxisChangedEvents.
  */
 public class SyncNumberAxis extends IdentifiableNumberAxis
         implements AxisChangeListener
--- a/artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java	Mon Aug 19 10:55:52 2013 +0200
@@ -54,10 +54,11 @@
 import org.w3c.dom.Document;
 
 /**
+ * Generator for diagrams with time on x axis.
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
-public abstract class TimeseriesChartGenerator extends ChartGenerator {
-
+public abstract class TimeseriesChartGenerator
+extends               ChartGenerator {
 
     /**
      * Inner class TimeseriesAxisDataset stores TimeSeriesCollection.
--- a/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtGenerator.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtGenerator.java	Mon Aug 19 10:55:52 2013 +0200
@@ -35,7 +35,6 @@
 
 import org.apache.log4j.Logger;
 import org.jfree.chart.annotations.XYTextAnnotation;
-import org.jfree.data.time.Day;
 import org.jfree.data.time.RegularTimePeriod;
 import org.jfree.data.time.FixedMillisecond;
 import org.jfree.data.time.TimeSeries;
@@ -270,9 +269,9 @@
 
         // Draw a line spanning the analysis time.
         series.add(rtp, value);
-        rtp = new Day(qwd.dateRange.getFrom());
+        rtp = new FixedMillisecond(qwd.dateRange.getFrom());
         series.addOrUpdate(rtp, value);
-        rtp = new Day(qwd.dateRange.getTo());
+        rtp = new FixedMillisecond(qwd.dateRange.getTo());
         series.addOrUpdate(rtp, value);
 
         tsc.addSeries(series);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceEpochGenerator.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceEpochGenerator.java	Mon Aug 19 10:55:52 2013 +0200
@@ -262,3 +262,4 @@
         }
     }
 }
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityGenerator.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityGenerator.java	Mon Aug 19 10:55:52 2013 +0200
@@ -140,6 +140,7 @@
      * @param attr
      *            theme for facet
      */
+    @Override
     public void doOut(ArtifactAndFacet artifactAndFacet, Document attr,
         boolean visible) {
         String name = artifactAndFacet.getFacetName();
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffHeightYearProcessor.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffHeightYearProcessor.java	Mon Aug 19 10:55:52 2013 +0200
@@ -26,6 +26,8 @@
     private final static Logger logger =
             Logger.getLogger(BedDiffHeightYearProcessor.class);
 
+    protected static double GAP_TOLERANCE = 0.101d;
+
     @Override
     public void doOut(
             XYChartGenerator generator,
@@ -62,7 +64,7 @@
         int axidx) {
 
         XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme);
-        StyledSeriesBuilder.addPoints(series, data.getHeightPerYearData(), false, 0.101d);
+        StyledSeriesBuilder.addPoints(series, data.getHeightPerYearData(), false, GAP_TOLERANCE);
 
         generator.addAxisSeries(series, axidx, visible);
     }
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffYearProcessor.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffYearProcessor.java	Mon Aug 19 10:55:52 2013 +0200
@@ -26,6 +26,8 @@
     private final static Logger logger =
             Logger.getLogger(BedDiffYearProcessor.class);
 
+    protected static double GAP_TOLERANCE = 0.101d;
+
     @Override
     public void doOut(
             XYChartGenerator generator,
@@ -71,10 +73,10 @@
 
         XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), attr);
         if (idx == 0) {
-            StyledSeriesBuilder.addPoints(series, data.getHeights1Data(), false, 0.101d);
+            StyledSeriesBuilder.addPoints(series, data.getHeights1Data(), false, GAP_TOLERANCE);
         }
         else {
-            StyledSeriesBuilder.addPoints(series, data.getHeights2Data(), false, 0.101d);
+            StyledSeriesBuilder.addPoints(series, data.getHeights2Data(), false, GAP_TOLERANCE);
         }
 
         generator.addAxisSeries(series, axidx, visible);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationExporter.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationExporter.java	Mon Aug 19 10:55:52 2013 +0200
@@ -16,6 +16,7 @@
 import java.util.Date;
 import java.util.Locale;
 import java.text.DateFormat;
+import java.text.NumberFormat;
 
 import org.w3c.dom.Document;
 
@@ -99,8 +100,11 @@
     public static final String CSV_C_FERGUSON =
         "export.sqrelation.csv.header.c.ferguson";
 
-    public static final String CSV_VARIANCE =
-        "export.sqrelation.csv.header.variance";
+    public static final String CSV_QMAX =
+        "export.sqrelation.csv.header.qmax";
+
+    public static final String CSV_SD =
+        "export.sqrelation.csv.header.sd";
 
     public static final String PDF_TITLE=
         "export.sqrelation.pdf.title";
@@ -136,9 +140,13 @@
             msg(CSV_PARAMETER,  CSV_PARAMETER),
             msg(CSV_COEFF_A   , CSV_COEFF_A),
             msg(CSV_COEFF_B   , CSV_COEFF_B),
+            msg(CSV_SD, CSV_SD),
+            msg(CSV_QMAX, CSV_QMAX),
+            msg(CSV_COEFF_R, CSV_COEFF_R),
             msg(CSV_N_TOTAL   , CSV_N_TOTAL),
             msg(CSV_N_OUTLIERS, CSV_N_OUTLIERS),
-            msg(CSV_VARIANCE  , CSV_VARIANCE)
+            msg(CSV_C_DUAN, CSV_C_DUAN),
+            msg(CSV_C_FERGUSON, CSV_C_FERGUSON)
         });
     }
 
@@ -160,6 +168,12 @@
                     ).format(result.getKm());
         List<String[]> retval = new ArrayList<String[]>();
 
+        NumberFormat sqAFormatter = Formatter.getSQRelationA(context);
+        NumberFormat sqBFormatter = Formatter.getSQRelationB(context);
+        NumberFormat fThreeFormatter = Formatter.getFormatter(context, 3, 3);
+        NumberFormat fTwoFormatter = Formatter.getFormatter(context, 2, 2);
+        NumberFormat fZeroFormatter = Formatter.getFormatter(context, 0, 0);
+
         for (int i = 0; i < SQResult.NUMBER_FRACTIONS; ++i) {
             SQFractionResult fraction = result.getFraction(i);
 
@@ -171,10 +185,17 @@
                 continue;
             }
 
-            String a, b, sd, o, t;
-            a  = Formatter.getSQRelationA(context).format(parameters.getValue(0, "a"));
-            b  = Formatter.getSQRelationB(context).format(parameters.getValue(0, "b"));
-            sd = Formatter.getVariance(context).format(Math.sqrt(parameters.getValue(0, "std_dev")));
+            String a, b, sd, o, t, max_q, c_ferguson, c_duan, r2;
+            a  = sqAFormatter.format(parameters.getValue(0, "a"));
+            b  = sqBFormatter.format(parameters.getValue(0, "b"));
+
+            /* The std_dev parameter contains the standard error actually */
+            sd = fThreeFormatter.format(parameters.getValue(0, "std_dev"));
+            max_q = fZeroFormatter.format(parameters.getValue(0, "max_q"));
+            c_ferguson = fTwoFormatter.format(parameters.getValue(0, "c_ferguson"));
+            c_duan = fTwoFormatter.format(parameters.getValue(0, "c_duan"));
+            r2 = fTwoFormatter.format(parameters.getValue(0, "r2"));
+
 
             o  = String.valueOf(fraction.totalNumOutliers());
             t  = String.valueOf(fraction.numMeasurements() + o);
@@ -184,9 +205,13 @@
                 name,
                 a,
                 b,
-                t,
-                o,
-                sd
+                sd, // 4
+                max_q, // 5
+                r2, // 6
+                t, // 7
+                o, // 8
+                c_duan, // 9
+                c_ferguson // 10
             });
         }
         return retval;
@@ -229,7 +254,8 @@
         source.addMetaData("outliertest", Resources.getMsg(meta,
                     access.getOutlierMethod(),
                     access.getOutlierMethod()));
-        source.addMetaData("outliers", access.getOutliers().toString());
+        source.addMetaData("outliers", Formatter.getRawFormatter(context).format(
+                    access.getOutliers()));
 
         source.addMetaData("calculation", Resources.getMsg(
                                             locale,
--- a/artifacts/src/main/java/org/dive4elements/river/utils/ArtifactMapfileGenerator.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/utils/ArtifactMapfileGenerator.java	Mon Aug 19 10:55:52 2013 +0200
@@ -16,6 +16,7 @@
 import org.dive4elements.river.artifacts.model.map.WMSLayerFacet;
 import org.dive4elements.river.artifacts.model.map.WSPLGENLayerFacet;
 import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.states.FloodMapState;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -135,11 +136,11 @@
         ShapefileReader sfr = new ShapefileReader(sf, true, false, null);
         ShapefileHeader sfh = sfr.getHeader();
 
-        String group      = uuid + MS_USERSHAPE_PREFIX;
+        String group      = MS_USERSHAPE_PREFIX + uuid;
         String groupTitle = "I18N_USER_SHAPE_TITLE";
 
         LayerInfo info = new LayerInfo();
-        info.setName(MS_USERSHAPE_PREFIX + uuid);
+        info.setName(MS_LAYER_PREFIX + FloodMapState.WSPLGEN_USER_RGD + uuid);
         if (sfh.getShapeType().isLineType()) {
             info.setType("LINE");
         }
@@ -156,7 +157,11 @@
         info.setGroupTitle(groupTitle);
         info.setSrid(wms.getSrid());
 
-        String nameUser = MS_LAYER_PREFIX + wms.getName();
+        //String nameUser = MS_LAYER_PREFIX + wms.getName();
+        // TODO: This rewrites the user-rgd mapfile fragment generated by
+        // HWSBarrierState. Otherwise we would have to fragments with same
+        // layer name. Should be refactored...
+        String nameUser = MS_LAYER_PREFIX + "user-rgd";
 
         Template tpl = getTemplateByName(SHP_LAYER_TEMPLATE);
         if (tpl == null) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/utils/BatchLoader.java	Mon Aug 19 10:55:52 2013 +0200
@@ -0,0 +1,116 @@
+/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.utils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.hibernate.SQLQuery;
+import org.hibernate.Session;
+
+/** To reduce the number of SQL queries send to the backend
+ *  (mainly by the fixings overviews) we execute them in batches of ids
+ *  and store the results in a small cache.
+ *  TODO: It currently relies on dynamic SQL.
+ *  Is there a way to use Hibernate with java.sql.Array
+ *  in cross database compatible manner?
+ */
+public abstract class BatchLoader<T> {
+
+    private static Logger log = Logger.getLogger(BatchLoader.class);
+
+    public static final int BATCH_SIZE = 100;
+
+    private Map<Integer, T> loaded;
+    private List<Integer>   rest;
+    private Session         session;
+    private String          sqlTemplate;
+
+    public BatchLoader(
+        List<Integer> columns,
+        Session       session,
+        String        sqlTemplate
+    ) {
+        rest             = new ArrayList<Integer>(columns.size());
+        loaded           = new HashMap<Integer, T>();
+        this.session     = session;
+        this.sqlTemplate = sqlTemplate;
+
+        // Insert in reverse order to minize searching.
+        for (int i = columns.size()-1; i >= 0; --i) {
+            rest.add(columns.get(i));
+        }
+    }
+
+    /** Searches for id and fill a batch to load containing the found id. */
+    private List<Integer> prepareBatch(int id) {
+        List<Integer> batch = new ArrayList<Integer>(BATCH_SIZE);
+
+        boolean found = false;
+
+        for (int i = rest.size()-1; batch.size() < BATCH_SIZE && i >= 0; --i) {
+            Integer cid = rest.get(i);
+            if (cid == id) {
+                found = true;
+                batch.add(cid);
+                rest.remove(i);
+            }
+            else if ((found && batch.size() < BATCH_SIZE)
+                 || (!found && batch.size() < BATCH_SIZE-1)) {
+                batch.add(cid);
+                rest.remove(i);
+            }
+        }
+
+        return batch;
+    }
+
+    /** Converts id to a list of comma separated ints. */
+    private static String idsAsString(List<Integer> ids) {
+        StringBuilder sb = new StringBuilder();
+        for (Iterator<Integer> i = ids.iterator(); i.hasNext();) {
+            sb.append(i.next());
+            if (i.hasNext()) {
+                sb.append(',');
+            }
+        }
+        return sb.toString();
+    }
+
+    /** Get data for id. */
+    public T get(int id) {
+        T already = loaded.get(id);
+        if (already != null) {
+            return already;
+        }
+
+        List<Integer> batch = prepareBatch(id);
+        if (batch.isEmpty()) {
+            return null;
+        }
+        String sql = sqlTemplate.replace("$IDS", idsAsString(batch));
+        if (log.isDebugEnabled()) {
+            log.debug(sql + " " + sql.length());
+        }
+        fill(session.createSQLQuery(sql));
+        return get(id);
+    }
+
+    /** Call this from fill() to store data in the cache. */
+    protected void cache(int key, T data) {
+        loaded.put(key, data);
+    }
+
+    /** Override this to fill the cache */
+    protected abstract void fill(SQLQuery query);
+}
--- a/artifacts/src/main/java/org/dive4elements/river/utils/RiverUtils.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/utils/RiverUtils.java	Mon Aug 19 10:55:52 2013 +0200
@@ -491,10 +491,14 @@
 
     public static Gauge getReferenceGauge(D4EArtifact flys) {
         Long officialNumber = flys.getDataAsLong("reference_gauge");
+        String river = getRivername(flys);
 
-        return officialNumber != null
-            ? Gauge.getGaugeByOfficialNumber(officialNumber)
-            : null;
+        if (officialNumber != null && river != null) {
+            return Gauge.getGaugeByOfficialNumber(officialNumber, river);
+        } else if (officialNumber != null) {
+            return Gauge.getGaugeByOfficialNumber(officialNumber);
+        }
+        return null;
     }
 
 
--- a/artifacts/src/main/resources/datacage-sql/org-h2-driver.properties	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/resources/datacage-sql/org-h2-driver.properties	Mon Aug 19 10:55:52 2013 +0200
@@ -17,7 +17,7 @@
 insert.out = INSERT INTO outs (id, artifact_id, name, description, out_type) VALUES (?, ?, ?, ?, ?)
 facet.id.nextval = SELECT NEXTVAL('FACETS_ID_SEQ')
 insert.facet = INSERT INTO facets (id, out_id, name, num, state, description) VALUES (?, ?, ?, ?, ?, ?)
-update.artifact.state = UPDATE artifacts SET state = ? WHERE gid = ?
+update.artifact.state = UPDATE artifacts SET state = ? WHERE id = ?
 
 update.collection.name = UPDATE collections SET name = ? WHERE gid = ?
 delete.artifact.from.collection = DELETE FROM collection_items WHERE collection_id = ? AND artifact_id = ?
--- a/artifacts/src/main/resources/messages.properties	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/resources/messages.properties	Mon Aug 19 10:55:52 2013 +0200
@@ -171,7 +171,7 @@
 chart.computed.discharge.curve.subtitle = {0}-km: {1,number,#.###}
 chart.computed.discharge.curve.yaxis.label = W [{0}]
 chart.computed.discharge.curve.curve.label = Discharge Curve {0} km {1}
-chart.computed.discharge.curve.gauge = Discharge curve at gauge {0} (km {1})
+chart.computed.discharge.curve.gauge = current DC {0} {1} - {2}
 chart.duration.curve.title = Duration Curve
 chart.duration.curve.subtitle = {0}-km: {1,number,#.###}
 chart.duration.curve.xaxis.label = Duration of Non-Exceedence [Days]
@@ -287,7 +287,7 @@
 bedquality.toplayer = 0.0m - 0.3m
 bedquality.sublayer = 0.1m - 0.5m
 facet.bedheight.diff.year = Bedheight Difference {0}
-facet.bedheight.diff.morph = sounding Width {0}
+facet.bedheight.diff.morph = sounding Width
 facet.bedheight.diff.height1 = Original Height Minuend {0}
 facet.bedheight.diff.height2 = Original Height Subtrahend {0}
 facet.bedheight.diff.absolute = Bedheight Difference/Year {0}
@@ -404,9 +404,10 @@
 export.sqrelation.csv.header.coeff.r = r^2
 export.sqrelation.csv.header.n.total = n total
 export.sqrelation.csv.header.n.outliers = n outliers
-export.sqrelation.csv.header.c.duan = C (DUAN)
-export.sqrelation.csv.header.c.ferguson = C (FERGUSON)
-export.sqrelation.csv.header.variance = Standard variance
+export.sqrelation.csv.header.c.duan = C (Duan)
+export.sqrelation.csv.header.c.ferguson = C (Ferguson)
+export.sqrelation.csv.header.sd = Standard error
+export.sqrelation.csv.header.qmax = Q max,measured
 export.sqrelation.pdf.file = /jasper/sqrelation_en.jasper
 export.sqrelation.pdf.mode = Load Discharge Relation
 export.minfo.bedquality.km = km
--- a/artifacts/src/main/resources/messages_de.properties	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/resources/messages_de.properties	Mon Aug 19 10:55:52 2013 +0200
@@ -171,7 +171,7 @@
 chart.computed.discharge.curve.subtitle = {0}-km: {1,number,#.###}
 chart.computed.discharge.curve.yaxis.label = W [{0}]
 chart.computed.discharge.curve.curve.label = Abflusskurve {0} km {1}
-chart.computed.discharge.curve.gauge = Abflusskurve an Pegel {0} (km {1})
+chart.computed.discharge.curve.gauge = aktuelle AT {0} {1} - {2}
 chart.duration.curve.title = Dauerlinie
 chart.duration.curve.subtitle = {0}-km: {1,number,#.###}
 chart.duration.curve.xaxis.label = Unterschreitungsdauer [Tage]
@@ -287,7 +287,7 @@
 bedquality.toplayer = 0,0m - 0,3m
 bedquality.sublayer = 0,1m - 0,5m
 facet.bedheight.diff.year = Sohlh\u00f6hendifferenz {0}
-facet.bedheight.diff.morph = gepeilte Breite {0}
+facet.bedheight.diff.morph = gepeilte Breite
 facet.bedheight.diff.height1 = H\u00f6he Minuend {0}
 facet.bedheight.diff.height2 = H\u00f6he Subtrahend {0}
 facet.bedheight.diff.absolute = Sohlh\u00f6hendifferenz/Jahr {0}
@@ -402,11 +402,12 @@
 export.sqrelation.csv.header.coeff.b = b
 export.sqrelation.csv.header.coeff.q = Q
 export.sqrelation.csv.header.coeff.r = r^2
-export.sqrelation.csv.header.n.total = n gesamt
+export.sqrelation.csv.header.n.total = n Gesamt
 export.sqrelation.csv.header.n.outliers = n Ausrei\u00dfer
-export.sqrelation.csv.header.c.duan = C (DUAN)
-export.sqrelation.csv.header.c.ferguson = C (FERGUSON)
-export.sqrelation.csv.header.variance = Standardabweichung
+export.sqrelation.csv.header.c.duan = C (Duan)
+export.sqrelation.csv.header.c.ferguson = C (Ferguson)
+export.sqrelation.csv.header.sd = Standardfehler
+export.sqrelation.csv.header.qmax = Q max,gemessen
 export.sqrelation.pdf.file = /jasper/sqrelation.jasper
 export.sqrelation.pdf.mode = Transport-Abfluss Beziehung
 export.minfo.bedquality.km = km
--- a/artifacts/src/main/resources/messages_de_DE.properties	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/resources/messages_de_DE.properties	Mon Aug 19 10:55:52 2013 +0200
@@ -170,7 +170,7 @@
 chart.computed.discharge.curve.subtitle = {0}-km: {1,number,#.###}
 chart.computed.discharge.curve.yaxis.label = W [{0}]
 chart.computed.discharge.curve.curve.label = Abflusskurve {0} km {1}
-chart.computed.discharge.curve.gauge = Abflusskurve an Pegel {0} (km {1})
+chart.computed.discharge.curve.gauge = aktuelle AT {0} {1} - {2}
 chart.duration.curve.title = Dauerlinie
 chart.duration.curve.subtitle = {0}-km: {1,number,#.###}
 chart.duration.curve.xaxis.label = Unterschreitungsdauer [Tage]
@@ -286,7 +286,7 @@
 bedquality.sublayer = 0,1m - 0,5m
 facet.bedheight.diff.year = Sohlh\u00f6hendifferenz {0}
 facet.bedheight.diff.year.raw = Sohlh\u00f6hendifferenz {0} (Rohdaten)
-facet.bedheight.diff.morph = gepeilte Breite {0}
+facet.bedheight.diff.morph = gepeilte Breite
 facet.bedheight.diff.height1 = H\u00f6he Minuend {0}
 facet.bedheight.diff.height2 = H\u00f6he Subtrahend {0}
 facet.bedheight.diff.absolute = Sohlh\u00f6hendifferenz/Jahr {0}
@@ -399,11 +399,12 @@
 export.sqrelation.csv.header.coeff.b = b
 export.sqrelation.csv.header.coeff.q = Q
 export.sqrelation.csv.header.coeff.r = r^2
-export.sqrelation.csv.header.n.total = n gesamt
+export.sqrelation.csv.header.n.total = n Gesamt
 export.sqrelation.csv.header.n.outliers = n Ausrei\u00dfer
-export.sqrelation.csv.header.c.duan = C (DUAN)
-export.sqrelation.csv.header.c.ferguson = C (FERGUSON)
-export.sqrelation.csv.header.variance = Standardabweichung
+export.sqrelation.csv.header.c.duan = C (Duan)
+export.sqrelation.csv.header.c.ferguson = C (Ferguson)
+export.sqrelation.csv.header.sd = Standardfehler
+export.sqrelation.csv.header.qmax = Q max,gemessen
 export.sqrelation.pdf.file = /jasper/sqrelation.jasper
 export.sqrelation.pdf.mode = Transport-Abfluss Beziehung
 export.minfo.bedquality.km = km
--- a/artifacts/src/main/resources/messages_en.properties	Mon Aug 19 10:55:13 2013 +0200
+++ b/artifacts/src/main/resources/messages_en.properties	Mon Aug 19 10:55:52 2013 +0200
@@ -171,6 +171,7 @@
 chart.computed.discharge.curve.subtitle = {0}-km: {1,number,#.###}
 chart.computed.discharge.curve.yaxis.label = W [{0}]
 chart.computed.discharge.curve.curve.label = Discharge Curve {0} km {1}
+chart.computed.discharge.curve.gauge = current DC {0} {1} - {2}
 chart.duration.curve.title = Duration Curve
 chart.duration.curve.subtitle = {0}-km: {1,number,#.###}
 chart.duration.curve.xaxis.label = Duration of Non-Exceedence [Days]
@@ -290,7 +291,7 @@
 bedquality.toplayer = 0.0m - 0.3m
 bedquality.sublayer = 0.1m - 0.5m
 facet.bedheight.diff.year = Bedheight Difference {0}
-facet.bedheight.diff.morph = sounding Width {0}
+facet.bedheight.diff.morph = sounding Width
 facet.bedheight.diff.height1 = Original Height Minuend {0}
 facet.bedheight.diff.height2 = Original Height Subtrahend {0}
 facet.bedheight.diff.absolute = Bedheight Difference/Year {0}
@@ -406,9 +407,10 @@
 export.sqrelation.csv.header.coeff.r = r^2
 export.sqrelation.csv.header.n.total = n total
 export.sqrelation.csv.header.n.outliers = n outliers
-export.sqrelation.csv.header.c.duan = C (DUAN)
-export.sqrelation.csv.header.c.ferguson = C (FERGUSON)
-export.sqrelation.csv.header.variance = Standard variance
+export.sqrelation.csv.header.c.duan = C (Duan)
+export.sqrelation.csv.header.c.ferguson = C (Ferguson)
+export.sqrelation.csv.header.sd = Standard error
+export.sqrelation.csv.header.qmax = Q max,measured
 export.sqrelation.pdf.file = /jasper/sqrelation_en.jasper
 export.sqrelation.pdf.mode = Load Discharge Relation
 export.minfo.bedquality.km = km
--- a/backend/src/main/java/org/dive4elements/river/model/CrossSection.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/backend/src/main/java/org/dive4elements/river/model/CrossSection.java	Mon Aug 19 10:55:52 2013 +0200
@@ -241,11 +241,19 @@
 
         List<Integer> results = sqlQuery.list();
 
-        for (Integer result: results) {
+        if (results.size() >= 1) {
+            Integer result = results.get(0);
             if (result == getId()) {
                 return true;
             }
         }
+        else {
+            logger.warn("No CS found that could be master.");
+        }
+
+        // TODO If there is none, might need a fallback.
+        // Formerly this was the most current CS (issue1157).
+
         return false;
     }
 }
--- a/backend/src/main/java/org/dive4elements/river/model/Gauge.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/backend/src/main/java/org/dive4elements/river/model/Gauge.java	Mon Aug 19 10:55:52 2013 +0200
@@ -223,7 +223,6 @@
         this.mainValues = mainValues;
     }
 
-
     public static Gauge getGaugeByOfficialNumber(long number) {
         Session session = SessionHolder.HOLDER.get();
 
@@ -237,6 +236,21 @@
         return results.isEmpty() ? null : results.get(0);
     }
 
+    public static Gauge getGaugeByOfficialNumber(long number, String river_name) {
+        Session session = SessionHolder.HOLDER.get();
+
+        Query query = session.createQuery(
+            "from Gauge as gau " +
+            "where gau.officialNumber=:number and gau.river.name=:river_name");
+
+        query.setParameter("number", number);
+        query.setParameter("river_name", river_name);
+
+        List<Gauge> results = query.list();
+
+        return results.isEmpty() ? null : results.get(0);
+    }
+
 
     public DischargeTable fetchMasterDischargeTable() {
         for (DischargeTable dt: dischargeTables) {
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Mon Aug 19 10:55:13 2013 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Mon Aug 19 10:55:52 2013 +0200
@@ -369,7 +369,7 @@
 error_gc_doc_not_valid = Capabilities document is not valid.
 error_malformed_url = The URL you have entered is not valid.
 error_no_dgm_selected = No DEM selected.
-error_invalid_dgm_selected = You have selected an invalid DEM.
+error_invalid_dgm_selected = An error occured while selecting the DEM.
 error_bad_dgm_range = You have selected a DEM with an invalid range.
 error_bad_dgm_river = You have selected a DEM for a wrong river.
 error_dialog_not_valid = One or more values are not valid.
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Mon Aug 19 10:55:13 2013 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Mon Aug 19 10:55:52 2013 +0200
@@ -369,7 +369,7 @@
 error_gc_doc_not_valid = Das Capabilities Dokument ist nicht valide.
 error_malformed_url = Die eingegebene URL ist ung\u00fcltig.
 error_no_dgm_selected = Sie haben kein DGM gew\u00e4hlt.
-error_invalid_dgm_selected = Sie haben ein falsches DGM gew\u00e4hlt.
+error_invalid_dgm_selected = Bei der Auswahl des DGMs ist ein Fehler aufgetreten.
 error_bad_dgm_range = Das gew\u00e4hlte DGM passt nicht zur gew\u00e4hlten Berechnungsstrecke.
 error_bad_dgm_river = Das gew\u00e4hlte DGM passt nicht zum gew\u00e4hlten Fluss.
 error_dialog_not_valid = Eine oder mehrere Daten sind nicht korrekt.
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties	Mon Aug 19 10:55:13 2013 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties	Mon Aug 19 10:55:52 2013 +0200
@@ -367,7 +367,7 @@
 error_gc_doc_not_valid = Capabilities document is not valid.
 error_malformed_url = The URL you have entered is not valid.
 error_no_dgm_selected = No DEM selected.
-error_invalid_dgm_selected = You have selected an invalid DEM.
+error_invalid_dgm_selected = An error occured while selecting the DEM.
 error_bad_dgm_range = You have selected a DEM with an invalid range.
 error_bad_dgm_river = You have selected a DEM for a wrong river.
 error_dialog_not_valid = One or more values are not valid.
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoService.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoService.java	Mon Aug 19 10:55:52 2013 +0200
@@ -28,7 +28,8 @@
      */
     DischargeInfoObject[] getDischargeInfo(
         String locale,
-        long gauge)
+        long gauge,
+        String river)
     throws ServerException;
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoServiceAsync.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoServiceAsync.java	Mon Aug 19 10:55:52 2013 +0200
@@ -21,6 +21,7 @@
     void getDischargeInfo(
         String locale,
         long gauge,
+        String river,
         AsyncCallback<DischargeInfoObject[]> cb);
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/GaugeTimeRangePanel.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/GaugeTimeRangePanel.java	Mon Aug 19 10:55:52 2013 +0200
@@ -105,7 +105,8 @@
 
         Config config = Config.getInstance();
         String url = config.getServerUrl();
-        yearTable.setDataSource(new DischargeInfoDataSource(url, gauge));
+        String river = artifact.getArtifactDescription().getRiver();
+        yearTable.setDataSource(new DischargeInfoDataSource(url, gauge, river));
 
         helperContainer.addMember(createHelperPanel());
 
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/range/DischargeInfoDataSource.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/range/DischargeInfoDataSource.java	Mon Aug 19 10:55:52 2013 +0200
@@ -20,7 +20,7 @@
     public static final String XPATH_DISCHARGE_DEFAULT = "/discharges/discharge";
 
 
-    public DischargeInfoDataSource(String url, long gauge) {
+    public DischargeInfoDataSource(String url, long gauge, String river) {
         setDataFormat(DSDataFormat.XML);
         setRecordXPath(XPATH_DISCHARGE_DEFAULT);
 
@@ -37,15 +37,16 @@
             "end", FieldType.TEXT, "end");
 
         setFields(desc, bfgid, start, end);
-        setDataURL(getServiceURL(url, gauge));
+        setDataURL(getServiceURL(url, gauge, river));
     }
 
 
-    protected String getServiceURL(String server, long gauge) {
+    protected String getServiceURL(String server, long gauge, String river) {
         String url = GWT.getModuleBaseURL();
         url += "dischargeinfoxml";
         url += "?server=" + server;
         url += "&gauge=" + String.valueOf(gauge);
+        url += "&river=" + river;
 
         return url;
     }
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoServiceImpl.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoServiceImpl.java	Mon Aug 19 10:55:52 2013 +0200
@@ -48,9 +48,11 @@
     public static final String XPATH_DISTANCES = "art:discharges/art:discharge";
 
 
+    @Override
     public DischargeInfoObject[] getDischargeInfo(
         String locale,
-        long gauge)
+        long gauge,
+        String river)
     throws ServerException
     {
         logger.info("DichargeInfoServiceImpl.getDischargeInfo");
@@ -67,6 +69,10 @@
         Element gaugeEl = ec.create("gauge");
         gaugeEl.setTextContent(String.valueOf(gauge));
 
+        Element riverEl = ec.create("river");
+        riverEl.setTextContent(river);
+
+        gaugeEl.appendChild(riverEl);
         doc.appendChild(gaugeEl);
 
         HttpClient client = new HttpClientImpl(url, locale);
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoXML.java	Mon Aug 19 10:55:13 2013 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoXML.java	Mon Aug 19 10:55:52 2013 +0200
@@ -50,6 +50,8 @@
 
         String gauge = req.getParameter("gauge");
 
+        String river = req.getParameter("river");
+
         Document doc = XMLUtils.newDocument();
 
         XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(
@@ -60,6 +62,12 @@
         Element gaugeEl = ec.create("gauge");
         gaugeEl.setTextContent(gauge);
 
+        if (river != null && !river.isEmpty()) {
+            Element riverEl = ec.create("river");
+            riverEl.setTextContent(river);
+            gaugeEl.appendChild(riverEl);
+        }
+
         doc.appendChild(gaugeEl);
 
         HttpClient client = new HttpClientImpl(url);

http://dive4elements.wald.intevation.org