teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.exports.minfo; rrenkert@4374: rrenkert@5631: import java.util.Arrays; rrenkert@6393: import java.util.Set; rrenkert@5631: rrenkert@4374: import org.apache.log4j.Logger; rrenkert@4374: import org.jfree.data.xy.XYSeries; rrenkert@4374: import org.w3c.dom.Document; rrenkert@4374: teichmann@5831: import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; teichmann@5831: import org.dive4elements.artifactdatabase.state.Facet; teichmann@5867: import org.dive4elements.river.artifacts.D4EArtifact; teichmann@5831: import org.dive4elements.river.artifacts.access.RangeAccess; teichmann@5831: import org.dive4elements.river.artifacts.access.SedimentLoadAccess; teichmann@5831: import org.dive4elements.river.artifacts.model.FacetTypes; teichmann@5831: import org.dive4elements.river.artifacts.model.FlowVelocityData; teichmann@5831: import org.dive4elements.river.artifacts.model.WKms; teichmann@5831: import org.dive4elements.river.artifacts.model.minfo.BedDiffEpochResult; teichmann@5831: import org.dive4elements.river.artifacts.model.minfo.BedDiffYearResult; rrenkert@6393: import org.dive4elements.river.artifacts.model.minfo.SedimentLoad; rrenkert@6393: import org.dive4elements.river.artifacts.model.minfo.SedimentLoadFraction; teichmann@5831: import org.dive4elements.river.exports.StyledSeriesBuilder; teichmann@5831: import org.dive4elements.river.exports.XYChartGenerator; teichmann@5831: import org.dive4elements.river.jfree.Bounds; teichmann@5831: import org.dive4elements.river.jfree.DoubleBounds; teichmann@5864: import org.dive4elements.river.jfree.RiverAnnotation; teichmann@5831: import org.dive4elements.river.jfree.StyledXYSeries; teichmann@5831: import org.dive4elements.river.utils.DataUtil; rrenkert@4374: rrenkert@4374: felix@6682: /** Generator for Longitudinal Sections of SedimentLoad-Calculations. */ rrenkert@4374: public class SedimentLoadLSGenerator rrenkert@4374: extends XYChartGenerator rrenkert@4374: implements FacetTypes rrenkert@4374: { felix@6682: /** Y-Axis enum defining the four possible axes. */ rrenkert@4374: public enum YAXIS { rrenkert@5631: L(0), rrenkert@5631: D(1), rrenkert@5631: DW(2), rrenkert@5631: V(3); rrenkert@4374: rrenkert@4374: protected int idx; rrenkert@4374: rrenkert@4374: private YAXIS(int c) { rrenkert@4374: idx = c; rrenkert@4374: } rrenkert@4374: } rrenkert@4374: /** The logger that is used in this generator. */ rrenkert@5631: private static Logger logger = Logger.getLogger(SedimentLoadLSGenerator.class); rrenkert@4374: rrenkert@4375: public static final String I18N_CHART_TITLE = "chart.sedimentload.ls.title"; rrenkert@4375: public static final String I18N_XAXIS_LABEL = "chart.sedimentload.ls.xaxis.label"; rrenkert@4520: public static final String I18N_YAXIS_LABEL_1 = "chart.sedimentload.ls.yaxis.label.tpera"; rrenkert@4520: public static final String I18N_YAXIS_LABEL_2 = "chart.sedimentload.ls.yaxis.label.m3pera"; rrenkert@5631: public static final String I18N_YAXIS_D_LABEL = "chart.beddifference.yaxis.label.diff"; rrenkert@5631: public static final String I18N_YAXIS_V_LABEL = rrenkert@5631: "chart.flow_velocity.section.yaxis.label"; rrenkert@5631: public final static String I18N_WDIFF_YAXIS_LABEL = rrenkert@5631: "chart.w_differences.yaxis.label"; rrenkert@4374: rrenkert@5631: public final static String I18N_WDIFF_YAXIS_LABEL_DEFAULT = "m"; rrenkert@4375: public static final String I18N_CHART_TITLE_DEFAULT = "Sedimentfracht"; rrenkert@4374: public static final String I18N_XAXIS_LABEL_DEFAULT = "Fluss-Km"; rrenkert@4520: public static final String I18N_YAXIS_LABEL_DEFAULT_1 = "[t/a]"; rrenkert@4520: public static final String I18N_YAXIS_LABEL_DEFAULT_2 = "[m\u00b3/a]"; rrenkert@5631: public static final String I18N_YAXIS_D_LABEL_DEFAULT = "delta S [m]"; rrenkert@5631: public static final String I18N_YAXIS_V_LABEL_DEFAULT = "Geschwindigkeit v [m/s]"; rrenkert@4520: felix@6682: /** Enumerator over y-axes. */ rrenkert@4374: @Override rrenkert@4374: protected YAxisWalker getYAxisWalker() { rrenkert@4374: return new YAxisWalker() { rrenkert@4374: rrenkert@4374: @Override rrenkert@4374: public int length() { rrenkert@4374: return YAXIS.values().length; rrenkert@4374: } rrenkert@4374: rrenkert@4374: @Override rrenkert@4374: public String getId(int idx) { rrenkert@4374: YAXIS[] yaxes = YAXIS.values(); rrenkert@4374: return yaxes[idx].toString(); rrenkert@4374: } rrenkert@4374: }; rrenkert@4374: } rrenkert@4374: rrenkert@4374: @Override rrenkert@4374: public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { rrenkert@4374: String name = bundle.getFacetName(); rrenkert@4374: rrenkert@4374: logger.debug("doOut: " + name); rrenkert@4374: rrenkert@4374: if (name == null) { rrenkert@4374: logger.error("No facet name for doOut(). No output generated!"); rrenkert@4374: return; rrenkert@4374: } rrenkert@4374: rrenkert@4374: Facet facet = bundle.getFacet(); rrenkert@6364: D4EArtifact artifact = (D4EArtifact)bundle.getArtifact(); rrenkert@4374: rrenkert@4374: if (facet == null) { rrenkert@4374: return; rrenkert@4374: } rrenkert@5631: if (getXBounds(0) != null && getDomainAxisRange() != null) { rrenkert@5631: logger.debug(Arrays.toString(getDomainAxisRangeFromRequest())); rrenkert@5631: Bounds bounds = rrenkert@5631: calculateZoom(getXBounds(0), getDomainAxisRange()); rrenkert@5631: context.putContextValue("startkm", bounds.getLower()); rrenkert@5631: context.putContextValue("endkm", bounds.getUpper()); rrenkert@5631: } rrenkert@5631: else if (getXBounds(0) != null && getDomainAxisRange() == null) { rrenkert@5631: context.putContextValue("startkm", getXBounds(0).getLower()); rrenkert@5631: context.putContextValue("endkm", getXBounds(0).getUpper()); rrenkert@5631: } rrenkert@5631: else if (getXBounds(0) == null && getDomainAxisRange() == null) { teichmann@6101: RangeAccess access = new RangeAccess(artifact); rrenkert@5631: context.putContextValue("startkm", access.getFrom()); rrenkert@5631: context.putContextValue("endkm", access.getTo()); rrenkert@5631: } rrenkert@5631: else if (getXBounds(0) == null && getDomainAxisRange() != null){ teichmann@6101: RangeAccess access = new RangeAccess(artifact); rrenkert@5631: Bounds b = new DoubleBounds(access.getFrom(), access.getTo()); rrenkert@5631: Bounds bounds = rrenkert@5631: calculateZoom(b, getDomainAxisRange()); rrenkert@5631: context.putContextValue("startkm", bounds.getLower()); rrenkert@5631: context.putContextValue("endkm", bounds.getUpper()); rrenkert@5631: } felix@6108: if (FacetTypes.IS.SEDIMENT_LOAD(name)) { felix@5653: doSedimentLoadOut( felix@5645: (double[][]) bundle.getData(context), rrenkert@4374: bundle, rrenkert@4374: attr, rrenkert@4374: visible); rrenkert@4374: } rrenkert@6393: else if (FacetTypes.IS.SEDIMENT_LOAD_UNKNOWN(name)) { rrenkert@6393: doSedimentLoadUnknownOut( rrenkert@6393: (SedimentLoad)bundle.getData(context), rrenkert@6393: bundle, rrenkert@6393: attr, rrenkert@6393: visible); rrenkert@6393: } rrenkert@5631: else if (name.equals(FLOW_VELOCITY_TOTALCHANNEL)) { rrenkert@5631: doFlowVelocityTotalOut( rrenkert@5631: (FlowVelocityData) bundle.getData(context), rrenkert@5631: bundle, rrenkert@5631: attr, rrenkert@5631: visible); rrenkert@5631: } rrenkert@5631: else if (name.equals(FLOW_VELOCITY_TOTALCHANNEL_FILTERED)) { rrenkert@5631: doFlowVelocityTotalOut( rrenkert@5631: (FlowVelocityData) bundle.getData(context), rrenkert@5631: bundle, rrenkert@5631: attr, rrenkert@5631: visible); rrenkert@5631: } rrenkert@5631: else if (name.equals(FLOW_VELOCITY_MAINCHANNEL)) { rrenkert@5631: doFlowVelocityMainOut( rrenkert@5631: (FlowVelocityData) bundle.getData(context), rrenkert@5631: bundle, rrenkert@5631: attr, rrenkert@5631: visible); rrenkert@5631: } rrenkert@5631: else if (name.equals(FLOW_VELOCITY_MAINCHANNEL_FILTERED)) { rrenkert@5631: doFlowVelocityMainOut( rrenkert@5631: (FlowVelocityData) bundle.getData(context), rrenkert@5631: bundle, rrenkert@5631: attr, rrenkert@5631: visible); rrenkert@5631: } rrenkert@5631: else if (name.equals(BED_DIFFERENCE_YEAR)) { rrenkert@5631: doBedDifferenceYearOut( rrenkert@5631: (BedDiffYearResult) bundle.getData(context), rrenkert@5631: bundle, rrenkert@5631: attr, rrenkert@5631: visible); rrenkert@5631: } rrenkert@5631: else if (name.equals(BED_DIFFERENCE_YEAR_FILTERED)) { rrenkert@5631: doBedDifferenceYearOut( rrenkert@5631: (BedDiffYearResult) bundle.getData(context), rrenkert@5631: bundle, rrenkert@5631: attr, rrenkert@5631: visible); rrenkert@5631: } rrenkert@5631: else if (name.equals(BED_DIFFERENCE_EPOCH)) { rrenkert@5631: doBedDifferenceEpochOut( rrenkert@5631: (BedDiffEpochResult) bundle.getData(context), rrenkert@5631: bundle, rrenkert@5631: attr, rrenkert@5631: visible); rrenkert@5631: } rrenkert@5631: else if (name.equals(W_DIFFERENCES)) { rrenkert@5631: doWDifferencesOut( rrenkert@5631: (WKms) bundle.getData(context), rrenkert@5631: bundle, rrenkert@5631: attr, rrenkert@5631: visible); rrenkert@5631: } rrenkert@4374: else if (name.equals(LONGITUDINAL_ANNOTATION)) { rrenkert@4374: doAnnotations( teichmann@5864: (RiverAnnotation) bundle.getData(context), rrenkert@4374: bundle, rrenkert@4374: attr, rrenkert@4374: visible); rrenkert@4374: } felix@4579: else if (FacetTypes.IS.MANUALPOINTS(name)) { felix@4579: doPoints( felix@4579: bundle.getData(context), felix@4579: bundle, felix@4579: attr, felix@4579: visible, felix@4579: YAXIS.L.idx); felix@4579: } rrenkert@4374: } rrenkert@4374: rrenkert@4374: @Override rrenkert@4374: protected String getDefaultChartTitle() { rrenkert@4374: return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); rrenkert@4374: } rrenkert@4374: rrenkert@4374: @Override rrenkert@4374: protected String getDefaultXAxisLabel() { rrenkert@4374: return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); rrenkert@4374: } rrenkert@4374: rrenkert@4374: @Override rrenkert@4374: protected String getDefaultYAxisLabel(int pos) { rrenkert@4374: String label = "default"; rrenkert@6364: if (pos == YAXIS.L.idx) { felix@6552: SedimentLoadAccess slaccess = felix@6552: new SedimentLoadAccess((D4EArtifact) getMaster()); felix@6552: String unit = slaccess.getUnit(); felix@6552: if (unit != null && unit.equals("m3_per_a")) { felix@6552: label = msg(I18N_YAXIS_LABEL_2, I18N_YAXIS_LABEL_DEFAULT_2); felix@6552: } felix@6552: else { felix@6552: label = msg(I18N_YAXIS_LABEL_1, I18N_YAXIS_LABEL_DEFAULT_1); felix@6552: } rrenkert@4374: } rrenkert@5631: else if (pos == YAXIS.V.idx) { rrenkert@5631: label = msg(I18N_YAXIS_V_LABEL, I18N_YAXIS_V_LABEL_DEFAULT); rrenkert@5631: } rrenkert@5631: else if (pos == YAXIS.D.idx) { rrenkert@5631: label = msg(I18N_YAXIS_D_LABEL, I18N_YAXIS_D_LABEL_DEFAULT); rrenkert@5631: } rrenkert@5631: else if (pos == YAXIS.DW.idx) { rrenkert@5631: label = msg(I18N_WDIFF_YAXIS_LABEL, I18N_WDIFF_YAXIS_LABEL_DEFAULT); rrenkert@5631: } rrenkert@5631: rrenkert@4374: return label; rrenkert@4374: } rrenkert@4374: felix@5653: protected void doSedimentLoadOut(double[][] data, rrenkert@4545: ArtifactAndFacet aandf, Document theme, boolean visible) { rrenkert@4545: felix@5653: // Allow for gaps (NaNs). felix@5653: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), false, theme); felix@5653: StyledSeriesBuilder.addPoints(series, data, false); felix@5645: felix@5645: addAxisSeries(series, YAXIS.L.idx, visible); teichmann@5650: } felix@5645: rrenkert@6393: protected void doSedimentLoadUnknownOut(SedimentLoad load, rrenkert@6393: ArtifactAndFacet aandf, Document theme, boolean visible) { rrenkert@6393: rrenkert@6393: Set kms = load.getKms(); rrenkert@6393: double[][] data = new double[2][kms.size()]; rrenkert@6393: int counter = 0; rrenkert@6393: for (Double km: kms) { rrenkert@6393: SedimentLoadFraction fraction = load.getFraction(km); rrenkert@6393: data[0][counter] = km; rrenkert@6393: data[1][counter] = fraction.getUnknown(); rrenkert@6393: counter++; rrenkert@6393: } rrenkert@6393: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); rrenkert@6393: StyledSeriesBuilder.addPoints(series, data, false); rrenkert@6393: rrenkert@6393: addAxisSeries(series, YAXIS.L.idx, visible); rrenkert@6393: } rrenkert@6393: rrenkert@5631: protected void doFlowVelocityMainOut( rrenkert@5631: FlowVelocityData data, rrenkert@5631: ArtifactAndFacet aandf, rrenkert@5631: Document theme, rrenkert@5631: boolean visible rrenkert@5631: ) { rrenkert@5631: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); rrenkert@5631: StyledSeriesBuilder.addPoints(series, data.getMainChannelPoints(), true); rrenkert@5631: rrenkert@5631: addAxisSeries(series, YAXIS.V.idx, visible); rrenkert@5631: } rrenkert@5631: rrenkert@5631: protected void doFlowVelocityTotalOut( rrenkert@5631: FlowVelocityData data, rrenkert@5631: ArtifactAndFacet aandf, rrenkert@5631: Document theme, rrenkert@5631: boolean visible rrenkert@5631: ) { rrenkert@5631: if (data == null) { rrenkert@5631: logger.warn("No data to add to FlowVelocity chart."); rrenkert@5631: return; rrenkert@5631: } rrenkert@5631: rrenkert@5631: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); rrenkert@5631: StyledSeriesBuilder.addPoints(series, data.getTotalChannelPoints(), true); rrenkert@5631: rrenkert@5631: addAxisSeries(series, YAXIS.V.idx, visible); rrenkert@5631: } rrenkert@5631: rrenkert@5631: protected void doBedDifferenceYearOut( rrenkert@5631: BedDiffYearResult data, rrenkert@5631: ArtifactAndFacet aandf, rrenkert@5631: Document theme, rrenkert@5631: boolean visible rrenkert@5631: ) { rrenkert@5631: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); rrenkert@5631: StyledSeriesBuilder.addPoints(series, data.getDifferencesData(), true); rrenkert@5631: rrenkert@5631: addAxisSeries(series, YAXIS.D.idx, visible); rrenkert@5631: } rrenkert@5631: rrenkert@5631: protected void doBedDifferenceEpochOut( rrenkert@5631: BedDiffEpochResult data, rrenkert@5631: ArtifactAndFacet aandf, rrenkert@5631: Document theme, rrenkert@5631: boolean visible rrenkert@5631: ) { rrenkert@5631: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); rrenkert@5631: StyledSeriesBuilder.addPoints(series, data.getDifferencesData(), true); rrenkert@5631: rrenkert@5631: addAxisSeries(series, YAXIS.D.idx, visible); rrenkert@5631: } rrenkert@5631: rrenkert@5631: protected void doWDifferencesOut( rrenkert@5631: WKms wkms, rrenkert@5631: ArtifactAndFacet aandf, rrenkert@5631: Document theme, rrenkert@5631: boolean visible rrenkert@5631: ) { rrenkert@5631: if (wkms == null) { rrenkert@5631: logger.warn("No data to add to WDifferencesChart."); rrenkert@5631: return; rrenkert@5631: } rrenkert@5631: rrenkert@5631: XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); rrenkert@5631: rrenkert@5631: StyledSeriesBuilder.addPoints(series, wkms); rrenkert@5631: rrenkert@5631: addAxisSeries(series, YAXIS.D.idx, visible); rrenkert@5631: if (DataUtil.guessWaterIncreasing(wkms.allWs())) { rrenkert@5631: setInverted(true); rrenkert@5631: } rrenkert@5631: } rrenkert@4374: } felix@6497: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :