christian@3055: package de.intevation.flys.exports.fixings; christian@3055: christian@3055: import de.intevation.artifactdatabase.state.ArtifactAndFacet; christian@3406: import de.intevation.flys.artifacts.FLYSArtifact; sascha@3408: import de.intevation.flys.artifacts.access.FixAnalysisAccess; christian@3406: import de.intevation.flys.artifacts.model.DateRange; christian@3055: import de.intevation.flys.artifacts.model.FacetTypes; felix@3578: import de.intevation.flys.artifacts.model.NamedDouble; ingo@3551: import de.intevation.flys.artifacts.model.QWDDateRange; christian@3056: import de.intevation.flys.artifacts.model.fixings.FixFunction; christian@3081: import de.intevation.flys.artifacts.model.fixings.FixWQCurveFacet; christian@3062: import de.intevation.flys.artifacts.model.fixings.QW; christian@3062: import de.intevation.flys.artifacts.model.fixings.QWD; christian@3406: import de.intevation.flys.artifacts.resources.Resources; christian@3055: import de.intevation.flys.exports.ChartGenerator; felix@3585: import de.intevation.flys.exports.StyledSeriesBuilder; christian@3194: import de.intevation.flys.jfree.CollisionFreeXYTextAnnotation; christian@3194: import de.intevation.flys.jfree.FLYSAnnotation; christian@3192: import de.intevation.flys.jfree.JFreeUtil; christian@3055: import de.intevation.flys.jfree.StyledXYSeries; christian@3286: import de.intevation.flys.utils.ThemeUtil; christian@3055: felix@3578: import org.jfree.chart.plot.Marker; felix@3578: import org.jfree.chart.plot.ValueMarker; felix@3578: import org.jfree.ui.RectangleAnchor; felix@3578: import org.jfree.ui.TextAnchor; felix@3578: felix@3578: import java.awt.BasicStroke; felix@3578: import java.awt.Color; felix@3578: felix@3578: christian@3200: import java.text.DateFormat; christian@3194: import java.util.ArrayList; christian@3194: import java.util.List; christian@3194: christian@3055: import org.apache.log4j.Logger; christian@3410: import org.jfree.chart.JFreeChart; christian@3194: import org.jfree.chart.annotations.XYTextAnnotation; christian@3410: import org.jfree.chart.title.TextTitle; christian@3055: import org.jfree.data.xy.XYSeries; christian@3055: import org.w3c.dom.Document; christian@3055: christian@3254: /** christian@3286: * Generator for WQ fixing charts. christian@3254: * @author Christian Lins christian@3254: */ sascha@3076: public class FixWQCurveGenerator sascha@3215: extends FixChartGenerator sascha@3215: implements FacetTypes christian@3055: { christian@3055: private static Logger logger = sascha@3057: Logger.getLogger(FixWQCurveGenerator.class); christian@3055: christian@3055: public static final String I18N_CHART_TITLE = christian@3055: "chart.fixings.wq.title"; christian@3055: christian@3055: public static final String I18N_CHART_SUBTITLE = christian@3055: "chart.fixings.wq.subtitle"; christian@3055: christian@3410: public static final String I18N_CHART_SUBTITLE1 = christian@3410: "chart.fixings.wq.subtitle1"; christian@3410: christian@3055: public static final String I18N_XAXIS_LABEL = christian@3055: "chart.fixings.wq.xaxis.label"; christian@3055: christian@3055: public static final String I18N_YAXIS_LABEL = christian@3055: "chart.fixings.wq.yaxis.label"; christian@3055: christian@3055: public static final String I18N_CHART_TITLE_DEFAULT = christian@3055: "Fixierungsanalyse"; christian@3055: christian@3055: public static final String I18N_XAXIS_LABEL_DEFAULT = christian@3055: "Q [m\u00B3/s]"; christian@3055: christian@3055: public static final String I18N_YAXIS_LABEL_DEFAULT = christian@3055: "W [NN + m]"; christian@3055: christian@3055: public static enum YAXIS { christian@3055: W(0), christian@3055: Q(1); christian@3055: public int idx; christian@3055: private YAXIS(int c) { christian@3055: idx = c; christian@3055: } christian@3055: } christian@3055: christian@3406: christian@3406: private FLYSArtifact artifact; christian@3406: christian@3406: christian@3055: @Override christian@3056: public void doOut(ArtifactAndFacet aaf, Document doc, boolean visible) { christian@3056: String name = aaf.getFacetName(); christian@3055: logger.debug("doOut: " + name); christian@3056: christian@3406: this.artifact = (FLYSArtifact)aaf.getArtifact(); christian@3406: christian@3133: if(name.startsWith(FIX_SECTOR_AVERAGE_WQ)) { christian@3056: doSectorAverageOut(aaf, doc, visible); christian@3062: } christian@3062: else if(FIX_ANALYSIS_EVENTS_WQ.equals(name)) { christian@3056: doAnalysisEventsOut(aaf, doc, visible); christian@3062: } christian@3062: else if(FIX_REFERENCE_EVENTS_WQ.equals(name)) { christian@3056: doReferenceEventsOut(aaf, doc, visible); christian@3062: } christian@3062: else if(FIX_WQ_CURVE.equals(name)) { christian@3056: doWQCurveOut(aaf, doc, visible); christian@3062: } christian@3062: else if(FIX_OUTLIER.equals(name)) { christian@3056: doOutlierOut(aaf, doc, visible); christian@3062: } felix@3578: else if(QSECTOR.equals(name)) { felix@3578: doQSectorOut(aaf, doc, visible); felix@3578: } felix@3585: else if(STATIC_WQ.equals(name)) { felix@3585: doWQOut(aaf.getData(context), aaf, doc, visible); felix@3585: } christian@3062: else { christian@3055: logger.warn("Unknown facet name " + name); christian@3055: return; christian@3055: } christian@3055: } christian@3055: christian@3091: /** Add sector average points to chart */ christian@3055: protected void doSectorAverageOut(ArtifactAndFacet aaf, Document doc, boolean visible) { christian@3062: logger.debug("doSectorAverageOut"); christian@3055: ingo@3551: QWDDateRange qwdd = (QWDDateRange) aaf.getData(context); ingo@3551: QWD qwd = qwdd != null ? qwdd.getQWD() : null; ingo@3551: christian@3132: if(qwd != null) { christian@3194: addQWSeries(new QWD[] { qwd }, aaf, doc, visible); christian@3062: } christian@3133: else { christian@3133: logger.debug("doSectorAverageOut: qwd == null"); christian@3133: } christian@3055: } christian@3055: christian@3091: /** Add analysis event points to chart */ christian@3055: protected void doAnalysisEventsOut(ArtifactAndFacet aaf, Document doc, boolean visible) { christian@3194: logger.debug("doAnalysisEventsOut"); christian@3055: christian@3194: QWD[] qwds = (QWD[])aaf.getData(context); christian@3194: if(qwds != null) { christian@3194: addQWSeries(qwds, aaf, doc, visible); christian@3062: } christian@3095: else { christian@3095: logger.debug("doAnalysisEventsOut: qwds == null"); christian@3095: } christian@3055: } christian@3055: christian@3091: /** Add reference event points to chart */ christian@3055: protected void doReferenceEventsOut(ArtifactAndFacet aaf, Document doc, boolean visible) { christian@3055: logger.debug("doReferenceEventsOut"); sascha@3110: christian@3062: QW[] qws = (QW[])aaf.getData(context); christian@3062: addQWSeries(qws, aaf, doc, visible); christian@3055: } christian@3055: christian@3056: protected void doWQCurveOut(ArtifactAndFacet aaf, Document doc, boolean visible) { christian@3056: logger.debug("doWQCurveOut"); christian@3055: christian@3081: FixWQCurveFacet facet = (FixWQCurveFacet)aaf.getFacet(); christian@3081: FixFunction func = (FixFunction)facet.getData( raimund@3088: aaf.getArtifact(), context); sascha@3073: sascha@3073: if (func == null) { christian@3081: logger.warn("doWQCurveOut: Facet does not contain FixFunction"); sascha@3073: return; sascha@3073: } sascha@3110: christian@3081: double maxQ = func.getMaxQ(); sascha@3073: sascha@3215: if (maxQ > 0) { christian@3192: StyledXYSeries series = JFreeUtil.sampleFunction2D( christian@3192: func.getFunction(), christian@3192: doc, christian@3192: aaf.getFacetDescription(), sascha@3215: 500, // number of samples sascha@3215: 0.0 , // start sascha@3215: maxQ); // end christian@3155: christian@3192: addAxisSeries(series, 0, visible); christian@3055: } christian@3062: else { christian@3081: logger.warn("doWQCurveOut: maxQ <= 0"); christian@3062: } christian@3055: } christian@3055: christian@3055: protected void doOutlierOut(ArtifactAndFacet aaf, Document doc, boolean visible) { christian@3055: logger.debug("doOutlierOut"); christian@3055: christian@3062: QW[] qws = (QW[])aaf.getData(context); christian@3062: addQWSeries(qws, aaf, doc, visible); christian@3062: } christian@3062: felix@3578: felix@3578: /** Add markers for q sectors. */ felix@3578: protected void doQSectorOut(ArtifactAndFacet aaf, Document theme, boolean visible) { felix@3578: logger.debug("doQSectorOut"); felix@3578: if (!visible) { felix@3578: return; felix@3578: } felix@3578: felix@3578: List qsectors = (List) aaf.getData(context); felix@3578: felix@3578: if (qsectors == null) { felix@3578: logger.warn("No QSectors coming from data."); felix@3578: return; felix@3578: } felix@3578: for (NamedDouble qsector : qsectors) { felix@3578: if (Double.isNaN(qsector.getValue())) { felix@3578: continue; felix@3578: } felix@3578: Marker m = new ValueMarker(qsector.getValue()); felix@3578: m.setPaint(Color.black); felix@3578: felix@3578: float[] dashes = ThemeUtil.parseLineStyle(theme); felix@3578: int size = ThemeUtil.parseLineWidth(theme); felix@3578: BasicStroke stroke; felix@3578: if (dashes.length <= 1) { felix@3578: stroke = new BasicStroke(Integer.valueOf(size)); felix@3578: } felix@3578: else { felix@3578: stroke = new BasicStroke(Integer.valueOf(size), felix@3578: BasicStroke.CAP_BUTT, felix@3578: BasicStroke.JOIN_ROUND, felix@3578: 1.0f, felix@3578: dashes, felix@3578: 0.0f); felix@3578: } felix@3578: m.setStroke(stroke); felix@3578: felix@3578: if (ThemeUtil.parseShowLineLabel(theme)) { felix@3578: m.setLabel(qsector.getName()); felix@3578: m.setPaint(ThemeUtil.parseTextColor(theme)); felix@3578: m.setLabelFont(ThemeUtil.parseTextFont(theme)); felix@3578: } felix@3578: Color paint = ThemeUtil.parseLineColorField(theme); felix@3578: if (paint != null) { felix@3578: m.setPaint(paint); felix@3578: } felix@3578: m.setLabelAnchor(RectangleAnchor.TOP_LEFT); felix@3578: m.setLabelTextAnchor(TextAnchor.TOP_LEFT); felix@3578: addDomainMarker(m); felix@3578: } felix@3578: } felix@3578: felix@3585: /** felix@3585: * Add WQ Data to plot. felix@3585: * @param wqkms data as double[][] felix@3585: */ felix@3585: protected void doWQOut( felix@3585: Object wqkms, felix@3585: ArtifactAndFacet aaf, felix@3585: Document theme, felix@3585: boolean visible felix@3585: ) { felix@3585: logger.debug("FixWQCurveGenerator: doWQOut"); felix@3585: double [][] data = (double [][]) wqkms; felix@3585: felix@3585: XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); felix@3585: StyledSeriesBuilder.addPoints(series, data, true); felix@3585: felix@3585: addAxisSeries(series, YAXIS.W.idx, visible); felix@3585: } felix@3585: christian@3286: protected void addQWSeries(QW[] qws, ArtifactAndFacet aaf, Document theme, boolean visible) { christian@3062: if(qws != null) { christian@3286: XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); christian@3194: List textAnnos = new ArrayList(); christian@3194: christian@3200: DateFormat dateFormat = DateFormat.getDateInstance( christian@3200: DateFormat.SHORT); christian@3200: christian@3062: for(QW qw : qws) { christian@3062: series.add(qw.getQ(), qw.getW()); christian@3194: christian@3194: XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( christian@3200: dateFormat.format(qw.getDate()), christian@3194: qw.getQ(), christian@3194: qw.getW()); christian@3194: textAnnos.add(anno); christian@3062: } christian@3062: christian@3062: addAxisSeries(series, 0, visible); christian@3286: if(visible && ThemeUtil.parseShowPointLabel(theme)) { christian@3286: FLYSAnnotation flysAnno = new FLYSAnnotation(null, null, null, theme); christian@3212: flysAnno.setTextAnnotations(textAnnos); christian@3212: addAnnotations(flysAnno); christian@3205: } christian@3055: } christian@3055: } christian@3055: christian@3055: @Override christian@3406: protected String getChartTitle() { christian@3406: return Resources.format( christian@3406: context.getMeta(), christian@3406: I18N_CHART_TITLE, christian@3406: I18N_CHART_TITLE_DEFAULT, christian@3406: context.getContextValue(CURRENT_KM)); christian@3406: } christian@3406: christian@3406: @Override christian@3055: protected String getDefaultChartTitle() { christian@3055: return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); christian@3055: } christian@3055: christian@3055: @Override christian@3406: protected String getDefaultChartSubtitle() { sascha@3408: FixAnalysisAccess access = new FixAnalysisAccess(artifact); christian@3409: DateRange dateRange = access.getDateRange(); christian@3409: DateRange refRange = access.getReferencePeriod(); ingo@3466: ingo@3466: if (dateRange != null && refRange != null) { ingo@3466: return Resources.format( ingo@3466: context.getMeta(), ingo@3466: I18N_CHART_SUBTITLE, ingo@3466: "", ingo@3466: access.getRiver(), ingo@3466: dateRange.getFrom(), ingo@3466: dateRange.getTo(), ingo@3466: refRange.getFrom(), ingo@3466: refRange.getTo()); ingo@3466: } ingo@3466: ingo@3466: return null; christian@3406: } christian@3406: christian@3406: @Override christian@3410: protected void addSubtitles(JFreeChart chart) { ingo@3466: String defaultSubtitle = getDefaultChartSubtitle(); ingo@3466: ingo@3466: if (defaultSubtitle == null || defaultSubtitle.length() == 0) { ingo@3466: return; ingo@3466: } ingo@3466: ingo@3466: chart.addSubtitle(new TextTitle(defaultSubtitle)); ingo@3466: christian@3410: StringBuilder buf = new StringBuilder(); christian@3410: christian@3410: // Add analysis periods as additional subtitle christian@3410: FixAnalysisAccess access = new FixAnalysisAccess(artifact); christian@3410: DateRange[] aperiods = access.getAnalysisPeriods(); christian@3410: buf.append(msg("fix.analysis.periods")); christian@3410: buf.append(": "); christian@3410: for(int n = 0; n < aperiods.length; n++) { christian@3410: buf.append( christian@3410: Resources.format( christian@3410: context.getMeta(), christian@3410: I18N_CHART_SUBTITLE1, christian@3410: "", christian@3410: aperiods[n].getFrom(), christian@3410: aperiods[n].getTo())); christian@3410: if(n + 1 < aperiods.length) { christian@3410: buf.append("; "); christian@3410: } christian@3410: } christian@3410: christian@3410: chart.addSubtitle(new TextTitle(buf.toString())); christian@3410: } christian@3410: christian@3410: @Override christian@3055: protected String getDefaultXAxisLabel() { christian@3055: return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); christian@3055: } christian@3055: christian@3055: @Override christian@3055: protected String getDefaultYAxisLabel(int pos) { christian@3055: return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); christian@3055: } christian@3055: christian@3055: @Override christian@3055: protected ChartGenerator.YAxisWalker getYAxisWalker() { christian@3055: return new YAxisWalker() { christian@3055: @Override christian@3055: public int length() { christian@3055: return YAXIS.values().length; christian@3055: } christian@3055: christian@3055: @Override christian@3055: public String getId(int idx) { christian@3055: YAXIS[] yaxes = YAXIS.values(); christian@3055: return yaxes[idx].toString(); christian@3055: } christian@3055: }; sascha@3076: } christian@3055: } christian@3055: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :