changeset 2702:4c00cf83fff1

Added state, calculation and csv exporter for MINFO flow velociy calculation. flys-artifacts/trunk@4418 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Wed, 16 May 2012 08:37:27 +0000
parents c553d4fa3957
children aa4391648a05
files flys-artifacts/ChangeLog flys-artifacts/doc/conf/artifacts/minfo.xml flys-artifacts/doc/conf/conf.xml flys-artifacts/src/main/java/de/intevation/flys/artifacts/MINFOArtifact.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FlowVelocityCalculation.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FlowVelocityData.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/FlowVelocityState.java flys-artifacts/src/main/java/de/intevation/flys/exports/FlowVelocityExporter.java flys-artifacts/src/main/java/de/intevation/flys/utils/Formatter.java
diffstat 9 files changed, 533 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Wed May 16 08:21:02 2012 +0000
+++ b/flys-artifacts/ChangeLog	Wed May 16 08:37:27 2012 +0000
@@ -1,3 +1,33 @@
+2012-05-16  Ingo Weinzierl <ingo@intevation.de>
+
+	* doc/conf/artifacts/minfo.xml: Added new state and csv export for MINFO flow
+	  velocity calculation.
+
+	* doc/conf/conf.xml: Registered a new CSV exporter for flow velocity
+	  values.
+
+	* src/main/java/de/intevation/flys/artifacts/model/FlowVelocityCalculation.java:
+	  New calculation for MINFO flow velocity. Actually, this is no
+	  calculation but a bundling of data.
+
+	* src/main/java/de/intevation/flys/artifacts/model/FlowVelocityData.java:
+	  New model class that is used to store flow velocity relevant data.
+
+	* src/main/java/de/intevation/flys/artifacts/states/FlowVelocityState.java:
+	  New state that triggers the FlowVelocityCalculation and creates new
+	  facets. Currently, only a CSV Facet is created.
+
+	* src/main/java/de/intevation/flys/artifacts/MINFOArtifact.java: Added
+	  methods to retrieve the IDs of main channels and total channels for the
+	  flow velocity calculation.
+
+	* src/main/java/de/intevation/flys/utils/Formatter.java: New formatters
+	  that are used in CSV exporter for flow velocity.
+
+	* src/main/java/de/intevation/flys/exports/FlowVelocityExporter.java: New
+	  concrete subclasses of AbstractExporter that currently implements the
+	  path to export FlowVelocityData as CSV.
+
 2012-05-16  Ingo Weinzierl <ingo@intevation.de>
 
 	* src/main/java/de/intevation/flys/artifacts/HYKArtifact.java,
--- a/flys-artifacts/doc/conf/artifacts/minfo.xml	Wed May 16 08:21:02 2012 +0000
+++ b/flys-artifacts/doc/conf/artifacts/minfo.xml	Wed May 16 08:37:27 2012 +0000
@@ -36,6 +36,24 @@
             <data name="main.channel"  type="intoptions"/>
         </state>
 
+        <transition transition="de.intevation.flys.artifacts.transitions.DefaultTransition">
+            <from state="state.minfo.dischargestate"/>
+            <to state="state.minfo.flow_velocity"/>
+        </transition>
+
+        <state id="state.minfo.flow_velocity" description="state.minfo.flow_velocity" state="de.intevation.flys.artifacts.states.FlowVelocityState" helpText="help.minfo.flowvelocity">
+            <outputmodes>
+                <outputmode name="flow_velocity_export" description="output.flow_velocity_export" mime-type="text/plain" type="export">
+                    <facets>
+                        <facet name="csv" description="facet.flow_velocity_export.csv" />
+                        <!--
+                        <facet name="pdf" description="facet.historical_discharge.pdf" />
+                        -->
+                    </facets>
+                </outputmode>
+            </outputmodes>
+        </state>
+
     </states>
 
 </artifact>
--- a/flys-artifacts/doc/conf/conf.xml	Wed May 16 08:21:02 2012 +0000
+++ b/flys-artifacts/doc/conf/conf.xml	Wed May 16 08:37:27 2012 +0000
@@ -227,6 +227,7 @@
         <output-generator name="historical_discharge">de.intevation.flys.exports.HistoricalDischargeCurveGenerator</output-generator>
         <output-generator name="historical_discharge_chartinfo">de.intevation.flys.exports.HistoricalDischargeCurveInfoGenerator</output-generator>
         <output-generator name="historical_discharge_export">de.intevation.flys.exports.HistoricalDischargeCurveExporter</output-generator>
+        <output-generator name="flow_velocity_export">de.intevation.flys.exports.FlowVelocityExporter</output-generator>
         <!-- Error report generators. -->
         <output-generator name="discharge_longitudinal_section_report">de.intevation.flys.exports.ReportGenerator</output-generator>
         <output-generator name="waterlevel_report">de.intevation.flys.exports.ReportGenerator</output-generator>
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/MINFOArtifact.java	Wed May 16 08:21:02 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/MINFOArtifact.java	Wed May 16 08:37:27 2012 +0000
@@ -244,5 +244,29 @@
         logger.warn("MINFOArtifact.getInitialFacetActivity: not implemented!");
         return 1;
     }
+
+
+    public int[] getMainChannels() {
+        String data = getDataAsString("main.channel");
+
+        if (data == null) {
+            logger.warn("No 'main.channel' parameter specified!");
+            return null;
+        }
+
+        return FLYSUtils.intArrayFromString(data);
+    }
+
+
+    public int[] getTotalChannels() {
+        String data = getDataAsString("total.channel");
+
+        if (data == null) {
+            logger.warn("No 'total.channel' parameter specified!");
+            return null;
+        }
+
+        return FLYSUtils.intArrayFromString(data);
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FlowVelocityCalculation.java	Wed May 16 08:37:27 2012 +0000
@@ -0,0 +1,155 @@
+package de.intevation.flys.artifacts.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import de.intevation.flys.model.DischargeZone;
+import de.intevation.flys.model.FlowVelocityModel;
+import de.intevation.flys.model.FlowVelocityModelValue;
+import de.intevation.flys.model.River;
+
+import de.intevation.flys.artifacts.MINFOArtifact;
+import de.intevation.flys.artifacts.model.FlowVelocityData;
+import de.intevation.flys.utils.FLYSUtils;
+
+
+public class FlowVelocityCalculation extends Calculation {
+
+    private static final Logger logger =
+        Logger.getLogger(FlowVelocityCalculation.class);
+
+
+    public CalculationResult calculate(MINFOArtifact artifact) {
+        logger.info("FlowVelocityCalculation.calculate");
+
+        int[] mainIds  = artifact.getMainChannels();
+        int[] totalIds = artifact.getTotalChannels();
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("Artifact '" + artifact.identifier() + "' contains:");
+            if (mainIds != null) {
+                logger.debug("   " + mainIds.length + " main channel ids");
+            }
+
+            if (totalIds != null) {
+                logger.debug("   " + totalIds.length + " total channel ids");
+            }
+        }
+
+        List<DischargeZone>     zones  = getDischargeZones(mainIds, totalIds);
+        List<FlowVelocityModel> models = getFlowVelocityModels(artifact, zones);
+
+        return buildCalculationResult(artifact, models);
+    }
+
+
+    protected List<DischargeZone> getDischargeZones(
+        int[] mainIds,
+        int[] totalIds
+    ) {
+        List<DischargeZone> zones = new ArrayList<DischargeZone>();
+
+        if (mainIds != null) {
+            for (int id: mainIds) {
+                DischargeZone zone = DischargeZone.getDischargeZoneById(id);
+
+                if (zone != null) {
+                    zones.add(zone);
+                }
+            }
+        }
+
+        if (totalIds != null) {
+            for (int id: totalIds) {
+                DischargeZone zone = DischargeZone.getDischargeZoneById(id);
+
+                if (zone != null) {
+                    zones.add(zone);
+                }
+            }
+        }
+
+        return zones;
+    }
+
+
+    protected List<FlowVelocityModel> getFlowVelocityModels(
+        MINFOArtifact       artifact,
+        List<DischargeZone> zones
+    ) {
+        River river = FLYSUtils.getRiver(artifact);
+
+        List<FlowVelocityModel> models = new ArrayList<FlowVelocityModel>();
+
+        for (DischargeZone zone: zones) {
+            List<FlowVelocityModel> model =
+                FlowVelocityModel.getModels(river, zone);
+
+            if (model != null) {
+                models.addAll(model);
+            }
+        }
+
+        return models;
+    }
+
+
+    protected void prepareData(
+        FlowVelocityData  data,
+        FlowVelocityModel model,
+        double kmLo,
+        double kmHi
+    ) {
+        List<FlowVelocityModelValue> values =
+            FlowVelocityModelValue.getValues(model, kmLo, kmHi);
+
+        logger.debug("Found " + values.size() + " values for model.");
+
+        for (FlowVelocityModelValue value: values) {
+            data.addKM(value.getStation().doubleValue());
+            data.addQ(value.getQ().doubleValue());
+            data.addVTotal(value.getTotalChannel().doubleValue());
+            data.addVMain(value.getMainChannel().doubleValue());
+            data.addTauMain(value.getShearStress().doubleValue());
+        }
+
+        DischargeZone zone = model.getDischargeZone();
+        String        lo   = zone.getLowerDischarge();
+        String        hi   = zone.getUpperDischarge();
+
+        if (lo.equals(hi)) {
+            data.setZone(lo);
+        }
+        else {
+            data.setZone(lo + " - " + hi);
+        }
+    }
+
+
+    protected CalculationResult buildCalculationResult(
+        MINFOArtifact           artifact,
+        List<FlowVelocityModel> models
+    ) {
+        double kmLo = artifact.getDataAsDouble("ld_from");
+        double kmHi = artifact.getDataAsDouble("ld_to");
+
+        logger.debug("Prepare data for km range: " + kmLo + " - " + kmHi);
+
+        FlowVelocityData[] data = new FlowVelocityData[models.size()];
+
+        for (int i = 0, n = models.size(); i < n; i++) {
+            FlowVelocityData d = new FlowVelocityData();
+
+            prepareData(d, models.get(i), kmLo, kmHi);
+
+            data[i] = d;
+        }
+
+        logger.debug("Calculation contains " + data.length + " data items.");
+
+        return new CalculationResult(data, this);
+    }
+}
+// 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/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FlowVelocityData.java	Wed May 16 08:37:27 2012 +0000
@@ -0,0 +1,78 @@
+package de.intevation.flys.artifacts.model;
+
+import java.io.Serializable;
+
+import gnu.trove.TDoubleArrayList;
+
+
+public class FlowVelocityData implements Serializable {
+
+    private TDoubleArrayList km;
+    private TDoubleArrayList vMain;
+    private TDoubleArrayList vTotal;
+    private TDoubleArrayList tauMain;
+    private TDoubleArrayList q;
+    private String zone;
+
+
+    protected FlowVelocityData() {
+        this.km      = new TDoubleArrayList();
+        this.vMain   = new TDoubleArrayList();
+        this.vTotal  = new TDoubleArrayList();
+        this.tauMain = new TDoubleArrayList();
+        this.q       = new TDoubleArrayList();
+    }
+
+
+    public void addKM(double km) {
+        this.km.add(km);
+    }
+
+    public double getKM(int idx) {
+        return km.get(idx);
+    }
+
+    public void addVMain(double vMain) {
+        this.vMain.add(vMain);
+    }
+
+    public double getVMain(int idx) {
+        return vMain.get(idx);
+    }
+
+    public void addVTotal(double vTotal) {
+        this.vTotal.add(vTotal);
+    }
+
+    public double getVTotal(int idx) {
+        return vTotal.get(idx);
+    }
+
+    public void addTauMain(double tauMain) {
+        this.tauMain.add(tauMain);
+    }
+
+    public double getTauMain(int idx) {
+        return tauMain.get(idx);
+    }
+
+    public void addQ(double q) {
+        this.q.add(q);
+    }
+
+    public double getQ(int idx) {
+        return q.get(idx);
+    }
+
+    public void setZone(String zone) {
+        this.zone = zone;
+    }
+
+    public String getZone() {
+        return zone;
+    }
+
+    public int size() {
+        return km.size();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/FlowVelocityState.java	Wed May 16 08:37:27 2012 +0000
@@ -0,0 +1,71 @@
+package de.intevation.flys.artifacts.states;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import de.intevation.artifactdatabase.state.Facet;
+
+import de.intevation.artifacts.CallContext;
+
+import de.intevation.flys.artifacts.FLYSArtifact;
+import de.intevation.flys.artifacts.MINFOArtifact;
+import de.intevation.flys.artifacts.model.CalculationResult;
+import de.intevation.flys.artifacts.model.DataFacet;
+import de.intevation.flys.artifacts.model.FacetTypes;
+import de.intevation.flys.artifacts.model.FlowVelocityCalculation;
+import de.intevation.flys.artifacts.model.FlowVelocityData;
+
+
+public class FlowVelocityState extends DefaultState implements FacetTypes {
+
+    private static Logger logger = Logger.getLogger(FlowVelocityState.class);
+
+
+    @Override
+    public Object computeAdvance(
+        FLYSArtifact artifact,
+        String       hash,
+        CallContext  context,
+        List<Facet>  facets,
+        Object       old
+    ) {
+        logger.debug("FlowVelocityState.computeAdvance");
+
+        List<Facet> newFacets = new ArrayList<Facet>();
+
+        CalculationResult res = old instanceof CalculationResult
+            ? (CalculationResult) old
+            : new FlowVelocityCalculation().calculate((MINFOArtifact) artifact);
+
+        if (facets == null || res == null) {
+            return res;
+        }
+
+        FlowVelocityData[] data = (FlowVelocityData[]) res.getData();
+
+        logger.debug("Calculated " + data.length + " FlowVelocityData objects");
+
+        String id = getID();
+
+        for (FlowVelocityData d: data) {
+            logger.error("TODO: Implement Facet creation for chart!");
+
+        }
+
+        Facet csv = new DataFacet(
+            CSV, "CSV data", ComputeType.ADVANCE, hash, id);
+
+        // TODO ADD PDF FACET
+
+        newFacets.add(csv);
+
+        logger.debug("Created " + newFacets.size() + " new Facets.");
+
+        facets.addAll(newFacets);
+
+        return res;
+    }
+}
+// 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/flys-artifacts/src/main/java/de/intevation/flys/exports/FlowVelocityExporter.java	Wed May 16 08:37:27 2012 +0000
@@ -0,0 +1,123 @@
+package de.intevation.flys.exports;
+
+import java.io.OutputStream;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Document;
+
+import org.apache.log4j.Logger;
+
+import au.com.bytecode.opencsv.CSVWriter;
+
+import de.intevation.artifacts.CallContext;
+
+import de.intevation.flys.artifacts.model.CalculationResult;
+import de.intevation.flys.artifacts.model.FlowVelocityData;
+import de.intevation.flys.utils.Formatter;
+
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class FlowVelocityExporter extends AbstractExporter {
+
+    private static final Logger logger =
+        Logger.getLogger(FlowVelocityExporter.class);
+
+
+    public static final String CSV_KM =
+        "export.flow_velocity.csv.header.km";
+
+    public static final String CSV_V_TOTAL =
+        "export.flow_velocity.csv.header.v_total";
+
+    public static final String CSV_V_MAIN =
+        "export.flow_velocity.csv.header.v_main";
+
+    public static final String CSV_TAU_MAIN =
+        "export.flow_velocity.csv.header.tau_main";
+
+    public static final String CSV_Q =
+        "export.flow_velocity.csv.header.q";
+
+    public static final String CSV_LOCATIONS =
+        "export.flow_velocity.csv.header.locations";
+
+
+    protected List<FlowVelocityData[]> data;
+
+
+    public void init(Document request, OutputStream out, CallContext cc) {
+        super.init(request, out, cc);
+        data = new ArrayList<FlowVelocityData[]>();
+    }
+
+
+    @Override
+    protected void addData(Object d) {
+        if (d instanceof CalculationResult) {
+            d = ((CalculationResult) d).getData();
+
+            if (d instanceof FlowVelocityData[]) {
+                logger.debug("Add new data of type FlowVelocityData");
+                data.add((FlowVelocityData[]) d);
+            }
+        }
+    }
+
+
+    @Override
+    protected void writeCSVData(CSVWriter writer) {
+        logger.info("FlowVelocityExporter.writeCSVData");
+        logger.debug("CSV gets " + data.size() + " FlowVelocityData objects.");
+
+        writeCSVHeader(writer);
+
+        for (FlowVelocityData[] d: data) {
+            data2CSV(writer, d);
+        }
+    }
+
+
+    protected void writeCSVHeader(CSVWriter writer) {
+        writer.writeNext(new String[] {
+            msg(CSV_KM, CSV_KM),
+            msg(CSV_V_TOTAL, CSV_V_TOTAL),
+            msg(CSV_V_MAIN, CSV_V_MAIN),
+            msg(CSV_TAU_MAIN, CSV_TAU_MAIN),
+            msg(CSV_Q, CSV_Q),
+            msg(CSV_LOCATIONS, CSV_LOCATIONS)
+        });
+    }
+
+
+    protected void data2CSV(CSVWriter writer, FlowVelocityData[] fData) {
+        logger.debug("Add next FlowVelocityData to CSV");
+
+        for (FlowVelocityData data: fData) {
+            for (int i = 0, n = data.size(); i < n; i++) {
+                NumberFormat kmF  = Formatter.getFlowVelocityKM(context);
+                NumberFormat valF = Formatter.getFlowVelocityValues(context);
+                NumberFormat qF   = Formatter.getFlowVelocityQ(context);
+
+                writer.writeNext(new String[] {
+                    kmF.format(data.getKM(i)),
+                    valF.format(data.getVMain(i)),
+                    valF.format(data.getVTotal(i)),
+                    valF.format(data.getTauMain(i)),
+                    qF.format(data.getQ(i)) + "=" + data.getZone(),
+                    "TODO: add Location for km"// TODO Add Locations
+                });
+            }
+        }
+    }
+
+
+    @Override
+    protected void writePDF(OutputStream out) {
+        logger.error("TODO: Implement FlowVelocityExporter.writePDF");
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/utils/Formatter.java	Wed May 16 08:21:02 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/utils/Formatter.java	Wed May 16 08:37:27 2012 +0000
@@ -48,6 +48,15 @@
     public static final int DURATION_D_MAX_DIGITS = 0;
 
 
+    // FLOW VELOCITY FORMATTER CONSTANTS
+    public static final int FLOW_VELOCITY_KM_MIN_DIGITS     = 3;
+    public static final int FLOW_VELOCITY_KM_MAX_DIGITS     = 3;
+    public static final int FLOW_VELOCITY_VALUES_MIN_DIGITS = 2;
+    public static final int FLOW_VELOCITY_VALUES_MAX_DIGITS = 2;
+    public static final int FLOW_VELOCITY_Q_MIN_DIGITS      = 0;
+    public static final int FLOW_VELOCITY_Q_MAX_DIGITS      = 2;
+
+
     public static NumberFormat getFormatter(CallMeta m, int min, int max){
         Locale       locale = Resources.getLocale(m);
         NumberFormat nf     = NumberFormat.getInstance(locale);
@@ -233,5 +242,29 @@
             CALCULATION_REPORT_KM_MIN_DIGITS,
             CALCULATION_REPORT_KM_MAX_DIGITS);
     }
+
+
+    public static NumberFormat getFlowVelocityKM(CallContext context) {
+        return getFormatter(
+            context,
+            FLOW_VELOCITY_KM_MIN_DIGITS,
+            FLOW_VELOCITY_KM_MAX_DIGITS);
+    }
+
+
+    public static NumberFormat getFlowVelocityValues(CallContext context) {
+        return getFormatter(
+            context,
+            FLOW_VELOCITY_VALUES_MIN_DIGITS,
+            FLOW_VELOCITY_VALUES_MAX_DIGITS);
+    }
+
+
+    public static NumberFormat getFlowVelocityQ(CallContext context) {
+        return getFormatter(
+            context,
+            FLOW_VELOCITY_Q_MIN_DIGITS,
+            FLOW_VELOCITY_Q_MAX_DIGITS);
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org