changeset 8587:07c9ac22f611

(issue1755) Generalise BedQuality result handling The bedquality calculation now produces a result for each time period which has BedQualityResultValues for each specific result type. Formally this was split up in density, porosity and diameter classes with some bedload diameter classes mixed in for extra fun. The intent of this commit is to allow more shared code and generic access patterns to the BedQuality results.
author Andre Heinecke <andre.heinecke@intevation.de>
date Wed, 18 Mar 2015 18:42:08 +0100
parents 19fde13e2db4
children 717b58b158c9
files artifacts/doc/conf/artifacts/minfo.xml artifacts/doc/conf/meta-data.xml artifacts/doc/conf/themes.xml artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDensitySubFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDensityTopFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterResult.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterSubFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterTopFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedPorositySubFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedPorosityTopFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityCalculation.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityDataFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityResult.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityResultValue.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterResult.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/BedQualityState.java artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityExporter.java artifacts/src/main/java/org/dive4elements/river/utils/DoubleUtil.java artifacts/src/main/resources/messages.properties artifacts/src/main/resources/messages_de.properties artifacts/src/main/resources/messages_de_DE.properties artifacts/src/main/resources/messages_en.properties
diffstat 24 files changed, 481 insertions(+), 1150 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/doc/conf/artifacts/minfo.xml	Tue Mar 17 18:52:00 2015 +0100
+++ b/artifacts/doc/conf/artifacts/minfo.xml	Wed Mar 18 18:42:08 2015 +0100
@@ -152,9 +152,9 @@
                         <facet name="flow_velocity.measurement" description="A facet for measured flow velocities"/>
                         <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations"/>
                         <facet name="flow_velocity.manualpoints"/>
-                        <facet name="bed_longitudinal_section.bed_diameter_toplayer"/>
-                        <facet name="bed_longitudinal_section.bed_diameter_sublayer"/>
-                        <facet name="bed_longitudinal_section.bedload_diameter"/>
+                        <facet name="bed_longitudinal_section.diameter.toplayer"/>
+                        <facet name="bed_longitudinal_section.diameter.sublayer"/>
+                        <facet name="bed_longitudinal_section.diameter.bedload"/>
                     </facets>
                 </outputmode>
                 <outputmode name="flow_velocity_export" description="output.flow_velocity_export" mime-type="text/plain" type="export">
@@ -463,17 +463,17 @@
             <outputmodes>
                 <outputmode name="bed_longitudinal_section" description="output.bed_longitudinal_section" mime-type="image/png" type="chart">
                     <facets>
-                        <facet name="bed_longitudinal_section.porosity_toplayer"/>
-                        <facet name="bed_longitudinal_section.porosity_sublayer"/>
-                        <facet name="bed_longitudinal_section.sediment_density_toplayer"/>
-                        <facet name="bed_longitudinal_section.sediment_density_sublayer"/>
-                        <facet name="bed_longitudinal_section.bed_diameter_toplayer"/>
-                        <facet name="bed_longitudinal_section.bed_diameter_sublayer"/>
-                        <facet name="bed_longitudinal_section.bed_diameter_data_top"/>
-                        <facet name="bed_longitudinal_section.bed_diameter_data_sub"/>
-                        <facet name="bed_longitudinal_section.bedload_diameter_data"/>
+                        <facet name="bed_longitudinal_section.porosity.toplayer"/>
+                        <facet name="bed_longitudinal_section.porosity.toplayer"/>
+                        <facet name="bed_longitudinal_section.density.toplayer"/>
+                        <facet name="bed_longitudinal_section.density.sublayer"/>
+                        <facet name="bed_longitudinal_section.diameter.toplayer"/>
+                        <facet name="bed_longitudinal_section.diameter.sublayer"/>
+                        <facet name="bed_longitudinal_section.diameter.toplayer.data"/>
+                        <facet name="bed_longitudinal_section.diameter.sublayer.data"/>
+                        <facet name="bed_longitudinal_section.diameter.bedload.data"/>
                         <facet name="bed_longitudinal_section.manualpoints" />
-                        <facet name="bed_longitudinal_section.bedload_diameter"/>
+                        <facet name="bed_longitudinal_section.diameter.bedload"/>
                         <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations"/>
                         <facet name="porosity" description="facet.porosity"/>
                     </facets>
--- a/artifacts/doc/conf/meta-data.xml	Tue Mar 17 18:52:00 2015 +0100
+++ b/artifacts/doc/conf/meta-data.xml	Wed Mar 18 18:42:08 2015 +0100
@@ -830,13 +830,13 @@
 
     <dc:macro name="bedquality">
       <dc:filter expr="$out_name = 'bed_longitudinal_section' and
-        ($facet_name = 'bed_longitudinal_section.bed_diameter_toplayer' or
-        $facet_name = 'bed_longitudinal_section.bed_diameter_sublayer' or
-        $facet_name = 'bed_longitudinal_section.bedload_diameter' or
-        $facet_name = 'bed_longitudinal_section.sediment_density_toplayer' or
-        $facet_name = 'bed_longitudinal_section.sediment_density_sublayer' or
-        $facet_name = 'bed_longitudinal_section.porosity_toplayer' or
-        $facet_name = 'bed_longitudinal_section.porosity_sublayer')">
+        ($facet_name = 'bed_longitudinal_section.diameter.toplayer' or
+        $facet_name = 'bed_longitudinal_section.diameter.sublayer' or
+        $facet_name = 'bed_longitudinal_section.diameter.bedload' or
+        $facet_name = 'bed_longitudinal_section.density.toplayer' or
+        $facet_name = 'bed_longitudinal_section.density.sublayer' or
+        $facet_name = 'bed_longitudinal_section.porosity.toplayer' or
+        $facet_name = 'bed_longitudinal_section.porosity.toplayer')">
         <dc:if test="dc:has-result()">
           <bed_quality>
             <dc:call-macro name="collection-group">
--- a/artifacts/doc/conf/themes.xml	Tue Mar 17 18:52:00 2015 +0100
+++ b/artifacts/doc/conf/themes.xml	Wed Mar 18 18:42:08 2015 +0100
@@ -213,16 +213,16 @@
         <mapping from="flow_velocity.measurement" to="FlowVelocityDischarge" />
         <mapping from="bedheight_middle.single" to="MiddleBedHeightSingle" />
         <mapping from="bedheight_middle.manualpoints" to="ManualPoints" />
-        <mapping from="bed_longitudinal_section.porosity_toplayer" to="PorosityTopLayer" />
-        <mapping from="bed_longitudinal_section.porosity_sublayer" to="PorositySubLayer" />
-        <mapping from="bed_longitudinal_section.sediment_density_toplayer" to="DensityTopLayer" />
-        <mapping from="bed_longitudinal_section.sediment_density_sublayer" to="DensitySublayer" />
-        <mapping from="bed_longitudinal_section.bed_diameter_toplayer" to="BedDiameterTopLayer" />
-        <mapping from="bed_longitudinal_section.bed_diameter_sublayer" to="BedDiameterSubLayer" />
-        <mapping from="bed_longitudinal_section.bedload_diameter" to="BedLoadDiameter" />
-        <mapping from="bed_longitudinal_section.bed_diameter_data_top" to="BedDiameterDataTop"/>
-        <mapping from="bed_longitudinal_section.bed_diameter_data_sub" to="BedDiameterDataSub"/>
-        <mapping from="bed_longitudinal_section.bedload_diameter_data" to="BedloadDiameterData"/>
+        <mapping from="bed_longitudinal_section.porosity.toplayer" to="PorosityTopLayer" />
+        <mapping from="bed_longitudinal_section.porosity.toplayer" to="PorositySubLayer" />
+        <mapping from="bed_longitudinal_section.density.toplayer" to="DensityTopLayer" />
+        <mapping from="bed_longitudinal_section.density.sublayer" to="DensitySublayer" />
+        <mapping from="bed_longitudinal_section.diameter.toplayer" to="BedDiameterTopLayer" />
+        <mapping from="bed_longitudinal_section.diameter.sublayer" to="BedDiameterSubLayer" />
+        <mapping from="bed_longitudinal_section.diameter.bedload" to="BedLoadDiameter" />
+        <mapping from="bed_longitudinal_section.diameter.toplayer.data" to="BedDiameterDataTop"/>
+        <mapping from="bed_longitudinal_section.diameter.sublayer.data" to="BedDiameterDataSub"/>
+        <mapping from="bed_longitudinal_section.diameter.bedload.data" to="BedloadDiameterData"/>
         <mapping from="bedheight_difference.year" to="BedheightDiffYear"/>
         <mapping from="bedheight_difference.year.filtered" to="BedheightDiffYear"/>
         <mapping from="bedheight_difference.morph_width" to="BedheightDiffMorphWidth"/>
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java	Tue Mar 17 18:52:00 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java	Wed Mar 18 18:42:08 2015 +0100
@@ -308,16 +308,17 @@
     String MIDDLE_BED_HEIGHT_SINGLE     = "bedheight_middle.single";
     String MIDDLE_BED_HEIGHT_ANNOTATION = "bedheight_middle.annotation";
 
