changeset 8014:b57ecf80e40c facet-metadata

merged default into branch facet-metadata.
author Tom Gottfried <tom@intevation.de>
date Tue, 08 Jul 2014 18:19:04 +0200
parents 107d38f6e489 (diff) 4ca747495cbf (current diff)
children b0d4b1a3c345 d410f2a27422
files artifacts/doc/conf/meta-data.xml
diffstat 75 files changed, 2438 insertions(+), 1069 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/doc/conf/meta-data.xml	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/doc/conf/meta-data.xml	Tue Jul 08 18:19:04 2014 +0200
@@ -1030,6 +1030,30 @@
       </dc:filter>
     </dc:macro>
 
+    <dc:macro name="middle_bedheights">
+      <dc:filter expr="($out_name = 'bedheight_middle') and
+          (starts-with($facet_name, 'bedheight_middle.single'))">
+        <dc:if test="dc:has-result()">
+          <middle_bedheights>
+            <dc:call-macro name="collection-group">
+              <middle_bedheight description="{dc:group-key()}">
+                <dc:for-each>
+                  <dc:element name="${facet_name}">
+                    <dc:attribute name="factory" value="minfo"/>
+                    <dc:attribute name="target_out" value="${out}"/>
+                    <dc:attribute name="description" value="${facet_description}"/>
+                    <dc:attribute name="ids" value="${facet_num}"/>
+                    <dc:attribute name="artifact-id" value="${a_gid}"/>
+                    <dc:attribute name="out" value="${out_name}"/>
+                  </dc:element>
+                </dc:for-each>
+              </middle_bedheight>
+            </dc:call-macro>
+          </middle_bedheights>
+        </dc:if>
+      </dc:filter>
+    </dc:macro>
+
     <dc:macro name="bedheight_differences">
       <dc:filter expr="($out_name = 'bed_difference_year' or $out_name = 'bed_difference_height_year') and
           (starts-with($facet_name, 'bedheight_difference.year') or starts-with($facet_name, 'bedheight_difference.height'))">
@@ -1313,6 +1337,7 @@
       <dc:call-macro name="longitudinal-section-fix"/>
       <dc:call-macro name="longitudinal-section-fix-vollmer"/>
       <dc:comment> MINFO </dc:comment>
+      <dc:call-macro name="middle_bedheights"/>
       <dc:call-macro name="bedheight_differences"/>
       <dc:call-macro name="bedquality"/>
       <dc:call-macro name="flow-velocity"/>
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/BedHeightsArtifact.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/BedHeightsArtifact.java	Tue Jul 08 18:19:04 2014 +0200
@@ -24,6 +24,7 @@
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.artifacts.model.minfo.BedHeightFacet;
 import org.dive4elements.river.artifacts.model.minfo.BedHeightFactory;
+import org.dive4elements.river.artifacts.model.minfo.BedHeightSoundingWidthFacet;
 import org.dive4elements.river.artifacts.states.StaticState;
 
 import org.dive4elements.river.artifacts.resources.Resources;
@@ -102,30 +103,32 @@
                     type = "singlevalues";
                     facetType = BEDHEIGHT_SOUNDING_WIDTH;
                 }
-                // e.g. 'single'
+                addStringData("height_id", parts[2]);
+                addStringData("time", parts[3]);
+                addStringData("type", type);
                 String btype = type;
                 int hId = Integer.parseInt(parts[2]);
-                if (name.equals("bedheight")) {
-                    addStringData("type", type);
-                    addStringData("height_id", parts[2]);
-                    addStringData("time", parts[3]);
-                }
+
                 if (type.equals("singlevalues")) {
                     btype = "single";
                 }
 
                 String bedHName = BedHeightFactory.getHeightName(btype, hId);
 
+                Facet facet =  null;
                 if (facetType.equals(BEDHEIGHT_SOUNDING_WIDTH)) {
                     bedHName = Resources.getMsg(
                         callMeta,
                         "facet.bedheight.sounding_width",
                         "facet.bedheight.sounding_widt",
                         new Object[] { bedHName });
+                    facet = new BedHeightSoundingWidthFacet(facetType, bedHName);
+                }
+                else {
+                    facet = new BedHeightFacet(
+                        facetType, bedHName, type);
                 }
 