-    String BED_QUALITY_POROSITY_TOPLAYER         = "bed_longitudinal_section.porosity_toplayer";
-    String BED_QUALITY_POROSITY_SUBLAYER         = "bed_longitudinal_section.porosity_sublayer";
-    String BED_QUALITY_BED_DIAMETER_TOPLAYER     = "bed_longitudinal_section.bed_diameter_toplayer";
-    String BED_QUALITY_BED_DIAMETER_SUBLAYER     = "bed_longitudinal_section.bed_diameter_sublayer";
-    String BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER = "bed_longitudinal_section.sediment_density_toplayer";
-    String BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER = "bed_longitudinal_section.sediment_density_sublayer";
-    String BED_QUALITY_BEDLOAD_DIAMETER          = "bed_longitudinal_section.bedload_diameter";
-    String BED_DIAMETER_DATA_TOP                 = "bed_longitudinal_section.bed_diameter_data_top";
-    String BED_DIAMETER_DATA_SUB                 = "bed_longitudinal_section.bed_diameter_data_sub";
-    String BEDLOAD_DIAMETER_DATA                 = "bed_longitudinal_section.bedload_diameter_data";
+    String BED_QUALITY_DATA_FACET                = "bed_longitudinal_section";
+    String BED_QUALITY_POROSITY_TOPLAYER         =  BED_QUALITY_DATA_FACET + ".porosity.toplayer";
+    String BED_QUALITY_POROSITY_SUBLAYER         =  BED_QUALITY_DATA_FACET + ".porosity.sublayer";
+    String BED_QUALITY_BED_DIAMETER_TOPLAYER     =  BED_QUALITY_DATA_FACET + ".diameter.toplayer";
+    String BED_QUALITY_BED_DIAMETER_SUBLAYER     =  BED_QUALITY_DATA_FACET + ".diameter.sublayer";
+    String BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER =  BED_QUALITY_DATA_FACET + ".density.toplayer";
+    String BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER =  BED_QUALITY_DATA_FACET + ".density.sublayer";
+    String BED_QUALITY_BEDLOAD_DIAMETER          =  BED_QUALITY_DATA_FACET + ".diameter.bedload";
+    String BED_DIAMETER_DATA_TOP                 =  BED_QUALITY_DATA_FACET + ".diameter.toplayer.data";
+    String BED_DIAMETER_DATA_SUB                 =  BED_QUALITY_DATA_FACET + ".diameter.sublayer.data";
+    String BEDLOAD_DIAMETER_DATA                 =  BED_QUALITY_DATA_FACET + ".diameter.bedload.data";
     String POROSITY                              = "porosity";
 
     String BED_DIFFERENCE_YEAR                   = "bedheight_difference.year";
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDensitySubFacet.java	Tue Mar 17 18:52:00 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +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 BedDensitySubFacet extends DataFacet {
-
-    private static final long serialVersionUID = 1L;
-
-    private static Logger log = 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) {
-        log.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 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDensityTopFacet.java	Tue Mar 17 18:52:00 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +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 BedDensityTopFacet extends DataFacet {
-
-    private static final long serialVersionUID = 1L;
-
-    private static Logger log = 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) {
-        log.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/BedDiameterResult.java	Tue Mar 17 18:52:00 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +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.dive4elements.river.utils.DoubleUtil;
-
-import gnu.trove.TDoubleArrayList;
-
-import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
-
-import org.apache.commons.math.ArgumentOutsideDomainException;
-
-public class BedDiameterResult
-extends BedQualityDiameterResult
-{
-    protected TDoubleArrayList diameterCap;
-    protected TDoubleArrayList diameterSub;
-
-    protected PolynomialSplineFunction interpolSub;
-    protected PolynomialSplineFunction interpolCap;
-    protected boolean nonInterpolSub;
-    protected boolean nonInterpolCap;
-
-    public BedDiameterResult (
-        String type,
-        TDoubleArrayList diameterCap,
-        TDoubleArrayList diameterSub,
-        TDoubleArrayList km
-    ) {
-        super(type, km);
-        this.diameterCap = diameterCap;
-        this.diameterSub = diameterSub;
-        interpolSub = null;
-        nonInterpolSub = false;
-        interpolCap = null;
-        nonInterpolCap = false;
-    }
-
-    public double getDiameterCap(int ndx) {
-        if (diameterCap != null) {
-            return this.diameterCap.get(ndx);
-        }
-        return Double.NaN;
-    }
-
-    public double getDiameterSub(int ndx) {
-        if (diameterSub != null) {
-            return this.diameterSub.get(ndx);
-        }
-        return Double.NaN;
-    }
-
-    public double getDiameterCap(double km) {
-        if (kms.indexOf(km) >= 0) {
-            return diameterCap.get(kms.indexOf(km));
-        }
-        return Double.NaN;
-    }
-
-    public double getDiameterCapInterpol(double km) {
-        if (nonInterpolCap) {
-            return Double.NaN;
-        }
-        if (interpolCap == null) {
-            interpolCap = DoubleUtil.getLinearInterpolator(kms, diameterCap);
-            if (interpolCap == null) {
-                nonInterpolCap = true;
-                return Double.NaN;
-            }
-        }
-        try {
-            return interpolCap.value(km);
-        } catch (ArgumentOutsideDomainException e) {
-            /* This is expected for many results. */
-            return Double.NaN;
-        }
-    }
-
-    public double getDiameterSub(double km) {
-        if (kms.indexOf(km) >= 0) {
-            return diameterSub.get(kms.indexOf(km));
-        }
-        return Double.NaN;
-    }
-
-    public double getDiameterSubInterpol(double km) {
-        if (nonInterpolSub) {
-            return Double.NaN;
-        }
-        if (interpolSub == null) {
-            interpolSub = DoubleUtil.getLinearInterpolator(kms, diameterSub);
-            if (interpolSub == null) {
-                nonInterpolSub = true;
-                return Double.NaN;
-            }
-        }
-        try {
-            return interpolSub.value(km);
-        } catch (ArgumentOutsideDomainException e) {
-            /* This is expected for many results. */
-            return Double.NaN;
-        }
-    }
-
-    public double[][] getDiameterCapData() {
-        return new double[][] {
-            kms.toNativeArray(),
-            diameterCap.toNativeArray()
-        };
-    }
-
-    public double[][] getDiameterSubData() {
-        return new double[][] {
-            kms.toNativeArray(),
-            diameterSub.toNativeArray()
-        };
-    }
-}
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterSubFacet.java	Tue Mar 17 18:52:00 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +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 BedDiameterSubFacet extends DataFacet {
-
-    private static final long serialVersionUID = 1L;
-
-    private static Logger log = 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.diameter");
-    }
-
-    public Object getData(Artifact artifact, CallContext context) {
-        log.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 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiameterTopFacet.java	Tue Mar 17 18:52:00 2015 +0100
+++ /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.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 log = 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.diameter");
-    }
-
-    public Object getData(Artifact artifact, CallContext context) {
-        log.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 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedPorositySubFacet.java	Tue Mar 17 18:52:00 2015 +0100
+++ /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.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 log = 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) {
-        log.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 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedPorosityTopFacet.java	Tue Mar 17 18:52:00 2015 +0100
+++ /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.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 log = 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) {
-        log.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/BedQualityCalculation.java	Tue Mar 17 18:52:00 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityCalculation.java	Wed Mar 18 18:42:08 2015 +0100
@@ -110,22 +110,14 @@
             BedQualityResult result = new BedQualityResult();
             result.setDateRange(dr);
             if (bedDiameter != null) {
-                result.add(calculateBedParameter(bedMeasurements, dr));
+                result.add(calculateBedParameter(bedMeasurements));
                 for (String bd : bedDiameter) {
-                    BedDiameterResult bedResult =
-                        calculateBed(bedMeasurements, bd, dr);
-
-                    // Avoid adding empty result sets.
-                    if (!bedResult.isEmpty()) {
-                        result.add(bedResult);
-                    }
+                    result.add (calculateBed(bedMeasurements, bd));
                 }
             }
             if (bedloadDiameter != null) {
                 for (String bld : bedloadDiameter) {
-                    BedloadDiameterResult loadResult =
-                        calculateBedload(loadMeasurements, bld, dr);
-                    result.add(loadResult);
+                    result.add(calculateBedload(loadMeasurements, bld));
                 }
             }
             results.add(result);
@@ -135,14 +127,13 @@
             results.toArray(new BedQualityResult[results.size()]), this);
     }
 
-    private BedParametersResult calculateBedParameter(
-        QualityMeasurements qm,
-        DateRange dr
+    private BedQualityResultValue[] calculateBedParameter(
+        QualityMeasurements qm
     ) {
         List<Double> kms = qm.getKms();
+        TDoubleArrayList location = new TDoubleArrayList();
         QualityMeasurements capFiltered = filterCapMeasurements(qm);
         QualityMeasurements subFiltered = filterSubMeasurements(qm);
-        TDoubleArrayList location = new TDoubleArrayList();
         TDoubleArrayList porosityCap = new TDoubleArrayList();
         TDoubleArrayList porositySub = new TDoubleArrayList();
         TDoubleArrayList densityCap = new TDoubleArrayList();
@@ -173,19 +164,24 @@
             densitySub.add((dSubRes / dSub.length) / 1000);
 
         }
-
-        return new BedParametersResult(
-            location,
-            porosityCap,
-            porositySub,
-            densityCap,
-            densitySub);
+        return new BedQualityResultValue[] {
+                new BedQualityResultValue("porosity",
+                        new double[][] {location.toNativeArray(), porositySub.toNativeArray()},
+                        "sublayer"),
+                new BedQualityResultValue("porosity",
+                        new double[][] {location.toNativeArray(), porosityCap.toNativeArray()},
+                        "toplayer"),
+                new BedQualityResultValue("density",
+                        new double[][] {location.toNativeArray(), densitySub.toNativeArray()},
+                        "sublayer"),
+                new BedQualityResultValue("density",
+                        new double[][] {location.toNativeArray(), densityCap.toNativeArray()},
+                        "toplayer")};
     }
 
-    protected BedDiameterResult calculateBed(
+    protected BedQualityResultValue[] calculateBed(
         QualityMeasurements qm,
-        String diameter,
-        DateRange range
+        String diameter
     ) {
         List<Double> kms = qm.getKms();
         TDoubleArrayList location = new TDoubleArrayList();
@@ -205,11 +201,13 @@
             avDiameterCap.add(avCap * 1000);// bring to mm.
             avDiameterSub.add(avSub * 1000);
         }
-        return new BedDiameterResult(
-            diameter,
-            avDiameterCap,
-            avDiameterSub,
-            location);
+        return new BedQualityResultValue[] {
+                new BedQualityResultValue(diameter,
+                        new double[][] {location.toNativeArray(), avDiameterSub.toNativeArray()},
+                        "sublayer"),
+                new BedQualityResultValue(diameter,
+                        new double[][] {location.toNativeArray(), avDiameterCap.toNativeArray()},
+                        "toplayer")};
     }
 
     private double[] calculateDensity(
@@ -241,10 +239,9 @@
         return results;
     }
 
-    protected BedloadDiameterResult calculateBedload(
+    protected BedQualityResultValue calculateBedload(
         QualityMeasurements qm,
-        String diameter,
-        DateRange range
+        String diameter
     ) {
         List<Double> kms = qm.getKms();
         TDoubleArrayList location = new TDoubleArrayList();
@@ -255,11 +252,9 @@
             location.add(km);
             avDiameter.add(mid * 1000);
         }
-        return new BedloadDiameterResult(
-            diameter,
-            avDiameter,
-            location,
-            range);
+        return new BedQualityResultValue(diameter,
+                new double[][] {location.toNativeArray(), avDiameter.toNativeArray()},
+                "bedload");
     }
 
     protected double calculateAverage(
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityDataFacet.java	Wed Mar 18 18:42:08 2015 +0100
@@ -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.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 BedQualityResults
+ */
+public class BedQualityDataFacet extends DataFacet {
+
+    private static final long serialVersionUID = 1L;
+
+    private static Logger log = Logger.getLogger(BedQualityDataFacet.class);
+
+    private String valueName; /* Name of the ResultValue underlying this facet */
+    private String valueType; /* Type of the ResultValue underlying this facet */
+
+    public BedQualityDataFacet() {
+        // required for clone operation deepCopy()
+    }
+
+    public BedQualityDataFacet(int idx, String name, String description,
+        ComputeType type, String stateId, String hash, String valueName, String valueType) {
+        super(idx, name, description, type, hash, stateId);
+        this.valueName = valueName;
+        this.valueType = valueType;
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", ""); /* check if those <^ be removed? */
+    }
+
+    @Override
+    public Object getData(Artifact artifact, CallContext context) {
+        log.debug("Get bedquality data: " + valueName + " - " + valueType);
+
+        D4EArtifact flys = (D4EArtifact) artifact;
+
+        CalculationResult res = (CalculationResult) flys.compute(context, hash,
+            stateId, type, false);
+
+        int ndx = index >> 8;
+        BedQualityResultValue value =
+            ((BedQualityResult[]) res.getData())[ndx].getValue(valueName, valueType);
+
+        if (value == null) {
+            /* Other facets check this so we do too */
+            return null;
+        }
+        return value.getData();
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        BedQualityDataFacet copy = new BedQualityDataFacet();
+        copy.set(this);
+        copy.type = type;
+        copy.hash = hash;
+        copy.stateId = stateId;
+        copy.valueName = valueName;
+        copy.valueType = valueType;
+        return copy;
+    }
+}
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityResult.java	Tue Mar 17 18:52:00 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityResult.java	Wed Mar 18 18:42:08 2015 +0100
@@ -18,53 +18,44 @@
 implements Serializable
 {
 
-    protected List<BedDiameterResult> bedResults;
-    protected List<BedloadDiameterResult> bedloadResults;
-    protected List<BedParametersResult> bedParameters;
+    protected LinkedList<BedQualityResultValue> values;
     protected DateRange dateRange;
 
     public BedQualityResult () {
-        bedResults = new LinkedList<BedDiameterResult>();
-        bedloadResults = new LinkedList<BedloadDiameterResult>();
-        bedParameters = new LinkedList<BedParametersResult>();
+        values = new LinkedList<BedQualityResultValue>();
     };
 
     public BedQualityResult (
-        List<BedDiameterResult> bedResults,
-        List<BedloadDiameterResult> bedloadResults,
-        List<BedParametersResult> bedParameters,
+        LinkedList<BedQualityResultValue> values,
         DateRange range
     ) {
         this.dateRange = range;
-        this.bedResults = bedResults;
-        this.bedloadResults = bedloadResults;
-        this.bedParameters = bedParameters;
-    }
-
-    public BedParametersResult[] getParameters() {
-        return bedParameters.toArray(
-            new BedParametersResult[bedParameters.size()]);
-    }
-
-    public BedDiameterResult[] getBedResults() {
-        return bedResults.toArray(new BedDiameterResult[bedResults.size()]);
+        this.values = values;
     }
 
-    public BedloadDiameterResult[] getBedloadResults() {
-        return bedloadResults.toArray(
-            new BedloadDiameterResult[bedloadResults.size()]);
+    public void add(BedQualityResultValue[] values) {
+        for (BedQualityResultValue value: values) {
+            add(value);
+        }
     }
 
-    public void add(BedloadDiameterResult result) {
-        bedloadResults.add(result);
+    public void add(BedQualityResultValue value) {
+        /* Add first is here to mimic the result sorting before
+         * a refactorization.*/
+        values.addFirst(value);
     }
 
-    public void add(BedDiameterResult result) {
-        bedResults.add(result);
+    public List<BedQualityResultValue> getValues() {
+        return values;
     }
 
-    public void add(BedParametersResult result) {
-        bedParameters.add(result);
+    public BedQualityResultValue getValue(String name, String type) {
+        for (BedQualityResultValue value: values) {
+            if (name.equals(value.getName()) && type.equals(value.getType())) {
+                return value;
+            }
+        }
+        return null;
     }
 
     public DateRange getDateRange() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityResultValue.java	Wed Mar 18 18:42:08 2015 +0100
@@ -0,0 +1,126 @@
+/* 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.river.utils.DoubleUtil;
+
+import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
+import org.apache.commons.math.ArgumentOutsideDomainException;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.HashSet;
+
+import java.io.Serializable;
+
+/** Holder of a specific result from the bed quality calculation.
+ *
+ * Data is always a map of km to value. The type "bedload"
+ * translates to german "Geschiebe" other results are either
+ * specific to the top or the sublayer of the riverbed.
+ *
+ * The name can be the diameter of this result for bed and bedload
+ * data.
+ **/
+public class BedQualityResultValue implements Serializable {
+    public static final String[] DIAMETER_NAMES = new String[] {
+        "D90",
+        "D84",
+        "D80",
+        "D75",
+        "D70",
+        "D60",
+        "D50",
+        "D40",
+        "D30",
+        "D25",
+        "D20",
+        "D16",
+        "D10",
+        "DM",
+        "DMIN",
+        "DMAX"
+    };
+
+    /* For ease of access */
+    public static final Set<String> DIAMETER_NAME_SET = new HashSet<String>(
+            Arrays.asList(DIAMETER_NAMES));
+
+    private String      name;
+    private String      type;
+    private double [][] data;
+    private transient PolynomialSplineFunction interpolFunc;
+
+    public BedQualityResultValue() {
+    }
+
+    public BedQualityResultValue(String name, double [][] data, String type) {
+        this.name = name;
+        setData(data);
+        this.type = type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public double [][] getData() {
+        return data;
+    }
+
+    public double getData(double x) {
+        int idx = Arrays.binarySearch(data[0], x);
+        if (idx < 0) {
+            return Double.NaN;
+        } else {
+            return data[1][idx];
+        }
+    }
+
+    public double getDataInterpolated(double x) {
+        if (interpolFunc == null) {
+            interpolFunc = DoubleUtil.getLinearInterpolator(data[0], data[1]);
+        }
+        try {
+            return interpolFunc.value(x);
+        } catch (ArgumentOutsideDomainException e) {
+            return getData(x);
+        }
+    }
+
+    public double [][] getDataInterpolated(double[] x) {
+        double y[] = new double[x.length];
+        int i = 0;
+        for (double point: x) {
+            y[i++] = getDataInterpolated(point);
+        }
+        return new double[][] {x, y};
+    }
+
+    public void setData(double [][] data) {
+        this.data = data;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    /** Checks wether or not the name matches that of a diameter */
+    public boolean isDiameterResult() {
+        return DIAMETER_NAME_SET.contains(name.toUpperCase());
+    }
+}
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedloadDiameterFacet.java	Tue Mar 17 18:52:00 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +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 bedload diameter data.
- *
- * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
- */
-public class BedloadDiameterFacet extends DataFacet {
-
-    private static final long serialVersionUID = 1L;
-
-    private static Logger log = Logger.getLogger(BedloadDiameterFacet.class);
-
-    public BedloadDiameterFacet() {
-        // required for clone operation deepCopy()
-    }
-
-    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.diameter");
-    }
-
-    public Object getData(Artifact artifact, CallContext context) {
-        log.debug("Get data for bedload 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].getBedloadResults(); // TODO CAST TO SPECIFIC CLASS
-
-        int ndy = index & 255;
-        if (raw != null && raw.length > ndy) {
-            BedloadDiameterResult data = (BedloadDiameterResult)raw[ndy];
-            return data.getDiameterData();
-        }
-        return null;
-    }
-
-    /** Copy deeply. */
-    @Override
-    public Facet deepCopy() {
-        BedloadDiameterFacet copy = new BedloadDiameterFacet();
-        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/BedloadDiameterResult.java	Tue Mar 17 18:52:00 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +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.dive4elements.river.artifacts.model.DateRange;
-import org.dive4elements.river.utils.DoubleUtil;
-
-import gnu.trove.TDoubleArrayList;
-
-import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
-
-import org.apache.commons.math.ArgumentOutsideDomainException;
-
-public class BedloadDiameterResult
-extends BedQualityDiameterResult
-{
-    protected TDoubleArrayList diameter;
-    protected PolynomialSplineFunction interpol;
-
-    /** Set to true if this result can't be interpolated.*/
-    protected boolean nonInterpolResult;
-
-    public BedloadDiameterResult(
-        String type,
-        TDoubleArrayList diameter,
-        TDoubleArrayList km,
-        DateRange range
-    ) {
-        super (type, km);
-        this.diameter = diameter;
-        interpol = null;
-        nonInterpolResult = false;
-    }
-
-    public double getDiameter(int ndx) {
-        if (diameter != null) {
-            return this.diameter.get(ndx);
-        }
-        return Double.NaN;
-    }
-
-    public double getDiameter(double km) {
-        if (kms.indexOf(km) >= 0) {
-            return diameter.get(kms.indexOf(km));
-        }
-        return Double.NaN;
-    }
-
-    public double getDiameterInterpol(double km) {
-        if (nonInterpolResult) {
-            return Double.NaN;
-        }
-        if (interpol == null) {
-            interpol = DoubleUtil.getLinearInterpolator(kms, diameter);
-            if (interpol == null) {
-                nonInterpolResult = true;
-                return Double.NaN;
-            }
-        }
-        try {
-            return interpol.value(km);
-        } catch (ArgumentOutsideDomainException e) {
-            /* This is expected for many results. */
-            return Double.NaN;
-        }
-    }
-
-    public double[][] getDiameterData() {
-        return new double[][] {
-            kms.toNativeArray(),
-            diameter.toNativeArray()
-        };
-    }
-}
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/BedQualityState.java	Tue Mar 17 18:52:00 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/BedQualityState.java	Wed Mar 18 18:42:08 2015 +0100
@@ -25,24 +25,17 @@
 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.BedDensityTopFacet;
-import org.dive4elements.river.artifacts.model.minfo.BedDensitySubFacet;
-import org.dive4elements.river.artifacts.model.minfo.BedDiameterTopFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedQualityDataFacet;
 import org.dive4elements.river.artifacts.model.minfo.BedDiameterDataFacet;
-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.BedPorositySubFacet;
-import org.dive4elements.river.artifacts.model.minfo.BedPorosityTopFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedloadDiameterDataFacet;
 import org.dive4elements.river.artifacts.model.minfo.BedQualityCalculation;
-import org.dive4elements.river.artifacts.model.minfo.BedQualityDiameterResult;
 import org.dive4elements.river.artifacts.model.minfo.BedQualityResult;
-import org.dive4elements.river.artifacts.model.minfo.BedloadDiameterDataFacet;
-import org.dive4elements.river.artifacts.model.minfo.BedloadDiameterFacet;
-import org.dive4elements.river.artifacts.model.minfo.BedloadDiameterResult;
+import org.dive4elements.river.artifacts.model.minfo.BedQualityResultValue;
 import org.dive4elements.river.artifacts.resources.Resources;
 import org.dive4elements.river.artifacts.states.DefaultState;
 
+/* TODO: Change data facets to live in the generalized data scheme and
+ * obsolute the obfuscated index magic. */
 
 public class BedQualityState extends DefaultState implements FacetTypes {
 
@@ -51,23 +44,19 @@
     private static final Logger log = Logger
         .getLogger(BedQualityState.class);
 
+    /* The suffix to append to interpol facets. */
+    public static final String I18N_INTERPOL_SUFFIX = "facet.bedquality.interpol.suffix";
+
+    /* I18n is in the pattern base.<name>.<type> with the optional suffix .data */
+    public static final String I18N_FACET_BED_BASE = "facet.bedquality.bed";
+
+    /* Data Layers */
+    public static final String I18N_FACET_BEDLOAD_DIAMETER_DATA = "facet.bedquality.bed.diameter.bedload.data";
+    public static final String I18N_FACET_BED_DIAMETER_DATA_TOPLAYER = "facet.bedquality.bed.diameter.toplayer.data";
+    public static final String I18N_FACET_BED_DIAMETER_DATA_SUBLAYER = "facet.bedquality.bed.diameter.sublayer.data";
     public static final String I18N_TOPLAYER = "bedquality.toplayer";
     public static final String I18N_SUBLAYER = "bedquality.sublayer";
 
-    /* Calculated layers */
-    public static final String I18N_FACET_BED_POROSITY_TOPLAYER = "facet.bedquality.bed.porosity.toplayer";
-    public static final String I18N_FACET_BED_POROSITY_SUBLAYER = "facet.bedquality.bed.porosity.sublayer";
-    public static final String I18N_FACET_BED_DENSITY_TOPLAYER = "facet.bedquality.bed.density.toplayer";
-    public static final String I18N_FACET_BED_DENSITY_SUBLAYER = "facet.bedquality.bed.density.sublayer";
-    public static final String I18N_FACET_BED_DIAMETER_TOPLAYER = "facet.bedquality.bed.diameter.toplayer";
-    public static final String I18N_FACET_BED_DIAMETER_SUBLAYER = "facet.bedquality.bed.diameter.sublayer";
-    public static final String I18N_FACET_BEDLOAD_DIAMETER = "facet.bedquality.bedload.diameter";
-
-    /* Data Layers */
-    public static final String I18N_FACET_BEDLOAD_DIAMETER_DATA = "facet.bedquality.bedload.diameter.data";
-    public static final String I18N_FACET_BED_DIAMETER_DATA_TOPLAYER = "facet.bedquality.bed.diameter.data.toplayer";
-    public static final String I18N_FACET_BED_DIAMETER_DATA_SUBLAYER = "facet.bedquality.bed.diameter.data.sublayer";
-
     static {
         // Active/deactivate facets.
         FacetActivity.Registry.getInstance().register(
@@ -123,13 +112,67 @@
         }
 
         generateFacets(context, newFacets, results, getID(), hash);
+        generateDataFacets(context, newFacets, access, getID(), hash);
         log.debug("Created " + newFacets.size() + " new Facets.");
-        generateDataFacets(context, newFacets, access, getID(), hash);
         facets.addAll(newFacets);
 
         return res;
     }
 
+    private int generateIndex(String diameter) {
+        int d = 0;
+        if(diameter.equals("d10")) {
+            d = 1;
+        }
+        else if (diameter.equals("d16")) {
+            d = 2;
+        }
+        else if (diameter.equals("d20")) {
+            d = 3;
+        }
+        else if (diameter.equals("d25")) {
+            d = 4;
+        }
+        else if (diameter.equals("d30")) {
+            d = 5;
+        }
+        else if (diameter.equals("d40")) {
+            d = 6;
+        }
+        else if (diameter.equals("d50")) {
+            d = 7;
+        }
+        else if (diameter.equals("d60")) {
+            d = 8;
+        }
+        else if (diameter.equals("d70")) {
+            d = 9;
+        }
+        else if (diameter.equals("d75")) {
+            d = 10;
+        }
+        else if (diameter.equals("d80")) {
+            d = 11;
+        }
+        else if (diameter.equals("d84")) {
+            d = 12;
+        }
+        else if (diameter.equals("d90")) {
+            d = 13;
+        }
+        else if (diameter.equals("dmin")) {
+            d = 14;
+        }
+        else if (diameter.equals("dmax")) {
+            d = 15;
+        }
+        else if (diameter.equals("dm")) {
+            d = 16;
+        }
+        int ndx = d << 1;
+        return ndx;
+    }
+
     private void generateDataFacets(
         CallContext context,
         List<Facet> newFacets,
@@ -143,7 +186,7 @@
             DateRange range = ranges.get(i);
             for (String diameter: diameters) {
                 int ndxTop = generateIndex(diameter);
-                int ndxSub = ndxTop; // TODO: Is this correct?
+                int ndxSub = ndxTop;
                 ndxTop += 1;
                 ndxTop = ndxTop << 3;
                 ndxSub = ndxSub << 3;
@@ -202,58 +245,12 @@
         }
     }
 
-    private int generateIndex(String diameter) {
-        int d = 0;
-        if(diameter.equals("d10")) {
-            d = 1;
-        }
-        else if (diameter.equals("d16")) {
-            d = 2;
-        }
-        else if (diameter.equals("d20")) {
-            d = 3;
-        }
-        else if (diameter.equals("d25")) {
-            d = 4;
-        }
-        else if (diameter.equals("d30")) {
-            d = 5;
-        }
-        else if (diameter.equals("d40")) {
-            d = 6;
-        }
-        else if (diameter.equals("d50")) {
-            d = 7;
-        }
-        else if (diameter.equals("d60")) {
-            d = 8;
-        }
-        else if (diameter.equals("d70")) {
-            d = 9;
-        }
-        else if (diameter.equals("d75")) {
-            d = 10;
-        }
-        else if (diameter.equals("d80")) {
-            d = 11;
-        }
-        else if (diameter.equals("d84")) {
-            d = 12;
-        }
-        else if (diameter.equals("d90")) {
-            d = 13;
-        }
-        else if (diameter.equals("dmin")) {
-            d = 14;
-        }
-        else if (diameter.equals("dmax")) {
-            d = 15;
-        }
-        else if (diameter.equals("dm")) {
-            d = 16;
-        }
-        int ndx = d << 1;
-        return ndx;
+
+    protected String getFacetName(BedQualityResultValue value) {
+        /* basename + name or "diameter" + .type */
+        return BED_QUALITY_DATA_FACET + "." +
+            (value.isDiameterResult() ? "diameter" : value.getName()) + "." +
+            value.getType();
     }
 
     protected void generateFacets(CallContext context, List<Facet> newFacets,
@@ -266,111 +263,37 @@
         for (int idx = 0; idx < results.length; idx++) {
             BedQualityResult result = results[idx];
             DateRange range = result.getDateRange();
-            BedDiameterResult[] bedDiameter = result.getBedResults();
-            for (int j = 0; j < bedDiameter.length; j++) {
-                newFacets.add(new BedDiameterTopFacet((idx << 8) + j,
-                    BED_QUALITY_BED_DIAMETER_TOPLAYER,
-                    getLayerDescription(
-                        meta,
-                        bedDiameter[j],
-                        range,
-                        I18N_FACET_BED_DIAMETER_TOPLAYER,
-                        true),
-                    ComputeType.ADVANCE, stateId, hash));
-
-                newFacets.add(new BedDiameterSubFacet((idx << 8) +j,
-                    BED_QUALITY_BED_DIAMETER_SUBLAYER,
-                    getLayerDescription(
-                        meta,
-                        bedDiameter[j],
-                        range,
-                        I18N_FACET_BED_DIAMETER_SUBLAYER,
-                        false),
-                    ComputeType.ADVANCE, stateId, hash));
-            }
-            BedloadDiameterResult[] bedloadDiameter = result.getBedloadResults();
-            for (int j = 0;  j < bedloadDiameter.length; j++) {
-                newFacets.add(new BedloadDiameterFacet(
-                    (idx << 8) + j,
-                    BED_QUALITY_BEDLOAD_DIAMETER,
-                    createDiameterDescription(
-                        meta, bedloadDiameter[j]),
+            int i = 0;
+            for (BedQualityResultValue value: result.getValues()) {
+                newFacets.add(new BedQualityDataFacet((idx << 8) + i++,
+                    getFacetName(value),
+                    getFacetDescription(meta, range, value),
                     ComputeType.ADVANCE,
-                    stateId,
-                    hash));
-
-            }
-            if (bedDiameter.length > 0) {
-                BedParametersResult[] bedParameters = result.getParameters();
-                for (int j = 0; j < bedParameters.length; j++) {
-                    newFacets.add(new BedPorosityTopFacet((idx << 8) + j,
-                        BED_QUALITY_POROSITY_TOPLAYER,
-                        getLayerDescription(
-                            meta,
-                            bedParameters[j],
-                            range,
-                            I18N_FACET_BED_POROSITY_TOPLAYER,
-                            true),
-                        ComputeType.ADVANCE, stateId, hash));
-
-                    newFacets.add(new BedPorositySubFacet((idx << 8) + j,
-                        BED_QUALITY_POROSITY_SUBLAYER,
-                        getLayerDescription(
-                            meta,
-                            bedParameters[j],
-                            range,
-                            I18N_FACET_BED_POROSITY_SUBLAYER,
-                            false),
-                        ComputeType.ADVANCE, stateId, hash));
-
-                    newFacets.add(new BedDensityTopFacet((idx << 8) + j,
-                        BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER,
-                        getLayerDescription(
-                            meta,
-                            bedParameters[j],
-                            range,
-                            I18N_FACET_BED_DENSITY_TOPLAYER,
-                            true),
-                        ComputeType.ADVANCE, stateId, hash));
-
-                    newFacets.add(new BedDensitySubFacet((idx << 8) + j,
-                        BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER,
-                        getLayerDescription(
-                            meta,
-                            bedParameters[j],
-                            range,
-                            I18N_FACET_BED_DENSITY_SUBLAYER,
-                            false),
-                        ComputeType.ADVANCE, stateId, hash));
-                }
+                    stateId, hash, value.getName(), value.getType()));
             }
         }
     }
 
-    protected String getLayerDescription(CallMeta meta,
-        Object result, DateRange range, String i18n, boolean topLayer) {
+    protected String getFacetDescription(CallMeta meta,
+                                         DateRange range,
+                                         BedQualityResultValue value) {
         Date from = range != null ? range.getFrom() : new Date();
         Date to = range != null ? range.getTo() : new Date();
 
-        String layer;
-        /* Maybe just a check if i18n ends with .sublayer? */
-        if (topLayer) {
-            layer = Resources.getMsg(meta, I18N_TOPLAYER, I18N_TOPLAYER);
+        final String layerSuffix =
+            Resources.getMsg(meta, "bedquality." + value.getType(), "");
+
+        /* This could probably be unified with the facet name */
+        final String i18n = I18N_FACET_BED_BASE + "." +
+            (value.isDiameterResult() ? "diameter" : value.getName()) + "." +
+            value.getType();
+
+        if (value.isDiameterResult()) {
+            /* Include the diameter in the description */
+            return Resources.getMsg(meta, i18n, i18n, new Object[] {
+                value.getName().toUpperCase(), from, to, layerSuffix });
         } else {
-            layer = Resources.getMsg(meta, I18N_SUBLAYER, I18N_SUBLAYER);
-        }
-        if (result instanceof BedDiameterResult) {
-            return Resources.getMsg(meta, i18n, i18n, new Object[] { ((BedDiameterResult)result).getType(),
-                from, to, layer });
-        } else {
-            return Resources.getMsg(meta, i18n, i18n, new Object[] { from, to, layer });
+            return Resources.getMsg(meta, i18n, i18n, new Object[] { from, to, layerSuffix });
         }
     }
-
-    protected String createDiameterDescription(CallMeta meta,
-        BedQualityDiameterResult result) {
-        return Resources.getMsg(meta, I18N_FACET_BEDLOAD_DIAMETER,
-            I18N_FACET_BEDLOAD_DIAMETER, new Object[] { result.getType() });
-    }
 }
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityExporter.java	Tue Mar 17 18:52:00 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityExporter.java	Wed Mar 18 18:42:08 2015 +0100
@@ -22,10 +22,8 @@
 
 import au.com.bytecode.opencsv.CSVWriter;
 import org.dive4elements.river.artifacts.model.CalculationResult;
-import org.dive4elements.river.artifacts.model.minfo.BedDiameterResult;
-import org.dive4elements.river.artifacts.model.minfo.BedParametersResult;
 import org.dive4elements.river.artifacts.model.minfo.BedQualityResult;
-import org.dive4elements.river.artifacts.model.minfo.BedloadDiameterResult;
+import org.dive4elements.river.artifacts.model.minfo.BedQualityResultValue;
 import org.dive4elements.river.exports.AbstractExporter;
 import org.dive4elements.river.utils.Formatter;
 
@@ -41,20 +39,8 @@
 
     private static final String CSV_HEADER_KM =
         "export.minfo.bedquality.km";
-    private static final String CSV_HEADER_DENSITY_CAP =
-        "export.minfo.bedquality.density_cap";
-    private static final String CSV_HEADER_DENSITY_SUB =
-        "export.minfo.bedquality.density_sub";
-    private static final String CSV_HEADER_POROSITY_CAP =
-        "export.minfo.bedquality.porosity_cap";
-    private static final String CSV_HEADER_POROSITY_SUB =
-        "export.minfo.bedquality.porosity_sub";
-    private static final String CSV_HEADER_BEDLOAD =
-        "export.minfo.bedquality.bedload";
-    private static final String CSV_HEADER_BED_CAP =
-        "export.minfo.bedquality.bed_cap";
-    private static final String CSV_HEADER_BED_SUB =
-        "export.minfo.bedquality.bed_sub";
+    private static final String CSV_HEADER_BASE =
+        "export.minfo.bedquality";
 
     private BedQualityResult[] results;
 
@@ -68,53 +54,18 @@
         double[] kms = new RangeAccess((D4EArtifact) master).getKmSteps();
 
         int cols = 1;
-        for (BedQualityResult result : results) {
-            BedDiameterResult[]     beds  = result.getBedResults();
-            BedloadDiameterResult[] loads = result.getBedloadResults();
-
-            cols += beds.length * 2;
-            if (beds.length > 0) {
-                cols += 4;
-            }
-            cols += loads.length;
+        for (BedQualityResult result: results) {
+            cols += result.getValues().size();
         }
 
         List<double[]> rows = new ArrayList<double[]>(kms.length);
         for (double km: kms) {
             double[] row = new double[cols];
             row[0] = km;
-            for (int j = 0; j < results.length; j++) {
-
-                BedloadDiameterResult[] loads = results[j].getBedloadResults();
-
-                for(int k = 0; k < loads.length; k++) {
-                    // k + 1: shift km column.
-                    // j* loads.length: shift periods.
-                    row[(k + 1) + (j * loads.length)] =
-                        loads[k].getDiameterInterpol(km);
-                }
-
-                BedDiameterResult[] beds = results[j].getBedResults();
-                if (beds.length == 0) {
-                    continue;
-                }
-                for (int k = 0; k < beds.length; k++) {
-                    // k * 2 + 1: shift km column.
-                    // j * beds.length * 2: shift periods.
-                    // loads.length * results.length: shift bed load columns.
-                    int ndx = (k * 2 + 1) + (j * beds.length * 2) + (loads.length * results.length);
-                    row[ndx] = beds[k].getDiameterCapInterpol(km);
-                    row[ndx + 1] = beds[k].getDiameterSubInterpol(km);
-                }
-
-                BedParametersResult[] params = results[j].getParameters();
-                for(int k = 0; k < params.length; k++) {
-                    // loads.length + (beds.lenght * 2) * (j + 1): shift bed and bedload columns.
-                    int ndx = 1 + (loads.length + (beds.length * 2) * (j + 1));
-                    row[ndx] = params[k].getDensityCapInterpol(km);
-                    row[ndx + 1] = params[k].getDensitySubInterpol(km);
-                    row[ndx + 2] = params[k].getPorosityCapInterpol(km);
-                    row[ndx + 3] = params[k].getPorositySubInterpol(km);
+            for (BedQualityResult result: results) {
+                int i = 1;
+                for (BedQualityResultValue value: result.getValues()) {
+                    row[i++] = value.getDataInterpolated(km);
                 }
             }
             rows.add(row);
@@ -170,48 +121,25 @@
         log.debug("writeCSVHeader()");
 
         List<String> header = new ArrayList<String>();
-        if (results != null)  {
-            header.add(msg(CSV_HEADER_KM, "km"));
-            for (int i = 0; i < results.length; i++) {
-                DateFormat df = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyyy");
-                String d1 = df.format(results[i].getDateRange().getFrom());
-                String d2 = df.format(results[i].getDateRange().getTo());
-                BedloadDiameterResult[] loads = results[i].getBedloadResults();
-                BedDiameterResult[] beds = results[i].getBedResults();
-                BedParametersResult[] params = results[i].getParameters();
-                for (int j = 0; j < loads.length; j++) {
-                    header.add(msg(CSV_HEADER_BEDLOAD, CSV_HEADER_BEDLOAD) +
-                        " - " +
-                        msg(loads[j].getType().toString(),
-                            loads[j].getType().toString()) + " - " +
-                        d1 + "-" + d2);
-                }
-                for (int j = 0; j < beds.length; j++) {
-                    header.add(msg(CSV_HEADER_BED_CAP, CSV_HEADER_BED_CAP) + " - " +
-                        msg(beds[j].getType().toString(),
-                            beds[j].getType().toString()) + " - " +
-                        d1 + "-" + d2);
-                    header.add(msg(CSV_HEADER_BED_SUB, CSV_HEADER_BED_SUB) + " - " +
-                        msg(beds[j].getType().toString(),
-                            beds[j].getType().toString()) + " - " +
-                        d1 + "-" + d2);
-                }
-                if (beds.length == 0) {
-                    continue;
-                }
-                if (params.length > 0) {
-                    header.add(
-                        msg(CSV_HEADER_DENSITY_CAP, CSV_HEADER_DENSITY_CAP) +
-                        " - " + d1 + "-" + d2);
-                    header.add(
-                        msg(CSV_HEADER_DENSITY_SUB, CSV_HEADER_DENSITY_SUB) +
-                        " - " + d1 + "-" + d2);
-                    header.add(
-                        msg(CSV_HEADER_POROSITY_CAP, CSV_HEADER_POROSITY_CAP) +
-                        " - " + d1 + "-" + d2);
-                    header.add(
-                        msg(CSV_HEADER_POROSITY_SUB, CSV_HEADER_POROSITY_SUB) +
-                        " - " + d1 + "-" + d2);
+        if (results == null)  {
+            writer.writeNext(header.toArray(new String[header.size()]));
+            return;
+        }
+
+        header.add(msg(CSV_HEADER_KM, "km"));
+        DateFormat df = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyyy");
+        for (BedQualityResult result: results) {
+            String d1 = df.format(result.getDateRange().getFrom());
+            String d2 = df.format(result.getDateRange().getTo());
+            for (BedQualityResultValue value: result.getValues()) {
+                String i18n;
+                if (value.isDiameterResult()) {
+                    i18n = CSV_HEADER_BASE + ".diameter." + value.getType();
+                    header.add(msg(i18n, i18n) +
+                        " - " + value.getName() + " - " + d1 + "-" + d2);
+                } else {
+                    i18n = CSV_HEADER_BASE + "." + value.getName() + "." + value.getType();
+                    header.add(msg(i18n, i18n) + " - " + d1 + "-" + d2);
                 }
             }
         }
--- a/artifacts/src/main/java/org/dive4elements/river/utils/DoubleUtil.java	Tue Mar 17 18:52:00 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/utils/DoubleUtil.java	Wed Mar 18 18:42:08 2015 +0100
@@ -316,10 +316,10 @@
     /** Convieniance function for results to get an interpolator.
      * This is basically a static wrapper to for LinearInterpolator.interpolate
      * with error handling. Returns null on error.*/
-    public static PolynomialSplineFunction getLinearInterpolator(TDoubleArrayList x, TDoubleArrayList y) {
+    public static PolynomialSplineFunction getLinearInterpolator(double[] x, double[] y) {
         LinearInterpolator lpol = new LinearInterpolator();
         try {
-            return lpol.interpolate(x.toNativeArray(), y.toNativeArray());
+            return lpol.interpolate(x, y);
         } catch (DimensionMismatchException e) {
             log.error("KMs and Result values have different sizes. Failed to interpolate: " +
                     e.getMessage());
@@ -330,5 +330,9 @@
         }
         return null;
     }
+
+    public static PolynomialSplineFunction getLinearInterpolator(TDoubleArrayList x, TDoubleArrayList y) {
+        return getLinearInterpolator(x.toNativeArray(), y.toNativeArray());
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/resources/messages.properties	Tue Mar 17 18:52:00 2015 +0100
+++ b/artifacts/src/main/resources/messages.properties	Wed Mar 18 18:42:08 2015 +0100
@@ -321,10 +321,11 @@
 facet.bedquality.bed.density.sublayer = Density ({0,date} - {1,date}) ({2})
 facet.bedquality.bed.diameter.toplayer = {0}_Bed ({1,date} - {2,date}) ({3})
 facet.bedquality.bed.diameter.sublayer = {0}_Bed ({1,date} - {2,date}) ({3})
-facet.bedquality.bed.diameter.data.toplayer = {0} Bed ({1,date} - {2,date}) ({3}) - measurements
-facet.bedquality.bed.diameter.data.sublayer = {0} Bed ({1,date} - {2,date}) ({3}) - measurements
-facet.bedquality.bedload.diameter.data = {0} Bedload - measurements
-facet.bedquality.bedload.diameter = {0}_Bedload
+facet.bedquality.bed.diameter.toplayer.data = {0} Bed ({1,date} - {2,date}) ({3}) - measurements
+facet.bedquality.bed.diameter.sublayer.data = {0} Bed ({1,date} - {2,date}) ({3}) - measurements
+facet.bedquality.bed.diameter.bedload.data = {0} Bedload - measurements
+facet.bedquality.bed.diameter.bedload = {0}_Bedload
+facet.bedquality.interpol.suffix = " - interpolated"
 bedquality.toplayer = 0.0m - 0.3m
 bedquality.sublayer = 0.1m - 0.5m
 facet.bedheight.diff.year = Bedheight Difference {0}
@@ -482,13 +483,13 @@
 export.sqrelation.measurements.pdf.file = /jasper/sqmeasurements_en.jasper
 export.sqrelation.pdf.mode = Load Discharge Relation
 export.minfo.bedquality.km = km
-export.minfo.bedquality.density_cap = Density Toplayer
-export.minfo.bedquality.density_sub = Density Sublayer
-export.minfo.bedquality.porosity_cap = Porosity Toplayer
-export.minfo.bedquality.porosity_sub = Porosity Sublayer
-export.minfo.bedquality.bedload = Bedload Diameter
-export.minfo.bedquality.bed_cap = Bed Diameter Toplayer
-export.minfo.bedquality.bed_sub = Bed Diameter Sublayer
+export.minfo.bedquality.density.toplayer = Density Toplayer
+export.minfo.bedquality.density.sublayer = Density Sublayer
+export.minfo.bedquality.porosity.toplayer = Porosity Toplayer
+export.minfo.bedquality.porosity.sublayer = Porosity Sublayer
+export.minfo.bedquality.diameter.bedload = Bedload Diameter
+export.minfo.bedquality.diameter.toplayer = Bed Diameter Toplayer
+export.minfo.bedquality.diameter.sublayer = Bed Diameter Sublayer
 export.minfo.beddifference.km = km
 export.minfo.beddifference.diff = Bedheight Difference [cm]
 export.minfo.beddifference.diff.pair = Difference pair
--- a/artifacts/src/main/resources/messages_de.properties	Tue Mar 17 18:52:00 2015 +0100
+++ b/artifacts/src/main/resources/messages_de.properties	Wed Mar 18 18:42:08 2015 +0100
@@ -322,10 +322,11 @@
 facet.bedquality.bed.density.sublayer = Dichte ({0,date} - {1,date}) ({2})
 facet.bedquality.bed.diameter.toplayer = {0}_Sohle ({1,date} - {2,date}) ({3})
 facet.bedquality.bed.diameter.sublayer = {0}_Sohle ({1,date} - {2,date}) ({3})
-facet.bedquality.bed.diameter.data.toplayer = {0} Sohle ({1,date} - {2,date}) ({3}) - Messungen
-facet.bedquality.bed.diameter.data.sublayer = {0} Sohle ({1,date} - {2,date}) ({3}) - Messungen
-facet.bedquality.bedload.diameter.data = {0} Geschiebe - Messungen
-facet.bedquality.bedload.diameter = {0}_Geschiebe
+facet.bedquality.bed.diameter.toplayer.data = {0} Sohle ({1,date} - {2,date}) ({3}) - Messungen
+facet.bedquality.bed.diameter.sublayer.data = {0} Sohle ({1,date} - {2,date}) ({3}) - Messungen
+facet.bedquality.bed.diameter.bedload.data = {0} Geschiebe - Messungen
+facet.bedquality.bed.diameter.bedload = {0}_Geschiebe
+facet.bedquality.interpol.suffix = " - interpoliert"
 bedquality.toplayer = 0,0m - 0,3m
 bedquality.sublayer = 0,1m - 0,5m
 facet.bedheight.diff.year = Sohlh\u00f6hendifferenz {0}
@@ -484,13 +485,13 @@
 export.sqrelation.measurements.pdf.file = /jasper/sqmeasurements.jasper
 export.sqrelation.pdf.mode = Transport-Abfluss Beziehung
 export.minfo.bedquality.km = km
-export.minfo.bedquality.density_cap = Sedimentdichte Deckschicht [t/m\u00b3]
-export.minfo.bedquality.density_sub = Sedimentdichte Unterschicht [t/m\u00b3]
-export.minfo.bedquality.porosity_cap = Porosit\u00e4t Deckschicht [%]
-export.minfo.bedquality.porosity_sub = Porosit\u00e4t Unterschicht [%]
-export.minfo.bedquality.bedload = Geschiebedurchmesser [mm]
-export.minfo.bedquality.bed_cap = Sohldurchmesser Deckschicht [mm]
-export.minfo.bedquality.bed_sub = Sohldurchmesser Unterschicht [mm]
+export.minfo.bedquality.density.toplayer = Sedimentdichte Deckschicht [t/m\u00b3]
+export.minfo.bedquality.density.sublayer = Sedimentdichte Unterschicht [t/m\u00b3]
+export.minfo.bedquality.porosity.toplayer = Porosit\u00e4t Deckschicht [%]
+export.minfo.bedquality.porosity.sublayer = Porosit\u00e4t Unterschicht [%]
+export.minfo.bedquality.diameter.bedload = Geschiebedurchmesser [mm]
+export.minfo.bedquality.diameter.toplayer = Sohldurchmesser Deckschicht [mm]
+export.minfo.bedquality.diameter.sublayer = Sohldurchmesser Unterschicht [mm]
 export.minfo.beddifference.km = Fluss-km
 export.minfo.beddifference.diff = Sohlh\u00f6hendifferenz [cm]
 export.minfo.beddifference.diff.pair = Differenzenpaar
--- a/artifacts/src/main/resources/messages_de_DE.properties	Tue Mar 17 18:52:00 2015 +0100
+++ b/artifacts/src/main/resources/messages_de_DE.properties	Wed Mar 18 18:42:08 2015 +0100
@@ -319,10 +319,11 @@
 facet.bedquality.bed.density.sublayer = Dichte ({0,date} - {1,date}) ({2})
 facet.bedquality.bed.diameter.toplayer = {0}_Sohle ({1,date} - {2,date}) ({3})
 facet.bedquality.bed.diameter.sublayer = {0}_Sohle ({1,date} - {2,date}) ({3})
-facet.bedquality.bed.diameter.data.toplayer = {0} Sohle ({1,date} - {2,date}) ({3}) - Messungen
-facet.bedquality.bed.diameter.data.sublayer = {0} Sohle ({1,date} - {2,date}) ({3}) - Messungen
-facet.bedquality.bedload.diameter.data = {0} Geschiebe - Messungen
-facet.bedquality.bedload.diameter = {0}_Geschiebe
+facet.bedquality.bed.diameter.toplayer.data = {0} Sohle ({1,date} - {2,date}) ({3}) - Messungen
+facet.bedquality.bed.diameter.sublayer.data = {0} Sohle ({1,date} - {2,date}) ({3}) - Messungen
+facet.bedquality.bed.diameter.bedload.data = {0} Geschiebe - Messungen
+facet.bedquality.bed.diameter.bedload = {0}_Geschiebe
+facet.bedquality.interpol.suffix = " - interpoliert"
 bedquality.toplayer = 0,0m - 0,3m
 bedquality.sublayer = 0,1m - 0,5m
 facet.bedheight.diff.year = Sohlh\u00f6hendifferenz {0}
@@ -480,13 +481,13 @@
 export.sqrelation.measurements.pdf.file = /jasper/sqmeasurements.jasper
 export.sqrelation.pdf.mode = Transport-Abfluss Beziehung
 export.minfo.bedquality.km = km
-export.minfo.bedquality.density_cap = Sedimentdichte Deckschicht [t/m\u00b3]
-export.minfo.bedquality.density_sub = Sedimentdichte Unterschicht [t/m\u00b3]
-export.minfo.bedquality.porosity_cap = Porosit\u00e4t Deckschicht [%]
-export.minfo.bedquality.porosity_sub = Porosit\u00e4t Unterschicht [%]
-export.minfo.bedquality.bedload = Geschiebedurchmesser [mm]
-export.minfo.bedquality.bed_cap = Sohldurchmesser Deckschicht [mm]
-export.minfo.bedquality.bed_sub = Sohldurchmesser Unterschicht [mm]
+export.minfo.bedquality.density.toplayer = Sedimentdichte Deckschicht [t/m\u00b3]
+export.minfo.bedquality.density.sublayer = Sedimentdichte Unterschicht [t/m\u00b3]
+export.minfo.bedquality.porosity.toplayer = Porosit\u00e4t Deckschicht [%]
+export.minfo.bedquality.porosity.sublayer = Porosit\u00e4t Unterschicht [%]
+export.minfo.bedquality.diameter.bedload = Geschiebedurchmesser [mm]
+export.minfo.bedquality.diameter.toplayer = Sohldurchmesser Deckschicht [mm]
+export.minfo.bedquality.diameter.sublayer = Sohldurchmesser Unterschicht [mm]
 export.minfo.beddifference.km = Fluss-km
 export.minfo.beddifference.diff = Sohlh\u00f6hendifferenz [cm]
 export.minfo.beddifference.diff.pair = Differenzenpaar
--- a/artifacts/src/main/resources/messages_en.properties	Tue Mar 17 18:52:00 2015 +0100
+++ b/artifacts/src/main/resources/messages_en.properties	Wed Mar 18 18:42:08 2015 +0100
@@ -323,10 +323,11 @@
 facet.bedquality.bed.density.sublayer = Density ({0,date} - {1,date}) ({2})
 facet.bedquality.bed.diameter.toplayer = {0}_Bed ({1,date} - {2,date}) ({3})
 facet.bedquality.bed.diameter.sublayer = {0}_Bed ({1,date} - {2,date}) ({3})
-facet.bedquality.bed.diameter.data.toplayer = {0} Bed ({1,date} - {2,date}) ({3}) - measurements
-facet.bedquality.bed.diameter.data.sublayer = {0} Bed ({1,date} - {2,date}) ({3}) - measurements
-facet.bedquality.bedload.diameter.data = {0} Bedload - measurements
-facet.bedquality.bedload.diameter = {0}_Bedload
+facet.bedquality.bed.diameter.toplayer.data = {0} Bed ({1,date} - {2,date}) ({3}) - measurements
+facet.bedquality.bed.diameter.sublayer.data = {0} Bed ({1,date} - {2,date}) ({3}) - measurements
+facet.bedquality.bed.diameter.bedload.data = {0} Bedload - measurements
+facet.bedquality.bed.diameter.bedload = {0}_Bedload
+facet.bedquality.interpol.suffix = " - interpolated"
 bedquality.toplayer = 0.0m - 0.3m
 bedquality.sublayer = 0.1m - 0.5m
 facet.bedheight.diff.year = Bedheight Difference {0}
@@ -484,13 +485,13 @@
 export.sqrelation.measurements.pdf.file = /jasper/sqmeasurements_en.jasper
 export.sqrelation.pdf.mode = Load Discharge Relation
 export.minfo.bedquality.km = km
-export.minfo.bedquality.density_cap = Density Toplayer [t/m\u00b3]
-export.minfo.bedquality.density_sub = Density Sublayer [t/m\u00b3]
-export.minfo.bedquality.porosity_cap = Porosity Toplayer [%]
-export.minfo.bedquality.porosity_sub = Porosity Sublayer [%]
-export.minfo.bedquality.bedload = Bedload Diameter [mm]
-export.minfo.bedquality.bed_cap = Bed Diameter Toplayer [mm]
-export.minfo.bedquality.bed_sub = Bed Diameter Sublayer [mm]
+export.minfo.bedquality.density.toplayer = Density Toplayer [t/m\u00b3]
+export.minfo.bedquality.density.sublayer = Density Sublayer [t/m\u00b3]
+export.minfo.bedquality.porosity.toplayer = Porosity Toplayer [%]
+export.minfo.bedquality.porosity.sublayer = Porosity Sublayer [%]
+export.minfo.bedquality.diameter.bedload = Bedload Diameter [mm]
+export.minfo.bedquality.diameter.toplayer = Bed Diameter Toplayer [mm]
+export.minfo.bedquality.diameter.sublayer = Bed Diameter Sublayer [mm]
 export.minfo.beddifference.km = km
 export.minfo.beddifference.diff = Bedheight Difference [cm]
 export.minfo.beddifference.diff.pair = Difference pair

http://dive4elements.wald.intevation.org