-                Facet facet = new BedHeightFacet(
-                        facetType, bedHName, type);
 
                 ArrayList<Facet> facets = new ArrayList<Facet>(1);
                 facets.add(facet);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FlowVelocityFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FlowVelocityFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -40,6 +40,8 @@
         String      hash
     ) {
         super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.flow_velocity.section.yaxis.label");
     }
 
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FlowVelocityFilterFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FlowVelocityFilterFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -44,6 +44,8 @@
         String      hash
     ) {
         super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.flow_velocity.section.yaxis.label");
     }
 
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/MiddleBedHeightCalculation.java	Thu Jul 03 16:36:43 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-/* 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;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.log4j.Logger;
-
-import org.dive4elements.artifacts.Artifact;
-import org.dive4elements.artifacts.common.utils.DateUtils;
-
-import org.dive4elements.river.model.BedHeightSingle;
-import org.dive4elements.river.model.BedHeightSingleValue;
-import org.dive4elements.river.model.TimeInterval;
-
-import org.dive4elements.river.artifacts.access.BedHeightAccess;
-
-
-public class MiddleBedHeightCalculation extends Calculation {
-
-    private static final Logger logger =
-        Logger.getLogger(MiddleBedHeightCalculation.class);
-
-
-    public CalculationResult calculate(BedHeightAccess access) {
-        logger.info("MiddleBedHeightCalculation.calculate");
-
-        int[] singleIds = access.getBedHeightSingleIDs();
-
-
-        if (logger.isDebugEnabled()) {
-            Artifact artifact = access.getArtifact();
-
-            logger.debug("Artifact '" + artifact.identifier() + "' contains:");
-            if (singleIds != null) {
-                logger.debug("   " + singleIds.length + " single bedheight ids");
-            }
-        }
-
-        List<BedHeightSingle> singles = getSingles(access, singleIds);
-
-        return buildCalculationResult(access, singles);
-    }
-
-
-    protected List<BedHeightSingle> getSingles(
-        BedHeightAccess access,
-        int[] ids
-    ) {
-        List<BedHeightSingle> singles = new ArrayList<BedHeightSingle>();
-
-        for (int id: ids) {
-            BedHeightSingle s = BedHeightSingle.getBedHeightSingleById(id);
-
-            if (s != null) {
-                singles.add(s);
-            }
-            else {
-                logger.warn("Cannot find Single by id: " + id);
-                // TODO ADD WARNING
-            }
-        }
-
-        return singles;
-    }
-
-
-    protected CalculationResult buildCalculationResult(
-        BedHeightAccess       access,
-        List<BedHeightSingle> singles
-    ) {
-        logger.info("MiddleBedHeightCalculation.buildCalculationResult");
-
-        double kmLo = access.getLowerKM();
-        double kmHi = access.getUpperKM();
-
-        List<MiddleBedHeightData> data = new ArrayList<MiddleBedHeightData>();
-
-        for (BedHeightSingle single: singles) {
-            MiddleBedHeightData d = prepareSingleData(single, kmLo, kmHi);
-
-            if (d != null) {
-                data.add(d);
-            }
-        }
-
-        logger.debug("Calculation results in " + data.size() + " data objects.");
-
-        return new CalculationResult((MiddleBedHeightData[])
-            data.toArray(new MiddleBedHeightData[data.size()]), this);
-    }
-
-
-    protected MiddleBedHeightData prepareSingleData(
-        BedHeightSingle single,
-        double kmLo,
-        double kmHi
-    ) {
-        logger.debug("Prepare data for single: " + single.getDescription());
-
-        List<BedHeightSingleValue> values =
-            BedHeightSingleValue.getBedHeightSingleValues(single, kmLo, kmHi);
-
-        int year = single.getYear() != null ? single.getYear() : 0;
-
-        MiddleBedHeightData data = new MiddleBedHeightData(
-            year,
-            year,
-            single.getEvaluationBy(),
-            single.getDescription());
-
-        for (BedHeightSingleValue value: values) {
-            if (value.getHeight() != null) {
-                double uncert = value.getUncertainty() != null ?
-                    value.getUncertainty().doubleValue() : Double.NaN;
-                double sounding = value.getSoundingWidth() != null ?
-                    value.getSoundingWidth().doubleValue() : Double.NaN;
-                double gap = value.getDataGap() != null ?
-                    value.getDataGap().doubleValue() : Double.NaN;
-                data.addAll(value.getStation().doubleValue(),
-                    value.getHeight().doubleValue(),
-                    uncert,
-                    sounding,
-                    gap,
-                    value.getWidth().doubleValue(),
-                    false);
-             }
-            else {
-                data.addAll(value.getStation().doubleValue(),
-                    0,
-                    0,
-                    0,
-                    0,
-                    0,
-                    true);
-            }
-        }
-
-        logger.debug("Single contains " + values.size() + " values");
-
-        return data;
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/MiddleBedHeightData.java	Thu Jul 03 16:36:43 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,221 +0,0 @@
-/* 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;
-
-import java.io.Serializable;
-
-import java.util.ArrayList;
-
-import gnu.trove.TDoubleArrayList;
-
-import org.dive4elements.artifacts.CallContext;
-
-import org.dive4elements.river.artifacts.resources.Resources;
-
-import org.apache.log4j.Logger;
-
-
-public class MiddleBedHeightData implements Serializable,
-                                            Comparable<MiddleBedHeightData> {
-
-    /** Very private logger. */
-    private static final Logger logger = Logger.getLogger(MiddleBedHeightData.class);
-
-    public static final String I18N_SINGLE_NAME = "facet.bedheight_middle.single";
-    public static final String I18N_EPOCH_NAME  = "facet.bedheight_middle.epoch";
-
-    private int    startYear;
-    private int    endYear;
-    private String evaluatedBy;
-    private String description;
-
-    private TDoubleArrayList km;
-    private TDoubleArrayList middleHeight;
-    private TDoubleArrayList uncertainty;
-    private TDoubleArrayList soundingWidth;
-    private TDoubleArrayList dataGap;
-    private TDoubleArrayList width;
-    private ArrayList empty;
-
-
-    protected MiddleBedHeightData(int start, int end, String eval, String desc) {
-        this.startYear   = start;
-        this.endYear     = end;
-        this.evaluatedBy = eval;
-        this.description = desc;
-
-        this.km            = new TDoubleArrayList();
-        this.middleHeight  = new TDoubleArrayList();
-        this.uncertainty   = new TDoubleArrayList();
-        this.soundingWidth = new TDoubleArrayList();
-        this.dataGap       = new TDoubleArrayList();
-        this.width         = new TDoubleArrayList();
-        this.empty         = new ArrayList();
-    }
-
-    public void addAll(double station, double height, double uncertainty,
-        double soundingWidth, double dataGap, double width, boolean isEmpty) {
-        addKM(station);
-        addMiddleHeight(height);
-        addUncertainty(uncertainty);
-        addSoundingWidth(soundingWidth);
-        addDataGap(dataGap);
-        addWidth(width);
-        addIsEmpty(isEmpty);
-    }
-
-
-    public int getStartYear() {
-        return startYear;
-    }
-
-    public int getEndYear() {
-        return endYear;
-    }
-
-    public String getEvaluatedBy() {
-        return evaluatedBy;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-
-    protected void addKM(double km) {
-        this.km.add(km);
-    }
-
-    public double getKM(int idx) {
-        return km.get(idx);
-    }
-
-    protected void addMiddleHeight(double middleHeight) {
-        this.middleHeight.add(middleHeight);
-    }
-
-    public double getMiddleHeight(int idx) {
-        return middleHeight.get(idx);
-    }
-
-    protected void addUncertainty(double uncertainty) {
-        this.uncertainty.add(uncertainty);
-    }
-
-    public double getUncertainty(int idx) {
-        return uncertainty.get(idx);
-    }
-
-    protected void addSoundingWidth(double soundingWidth) {
-        this.soundingWidth.add(soundingWidth);
-    }
-
-    public double getSoundingWidth(int idx) {
-        return soundingWidth.get(idx);
-    }
-
-    protected void addDataGap(double gap) {
-        this.dataGap.add(gap);
-    }
-
-    public double getDataGap(int idx) {
-        return dataGap.get(idx);
-    }
-
-    protected void addIsEmpty(boolean empty) {
-        this.empty.add(empty);
-    }
-
-    public boolean isEmpty(int idx) {
-        return (Boolean) empty.get(idx);
-    }
-
-
-    protected void addWidth(double width) {
-        this.width.add(width);
-    }
-
-    public double getWidth(int idx) {
-        return width.get(idx);
-    }
-
-    public int size() {
-        return km.size();
-    }
-
-
-    /**
-     * Get the points, ready to be drawn
-     * @return [[km1, km2,...],[height1,height2,...]]
-     */
-    public double[][] getMiddleHeightsPoints() {
-        double[][] points = new double[2][size()];
-
-        for (int i = 0, n = size(); i < n; i++) {
-            if (isEmpty(i)) {
-                points[0][i] = getKM(i);
-                points[1][i] = Double.NaN;
-            }
-            else {
-                points[0][i] = getKM(i);
-                points[1][i] = getMiddleHeight(i);
-            }
-        }
-
-        return points;
-    }
-
-
-    public String getSoundingName(CallContext context) {
-        if (getStartYear() == getEndYear()) {
-            return Resources.getMsg(
-                context.getMeta(),
-                I18N_SINGLE_NAME,
-                I18N_SINGLE_NAME,
-                new Object[] { getStartYear() }
-            );
-        }
-        else {
-            return Resources.getMsg(
-                context.getMeta(),
-                I18N_EPOCH_NAME,
-                I18N_EPOCH_NAME,
-                new Object[] { getStartYear(), getEndYear() }
-            );
-        }
-    }
-
-    @Override
-    public int compareTo(MiddleBedHeightData other) {
-
-        int descCompared = description.compareTo(other.getDescription());
-
-        if (descCompared != 0) {
-            return descCompared;
-        }
-
-        if (size() == 0 || other.size() == 0) {
-            if (size() == 0 && other.size() > 0) {
-                return 1;
-            } else if (size() > 0 && other.size() == 0) {
-                return -1;
-            } else if (size() == 0 && other.size() == 0) {
-               return 0;
-            }
-        }
-
-        if (getKM(0) < other.getKM(0)) {
-            return -1;
-        } else if (getKM(0) > other.getKM(0)) {
-            return 1;
-        }
-        return 0;
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/MiddleBedHeightFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/* 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;
-
-import org.dive4elements.artifactdatabase.state.Facet;
-
-import org.dive4elements.artifacts.Artifact;
-import org.dive4elements.artifacts.CallContext;
-
-import org.dive4elements.river.artifacts.D4EArtifact;
-
-import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
-
-import org.apache.log4j.Logger;
-
-
-/**
- * Facet of a MiddleBedHeight curve.
- */
-public class MiddleBedHeightFacet extends DataFacet {
-
-    private static Logger logger = Logger.getLogger(MiddleBedHeightFacet.class);
-
-
-    public MiddleBedHeightFacet() {
-        // required for clone operation deepCopy()
-    }
-
-
-    public MiddleBedHeightFacet(
-        int         idx,
-        String      name,
-        String      description,
-        ComputeType type,
-        String      stateId,
-        String      hash
-    ) {
-        super(idx, name, description, type, hash, stateId);
-    }
-
-
-    public Object getData(Artifact artifact, CallContext context) {
-        logger.debug("Get data for middle bed height at index: " + index);
-
-        D4EArtifact flys = (D4EArtifact) artifact;
-
-        CalculationResult res = (CalculationResult)
-            flys.compute(context, hash, stateId, type, false);
-
-        MiddleBedHeightData[] data = (MiddleBedHeightData[]) res.getData();
-
-        return data[index];
-    }
-
-
-    /** Copy deeply. */
-    @Override
-    public Facet deepCopy() {
-        MiddleBedHeightFacet copy = new MiddleBedHeightFacet();
-        copy.set(this);
-        copy.type    = type;
-        copy.hash    = hash;
-        copy.stateId = stateId;
-        return copy;
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDensityFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/* 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.minfo;
-
-import org.apache.log4j.Logger;
-
-import org.dive4elements.artifactdatabase.state.Facet;
-import org.dive4elements.artifacts.Artifact;
-import org.dive4elements.artifacts.CallContext;
-import org.dive4elements.river.artifacts.D4EArtifact;
-import org.dive4elements.river.artifacts.model.CalculationResult;
-import org.dive4elements.river.artifacts.model.DataFacet;
-import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
-
-
-/**
- * Facet for serving bed density data.
- *
- * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
- */
-public class BedDensityFacet extends DataFacet {
-
-    private static final long serialVersionUID = 1L;
-
-    private static Logger logger = Logger.getLogger(BedDensityFacet.class);
-
-    public BedDensityFacet() {
-    }
-
-    public BedDensityFacet(int idx, String name, String description,
-        ComputeType type, String stateId, String hash) {
-        super(idx, name, description, type, hash, stateId);
-    }
-
-    public Object getData(Artifact artifact, CallContext context) {
-        logger.debug("Get data for bed density at index: " + index);
-
-        D4EArtifact flys = (D4EArtifact) artifact;
-
-        CalculationResult res = (CalculationResult) flys.compute(context, hash,
-            stateId, type, false);
-
-        int ndx = index >> 8;
-        Object[] data =
-            ((BedQualityResult[]) res.getData())[ndx].getParameters(); // TODO CAST TO SPECIFIC CLASS
-
-        int ndy = index & 255;
-        return data != null && data.length > ndy ? data[ndy] : null;
-    }
-
-    /** Copy deeply. */
-    @Override
-    public Facet deepCopy() {
-        BedDensityFacet copy = new BedDensityFacet();
-        copy.set(this);
-        copy.type = type;
-        copy.hash = hash;
-        copy.stateId = stateId;
-        return copy;
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDensitySubFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,74 @@
+/* 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.minfo;
+
+import org.apache.log4j.Logger;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+/**
+ * Facet for serving bed density data.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class BedDensitySubFacet extends DataFacet {
+
+    private static final long serialVersionUID = 1L;
+
+    private static Logger logger = Logger.getLogger(BedDensitySubFacet.class);
+
+    public BedDensitySubFacet() {
+    }
+
+    public BedDensitySubFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedquality.yaxis.label.density");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed density at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        int ndx = index >> 8;
+        BedParametersResult[] data =
+            ((BedQualityResult[]) res.getData())[ndx].getParameters(); // TODO CAST TO SPECIFIC CLASS
+
+        int ndy = index & 255;
+        if (data != null && data.length > ndy) {
+            BedParametersResult result = data[ndy];
+            return result.getDensitySubData();
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDensitySubFacet copy = new BedDensitySubFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDensityTopFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,74 @@
+/* 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.minfo;
+
+import org.apache.log4j.Logger;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+/**
+ * Facet for serving bed density data.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class BedDensityTopFacet extends DataFacet {
+
+    private static final long serialVersionUID = 1L;
+
+    private static Logger logger = Logger.getLogger(BedDensityTopFacet.class);
+
+    public BedDensityTopFacet() {
+    }
+
+    public BedDensityTopFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedquality.yaxis.label.density");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed density at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        int ndx = index >> 8;
+        BedParametersResult[] data =
+            ((BedQualityResult[]) res.getData())[ndx].getParameters(); // TODO CAST TO SPECIFIC CLASS
+
+        int ndy = index & 255;
+        if (data != null && data.length > ndy) {
+            BedParametersResult result = data[ndy];
+            return result.getDensityCapData();
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDensityTopFacet copy = new BedDensityTopFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterDataFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterDataFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -28,6 +28,8 @@
         String hash
     ) {
         super(ndx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedquality.yaxis.label.diameter");
     }
 
     public Object getData(Artifact artifact, CallContext context) {
@@ -77,7 +79,7 @@
             }
         }
         BedDiameterData bdd = new BedDiameterData(diameter, kms, data);
-        return bdd;
+        return bdd.getDiameterData();
     }
 
     /** Copy deeply. */
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/* 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.minfo;
-
-import org.apache.log4j.Logger;
-
-import org.dive4elements.artifactdatabase.state.Facet;
-import org.dive4elements.artifacts.Artifact;
-import org.dive4elements.artifacts.CallContext;
-import org.dive4elements.river.artifacts.D4EArtifact;
-import org.dive4elements.river.artifacts.model.CalculationResult;
-import org.dive4elements.river.artifacts.model.DataFacet;
-import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
-
-
-/**
- * Facet for serving bed diameter data.
- *
- * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
- */
-public class BedDiameterFacet extends DataFacet {
-
-    private static final long serialVersionUID = 1L;
-
-    private static Logger logger = Logger.getLogger(BedDiameterFacet.class);
-
-    public BedDiameterFacet() {
-    }
-
-    public BedDiameterFacet(int idx, String name, String description,
-        ComputeType type, String stateId, String hash) {
-        super(idx, name, description, type, hash, stateId);
-    }
-
-    public Object getData(Artifact artifact, CallContext context) {
-        logger.debug("Get data for bed diameter at index: " + index);
-
-        D4EArtifact flys = (D4EArtifact) artifact;
-
-        CalculationResult res = (CalculationResult) flys.compute(context, hash,
-            stateId, type, false);
-
-        int ndx = index >> 8;
-        Object[] data = ((BedQualityResult[]) res.getData())[ndx].getBedResults(); // TODO CAST TO SPECIFIC CLASS
-
-        int ndy = index & 255;
-        return data != null && data.length > ndy ? data[ndy] : null;
-    }
-
-    /** Copy deeply. */
-    @Override
-    public Facet deepCopy() {
-        BedDiameterFacet copy = new BedDiameterFacet();
-        copy.set(this);
-        copy.type = type;
-        copy.hash = hash;
-        copy.stateId = stateId;
-        return copy;
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterSubFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,74 @@
+/* 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.minfo;
+
+import org.apache.log4j.Logger;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+/**
+ * Facet for serving bed diameter data.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class BedDiameterSubFacet extends DataFacet {
+
+    private static final long serialVersionUID = 1L;
+
+    private static Logger logger = Logger.getLogger(BedDiameterSubFacet.class);
+
+    public BedDiameterSubFacet() {
+    }
+
+    public BedDiameterSubFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedquality.yaxis.label");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed diameter at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        int ndx = index >> 8;
+        Object[] raw =
+            ((BedQualityResult[]) res.getData())[ndx].getBedResults();
+
+        int ndy = index & 255;
+        if (raw != null && raw.length > ndy) {
+            BedDiameterResult data = (BedDiameterResult)raw[ndy];
+            return data.getDiameterSubData();
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDiameterSubFacet copy = new BedDiameterSubFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterTopFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,73 @@
+/* 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.minfo;
+
+import org.apache.log4j.Logger;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+/**
+ * Facet for serving bed diameter data.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class BedDiameterTopFacet extends DataFacet {
+
+    private static final long serialVersionUID = 1L;
+
+    private static Logger logger = Logger.getLogger(BedDiameterTopFacet.class);
+
+    public BedDiameterTopFacet() {
+    }
+
+    public BedDiameterTopFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedquality.yaxis.label");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed diameter at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        int ndx = index >> 8;
+        Object[] raw = ((BedQualityResult[]) res.getData())[ndx].getBedResults(); // TODO CAST TO SPECIFIC CLASS
+
+        int ndy = index & 255;
+        if (raw != null && raw.length > ndy) {
+            BedDiameterResult data = (BedDiameterResult)raw[ndy];
+            return data.getDiameterCapData();
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDiameterTopFacet copy = new BedDiameterTopFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,66 @@
+/* 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.minfo;
+
+import org.apache.log4j.Logger;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+public class BedDiffFacet
+extends DataFacet
+{
+    private static Logger logger = Logger.getLogger(BedDiffFacet.class);
+
+    public BedDiffFacet() {
+    }
+
+    public BedDiffFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.beddifference.yaxis.label.diff");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed density at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        BedDiffYearResult[] resultData =
+            (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
+
+        if (resultData != null && resultData.length > index) {
+            BedDiffYearResult data = resultData[index];
+            return data.getDifferencesData();
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDiffFacet copy = new BedDiffFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffFilterFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,83 @@
+/* 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.minfo;
+
+import org.apache.log4j.Logger;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RiverAccess;
+import org.dive4elements.river.artifacts.context.RiverContext;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.math.MovingAverage;
+import org.dive4elements.river.artifacts.model.ZoomScale;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+public class BedDiffFilterFacet
+extends DataFacet
+{
+    private static Logger logger = Logger.getLogger(BedDiffFilterFacet.class);
+
+    public BedDiffFilterFacet() {
+    }
+
+    public BedDiffFilterFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.beddifference.yaxis.label.diff");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed density at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        BedDiffYearResult[] data =
+            (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
+        Double start = (Double)context.getContextValue("startkm");
+        Double end = (Double)context.getContextValue("endkm");
+        if(start != null && end != null) {
+            RiverContext fc = (RiverContext)context.globalContext();
+            // Adaptive smoothing, based on zoom factor/diagram extents.
+            ZoomScale scales = (ZoomScale)fc.get("zoomscale");
+            RiverAccess access = new RiverAccess((D4EArtifact)artifact);
+            String river = access.getRiverName();
+
+            double radius = scales.getRadius(river, start, end);
+            BedDiffYearResult oldData = data[index];
+            double[][] diffs = MovingAverage.weighted(oldData.getDifferencesData(), radius);
+            this.metaData.put(
+                Resources.getMsg(context.getMeta(),
+                    "chart.subtitle.radius", new Object[] { radius }), "");
+            return diffs;
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDiffFilterFacet copy = new BedDiffFilterFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffHeightMinFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,58 @@
+package org.dive4elements.river.artifacts.model.minfo;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+public class BedDiffHeightMinFacet
+extends DataFacet
+implements FacetTypes
+{
+    private static Logger logger = Logger.getLogger(BedDiffHeightMinFacet.class);
+
+    public BedDiffHeightMinFacet() {
+    }
+
+    public BedDiffHeightMinFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.beddifference.yaxis.label.diff");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed density at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        BedDiffYearResult[] resultData =
+            (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
+
+        if (resultData != null && resultData.length > index) {
+            BedDiffYearResult data = resultData[index];
+            return data.getHeights1Data();
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDiffHeightMinFacet copy = new BedDiffHeightMinFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffHeightMinFilterFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,83 @@
+/* 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.minfo;
+
+import org.apache.log4j.Logger;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RiverAccess;
+import org.dive4elements.river.artifacts.context.RiverContext;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.math.MovingAverage;
+import org.dive4elements.river.artifacts.model.ZoomScale;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+public class BedDiffHeightMinFilterFacet
+extends DataFacet
+{
+    private static Logger logger = Logger.getLogger(BedDiffHeightMinFilterFacet.class);
+
+    public BedDiffHeightMinFilterFacet() {
+    }
+
+    public BedDiffHeightMinFilterFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.beddifference.yaxis.label.diff");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed density at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        BedDiffYearResult[] data =
+            (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
+        Double start = (Double)context.getContextValue("startkm");
+        Double end = (Double)context.getContextValue("endkm");
+        if(start != null && end != null) {
+            RiverContext fc = (RiverContext)context.globalContext();
+            // Adaptive smoothing, based on zoom factor/diagram extents.
+            ZoomScale scales = (ZoomScale)fc.get("zoomscale");
+            RiverAccess access = new RiverAccess((D4EArtifact)artifact);
+            String river = access.getRiverName();
+
+            double radius = scales.getRadius(river, start, end);
+            BedDiffYearResult oldData = data[index];
+            double[][] heights = MovingAverage.weighted(oldData.getHeights1Data(), radius);
+            this.metaData.put(
+                Resources.getMsg(context.getMeta(),
+                    "chart.subtitle.radius", new Object[] { radius }), "");
+            return heights;
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDiffHeightMinFilterFacet copy = new BedDiffHeightMinFilterFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffHeightSubFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,58 @@
+package org.dive4elements.river.artifacts.model.minfo;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+public class BedDiffHeightSubFacet
+extends DataFacet
+implements FacetTypes
+{
+    private static Logger logger = Logger.getLogger(BedDiffHeightSubFacet.class);
+
+    public BedDiffHeightSubFacet() {
+    }
+
+    public BedDiffHeightSubFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.beddifference.yaxis.label.diff");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed density at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        BedDiffYearResult[] resultData =
+            (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
+
+        if (resultData != null && resultData.length > index) {
+            BedDiffYearResult data = resultData[index];
+            return data.getHeights2Data();
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDiffHeightSubFacet copy = new BedDiffHeightSubFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffHeightSubFilterFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,83 @@
+/* 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.minfo;
+
+import org.apache.log4j.Logger;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RiverAccess;
+import org.dive4elements.river.artifacts.context.RiverContext;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.math.MovingAverage;
+import org.dive4elements.river.artifacts.model.ZoomScale;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+public class BedDiffHeightSubFilterFacet
+extends DataFacet
+{
+    private static Logger logger = Logger.getLogger(BedDiffHeightSubFilterFacet.class);
+
+    public BedDiffHeightSubFilterFacet() {
+    }
+
+    public BedDiffHeightSubFilterFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.beddifference.yaxis.label.diff");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed density at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        BedDiffYearResult[] data =
+            (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
+        Double start = (Double)context.getContextValue("startkm");
+        Double end = (Double)context.getContextValue("endkm");
+        if(start != null && end != null) {
+            RiverContext fc = (RiverContext)context.globalContext();
+            // Adaptive smoothing, based on zoom factor/diagram extents.
+            ZoomScale scales = (ZoomScale)fc.get("zoomscale");
+            RiverAccess access = new RiverAccess((D4EArtifact)artifact);
+            String river = access.getRiverName();
+
+            double radius = scales.getRadius(river, start, end);
+            BedDiffYearResult oldData = data[index];
+            double[][] heights = MovingAverage.weighted(oldData.getHeights2Data(), radius);
+            this.metaData.put(
+                Resources.getMsg(context.getMeta(),
+                    "chart.subtitle.radius", new Object[] { radius }), "");
+            return heights;
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDiffHeightSubFilterFacet copy = new BedDiffHeightSubFilterFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffMorphMinFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,58 @@
+package org.dive4elements.river.artifacts.model.minfo;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+public class BedDiffMorphMinFacet
+extends DataFacet
+implements FacetTypes
+{
+    private static Logger logger = Logger.getLogger(BedDiffMorphMinFacet.class);
+
+    public BedDiffMorphMinFacet() {
+    }
+
+    public BedDiffMorphMinFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.beddifference.yaxis.label.morph");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed density at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        BedDiffYearResult[] resultData =
+            (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
+
+        if (resultData != null && resultData.length > index) {
+            BedDiffYearResult data = resultData[index];
+            return data.getMorphWidth1Data();
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDiffMorphMinFacet copy = new BedDiffMorphMinFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffMorphSubFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,58 @@
+package org.dive4elements.river.artifacts.model.minfo;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+public class BedDiffMorphSubFacet
+extends DataFacet
+implements FacetTypes
+{
+    private static Logger logger = Logger.getLogger(BedDiffMorphSubFacet.class);
+
+    public BedDiffMorphSubFacet() {
+    }
+
+    public BedDiffMorphSubFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.beddifference.yaxis.label.morph");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed density at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        BedDiffYearResult[] resultData =
+            (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
+
+        if (resultData != null && resultData.length > index) {
+            BedDiffYearResult data = resultData[index];
+            return data.getMorphWidth2Data();
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDiffMorphSubFacet copy = new BedDiffMorphSubFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffPerYearFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,58 @@
+package org.dive4elements.river.artifacts.model.minfo;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+public class BedDiffPerYearFacet
+extends DataFacet
+implements FacetTypes
+{
+    private static Logger logger = Logger.getLogger(BedDiffPerYearFacet.class);
+
+    public BedDiffPerYearFacet() {
+    }
+
+    public BedDiffPerYearFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.beddifference.height.yaxis.label");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed density at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        BedDiffYearResult[] resultData =
+            (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
+
+        if (resultData != null && resultData.length > index) {
+            BedDiffYearResult data = resultData[index];
+            return data.getHeightPerYearData();
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDiffPerYearFacet copy = new BedDiffPerYearFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffPerYearFilterFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,83 @@
+/* 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.minfo;
+
+import org.apache.log4j.Logger;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RiverAccess;
+import org.dive4elements.river.artifacts.context.RiverContext;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.math.MovingAverage;
+import org.dive4elements.river.artifacts.model.ZoomScale;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+public class BedDiffPerYearFilterFacet
+extends DataFacet
+{
+    private static Logger logger = Logger.getLogger(BedDiffPerYearFilterFacet.class);
+
+    public BedDiffPerYearFilterFacet() {
+    }
+
+    public BedDiffPerYearFilterFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.beddifference.height.yaxis.label");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed density at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        BedDiffYearResult[] data =
+            (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
+        Double start = (Double)context.getContextValue("startkm");
+        Double end = (Double)context.getContextValue("endkm");
+        if(start != null && end != null) {
+            RiverContext fc = (RiverContext)context.globalContext();
+            // Adaptive smoothing, based on zoom factor/diagram extents.
+            ZoomScale scales = (ZoomScale)fc.get("zoomscale");
+            RiverAccess access = new RiverAccess((D4EArtifact)artifact);
+            String river = access.getRiverName();
+
+            double radius = scales.getRadius(river, start, end);
+            BedDiffYearResult oldData = data[index];
+            double[][] diffs = MovingAverage.weighted(oldData.getHeightPerYearData(), radius);
+            this.metaData.put(
+                Resources.getMsg(context.getMeta(),
+                    "chart.subtitle.radius", new Object[] { radius }), "");
+            return diffs;
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDiffPerYearFilterFacet copy = new BedDiffPerYearFilterFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffSoundingWidthFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,58 @@
+package org.dive4elements.river.artifacts.model.minfo;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+public class BedDiffSoundingWidthFacet
+extends DataFacet
+implements FacetTypes
+{
+    private static Logger logger = Logger.getLogger(BedDiffSoundingWidthFacet.class);
+
+    public BedDiffSoundingWidthFacet() {
+    }
+
+    public BedDiffSoundingWidthFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedheight_middle.sounding.yaxis.label");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed density at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        BedDiffYearResult[] resultData =
+            (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
+
+        if (resultData != null && resultData.length > index) {
+            BedDiffYearResult data = resultData[index];
+            return data.getSoundingWidthData();
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedDiffSoundingWidthFacet copy = new BedDiffSoundingWidthFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffYearFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/* 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.minfo;
-
-import org.apache.log4j.Logger;
-
-import org.dive4elements.artifactdatabase.state.Facet;
-import org.dive4elements.artifacts.Artifact;
-import org.dive4elements.artifacts.CallContext;
-import org.dive4elements.river.artifacts.D4EArtifact;
-import org.dive4elements.river.artifacts.model.CalculationResult;
-import org.dive4elements.river.artifacts.model.DataFacet;
-import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
-
-
-public class BedDiffYearFacet
-extends DataFacet
-{
-    private static Logger logger = Logger.getLogger(BedDiffYearFacet.class);
-
-    public BedDiffYearFacet() {
-    }
-
-    public BedDiffYearFacet(int idx, String name, String description,
-        ComputeType type, String stateId, String hash) {
-        super(idx, name, description, type, hash, stateId);
-    }
-
-    public Object getData(Artifact artifact, CallContext context) {
-        logger.debug("Get data for bed density at index: " + index);
-
-        D4EArtifact flys = (D4EArtifact) artifact;
-
-        CalculationResult res = (CalculationResult) flys.compute(context, hash,
-            stateId, type, false);
-
-        BedDiffYearResult[] data =
-            (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
-
-        return data != null && data.length > index ? data[index] : null;
-    }
-
-    /** Copy deeply. */
-    @Override
-    public Facet deepCopy() {
-        BedDiffYearFacet copy = new BedDiffYearFacet();
-        copy.set(this);
-        copy.type = type;
-        copy.hash = hash;
-        copy.stateId = stateId;
-        return copy;
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffYearFilterFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/* 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.minfo;
-
-import org.apache.log4j.Logger;
-
-import org.dive4elements.artifactdatabase.state.Facet;
-import org.dive4elements.artifacts.Artifact;
-import org.dive4elements.artifacts.CallContext;
-import org.dive4elements.river.artifacts.D4EArtifact;
-import org.dive4elements.river.artifacts.access.RiverAccess;
-import org.dive4elements.river.artifacts.context.RiverContext;
-import org.dive4elements.river.artifacts.model.CalculationResult;
-import org.dive4elements.river.artifacts.model.DataFacet;
-import org.dive4elements.river.artifacts.math.MovingAverage;
-import org.dive4elements.river.artifacts.model.ZoomScale;
-import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
-
-
-public class BedDiffYearFilterFacet
-extends DataFacet
-{
-    private static Logger logger = Logger.getLogger(BedDiffYearFilterFacet.class);
-
-    public BedDiffYearFilterFacet() {
-    }
-
-    public BedDiffYearFilterFacet(int idx, String name, String description,
-        ComputeType type, String stateId, String hash) {
-        super(idx, name, description, type, hash, stateId);
-    }
-
-    public Object getData(Artifact artifact, CallContext context) {
-        logger.debug("Get data for bed density at index: " + index);
-
-        D4EArtifact flys = (D4EArtifact) artifact;
-
-        CalculationResult res = (CalculationResult) flys.compute(context, hash,
-            stateId, type, false);
-
-        BedDiffYearResult[] data =
-            (BedDiffYearResult[]) res.getData(); // TODO CAST TO SPECIFIC CLASS
-        Double start = (Double)context.getContextValue("startkm");
-        Double end = (Double)context.getContextValue("endkm");
-        if(start != null && end != null) {
-            RiverContext fc = (RiverContext)context.globalContext();
-            // Adaptive smoothing, based on zoom factor/diagram extents.
-            ZoomScale scales = (ZoomScale)fc.get("zoomscale");
-            RiverAccess access = new RiverAccess((D4EArtifact)artifact);
-            String river = access.getRiverName();
-
-            double radius = scales.getRadius(river, start, end);
-            BedDiffYearResult oldData = data[index];
-            BedDiffYearResult newData = new BedDiffYearResult();
-            newData.setStart(oldData.getStart());
-            newData.setEnd(oldData.getEnd());
-            double[][] diffs = MovingAverage.weighted(oldData.getDifferencesData(), radius);
-            double[][] heights1 = MovingAverage.weighted(oldData.getHeights1Data(), radius);
-            double[][] heights2 = MovingAverage.weighted(oldData.getHeights2Data(), radius);
-            double[][] morph1 = oldData.getMorphWidth1Data();
-            double[][] morph2 = oldData.getMorphWidth2Data();
-            double[][] sounding = oldData.getSoundingWidthData();
-            double[][] year = MovingAverage.weighted(oldData.getHeightPerYearData(), radius);
-            for(int j = 0; j < diffs[0].length; j++) {
-                newData.addKm(diffs[0][j]);
-                newData.addBedHeights(year[1][j]);
-                newData.addMorphWidth1(morph1[1][j]);
-                newData.addMorphWidth2(morph2[1][j]);
-                newData.addSoundingWidth(sounding[1][j]);
-                newData.addDifference(diffs[1][j]);
-                newData.addHeight1(heights1[1][j]);
-                newData.addHeight2(heights2[1][j]);
-            }
-            return newData;
-        }
-        return data != null && data.length > index ? data[index] : null;
-    }
-
-    /** Copy deeply. */
-    @Override
-    public Facet deepCopy() {
-        BedDiffYearFilterFacet copy = new BedDiffYearFilterFacet();
-        copy.set(this);
-        copy.type = type;
-        copy.hash = hash;
-        copy.stateId = stateId;
-        return copy;
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -8,6 +8,11 @@
 
 package org.dive4elements.river.artifacts.model.minfo;
 
+import gnu.trove.TDoubleArrayList;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.D4EArtifact;
@@ -21,6 +26,8 @@
 extends      BlackboardDataFacet
 implements   FacetTypes {
 
+    private static final Logger logger = Logger.getLogger(BedHeightFacet.class);
+
     private String type;
 
     public BedHeightFacet(String name, String description, String type) {
@@ -28,6 +35,8 @@
         this.description = description;
         this.type = type;
         this.index = 0;
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedheight.height.yaxis.label");
     }
 
     /**
@@ -48,18 +57,36 @@
              * @return List of {@link BedHeightSingleValue}s */
             BedHeightSingle single = BedHeightSingle.getBedHeightSingleById(
                     access.getHeightId());
-            return BedHeightSingleValue.getBedHeightSingleValues(single,
+            List<BedHeightSingleValue> bedheightValues =
+                BedHeightSingleValue.getBedHeightSingleValues(
+                    single,
                     access.getFrom(),
                     access.getTo());
+            double[][] values = new double[2][bedheightValues.size()];
+            int i = 0;
+            for (BedHeightSingleValue bedheightValue : bedheightValues) {
+                values[0][i] = bedheightValue.getStation();
+                values[1][i] = bedheightValue.getHeight();
+                i++;
+            }
+            return values;
         }
         else {
             /* Former doc (from BedHeightAccess):
              * Return the {@link BedHeight} at the height_id and time of the artifact
              * @return {@link BedHeight} */
-            return BedHeightFactory.getHeight(
+            BedHeightData data = BedHeightFactory.getHeight(
                 access.getType(),
                 access.getHeightId(),
                 access.getTime());
+            //data.removeNaNs();
+            TDoubleArrayList stations= data.getStations();
+            double[][] values = new double[2][stations.size()];
+            for (int i = 0; i < stations.size(); i++) {
+                values[0][i] = stations.get(i);
+                values[1][i] = data.getHeight(i);
+            }
+            return values;
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightSoundingWidthFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,70 @@
+package org.dive4elements.river.artifacts.model.minfo;
+
+import java.util.List;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.BedHeightAccess;
+import org.dive4elements.river.artifacts.model.BlackboardDataFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.model.BedHeightSingle;
+import org.dive4elements.river.model.BedHeightSingleValue;
+
+
+public class BedHeightSoundingWidthFacet
+extends BlackboardDataFacet
+implements FacetTypes
+{
+    public BedHeightSoundingWidthFacet(String name, String description) {
+        this.name = name;
+        this.description = description;
+        this.index = 0;
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedheight.height.yaxis.label");
+    }
+
+    /**
+     * Returns the data this facet requires.
+     *
+     * @param artifact the owner artifact.
+     * @param context  the CallContext (ignored).
+     *
+     * @return the data.
+     */
+    @Override
+    public Object getData(Artifact artifact, CallContext context) {
+        BedHeightAccess access = new BedHeightAccess((D4EArtifact)artifact);
+        /* Former doc (from BedHeightAccess):
+         * Return a {@link List} of {@link BedHeightSingleValue}s
+         * at the range of the artifact
+         * @return List of {@link BedHeightSingleValue}s */
+        BedHeightSingle single = BedHeightSingle.getBedHeightSingleById(
+                access.getHeightId());
+        List<BedHeightSingleValue> bedheightValues =
+            BedHeightSingleValue.getBedHeightSingleValues(
+                single,
+                access.getFrom(),
+                access.getTo());
+        double[][] values = new double[2][bedheightValues.size()];
+        int i = 0;
+        for (BedHeightSingleValue bedheightValue : bedheightValues) {
+            values[0][i] = bedheightValue.getStation();
+            values[1][i] = bedheightValue.getSoundingWidth();
+            i++;
+        }
+        return values;
+    }
+
+    /**
+     * Create a deep copy of this Facet.
+     * @return a deep copy.
+     */
+    @Override
+    public BedHeightSoundingWidthFacet deepCopy() {
+        BedHeightSoundingWidthFacet copy =
+            new BedHeightSoundingWidthFacet(name, description);
+        copy.set(this);
+        return copy;
+    }
+}
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedPorosityFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/* 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.minfo;
-
-import org.apache.log4j.Logger;
-
-import org.dive4elements.artifactdatabase.state.Facet;
-import org.dive4elements.artifacts.Artifact;
-import org.dive4elements.artifacts.CallContext;
-import org.dive4elements.river.artifacts.D4EArtifact;
-import org.dive4elements.river.artifacts.model.CalculationResult;
-import org.dive4elements.river.artifacts.model.DataFacet;
-import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
-
-
-/**
- * Facet for serving bed porosity data.
- *
- * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
- */
-public class BedPorosityFacet extends DataFacet {
-
-    private static final long serialVersionUID = 1L;
-
-    private static Logger logger = Logger.getLogger(BedPorosityFacet.class);
-
-    public BedPorosityFacet() {
-    }
-
-    public BedPorosityFacet(int idx, String name, String description,
-        ComputeType type, String stateId, String hash) {
-        super(idx, name, description, type, hash, stateId);
-    }
-
-    public Object getData(Artifact artifact, CallContext context) {
-        logger.debug("Get data for bed porosity at index: " + index);
-
-        D4EArtifact flys = (D4EArtifact) artifact;
-
-        CalculationResult res = (CalculationResult) flys.compute(context, hash,
-            stateId, type, false);
-
-        int ndx = index >> 8;
-        Object[] data = ((BedQualityResult[]) res.getData())[ndx].getParameters(); // TODO CAST TO SPECIFIC CLASS
-
-        int ndy = index & 255;
-        return data != null && data.length > ndy ? data[ndy] : null;
-    }
-
-    /** Copy deeply. */
-    @Override
-    public Facet deepCopy() {
-        BedPorosityFacet copy = new BedPorosityFacet();
-        copy.set(this);
-        copy.type = type;
-        copy.hash = hash;
-        copy.stateId = stateId;
-        return copy;
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedPorositySubFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,73 @@
+/* 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.minfo;
+
+import org.apache.log4j.Logger;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+/**
+ * Facet for serving bed porosity data.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class BedPorositySubFacet extends DataFacet {
+
+    private static final long serialVersionUID = 1L;
+
+    private static Logger logger = Logger.getLogger(BedPorositySubFacet.class);
+
+    public BedPorositySubFacet() {
+    }
+
+    public BedPorositySubFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedquality.yaxis.label.porosity");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed porosity at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        int ndx = index >> 8;
+        Object[] raw = ((BedQualityResult[]) res.getData())[ndx].getParameters(); // TODO CAST TO SPECIFIC CLASS
+
+        int ndy = index & 255;
+        if (raw != null && raw.length > ndy) {
+            BedParametersResult data = (BedParametersResult)raw[ndy];
+            return data.getPorositySubData();
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedPorositySubFacet copy = new BedPorositySubFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedPorosityTopFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,73 @@
+/* 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.minfo;
+
+import org.apache.log4j.Logger;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+/**
+ * Facet for serving bed porosity data.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class BedPorosityTopFacet extends DataFacet {
+
+    private static final long serialVersionUID = 1L;
+
+    private static Logger logger = Logger.getLogger(BedPorosityTopFacet.class);
+
+    public BedPorosityTopFacet() {
+    }
+
+    public BedPorosityTopFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedquality.yaxis.label.porosity");
+    }
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for bed porosity at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        int ndx = index >> 8;
+        Object[] raw = ((BedQualityResult[]) res.getData())[ndx].getParameters(); // TODO CAST TO SPECIFIC CLASS
+
+        int ndy = index & 255;
+        if (raw != null && raw.length > ndy) {
+            BedParametersResult data = (BedParametersResult)raw[ndy];
+            return data.getPorosityCapData();
+        }
+        return null;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedPorosityTopFacet copy = new BedPorosityTopFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterDataFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterDataFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -29,6 +29,8 @@
         String hash
     ) {
         super(ndx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedquality.yaxis.label");
     }
 
     public Object getData(Artifact artifact, CallContext context) {
@@ -71,7 +73,7 @@
             data.add(m.getDiameter(diameter)*1000);
         }
         BedDiameterData bdd = new BedDiameterData(diameter, kms, data);
-        return bdd;
+        return bdd.getDiameterData();
     }
 
     /** Copy deeply. */
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -37,6 +37,8 @@
     public BedloadDiameterFacet(int idx, String name, String description,
         ComputeType type, String stateId, String hash) {
         super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedquality.yaxis.label");
     }
 
     public Object getData(Artifact artifact, CallContext context) {
@@ -48,11 +50,15 @@
             stateId, type, false);
 
         int ndx = index >> 8;
-        Object[] data =
+        Object[] raw =
             ((BedQualityResult[]) res.getData())[ndx].getBedloadResults(); // TODO CAST TO SPECIFIC CLASS
 
         int ndy = index & 255;
-        return data != null && data.length > ndy ? data[ndy] : null;
+        if (raw != null && raw.length > ndy) {
+            BedloadDiameterResult data = (BedloadDiameterResult)raw[ndy];
+            return data.getDiameterData();
+        }
+        return null;
     }
 
     /** Copy deeply. */
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/FlowVelocityMeasurementFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/FlowVelocityMeasurementFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -29,6 +29,8 @@
         this.name = name;
         this.description = description;
         this.index = 0;
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.flow_velocity.section.yaxis.label");
     }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MiddleBedHeightCalculation.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,166 @@
+/* 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.minfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.river.model.BedHeightSingle;
+import org.dive4elements.river.model.BedHeightSingleValue;
+import org.dive4elements.river.artifacts.access.BedHeightAccess;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.minfo.MiddleBedHeightData;
+
+
+public class MiddleBedHeightCalculation extends Calculation {
+
+    private static final Logger logger =
+        Logger.getLogger(MiddleBedHeightCalculation.class);
+
+
+    public CalculationResult calculate(BedHeightAccess access) {
+        logger.info("MiddleBedHeightCalculation.calculate");
+
+        int[] singleIds = access.getBedHeightSingleIDs();
+
+
+        if (logger.isDebugEnabled()) {
+            Artifact artifact = access.getArtifact();
+
+            logger.debug("Artifact '" + artifact.identifier() + "' contains:");
+            if (singleIds != null) {
+                logger.debug("   " + singleIds.length + " single bedheight ids");
+            }
+        }
+
+        List<BedHeightSingle> singles = getSingles(access, singleIds);
+
+        return buildCalculationResult(access, singles);
+    }
+
+
+    protected List<BedHeightSingle> getSingles(
+        BedHeightAccess access,
+        int[] ids
+    ) {
+        List<BedHeightSingle> singles = new ArrayList<BedHeightSingle>();
+
+        for (int id: ids) {
+            BedHeightSingle s = BedHeightSingle.getBedHeightSingleById(id);
+
+            if (s != null) {
+                singles.add(s);
+            }
+            else {
+                logger.warn("Cannot find Single by id: " + id);
+                // TODO ADD WARNING
+            }
+        }
+
+        return singles;
+    }
+
+
+    protected CalculationResult buildCalculationResult(
+        BedHeightAccess       access,
+        List<BedHeightSingle> singles
+    ) {
+        logger.info("MiddleBedHeightCalculation.buildCalculationResult");
+
+        double kmLo = access.getLowerKM();
+        double kmHi = access.getUpperKM();
+
+        List<MiddleBedHeightData> data = new ArrayList<MiddleBedHeightData>();
+
+        for (BedHeightSingle single: singles) {
+            MiddleBedHeightData d = prepareSingleData(single, kmLo, kmHi);
+
+            if (d != null) {
+                data.add(d);
+            }
+        }
+
+        logger.debug("Calculation results in " + data.size() + " data objects.");
+
+        return new CalculationResult((MiddleBedHeightData[])
+            data.toArray(new MiddleBedHeightData[data.size()]), this);
+    }
+
+
+    protected MiddleBedHeightData prepareSingleData(
+        BedHeightSingle single,
+        double kmLo,
+        double kmHi
+    ) {
+        logger.debug("Prepare data for single: " + single.getDescription());
+
+        List<BedHeightSingleValue> values =
+            BedHeightSingleValue.getBedHeightSingleValues(single, kmLo, kmHi);
+
+        int year = single.getYear() != null ? single.getYear() : 0;
+
+        String curElevModel = single.getCurElevationModel() != null ?
+            single.getCurElevationModel().getName() : "";
+        String oldElevModel = single.getOldElevationModel() != null ?
+            single.getOldElevationModel().getName() : "";
+        String riverElevModel = single.getRiver().getWstUnit() != null ?
+            single.getRiver().getWstUnit().getName() : "";
+        String type = single.getType() != null ?
+            single.getType().getName() : "";
+        String locationSystem = single.getLocationSystem() != null ?
+            single.getLocationSystem().getName() : "";
+        MiddleBedHeightData data = new MiddleBedHeightData(
+            year,
+            year,
+            single.getEvaluationBy(),
+            single.getDescription(),
+            curElevModel,
+            oldElevModel,
+            riverElevModel,
+            type,
+            locationSystem,
+            single.getSoundingWidth());
+
+        for (BedHeightSingleValue value: values) {
+            if (value.getHeight() != null) {
+                double uncert = value.getUncertainty() != null ?
+                    value.getUncertainty().doubleValue() : Double.NaN;
+                double sounding = value.getSoundingWidth() != null ?
+                    value.getSoundingWidth().doubleValue() : Double.NaN;
+                double gap = value.getDataGap() != null ?
+                    value.getDataGap().doubleValue() : Double.NaN;
+                data.addAll(value.getStation().doubleValue(),
+                    value.getHeight().doubleValue(),
+                    uncert,
+                    sounding,
+                    gap,
+                    value.getWidth().doubleValue(),
+                    false);
+             }
+            else {
+                data.addAll(value.getStation().doubleValue(),
+                    0,
+                    0,
+                    0,
+                    0,
+                    0,
+                    true);
+            }
+        }
+
+        logger.debug("Single contains " + values.size() + " values");
+
+        return data;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MiddleBedHeightData.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,262 @@
+/* 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.minfo;
+
+import java.io.Serializable;
+
+import java.util.ArrayList;
+
+import gnu.trove.TDoubleArrayList;
+
+import org.dive4elements.artifacts.CallContext;
+
+import org.dive4elements.river.artifacts.resources.Resources;
+
+import org.apache.log4j.Logger;
+
+
+public class MiddleBedHeightData implements Serializable,
+                                            Comparable<MiddleBedHeightData> {
+
+    /** Very private logger. */
+    private static final Logger logger = Logger.getLogger(MiddleBedHeightData.class);
+
+    public static final String I18N_SINGLE_NAME = "facet.bedheight_middle.single";
+    public static final String I18N_EPOCH_NAME  = "facet.bedheight_middle.epoch";
+
+    private int    startYear;
+    private int    endYear;
+    private String evaluatedBy;
+    private String description;
+
+    private TDoubleArrayList km;
+    private TDoubleArrayList middleHeight;
+    private TDoubleArrayList uncertainty;
+    private TDoubleArrayList soundingWidth;
+    private TDoubleArrayList dataGap;
+    private TDoubleArrayList width;
+    private String type;
+    private String locationSystem;
+    private Integer soundWidth;
+    private String oldElevationModel;
+    private String curElevationModel;
+    private String riverElevationModel;
+    private ArrayList empty;
+
+
+    protected MiddleBedHeightData(int start, int end, String eval, String desc,
+        String curElevationModel, String oldElevationModel,
+        String riverElevationModel, String type,
+        String locationSystem, Integer soundingWidth) {
+        this.startYear   = start;
+        this.endYear     = end;
+        this.evaluatedBy = eval;
+        this.description = desc;
+        this.curElevationModel = curElevationModel;
+        this.oldElevationModel = oldElevationModel;
+        this.riverElevationModel = riverElevationModel;
+        this.type = type;
+        this.locationSystem = locationSystem;
+        this.soundWidth = soundingWidth;
+
+        this.km            = new TDoubleArrayList();
+        this.middleHeight  = new TDoubleArrayList();
+        this.uncertainty   = new TDoubleArrayList();
+        this.soundingWidth = new TDoubleArrayList();
+        this.dataGap       = new TDoubleArrayList();
+        this.width         = new TDoubleArrayList();
+        this.empty         = new ArrayList();
+    }
+
+    public void addAll(double station, double height, double uncertainty,
+        double soundingWidth, double dataGap, double width, boolean isEmpty) {
+        addKM(station);
+        addMiddleHeight(height);
+        addUncertainty(uncertainty);
+        addSoundingWidth(soundingWidth);
+        addDataGap(dataGap);
+        addWidth(width);
+        addIsEmpty(isEmpty);
+    }
+
+
+    public int getStartYear() {
+        return startYear;
+    }
+
+    public int getEndYear() {
+        return endYear;
+    }
+
+    public String getEvaluatedBy() {
+        return evaluatedBy;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public String getCurElevationModel() {
+        return this.curElevationModel;
+    }
+
+    public String getOldElevationModel() {
+        return this.oldElevationModel;
+    }
+
+    public String getRiverElevationModel() {
+        return this.riverElevationModel;
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    public String getLocationSystem() {
+        return this.locationSystem;
+    }
+
+    public String getSoundingWidth() {
+        return this.soundWidth.toString();
+    }
+    protected void addKM(double km) {
+        this.km.add(km);
+    }
+
+    public double getKM(int idx) {
+        return km.get(idx);
+    }
+
+    public TDoubleArrayList getStations() {
+        return this.km;
+    }
+
+    protected void addMiddleHeight(double middleHeight) {
+        this.middleHeight.add(middleHeight);
+    }
+
+    public double getMiddleHeight(int idx) {
+        return middleHeight.get(idx);
+    }
+
+    protected void addUncertainty(double uncertainty) {
+        this.uncertainty.add(uncertainty);
+    }
+
+    public double getUncertainty(int idx) {
+        return uncertainty.get(idx);
+    }
+
+    protected void addSoundingWidth(double soundingWidth) {
+        this.soundingWidth.add(soundingWidth);
+    }
+
+    public double getSoundingWidth(int idx) {
+        return soundingWidth.get(idx);
+    }
+
+    protected void addDataGap(double gap) {
+        this.dataGap.add(gap);
+    }
+
+    public double getDataGap(int idx) {
+        return dataGap.get(idx);
+    }
+
+    protected void addIsEmpty(boolean empty) {
+        this.empty.add(empty);
+    }
+
+    public boolean isEmpty(int idx) {
+        return (Boolean) empty.get(idx);
+    }
+
+
+    protected void addWidth(double width) {
+        this.width.add(width);
+    }
+
+    public double getWidth(int idx) {
+        return width.get(idx);
+    }
+
+    public int size() {
+        return km.size();
+    }
+
+
+    /**
+     * Get the points, ready to be drawn
+     * @return [[km1, km2,...],[height1,height2,...]]
+     */
+    public double[][] getMiddleHeightsPoints() {
+        double[][] points = new double[2][size()];
+
+        for (int i = 0, n = size(); i < n; i++) {
+            if (isEmpty(i)) {
+                points[0][i] = getKM(i);
+                points[1][i] = Double.NaN;
+            }
+            else {
+                points[0][i] = getKM(i);
+                points[1][i] = getMiddleHeight(i);
+            }
+        }
+
+        return points;
+    }
+
+
+    public String getSoundingName(CallContext context) {
+        if (getStartYear() == getEndYear()) {
+            return Resources.getMsg(
+                context.getMeta(),
+                I18N_SINGLE_NAME,
+                I18N_SINGLE_NAME,
+                new Object[] { getStartYear() }
+            );
+        }
+        else {
+            return Resources.getMsg(
+                context.getMeta(),
+                I18N_EPOCH_NAME,
+                I18N_EPOCH_NAME,
+                new Object[] { getStartYear(), getEndYear() }
+            );
+        }
+    }
+
+    @Override
+    public int compareTo(MiddleBedHeightData other) {
+
+        int descCompared = description.compareTo(other.getDescription());
+
+        if (descCompared != 0) {
+            return descCompared;
+        }
+
+        if (size() == 0 || other.size() == 0) {
+            if (size() == 0 && other.size() > 0) {
+                return 1;
+            } else if (size() > 0 && other.size() == 0) {
+                return -1;
+            } else if (size() == 0 && other.size() == 0) {
+               return 0;
+            }
+        }
+
+        if (getKM(0) < other.getKM(0)) {
+            return -1;
+        } else if (getKM(0) > other.getKM(0)) {
+            return 1;
+        }
+        return 0;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MiddleBedHeightFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,79 @@
+/* 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.minfo;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+
+import org.dive4elements.river.artifacts.D4EArtifact;
+
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+import org.apache.log4j.Logger;
+
+
+/**
+ * Facet of a MiddleBedHeight curve.
+ */
+public class MiddleBedHeightFacet extends DataFacet {
+
+    private static Logger logger = Logger.getLogger(MiddleBedHeightFacet.class);
+
+
+    public MiddleBedHeightFacet() {
+        // required for clone operation deepCopy()
+    }
+
+
+    public MiddleBedHeightFacet(
+        int         idx,
+        String      name,
+        String      description,
+        ComputeType type,
+        String      stateId,
+        String      hash
+    ) {
+        super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedheight_middle.section.yaxis.label");
+    }
+
+
+    public Object getData(Artifact artifact, CallContext context) {
+        logger.debug("Get data for middle bed height at index: " + index);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult)
+            flys.compute(context, hash, stateId, type, false);
+
+        MiddleBedHeightData[] resultData =
+            (MiddleBedHeightData[]) res.getData();
+        MiddleBedHeightData data = resultData[index];
+
+        return data.getMiddleHeightsPoints();
+    }
+
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        MiddleBedHeightFacet copy = new MiddleBedHeightFacet();
+        copy.set(this);
+        copy.type    = type;
+        copy.hash    = hash;
+        copy.stateId = stateId;
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MorphologicWidthFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MorphologicWidthFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -36,6 +36,8 @@
     public MorphologicWidthFacet(int idx, String name, String description,
         ComputeType type, String stateId, String hash) {
         super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.beddifference.yaxis.label.morph");
     }
 
     public Object getData(Artifact artifact, CallContext context) {
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/PorosityFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/PorosityFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -42,6 +42,8 @@
     public PorosityFacet(int idx, String name, String description,
         ComputeType type, String stateId, String hash) {
         super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedquality.yaxis.label.porosity");
     }
 
     public Object getData(Artifact artifact, CallContext context) {
@@ -52,7 +54,7 @@
         Porosity porosity =
             PorosityFactory.getPorosity(Integer.valueOf(porosity_id));
 
-        return porosity;
+        return porosity.getAsArray();
     }
 
     /** Copy deeply. */
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensityFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensityFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -39,6 +39,8 @@
     public SedimentDensityFacet(int idx, String name, String description,
         ComputeType type, String stateId, String hash) {
         super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.yaxis.label.sedimentdensity");
     }
 
     @Override
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -54,6 +54,8 @@
     public SedimentLoadFacet(int idx, String name, String description,
         ComputeType type, String stateId, String hash) {
         super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "");
     }
 
     @Override
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadUnknownFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadUnknownFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -22,6 +22,8 @@
     public SedimentLoadUnknownFacet(int idx, String name, String description,
         ComputeType type, String stateId, String hash) {
         super(idx, name, description, type, hash, stateId);
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "");
     }
 
     /** Get data from SedimentLoad with unknown type, from factory. */
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQCurveFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQCurveFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -58,6 +58,8 @@
     ) {
         super(idx, name, description, ComputeType.ADVANCE, hash, stateId);
         this.fractionIdx = fractionIdx;
+        this.metaData.put("X", "chart.sq_relation.xaxis.label");
+        this.metaData.put("Y", "chart.sq_relation.yaxis.label");
     }
 
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQMeasurementFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQMeasurementFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -49,6 +49,8 @@
     ) {
         super(idx, name, description, ComputeType.ADVANCE, hash, stateId);
         this.fractionIdx = fractionIdx;
+        this.metaData.put("X", "chart.sq_relation.xaxis.label");
+        this.metaData.put("Y", "chart.sq_relation.yaxis.label");
     }
 
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOutlierCurveFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOutlierCurveFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -53,6 +53,9 @@
     ) {
         super(idx, name, description, ComputeType.ADVANCE, hash, stateId);
         this.fractionIdx = fractionIdx;
+        this.metaData.put("X", "chart.sq_relation.xaxis.label");
+        this.metaData.put("Y", "chart.sq_relation.yaxis.label");
+
     }
 
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOutlierFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOutlierFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -49,6 +49,8 @@
     ) {
         super(idx, name, description, ComputeType.ADVANCE, hash, stateId);
         this.fractionIdx = fractionIdx;
+        this.metaData.put("X", "chart.sq_relation.xaxis.label");
+        this.metaData.put("Y", "chart.sq_relation.yaxis.label");
     }
 
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOutlierMeasurementFacet.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQOutlierMeasurementFacet.java	Tue Jul 08 18:19:04 2014 +0200
@@ -47,6 +47,8 @@
     ) {
         super(idx, name, description, ComputeType.ADVANCE, hash, stateId);
         this.fractionIdx = fractionIdx;
+        this.metaData.put("X", "chart.sq_relation.xaxis.label");
+        this.metaData.put("Y", "chart.sq_relation.yaxis.label");
     }
 
     @Override
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/MiddleBedHeight.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/MiddleBedHeight.java	Tue Jul 08 18:19:04 2014 +0200
@@ -22,9 +22,12 @@
 import org.dive4elements.river.artifacts.model.CalculationResult;
 import org.dive4elements.river.artifacts.model.DataFacet;
 import org.dive4elements.river.artifacts.model.FacetTypes;
-import org.dive4elements.river.artifacts.model.MiddleBedHeightData;
-import org.dive4elements.river.artifacts.model.MiddleBedHeightFacet;
-import org.dive4elements.river.artifacts.model.MiddleBedHeightCalculation;
+import org.dive4elements.river.artifacts.model.minfo.MiddleBedHeightCalculation;
+import org.dive4elements.river.artifacts.model.minfo.MiddleBedHeightData;
+import org.dive4elements.river.artifacts.model.minfo.MiddleBedHeightFacet;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.Unit;
 
 
 /** State in which Middle Bed Heights are generated. */
@@ -47,6 +50,8 @@
         List<Facet> newFacets = new ArrayList<Facet>();
 
         BedHeightAccess access = new BedHeightAccess(artifact);
+        River river = access.getRiver();
+        Unit u = river.getWstUnit();
 
         CalculationResult res = old instanceof CalculationResult
             ? (CalculationResult) old
@@ -65,24 +70,54 @@
 
         for (MiddleBedHeightData d: data) {
             if (d.getStartYear() == d.getEndYear()) {
-                newFacets.add(new MiddleBedHeightFacet(
+                MiddleBedHeightFacet mf = new MiddleBedHeightFacet(
                     idx,
                     MIDDLE_BED_HEIGHT_SINGLE,
                     d.getDescription(),
                     ComputeType.ADVANCE,
                     id,
                     hash
-                ));
+                );
+                mf.addMetaData(Resources.getMsg(
+                    context.getMeta(),
+                    "chart.bedheight_middle.export.curelev",
+                    "Current elevation model"),
+                    d.getCurElevationModel());
+                mf.addMetaData(Resources.getMsg(
+                    context.getMeta(),
+                    "chart.bedheight_middle.export.oldelev",
+                    "Old elevation model"),
+                    d.getOldElevationModel());
+                mf.addMetaData(Resources.getMsg(
+                    context.getMeta(),
+                    "chart.bedheight_middle.export.unit",
+                    "River elevation model"), u.getName());
+                newFacets.add(mf);
             }
             else {
-                newFacets.add(new MiddleBedHeightFacet(
+                MiddleBedHeightFacet mf = new MiddleBedHeightFacet(
                     idx,
                     MIDDLE_BED_HEIGHT_EPOCH,
                     d.getDescription(),
                     ComputeType.ADVANCE,
                     id,
                     hash
-                ));
+                );
+                mf.addMetaData(Resources.getMsg(
+                    context.getMeta(),
+                    "chart.bedheight_middle.export.curelev",
+                    "Current elevation model"),
+                    d.getCurElevationModel());
+                mf.addMetaData(Resources.getMsg(
+                    context.getMeta(),
+                    "chart.bedheight_middle.export.oldelev",
+                    "Old elevation model"),
+                    d.getOldElevationModel());
+                mf.addMetaData(Resources.getMsg(
+                    context.getMeta(),
+                    "chart.bedheight_middle.export.unit",
+                    "River elevation model"), u.getName());
+                newFacets.add(mf);
             }
 
             idx++;
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/BedQualityState.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/BedQualityState.java	Tue Jul 08 18:19:04 2014 +0200
@@ -25,12 +25,15 @@
 import org.dive4elements.river.artifacts.model.DataFacet;
 import org.dive4elements.river.artifacts.model.DateRange;
 import org.dive4elements.river.artifacts.model.FacetTypes;
-import org.dive4elements.river.artifacts.model.minfo.BedDensityFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDensityTopFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDensitySubFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDiameterTopFacet;
 import org.dive4elements.river.artifacts.model.minfo.BedDiameterDataFacet;
-import org.dive4elements.river.artifacts.model.minfo.BedDiameterFacet;
 import org.dive4elements.river.artifacts.model.minfo.BedDiameterResult;
+import org.dive4elements.river.artifacts.model.minfo.BedDiameterSubFacet;
 import org.dive4elements.river.artifacts.model.minfo.BedParametersResult;
-import org.dive4elements.river.artifacts.model.minfo.BedPorosityFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedPorositySubFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedPorosityTopFacet;
 import org.dive4elements.river.artifacts.model.minfo.BedQualityCalculation;
 import org.dive4elements.river.artifacts.model.minfo.BedQualityDiameterResult;
 import org.dive4elements.river.artifacts.model.minfo.BedQualityResult;
@@ -257,7 +260,7 @@
             DateRange range = result.getDateRange();
             BedDiameterResult[] bedDiameter = result.getBedResults();
             for (int j = 0; j < bedDiameter.length; j++) {
-                newFacets.add(new BedDiameterFacet((idx << 8) + j,
+                newFacets.add(new BedDiameterTopFacet((idx << 8) + j,
                     BED_QUALITY_BED_DIAMETER_TOPLAYER,
                     createDiameterTopLayerDescription(
                         meta,
@@ -265,7 +268,7 @@
                         range),
                     ComputeType.ADVANCE, stateId, hash));
 
-                newFacets.add(new BedDiameterFacet((idx << 8) +j,
+                newFacets.add(new BedDiameterSubFacet((idx << 8) +j,
                     BED_QUALITY_BED_DIAMETER_SUBLAYER,
                     createDiameterSubLayerDescription(
                         meta,
@@ -288,7 +291,7 @@
             if (bedDiameter.length > 0) {
                 BedParametersResult[] bedParameters = result.getParameters();
                 for (int j = 0; j < bedParameters.length; j++) {
-                    newFacets.add(new BedPorosityFacet((idx << 8) + j,
+                    newFacets.add(new BedPorosityTopFacet((idx << 8) + j,
                         BED_QUALITY_POROSITY_TOPLAYER,
                         createPorosityTopLayerDescription(
                             meta,
@@ -296,7 +299,7 @@
                             range),
                         ComputeType.ADVANCE, stateId, hash));
 
-                    newFacets.add(new BedPorosityFacet((idx << 8) + j,
+                    newFacets.add(new BedPorositySubFacet((idx << 8) + j,
                         BED_QUALITY_POROSITY_SUBLAYER,
                         createPorositySubLayerDescription(
                             meta,
@@ -304,7 +307,7 @@
                             range),
                         ComputeType.ADVANCE, stateId, hash));
 
-                    newFacets.add(new BedDensityFacet((idx << 8) + j,
+                    newFacets.add(new BedDensityTopFacet((idx << 8) + j,
                         BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER,
                         createDensityTopLayerDescription(
                             meta,
@@ -312,7 +315,7 @@
                             range),
                         ComputeType.ADVANCE, stateId, hash));
 
-                    newFacets.add(new BedDensityFacet((idx << 8) + j,
+                    newFacets.add(new BedDensitySubFacet((idx << 8) + j,
                         BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER,
                         createDensitySubLayerDescription(
                             meta,
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferencesState.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferencesState.java	Tue Jul 08 18:19:04 2014 +0200
@@ -25,8 +25,17 @@
 import org.dive4elements.river.artifacts.model.DataFacet;
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.artifacts.model.minfo.BedDiffCalculation;
-import org.dive4elements.river.artifacts.model.minfo.BedDiffYearFacet;
-import org.dive4elements.river.artifacts.model.minfo.BedDiffYearFilterFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDiffFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDiffHeightMinFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDiffHeightMinFilterFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDiffHeightSubFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDiffHeightSubFilterFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDiffMorphMinFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDiffMorphSubFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDiffPerYearFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDiffPerYearFilterFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDiffSoundingWidthFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedDiffFilterFacet;
 import org.dive4elements.river.artifacts.model.minfo.BedDiffYearResult;
 import org.dive4elements.river.artifacts.model.minfo.BedDifferencesResult;
 import org.dive4elements.river.artifacts.resources.Resources;
@@ -112,7 +121,7 @@
         newFacets.add(new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, hash, id));
         for (int idx = 0; idx < results.length; idx++) {
             if (results[idx] instanceof BedDiffYearResult) {
-                newFacets.add(new BedDiffYearFacet(
+                newFacets.add(new BedDiffFacet(
                     idx,
                     BED_DIFFERENCE_YEAR,
                     createBedDiffYearDescription(
@@ -122,28 +131,28 @@
                     ComputeType.ADVANCE,
                     stateId,
                     hash));
-                newFacets.add(new BedDiffYearFacet(
+                newFacets.add(new BedDiffSoundingWidthFacet(
                     idx,
                     BED_DIFFERENCE_SOUNDING_WIDTH,
                     createBedDiffSoundingDescription(meta),
                     ComputeType.ADVANCE,
                     stateId,
                     hash));
-                newFacets.add(new BedDiffYearFacet(
+                newFacets.add(new BedDiffMorphMinFacet(
                     idx,
                     BED_DIFFERENCE_MORPH_WIDTH1,
                     createBedDiffMorph1Description(meta),
                     ComputeType.ADVANCE,
                     stateId,
                     hash));
-                newFacets.add(new BedDiffYearFacet(
+                newFacets.add(new BedDiffMorphSubFacet(
                     idx,
                     BED_DIFFERENCE_MORPH_WIDTH2,
                     createBedDiffMorph2Description(meta),
                     ComputeType.ADVANCE,
                     stateId,
                     hash));
-                newFacets.add(new BedDiffYearFacet(
+                newFacets.add(new BedDiffHeightMinFacet(
                     idx,
                     BED_DIFFERENCE_YEAR_HEIGHT1,
                     createBedDiffHeightDescription(
@@ -154,7 +163,7 @@
                     ComputeType.ADVANCE,
                     stateId,
                     hash));
-                 newFacets.add(new BedDiffYearFacet(
+                 newFacets.add(new BedDiffHeightSubFacet(
                     idx,
                     BED_DIFFERENCE_YEAR_HEIGHT2,
                     createBedDiffHeightDescription(
@@ -165,7 +174,7 @@
                     ComputeType.ADVANCE,
                     stateId,
                     hash));
-                newFacets.add(new BedDiffYearFacet(
+                newFacets.add(new BedDiffPerYearFacet(
                     idx,
                     BED_DIFFERENCE_HEIGHT_YEAR,
                     createBedDiffAbsoluteDescription(
@@ -175,7 +184,7 @@
                     ComputeType.ADVANCE,
                     stateId,
                     hash));
-                newFacets.add(new BedDiffYearFilterFacet(
+                newFacets.add(new BedDiffFilterFacet(
                     idx,
                     BED_DIFFERENCE_YEAR_FILTERED,
                     createBedDiffYearDescription(
@@ -185,7 +194,7 @@
                     ComputeType.ADVANCE,
                     stateId,
                     hash));
-                newFacets.add(new BedDiffYearFilterFacet(
+                newFacets.add(new BedDiffHeightMinFilterFacet(
                     idx,
                     BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED,
                     createBedDiffHeightDescription(
@@ -196,7 +205,7 @@
                     ComputeType.ADVANCE,
                     stateId,
                     hash));
-                 newFacets.add(new BedDiffYearFilterFacet(
+                 newFacets.add(new BedDiffHeightSubFilterFacet(
                     idx,
                     BED_DIFFERENCE_YEAR_HEIGHT2_FILTERED,
                     createBedDiffHeightDescription(
@@ -207,7 +216,7 @@
                     ComputeType.ADVANCE,
                     stateId,
                     hash));
-                newFacets.add(new BedDiffYearFilterFacet(
+                newFacets.add(new BedDiffPerYearFilterFacet(
                     idx,
                     BED_DIFFERENCE_HEIGHT_YEAR_FILTERED,
                     createBedDiffAbsoluteDescription(
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ChartExportHelper.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartExportHelper.java	Tue Jul 08 18:19:04 2014 +0200
@@ -20,8 +20,6 @@
 import java.awt.Graphics2D;
 import java.awt.Transparency;
 
-import java.awt.geom.Rectangle2D.Double;
-
 import java.awt.geom.Rectangle2D;
 
 import java.io.IOException;
@@ -30,6 +28,7 @@
 import java.io.UnsupportedEncodingException;
 
 import java.text.NumberFormat;
+import java.util.Map;
 
 import org.jfree.chart.ChartRenderingInfo;
 
@@ -50,6 +49,7 @@
 
 import org.dive4elements.artifacts.common.utils.XMLUtils;
 
+import org.dive4elements.river.jfree.XYMetaSeriesCollection;
 import org.dive4elements.river.utils.Formatter;
 
 
@@ -317,7 +317,11 @@
             for (int j = 0; j < scount; j++) {
                 Comparable seriesKey = data.getSeriesKey(j);
                 log.debug("series key: " + seriesKey.toString());
-                writeCSVHeader(writer, seriesKey.toString());
+                Map<String, String> metaData = null;
+                if (data instanceof XYMetaSeriesCollection) {
+                    metaData = ((XYMetaSeriesCollection) data).getMetaData();
+                }
+                writeCSVHeader(writer, seriesKey.toString(), metaData);
                 writeCSVData(writer, data, format);
             }
         }
@@ -330,11 +334,31 @@
     }
 
 
-    protected static void writeCSVHeader(CSVWriter writer, String key) {
+    protected static void writeCSVHeader(
+        CSVWriter writer,
+        String key,
+        Map<String, String> metaData)
+    {
         writer.writeNext(new String[] {"#"});
-        writer.writeNext(new String[] {"# " + key});
-        writer.writeNext(new String[] {"#"});
-        writer.writeNext(new String[] {"X", "Y"});
+        if (metaData != null) {
+            writer.writeNext(new String[] {"# " + key});
+            for (Map.Entry<String, String> entry: metaData.entrySet()) {
+                if (entry.getKey().equals("X") || entry.getKey().equals("Y")) {
+                    continue;
+                }
+                writer.writeNext(new String[]
+                    {"# " + entry.getKey() + ": " + entry.getValue()});
+            }
+            writer.writeNext(new String[] {"#"});
+            writer.writeNext(new String[] {
+                metaData.get("X") != null ? metaData.get("X") : "X",
+                metaData.get("Y") != null ? metaData.get("Y") : "Y"});
+        }
+        else {
+            writer.writeNext(new String[] {"# " + key});
+            writer.writeNext(new String[] {"#"});
+            writer.writeNext(new String[] {"X", "Y"});
+        }
     }
 
 
--- a/artifacts/src/main/java/org/dive4elements/river/exports/DiagramGenerator.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/DiagramGenerator.java	Tue Jul 08 18:19:04 2014 +0200
@@ -44,6 +44,7 @@
 import org.dive4elements.river.jfree.Bounds;
 import org.dive4elements.river.jfree.DoubleBounds;
 import org.dive4elements.river.jfree.StyledAreaSeriesCollection;
+import org.dive4elements.river.jfree.XYMetaSeriesCollection;
 
 import org.dive4elements.river.themes.ThemeDocument;
 import org.dive4elements.river.utils.RiverUtils;
@@ -494,7 +495,7 @@
         logger.debug("Y Range of XYSeries: " +
             series.getMinY() + " | " + series.getMaxY());
 
-        addAxisDataset(new XYSeriesCollection(series), index, visible);
+        addAxisDataset(new XYMetaSeriesCollection(series), index, visible);
     }
 
     /**
--- a/artifacts/src/main/java/org/dive4elements/river/exports/MiddleBedHeightExporter.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/MiddleBedHeightExporter.java	Tue Jul 08 18:19:04 2014 +0200
@@ -22,7 +22,7 @@
 
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.model.CalculationResult;
-import org.dive4elements.river.artifacts.model.MiddleBedHeightData;
+import org.dive4elements.river.artifacts.model.minfo.MiddleBedHeightData;
 
 import org.dive4elements.river.model.River;
 
@@ -63,6 +63,32 @@
     public static final String CSV_LOCATIONS =
         "export.bedheight_middle.csv.header.locations";
 
+    public static final String CSV_META_YEAR =
+        "export.bedheight_middle.csv.header.year";
+
+    public static final String CSV_META_TYPE =
+        "export.bedheight_middle.csv.header.type";
+
+    public static final String CSV_META_CUR_ELEV_MODEL =
+        "export.bedheight_middle.csv.header.cur.elevation";
+
+    public static final String CSV_META_OLD_ELEV_MODEL =
+        "export.bedheight_middle.csv.header.old.elevation";
+
+    public static final String CSV_META_RIVER_ELEV_MODEL =
+        "export.bedheight_middle.csv.header.river.elevation";
+
+    public static final String CSV_META_SOUNDING_WIDTH =
+        "export.bedheight_middle.csv.header.sounding.width";
+
+    public static final String CSV_META_RANGE =
+        "export.bedheight_middle.csv.header.range";
+
+    public static final String CSV_META_LOC_SYSTEM =
+        "export.bedheight_middle.csv.header.location.system";
+
+    public static final String CSV_META_EVAL_BY =
+        "export.bedheight_middle.csv.header.evalby";
 
     protected List<MiddleBedHeightData> data;
 
@@ -90,7 +116,6 @@
         logger.info("MiddleBedHeightExporter.writeCSVData");
         logger.debug("CSV gets " + data.size() + " MiddleBedHeightData objects.");
 
-        writeCSVHeader(writer);
 
         Collections.sort(data);
 
@@ -121,6 +146,10 @@
 
         D4EArtifact flys = (D4EArtifact) master;
 
+        writeMetaData(writer, data);
+
+        writeCSVHeader(writer);
+
         NumberFormat kmF     = Formatter.getMiddleBedHeightKM(context);
         NumberFormat heightF = Formatter.getMiddleBedHeightHeight(context);
         NumberFormat uncertF = Formatter.getMiddleBedHeightUncert(context);
@@ -176,6 +205,33 @@
     }
 
 
+    private void writeMetaData(CSVWriter writer, MiddleBedHeightData data) {
+         writer.writeNext(new String[]{"#"});
+         String year = "";
+         if (data.getStartYear() != 0) {
+             year = String.valueOf(data.getStartYear());
+         }
+         writer.writeNext(new String[]{"# " + msg(CSV_META_YEAR) +
+             ": " + year});
+         writer.writeNext(new String[]{"# " + msg(CSV_META_TYPE) +
+             ": " + data.getType()});
+         writer.writeNext(new String[]{"# " + msg(CSV_META_LOC_SYSTEM) +
+             ": " + data.getLocationSystem()});
+         writer.writeNext(new String[]{"# " + msg(CSV_META_CUR_ELEV_MODEL) +
+             ": " + data.getCurElevationModel()});
+         writer.writeNext(new String[]{"# " + msg(CSV_META_OLD_ELEV_MODEL) +
+             ": " + data.getOldElevationModel()});
+         writer.writeNext(new String[]{"# " + msg(CSV_META_RIVER_ELEV_MODEL) +
+             ": " + data.getRiverElevationModel()});
+         writer.writeNext(new String[]{"# " + msg(CSV_META_SOUNDING_WIDTH) +
+             ": " + data.getSoundingWidth()});
+         writer.writeNext(new String[]{"# " + msg(CSV_META_RANGE) +
+             ": " + data.getStations().min() + " - " + data.getStations().max()});
+         writer.writeNext(new String[]{"# " + msg(CSV_META_EVAL_BY) +
+             ": " + data.getEvaluatedBy()});
+         writer.writeNext(new String[]{"#"});
+    }
+
     @Override
     protected void writePDF(OutputStream out) {
         logger.error("TODO: Implement FlowVelocityExporter.writePDF");
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffHeightYearProcessor.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffHeightYearProcessor.java	Tue Jul 08 18:19:04 2014 +0200
@@ -8,6 +8,8 @@
 
 package org.dive4elements.river.exports.process;
 
+import java.util.Map;
+
 import org.apache.log4j.Logger;
 import org.jfree.data.xy.XYSeries;
 
@@ -47,15 +49,36 @@
             DiagramGenerator generator,
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
-            boolean          visible) {
+            boolean          visible
+    ) {
         CallContext context = generator.getCallContext();
         Object data = bundle.getData(context);
+        Map<String, String> metaData = bundle.getFacet().getMetaData(
+            bundle.getArtifact(), context);
 
-        if (!(data instanceof BedDiffYearResult)) {
+        if (!(data instanceof double[][])) {
             // Should not happen if canHandle is correct
             logger.error("Can't process " + data.getClass().getName() + " objects");
             return;
         }
+
+        setSubtitleRadius(generator, bundle, context);
+
+        double[][] bData = (double[][]) data;
+
+        StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
+        series.putMetaData(metaData, bundle.getArtifact(), context);
+
+        StyledSeriesBuilder.addPoints(series, bData, false, GAP_TOLERANCE);
+
+        generator.addAxisSeries(series, axisName, visible);
+    }
+
+    private void setSubtitleRadius(
+        DiagramGenerator generator,
+        ArtifactAndFacet bundle,
+        CallContext context
+    ) {
         Double start = (Double)context.getContextValue("startkm");
         Double end = (Double)context.getContextValue("endkm");
         if (start != null && end != null) {
@@ -72,11 +95,6 @@
                 I18N_SUBTITLE_RADIUS,
                 new Object[] { radius }));
         }
-        BedDiffYearResult bData = (BedDiffYearResult) data;
-        XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
-        StyledSeriesBuilder.addPoints(series, bData.getHeightPerYearData(), false, GAP_TOLERANCE);
-
-        generator.addAxisSeries(series, axisName, visible);
     }
 
     @Override
@@ -90,15 +108,15 @@
         CallContext context = generator.getCallContext();
         Object data = bundle.getData(context);
 
-        if (!(data instanceof BedDiffYearResult)) {
+        if (!(data instanceof double[][])) {
             // Should not happen if canHandle is correct
             logger.error("Can't process " + data.getClass().getName() + " objects");
             return;
         }
 
-        BedDiffYearResult bData = (BedDiffYearResult) data;
+        double[][] bData = (double[][]) data;
         XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
-        StyledSeriesBuilder.addPoints(series, bData.getHeightPerYearData(), false, GAP_TOLERANCE);
+        StyledSeriesBuilder.addPoints(series, bData, false, GAP_TOLERANCE);
 
         generator.addAxisSeries(series, index, visible);
     }
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffYearProcessor.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffYearProcessor.java	Tue Jul 08 18:19:04 2014 +0200
@@ -8,9 +8,9 @@
 
 package org.dive4elements.river.exports.process;
 
+import java.util.Map;
+
 import org.apache.log4j.Logger;
-import org.jfree.data.xy.XYSeries;
-
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.D4EArtifact;
@@ -18,7 +18,6 @@
 import org.dive4elements.river.artifacts.context.RiverContext;
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.artifacts.model.ZoomScale;
-import org.dive4elements.river.artifacts.model.minfo.BedDiffYearResult;
 import org.dive4elements.river.artifacts.resources.Resources;
 import org.dive4elements.river.exports.StyledSeriesBuilder;
 import org.dive4elements.river.exports.DiagramGenerator;
@@ -34,6 +33,8 @@
 
     protected static double GAP_TOLERANCE = 0.101d;
 
+    protected String yAxisLabel;
+
     public static final String I18N_AXIS_LABEL =
         "chart.beddifference.yaxis.label.diff";
     public static final String I18N_AXIS_LABEL_DEFAULT =
@@ -46,41 +47,60 @@
             DiagramGenerator generator,
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
-            boolean          visible) {
+            boolean          visible
+    ) {
         CallContext context = generator.getCallContext();
-        Object data = bundle.getData(context);
-        if (data instanceof BedDiffYearResult) {
-            Double start = (Double)context.getContextValue("startkm");
-            Double end = (Double)context.getContextValue("endkm");
-            if (start != null && end != null) {
-                D4EArtifact artifact = (D4EArtifact)bundle.getArtifact();
-                RiverContext fc = (RiverContext)context.globalContext();
-                // Adaptive smoothing, based on zoom factor/diagram extents.
-                ZoomScale scales = (ZoomScale)fc.get("zoomscale");
-                RiverAccess access = new RiverAccess((D4EArtifact)artifact);
-                String river = access.getRiverName();
+        Map<String, String> metaData =
+            bundle.getFacet().getMetaData(bundle.getArtifact(), context);
+        yAxisLabel = metaData.get("Y");
 
-                double radius = scales.getRadius(river, start, end);
-                generator.addSubtitle(Resources.getMsg(
-                    context.getMeta(),
-                    I18N_SUBTITLE_RADIUS,
-                    new Object[] { radius }));
-            }
-            String facetType = bundle.getFacetName();
-            BedDiffYearResult bData = (BedDiffYearResult) data;
+        setSubtitleRadius(generator, bundle, context);
 
-            XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
-            StyledSeriesBuilder.addPointsFactorY(series,
-                bData.getDifferencesData(),
-                false,
-                GAP_TOLERANCE,
-                100d);
-
-            generator.addAxisSeries(series, axisName, visible);
-
+        Object data = bundle.getData(context);
+        if (data == null) {
             return;
         }
-        logger.error("Can't process " + data.getClass().getName() + " objects");
+
+        if (!(data instanceof double[][])) {
+            logger.error("Can't process " + data.getClass().getName() + " objects");
+            return;
+        }
+        double[][] bData = (double[][]) data;
+
+        StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
+        series.putMetaData(metaData, bundle.getArtifact(), context);
+        StyledSeriesBuilder.addPointsFactorY(series,
+            bData,
+            false,
+            GAP_TOLERANCE,
+            100d);
+
+        generator.addAxisSeries(series, axisName, visible);
+
+        return;
+    }
+
+    private void setSubtitleRadius(
+        DiagramGenerator generator,
+        ArtifactAndFacet bundle,
+        CallContext context
+    ) {
+        Double start = (Double)context.getContextValue("startkm");
+        Double end = (Double)context.getContextValue("endkm");
+        if (start != null && end != null) {
+            D4EArtifact artifact = (D4EArtifact)bundle.getArtifact();
+            RiverContext fc = (RiverContext)context.globalContext();
+            // Adaptive smoothing, based on zoom factor/diagram extents.
+            ZoomScale scales = (ZoomScale)fc.get("zoomscale");
+            RiverAccess access = new RiverAccess((D4EArtifact)artifact);
+            String river = access.getRiverName();
+
+            double radius = scales.getRadius(river, start, end);
+            generator.addSubtitle(Resources.getMsg(
+                context.getMeta(),
+                I18N_SUBTITLE_RADIUS,
+                new Object[] { radius }));
+        }
     }
 
     @Override
@@ -91,9 +111,12 @@
 
     @Override
     public String getAxisLabel(DiagramGenerator generator) {
+        if (yAxisLabel != null && !yAxisLabel.isEmpty()) {
+            return generator.msg(yAxisLabel, I18N_AXIS_LABEL_DEFAULT);
+        }
         return generator.msg(
-                I18N_AXIS_LABEL,
-                I18N_AXIS_LABEL_DEFAULT);
+            I18N_AXIS_LABEL,
+            I18N_AXIS_LABEL_DEFAULT);
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedHeightProcessor.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedHeightProcessor.java	Tue Jul 08 18:19:04 2014 +0200
@@ -8,7 +8,7 @@
 
 package org.dive4elements.river.exports.process;
 
-import java.util.List;
+import java.util.Map;
 
 import org.apache.log4j.Logger;
 import org.jfree.data.xy.XYSeries;
@@ -16,16 +16,13 @@
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.D4EArtifact;
-import org.dive4elements.river.artifacts.model.minfo.BedHeightSingleData;
-import org.dive4elements.river.artifacts.model.minfo.BedDiffYearResult;
+import org.dive4elements.river.artifacts.access.RiverAccess;
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.exports.XYChartGenerator;
 import org.dive4elements.river.exports.DiagramGenerator;
 import org.dive4elements.river.exports.StyledSeriesBuilder;
 import org.dive4elements.river.jfree.StyledXYSeries;
-import org.dive4elements.river.model.BedHeightSingleValue;
 import org.dive4elements.river.themes.ThemeDocument;
-import org.dive4elements.river.utils.RiverUtils;
 
 public class BedHeightProcessor extends DefaultProcessor {
 
@@ -39,6 +36,8 @@
 
     protected static final double GAP_TOLERANCE = 0.101d;
 
+    protected String yAxisLabel;
+
     @Override
     public void doOut(
             DiagramGenerator generator,
@@ -46,7 +45,9 @@
             ThemeDocument    theme,
             boolean          visible) {
         XYSeries series = prepareSeries(bundle, theme, generator.getCallContext());
-        generator.addAxisSeries(series, axisName, visible);
+        if (series != null) {
+            generator.addAxisSeries(series, axisName, visible);
+        }
     }
 
     @Override
@@ -58,64 +59,39 @@
             int index
     ) {
         XYSeries series = prepareSeries(bundle, theme, generator.getCallContext());
-        generator.addAxisSeries(series, index, visible);
+        if (series != null) {
+            generator.addAxisSeries(series, index, visible);
+        }
     }
 
     /** Prepare an series, independent of axis. */
-    private XYSeries prepareSeries(ArtifactAndFacet bundle,
-        ThemeDocument theme, CallContext context) {
-        Object data = bundle.getData(context);
-        XYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
+    private XYSeries prepareSeries(
+        ArtifactAndFacet bundle,
+        ThemeDocument theme,
+        CallContext context
+    ) {
+        Map<String, String> metaData = bundle.getFacet().getMetaData(
+            bundle.getArtifact(), context);
+        StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 theme);
-        if (data instanceof BedDiffYearResult) {
-            BedDiffYearResult bData = (BedDiffYearResult) data;
-
-            double[][] points;
-            String facetType = bundle.getFacetName();
-
-            if (FacetTypes.BED_DIFFERENCE_YEAR_HEIGHT1.equals(facetType) ||
-                FacetTypes.BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED.equals(facetType)) {
-                points = bData.getHeights1Data();
-            } else {
-                points = bData.getHeights2Data();
-            }
-            StyledSeriesBuilder.addPointsFactorY(series,
-                    points,
-                    false,
-                    GAP_TOLERANCE,
-                    1d);
-        } else if (data instanceof BedHeightSingleData) {
-            BedHeightSingleData bData = (BedHeightSingleData)data;
-            double[][] points = new double[][]
-                {bData.getStations().toNativeArray(), bData.getHeights()};
+        series.putMetaData(metaData, bundle.getArtifact(), context);
+        yAxisLabel = metaData.get("Y");
 
-            logger.debug("doBedheightSingleOut");
-            StyledSeriesBuilder.addPointsFactorY(series,
-                    points,
-                    false,
-                    GAP_TOLERANCE,
-                    1d);
+        Object raw = bundle.getData(context);
+        if (raw == null) {
+            return null;
         }
-        else if (data instanceof List<?>) {
-            List<BedHeightSingleValue> bData = (List<BedHeightSingleValue>)data;
-            double[][] points = new double[2][];
-
-            logger.debug("doBedheightSingleValueOut");
+        if (!(raw instanceof double[][])) {
+            logger.error("Unkown datatype: " + raw.getClass().getName());
+            return null;
+        }
 
-            for(int i = 0; i < bData.size(); i++) {
-                BedHeightSingleValue bvalue = bData.get(i);
-                points[0][i] = bvalue.getStation();
-                points[1][i] = bvalue.getHeight();
-            }
-            StyledSeriesBuilder.addPointsFactorY(series,
-                    points,
-                    false,
-                    GAP_TOLERANCE,
-                    1d);
-        }
-        else {
-            logger.error("Unknown data type " + data.getClass());
-        }
+        double[][] data = (double[][])raw;
+        StyledSeriesBuilder.addPointsFactorY(series,
+            data,
+            false,
+            GAP_TOLERANCE,
+            1d);
         return series;
     }
 
@@ -133,8 +109,15 @@
     public String getAxisLabel(DiagramGenerator generator) {
         D4EArtifact flys = (D4EArtifact) generator.getMaster();
 
-        String unit = RiverUtils.getRiver(flys).getWstUnit().getName();
+        RiverAccess access = new RiverAccess(flys);
+        String unit = access.getRiver().getWstUnit().getName();
 
+        if (yAxisLabel != null && !yAxisLabel.isEmpty()) {
+            return generator.msg(
+                yAxisLabel,
+                I18N_AXIS_LABEL_DEFAULT,
+                new Object[] {unit});
+        }
         return generator.msg(
                 I18N_AXIS_LABEL,
                 I18N_AXIS_LABEL_DEFAULT,
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedQualityDensityProcessor.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedQualityDensityProcessor.java	Tue Jul 08 18:19:04 2014 +0200
@@ -8,9 +8,9 @@
 
 package org.dive4elements.river.exports.process;
 
+import java.util.Map;
+
 import org.apache.log4j.Logger;
-import org.jfree.data.xy.XYSeries;
-
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.model.FacetTypes;
@@ -19,8 +19,6 @@
 import org.dive4elements.river.jfree.StyledXYSeries;
 import org.dive4elements.river.themes.ThemeDocument;
 
-import org.dive4elements.river.artifacts.model.minfo.BedParametersResult;
-
 public class BedQualityDensityProcessor extends DefaultProcessor {
 
     private final static Logger logger =
@@ -31,6 +29,7 @@
     public static final String I18N_AXIS_LABEL =
         "chart.bedquality.yaxis.label.density";
 
+    protected String yAxisLabel;
     @Override
     public void doOut(
             DiagramGenerator generator,
@@ -38,21 +37,23 @@
             ThemeDocument    theme,
             boolean          visible) {
         CallContext context = generator.getCallContext();
-        XYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
+        StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 theme);
-        Object data = bundle.getData(context);
-        String facetName = bundle.getFacetName();
-        double [][] points;
+        Map<String, String> metaData = bundle.getFacet().getMetaData();
+        series.putMetaData(metaData, bundle.getArtifact(), context);
+        yAxisLabel = metaData.get("Y");
 
-        if (facetName.equals(FacetTypes.BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER)) {
-            points = ((BedParametersResult) data).getDensityCapData();
-        } else if (facetName.equals(FacetTypes.BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER)) {
-            points = ((BedParametersResult) data).getDensitySubData();
-        } else {
-            logger.error("Unknown facet name: " + facetName);
+        Object data = bundle.getData(context);
+        if (data == null) {
             return;
         }
-        StyledSeriesBuilder.addPoints(series, points, true);
+        if (!(data instanceof double[][])) {
+            logger.error("Unknown data type: " + data.getClass().getName());
+            return;
+        }
+
+        double[][] values = (double[][])data;
+        StyledSeriesBuilder.addPoints(series, values, true);
 
         generator.addAxisSeries(series, axisName, visible);
     }
@@ -65,6 +66,9 @@
 
     @Override
     public String getAxisLabel(DiagramGenerator generator) {
+        if (yAxisLabel != null && !yAxisLabel.isEmpty()) {
+            return generator.msg(yAxisLabel, I18N_AXIS_LABEL_DEFAULT);
+        }
         return generator.msg(
                 I18N_AXIS_LABEL,
                 I18N_AXIS_LABEL_DEFAULT);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedQualityDiameterProcessor.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedQualityDiameterProcessor.java	Tue Jul 08 18:19:04 2014 +0200
@@ -8,9 +8,9 @@
 
 package org.dive4elements.river.exports.process;
 
+import java.util.Map;
+
 import org.apache.log4j.Logger;
-import org.jfree.data.xy.XYSeries;
-
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.model.FacetTypes;
@@ -19,10 +19,6 @@
 import org.dive4elements.river.jfree.StyledXYSeries;
 import org.dive4elements.river.themes.ThemeDocument;
 
-import org.dive4elements.river.artifacts.model.minfo.BedDiameterData;
-import org.dive4elements.river.artifacts.model.minfo.BedDiameterResult;
-import org.dive4elements.river.artifacts.model.minfo.BedloadDiameterResult;
-
 public class BedQualityDiameterProcessor extends DefaultProcessor {
 
     private final static Logger logger =
@@ -33,6 +29,7 @@
     public static final String I18N_AXIS_LABEL =
         "chart.bedquality.yaxis.label.diameter";
 
+    protected String yAxisLabel;
     @Override
     public void doOut(
             DiagramGenerator generator,
@@ -40,27 +37,21 @@
             ThemeDocument    theme,
             boolean          visible) {
         CallContext context = generator.getCallContext();
-        XYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
+        Map<String, String> metaData = bundle.getFacet().getMetaData();
+        StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 theme);
+        series.putMetaData(metaData, bundle.getArtifact(), context);
+        yAxisLabel = metaData.get("Y");
         Object data = bundle.getData(context);
-        String facetName = bundle.getFacetName();
-        double [][] points;
-
-        if (facetName.equals(FacetTypes.BED_QUALITY_BED_DIAMETER_TOPLAYER)) {
-            points = ((BedDiameterResult) data).getDiameterCapData();
-        } else if (facetName.equals(FacetTypes.BED_QUALITY_BED_DIAMETER_SUBLAYER)) {
-            points = ((BedDiameterResult) data).getDiameterSubData();
-        } else if (facetName.equals(FacetTypes.BED_QUALITY_BEDLOAD_DIAMETER)) {
-            points = ((BedloadDiameterResult) data).getDiameterData();
-        } else if (facetName.equals(FacetTypes.BED_DIAMETER_DATA_TOP) ||
-                 facetName.equals(FacetTypes.BED_DIAMETER_DATA_SUB) ||
-                 facetName.equals(FacetTypes.BEDLOAD_DIAMETER_DATA)) {
-            points = ((BedDiameterData) data).getDiameterData();
-        } else {
-            logger.error("Unknown facet name: " + facetName);
+        if (data == null) {
             return;
         }
-        StyledSeriesBuilder.addPoints(series, points, true);
+        if (!(data instanceof double[][])) {
+            logger.error("Unknown data type: " + data.getClass().getName());
+            return;
+        }
+        double[][] values = (double[][])data;
+        StyledSeriesBuilder.addPoints(series, values, true);
 
         generator.addAxisSeries(series, axisName, visible);
     }
@@ -77,6 +68,9 @@
 
     @Override
     public String getAxisLabel(DiagramGenerator generator) {
+        if (yAxisLabel != null && !yAxisLabel.isEmpty()) {
+            return generator.msg(yAxisLabel, I18N_AXIS_LABEL_DEFAULT);
+        }
         return generator.msg(
                 I18N_AXIS_LABEL,
                 I18N_AXIS_LABEL_DEFAULT);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedQualityPorosityProcessor.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedQualityPorosityProcessor.java	Tue Jul 08 18:19:04 2014 +0200
@@ -8,9 +8,9 @@
 
 package org.dive4elements.river.exports.process;
 
+import java.util.Map;
+
 import org.apache.log4j.Logger;
-import org.jfree.data.xy.XYSeries;
-
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.model.FacetTypes;
@@ -19,9 +19,6 @@
 import org.dive4elements.river.jfree.StyledXYSeries;
 import org.dive4elements.river.themes.ThemeDocument;
 
-import org.dive4elements.river.artifacts.model.minfo.BedParametersResult;
-import org.dive4elements.river.artifacts.model.minfo.Porosity;
-
 public class BedQualityPorosityProcessor extends DefaultProcessor {
 
     private final static Logger logger =
@@ -32,6 +29,8 @@
     public static final String I18N_AXIS_LABEL =
         "chart.bedquality.yaxis.label.porosity";
 
+    protected String yAxisLabel;
+
     @Override
     public void doOut(
             DiagramGenerator generator,
@@ -39,23 +38,23 @@
             ThemeDocument    theme,
             boolean          visible) {
         CallContext context = generator.getCallContext();
-        XYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
+        Map<String, String> metaData = bundle.getFacet().getMetaData();
+        StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 theme);
-        Object data = bundle.getData(context);
-        String facetName = bundle.getFacetName();
-        double [][] points;
+        series.putMetaData(metaData, bundle.getArtifact(), context);
+        yAxisLabel = metaData.get("Y");
 
-        if (facetName.equals(FacetTypes.BED_QUALITY_POROSITY_TOPLAYER)) {
-            points = ((BedParametersResult) data).getPorosityCapData();
-        } else if (facetName.equals(FacetTypes.BED_QUALITY_POROSITY_SUBLAYER)) {
-            points = ((BedParametersResult) data).getPorositySubData();
-        } else if (facetName.equals(FacetTypes.POROSITY)) {
-            points = ((Porosity)data).getAsArray();
-        } else {
-            logger.error("Unknown facet name: " + facetName);
+        Object raw = bundle.getData(context);
+        if (raw == null) {
             return;
         }
-        StyledSeriesBuilder.addPoints(series, points, true);
+        if (!(raw instanceof double[][])) {
+            logger.error("Unknown data type: " + raw.getClass().getName());
+            return;
+        }
+
+        double[][] values = (double[][])raw;
+        StyledSeriesBuilder.addPoints(series, values, true);
 
         generator.addAxisSeries(series, axisName, visible);
     }
@@ -69,6 +68,9 @@
 
     @Override
     public String getAxisLabel(DiagramGenerator generator) {
+        if (yAxisLabel != null && !yAxisLabel.isEmpty()) {
+            return generator.msg(yAxisLabel, I18N_AXIS_LABEL_DEFAULT);
+        }
         return generator.msg(
                 I18N_AXIS_LABEL,
                 I18N_AXIS_LABEL_DEFAULT);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedWidthProcessor.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedWidthProcessor.java	Tue Jul 08 18:19:04 2014 +0200
@@ -9,9 +9,7 @@
 package org.dive4elements.river.exports.process;
 
 import org.apache.log4j.Logger;
-import org.jfree.data.xy.XYSeries;
-
-import java.util.List;
+import java.util.Map;
 
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
 import org.dive4elements.artifacts.CallContext;
@@ -22,10 +20,6 @@
 import org.dive4elements.river.jfree.StyledXYSeries;
 import org.dive4elements.river.themes.ThemeDocument;
 
-import org.dive4elements.river.artifacts.model.minfo.BedDiffYearResult;
-import org.dive4elements.river.model.BedHeightSingleValue;
-import org.dive4elements.river.artifacts.model.minfo.BedHeightSingleData;
-
 import org.dive4elements.river.artifacts.model.minfo.MorphologicWidth;
 
 public class BedWidthProcessor extends DefaultProcessor {
@@ -38,6 +32,8 @@
     public static final String I18N_AXIS_LABEL =
         "chart.beddifference.yaxis.label.morph";
 
+    protected String yAxisLabel;
+
     public static final double GAP_WIDTH = 100.0;
 
     @Override
@@ -47,45 +43,22 @@
             ThemeDocument    theme,
             boolean          visible) {
         CallContext context = generator.getCallContext();
-        XYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
+        Map<String, String> metaData = bundle.getFacet().getMetaData();
+        StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 theme);
+        series.putMetaData(metaData, bundle.getArtifact(), context);
+        yAxisLabel = metaData.get("Y");
         Object data = bundle.getData(context);
-        String facetName = bundle.getFacetName();
 
-        if (facetName.equals(FacetTypes.BED_DIFFERENCE_SOUNDING_WIDTH) &&
-            data instanceof BedDiffYearResult) {
-            BedDiffYearResult bData = (BedDiffYearResult) data;
-            StyledSeriesBuilder.addPoints(
-                series,
-                bData.getSoundingWidthData(),
-                false,
-                0.110d);
-        } else if (facetName.equals(FacetTypes.BED_DIFFERENCE_MORPH_WIDTH1) &&
-            data instanceof BedDiffYearResult) {
-            BedDiffYearResult bData = (BedDiffYearResult) data;
-            StyledSeriesBuilder.addPoints(series, bData.getMorphWidth1Data(), true);
-        } else if (facetName.equals(FacetTypes.BED_DIFFERENCE_MORPH_WIDTH2) &&
-            data instanceof BedDiffYearResult) {
-            BedDiffYearResult bData = (BedDiffYearResult) data;
-            StyledSeriesBuilder.addPoints(series, bData.getMorphWidth2Data(), true);
-        } else if (data instanceof MorphologicWidth) {
+        if (data instanceof MorphologicWidth) {
             MorphologicWidth bData = (MorphologicWidth) data;
             StyledSeriesBuilder.addPoints(series, bData.getAsArray(), true);
-        } else if (data instanceof BedHeightSingleData) {
-            BedHeightSingleData bData = (BedHeightSingleData)data;
-            double[] width = bData.getSoundingWidths();
-            double[] stations = bData.getStations().toNativeArray();
-
+        } else if (data instanceof double[][]) {
             GapInserter gi = new GapInserter(series, GAP_WIDTH);
 
-            for (int i = 0; i < width.length; i++) {
-                gi.add(stations[i], width[i]);
-            }
-        } else if (data instanceof List<?>) {
-            List<BedHeightSingleValue> bData = (List<BedHeightSingleValue>)data;
-
-            for(BedHeightSingleValue bvalue: bData) {
-                series.add(bvalue.getStation(), bvalue.getSoundingWidth());
+            double[][]values = (double[][]) data;
+            for (int i = 0; i < values[0].length; i++) {
+                gi.add(values[0][i], values[1][i]);
             }
         } else {
             logger.error("Unknown data for facet: " + bundle.getFacetName());
@@ -105,6 +78,9 @@
 
     @Override
     public String getAxisLabel(DiagramGenerator generator) {
+        if (yAxisLabel != null && !yAxisLabel.isEmpty()) {
+            return generator.msg(yAxisLabel, I18N_AXIS_LABEL_DEFAULT);
+        }
         return generator.msg(
                 I18N_AXIS_LABEL,
                 I18N_AXIS_LABEL_DEFAULT);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/FlowVelocityProcessor.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/FlowVelocityProcessor.java	Tue Jul 08 18:19:04 2014 +0200
@@ -8,6 +8,8 @@
 
 package org.dive4elements.river.exports.process;
 
+import java.util.Map;
+
 import org.apache.log4j.Logger;
 import org.jfree.data.xy.XYSeries;
 
@@ -39,6 +41,9 @@
     public static final String I18N_SUBTITLE_RADIUS =
         "chart.subtitle.radius";
 
+
+    protected String yAxisLabel;
+
     @Override
     public void doOut(
             DiagramGenerator generator,
@@ -46,8 +51,11 @@
             ThemeDocument    theme,
             boolean          visible) {
         CallContext context = generator.getCallContext();
-        XYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
+        Map<String, String> metaData = bundle.getFacet().getMetaData();
+        StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 theme);
+        series.putMetaData(metaData, bundle.getArtifact(), context);
+        yAxisLabel = metaData.get("Y");
         String facetName = bundle.getFacetName();
         Object data = bundle.getData(context);
         if (data == null) {
@@ -107,6 +115,9 @@
 
     @Override
     public String getAxisLabel(DiagramGenerator generator) {
+        if (yAxisLabel != null && !yAxisLabel.isEmpty()) {
+            return generator.msg(yAxisLabel, I18N_AXIS_LABEL_DEFAULT);
+        }
         return generator.msg(
                 I18N_AXIS_LABEL,
                 I18N_AXIS_LABEL_DEFAULT);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/MiddleBedHeightProcessor.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/MiddleBedHeightProcessor.java	Tue Jul 08 18:19:04 2014 +0200
@@ -8,20 +8,19 @@
 
 package org.dive4elements.river.exports.process;
 
+import java.util.Map;
+
 import org.apache.log4j.Logger;
 
-import org.jfree.data.xy.XYSeries;
-
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
 import org.dive4elements.artifacts.CallContext;
 
-import org.dive4elements.river.artifacts.model.MiddleBedHeightData;
 import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RiverAccess;
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.themes.ThemeDocument;
 import org.dive4elements.river.exports.DiagramGenerator;
 import org.dive4elements.river.exports.StyledSeriesBuilder;
-import org.dive4elements.river.utils.RiverUtils;
 import org.dive4elements.river.jfree.StyledXYSeries;
 
 public class MiddleBedHeightProcessor extends DefaultProcessor {
@@ -36,6 +35,8 @@
     public static final String I18N_AXIS_LABEL_DEFAULT =
         "mittlere Sohlhöhen [müNN]";
 
+    protected String yAxisLabel;
+
     @Override
     public void doOut(
             DiagramGenerator generator,
@@ -43,14 +44,24 @@
             ThemeDocument    theme,
             boolean          visible) {
         CallContext context = generator.getCallContext();
-        logger.debug("Processing: " + bundle.getFacetName());
-        MiddleBedHeightData data =
-            (MiddleBedHeightData) bundle.getData(context);
+        Map<String, String> metaData = bundle.getFacet().getMetaData();
+        yAxisLabel = metaData.get("Y");
 
-        XYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
+        Object raw = bundle.getData(context);
+        if (raw == null) {
+            return;
+        }
+        if (!(raw instanceof double[][])) {
+            logger.error("Unkonwn data type: " + raw.getClass().getName());
+            return;
+        }
+
+        double[][] data = (double[][])raw;
+        StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 theme);
+        series.putMetaData(metaData, bundle.getArtifact(), context);
 
-        StyledSeriesBuilder.addPoints(series, data.getMiddleHeightsPoints(),
+        StyledSeriesBuilder.addPoints(series, data,
                 false, 0.110d);
 
         generator.addAxisSeries(series, axisName, visible);
@@ -60,8 +71,15 @@
     public String getAxisLabel(DiagramGenerator generator) {
         D4EArtifact flys = (D4EArtifact) generator.getMaster();
 
-        String unit = RiverUtils.getRiver(flys).getWstUnit().getName();
+        RiverAccess access = new RiverAccess(flys);
+        String unit = access.getRiver().getWstUnit().getName();
 
+        if (yAxisLabel != null && !yAxisLabel.isEmpty()) {
+            return generator.msg(
+                yAxisLabel,
+                I18N_AXIS_LABEL_DEFAULT,
+                new Object[] { unit });
+        }
         return generator.msg(
                 I18N_AXIS_LABEL,
                 I18N_AXIS_LABEL_DEFAULT,
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/SQRelationProcessor.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/SQRelationProcessor.java	Tue Jul 08 18:19:04 2014 +0200
@@ -8,6 +8,8 @@
 
 package org.dive4elements.river.exports.process;
 
+import java.util.Map;
+
 import org.apache.log4j.Logger;
 import org.jfree.data.xy.XYSeries;
 
@@ -41,10 +43,11 @@
             boolean          visible) {
         CallContext context = generator.getCallContext();
         String facetName = bundle.getFacetName();
-        XYSeries series;
+        StyledXYSeries series;
         Object data = bundle.getData(context);
         String desc = bundle.getFacetDescription();
-
+        Map<String, String> metaData =
+            bundle.getFacet().getMetaData(bundle.getArtifact(), context);
         if (data == null) {
             // Check has been here before so we keep it but
             // this should never happen.
@@ -80,6 +83,7 @@
             logger.error("Could not handle: " + facetName);
             return;
         }
+        series.putMetaData(metaData, bundle.getArtifact(), context);
 
         if (logger.isDebugEnabled()) {
             logger.debug("Series '" + desc + "' has "
--- a/artifacts/src/main/java/org/dive4elements/river/jfree/StyledXYSeries.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StyledXYSeries.java	Tue Jul 08 18:19:04 2014 +0200
@@ -9,9 +9,17 @@
 package org.dive4elements.river.jfree;
 
 import java.util.List;
+import java.util.Map;
 
 import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RiverAccess;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.model.Unit;
 import org.dive4elements.river.themes.ThemeDocument;
+import org.dive4elements.river.utils.RiverUtils;
 
 import org.jfree.data.xy.XYDataItem;
 import org.jfree.data.xy.XYSeries;
@@ -21,7 +29,9 @@
 /**
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
-public class StyledXYSeries extends XYSeries implements StyledSeries, HasLabel {
+public class StyledXYSeries
+extends XYSeries
+implements StyledSeries, HasLabel, XYMetaDataset {
 
     private static final Logger logger = Logger.getLogger(StyledXYSeries.class);
 
@@ -30,6 +40,8 @@
     /** If this Series is to be labelled, use this String as label. */
     protected String label;
 
+    /** The meta data for this series. */
+    protected Map<String, String> metaData;
 
     public StyledXYSeries(String key, ThemeDocument theme) {
         this(key, true, theme, (Shape)null);
@@ -115,5 +127,35 @@
             add(item.getXValue(), item.getYValue());
         }
     }
+
+
+    @Override
+    public Map<String, String> getMetaData() {
+        return metaData;
+    }
+
+
+    @Override
+    public void putMetaData(Map<String, String> metaData,
+        Artifact artifact,
+        CallContext context) {
+        this.metaData = metaData;
+        D4EArtifact d4e = (D4EArtifact) artifact;
+        RiverAccess access = new RiverAccess(d4e);
+        Unit unit = RiverUtils.getRiver(d4e).getWstUnit();
+        if (metaData.containsKey("X")) {
+            this.metaData.put("X",
+                Resources.getMsg(
+                    context.getMeta(),
+                    metaData.get("X"),
+                    new Object[] { access.getRiverName() }));
+        }
+        if (metaData.containsKey("Y")) {
+            this.metaData.put("Y",
+                Resources.getMsg(
+                    context.getMeta(),
+                    metaData.get("Y"), new Object[] { unit.getName() }));
+        }
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/XYMetaDataset.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,32 @@
+/* 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.jfree;
+
+import java.util.Map;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+
+
+public interface XYMetaDataset
+{
+
+    /**
+     * The meta data for this data set.
+     */
+    Map<String, String> getMetaData();
+
+    /**
+     * Add meta data for this data set.
+     */
+    void putMetaData(
+        Map<String, String> metaData,
+        Artifact artifact,
+        CallContext context);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/XYMetaSeriesCollection.java	Tue Jul 08 18:19:04 2014 +0200
@@ -0,0 +1,28 @@
+package org.dive4elements.river.jfree;
+
+import java.util.Map;
+
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
+
+
+public class XYMetaSeriesCollection
+extends XYSeriesCollection
+{
+
+    protected Map<String, String> metaData;
+
+    public XYMetaSeriesCollection(XYSeries series) {
+        super(series);
+        if (series instanceof XYMetaDataset) {
+            this.metaData = ((XYMetaDataset) series).getMetaData();
+        }
+        else {
+            metaData = null;
+        }
+    }
+
+    public Map<String, String> getMetaData() {
+        return this.metaData;
+    }
+}
--- a/artifacts/src/main/resources/messages.properties	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/resources/messages.properties	Tue Jul 08 18:19:04 2014 +0200
@@ -224,6 +224,9 @@
 chart.bedheight_middle.section.title=Middle Bed Height
 chart.bedheight_middle.section.yaxis.label=middle Bed Height [{0}]
 chart.bedheight_middle.sounding.yaxis.label=Sounding Width [m]
+chart.bedheight_middle.export.unit = River elevation model
+chart.bedheight_middle.export.curelev = Current elevation model
+chart.bedheight_middle.export.oldelev = Old elevation model
 
 chart.bedheight.height.yaxis.label=Bed Height [{0}]
 
@@ -415,6 +418,15 @@
 export.bedheight_middle.csv.header.soundingwidth = Sounding Width [m]
 export.bedheight_middle.csv.header.width = morphological active width [m]
 export.bedheight_middle.csv.header.locations = Location
+export.bedheight_middle.csv.header.year = Year
+export.bedheight_middle.csv.header.type = Type
+export.bedheight_middle.csv.header.cur.elevation = Current elevation model
+export.bedheight_middle.csv.header.old.elevation = Old elevation model
+export.bedheight_middle.csv.header.sounding.width = Sounding width
+export.bedheight_middle.csv.header.range = Range
+export.bedheight_middle.csv.header.location.system = Location system
+export.bedheight_middle.csv.header.evalby = Evaluated by
+export.bedheight_middle.csv.header.river.elevation = River elevation model
 export.sedimentload_ls.csv.header.km = km
 export.sedimentload_ls.csv.header.year = year
 export.sedimentload_ls.csv.header.coarse = coarse
--- a/artifacts/src/main/resources/messages_de.properties	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/resources/messages_de.properties	Tue Jul 08 18:19:04 2014 +0200
@@ -224,6 +224,9 @@
 chart.bedheight_middle.section.title=Mittlere Sohlh\u00f6he
 chart.bedheight_middle.section.yaxis.label=mittlere Sohlh\u00f6hen [{0}]
 chart.bedheight_middle.sounding.yaxis.label=Gepeilte Breite [m]
+chart.bedheight_middle.export.unit = H\u00f6hensystem des Flusses
+chart.bedheight_middle.export.curelev = H\u00f6hensystem
+chart.bedheight_middle.export.oldelev = urspr\u00fcngliches H\u00f6hensystem
 
 chart.bedheight.height.yaxis.label=Sohlh\u00f6he [{0}]
 
@@ -416,6 +419,15 @@
 export.bedheight_middle.csv.header.soundingwidth = Peilbreite [m]
 export.bedheight_middle.csv.header.width = morphologisch ausgewertete Breite [m]
 export.bedheight_middle.csv.header.locations = Streckendaten
+export.bedheight_middle.csv.header.year = Jahr
+export.bedheight_middle.csv.header.type = Aufnahmeart
+export.bedheight_middle.csv.header.cur.elevation = H\u00f6hensystem
+export.bedheight_middle.csv.header.old.elevation = urspr\u00fcngliches H\u00f6hensystem
+export.bedheight_middle.csv.header.river.elevation = H\u00f6hensystem des Flusses
+export.bedheight_middle.csv.header.sounding.width = ausgewertete Peilbreite
+export.bedheight_middle.csv.header.range = Strecke
+export.bedheight_middle.csv.header.location.system = Lagesystem
+export.bedheight_middle.csv.header.evalby = Auswerter
 export.sedimentload_ls.csv.header.km = km
 export.sedimentload_ls.csv.header.year = Jahr
 export.sedimentload_ls.csv.header.coarse = Kies(g)
--- a/artifacts/src/main/resources/messages_de_DE.properties	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/resources/messages_de_DE.properties	Tue Jul 08 18:19:04 2014 +0200
@@ -222,6 +222,9 @@
 chart.bedheight_middle.section.title=Mittlere Sohlh\u00f6he
 chart.bedheight_middle.section.yaxis.label=mittlere Sohlh\u00f6hen [{0}]
 chart.bedheight_middle.sounding.yaxis.label=Gepeilte Breite [m]
+chart.bedheight_middle.export.unit = H\u00f6hensystem des Flusses
+chart.bedheight_middle.export.curelev = H\u00f6hensystem
+chart.bedheight_middle.export.oldelev = urspr\u00fcngliches H\u00f6hensystem
 
 chart.bedheight.height.yaxis.label=Sohlh\u00f6he [{0}]
 
@@ -413,6 +416,15 @@
 export.bedheight_middle.csv.header.soundingwidth = Peilbreite [m]
 export.bedheight_middle.csv.header.width = morphologisch ausgewertete Breite [m]
 export.bedheight_middle.csv.header.locations = Streckendaten
+export.bedheight_middle.csv.header.year = Jahr
+export.bedheight_middle.csv.header.type = Aufnahmeart
+export.bedheight_middle.csv.header.cur.elevation = H\u00f6hensystem
+export.bedheight_middle.csv.header.old.elevation = urspr\u00fcngliches H\u00f6hensystem
+export.bedheight_middle.csv.header.sounding.width = ausgewertete Peilbreite
+export.bedheight_middle.csv.header.range = Strecke
+export.bedheight_middle.csv.header.location.system = Lagesystem
+export.bedheight_middle.csv.header.evalby = Auswerter
+export.bedheight_middle.csv.header.river.elevation = H\u00f6hensystem des Flusses
 export.sedimentload_ls.csv.header.km = km
 export.sedimentload_ls.csv.header.year = Jahr
 export.sedimentload_ls.csv.header.coarse = Kies(g)
--- a/artifacts/src/main/resources/messages_en.properties	Thu Jul 03 16:36:43 2014 +0200
+++ b/artifacts/src/main/resources/messages_en.properties	Tue Jul 08 18:19:04 2014 +0200
@@ -226,6 +226,9 @@
 chart.bedheight_middle.section.title=Middle Bed Height
 chart.bedheight_middle.section.yaxis.label=middle Bed Height [{0}]
 chart.bedheight_middle.sounding.yaxis.label=Sounding Width [m]
+chart.bedheight_middle.export.unit = River elevation model
+chart.bedheight_middle.export.curelev = Current elevation model
+chart.bedheight_middle.export.oldelev = Old elevation model
 
 chart.bedheight.height.yaxis.label=Bed Height [{0}]
 
@@ -418,6 +421,15 @@
 export.bedheight_middle.csv.header.soundingwidth = Sounding Width [m]
 export.bedheight_middle.csv.header.width = morphological active width [m]
 export.bedheight_middle.csv.header.locations = Location
+export.bedheight_middle.csv.header.year = Year
+export.bedheight_middle.csv.header.type = Type
+export.bedheight_middle.csv.header.cur.elevation = Current elevation model
+export.bedheight_middle.csv.header.old.elevation = Old elevation model
+export.bedheight_middle.csv.header.sounding.width = Sounding width
+export.bedheight_middle.csv.header.range = Range
+export.bedheight_middle.csv.header.location.system = Location system
+export.bedheight_middle.csv.header.evalby = Evaluated by
+export.bedheight_middle.csv.header.river.elevation = River elevation model
 export.sedimentload_ls.csv.header.km = km
 export.sedimentload_ls.csv.header.year = year
 export.sedimentload_ls.csv.header.coarse = coarse
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Thu Jul 03 16:36:43 2014 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Tue Jul 08 18:19:04 2014 +0200
@@ -852,6 +852,8 @@
 
     String bedheight_differences();
 
+    String middle_bedheights();
+
     String vollmer_waterlevels();
 
     String old_calculations();
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Thu Jul 03 16:36:43 2014 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Tue Jul 08 18:19:04 2014 +0200
@@ -440,6 +440,7 @@
 waterlevels_fix_vollmer = Fixation analysis (Vollmer)
 beddifferences = Bedheight Differences
 bedheight_differences = Bedheight Differences
+middle_bedheights = Middle Bedheights
 vollmer_waterlevels = Vollmer Waterlevels
 old_calculations = Former Calculations
 officiallines = Official lines
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Thu Jul 03 16:36:43 2014 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Tue Jul 08 18:19:04 2014 +0200
@@ -444,6 +444,7 @@
 waterlevels_fix_vollmer = Ausgelagerte Wasserspiegellagen
 beddifferences = Sohlh\u00f6hendifferenzen
 bedheight_differences = Sohlh\u00f6hendifferenzen
+middle_bedheights = Mittlere Sohlh\u00f6hen
 vollmer_waterlevels = Ausgelagerte WSPL.
 old_calculations = Fr\u00fchere Berechnungen
 officiallines = Amtliche Linien
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties	Thu Jul 03 16:36:43 2014 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties	Tue Jul 08 18:19:04 2014 +0200
@@ -443,6 +443,7 @@
 waterlevels_fix_vollmer = Fixation analysis (Vollmer)
 beddifferences = Bedheight Differences
 bedheight_differences = Bedheight Differences
+middle_bedheights = Middle Bedheights
 vollmer_waterlevels = Vollmer Waterlevels
 old_calculations = Former Calculations
 officiallines = Official lines

http://dive4elements.wald.intevation.org