001 /**
002 * Copyright (c) 2011, SIB. All rights reserved.
003 *
004 * SIB (Swiss Institute of Bioinformatics) - http://www.isb-sib.ch Host -
005 * https://sourceforge.net/projects/javaprotlib/
006 *
007 * Redistribution and use in source and binary forms, with or without
008 * modification, are permitted provided that the following conditions are met:
009 * Redistributions of source code must retain the above copyright notice, this
010 * list of conditions and the following disclaimer. Redistributions in binary
011 * form must reproduce the above copyright notice, this list of conditions and
012 * the following disclaimer in the documentation and/or other materials provided
013 * with the distribution. Neither the name of the SIB/GENEBIO nor the names of
014 * its contributors may be used to endorse or promote products derived from this
015 * software without specific prior written permission.
016 *
017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
020 * ARE DISCLAIMED. IN NO EVENT SHALL SIB/GENEBIO BE LIABLE FOR ANY DIRECT,
021 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
024 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027 */
028 package org.expasy.jpl.commons.collection.render;
029
030
031 import java.awt.Dimension;
032 import java.awt.Paint;
033 import java.awt.image.BufferedImage;
034 import java.io.File;
035 import java.io.IOException;
036 import java.util.ArrayList;
037 import java.util.List;
038 import org.expasy.jpl.commons.base.render.ChartRenderer;
039 import org.expasy.jpl.commons.base.render.ImageFormat;
040 import org.expasy.jpl.commons.collection.Interval;
041 import org.jfree.chart.ChartRenderingInfo;
042 import org.jfree.chart.ChartUtilities;
043 import org.jfree.chart.JFreeChart;
044 import org.jfree.chart.annotations.XYTextAnnotation;
045 import org.jfree.chart.axis.AxisLocation;
046 import org.jfree.chart.axis.NumberAxis;
047 import org.jfree.chart.plot.DatasetRenderingOrder;
048 import org.jfree.chart.plot.XYPlot;
049 import org.jfree.chart.renderer.xy.XYItemRenderer;
050 import org.jfree.data.xy.XYSeries;
051 import org.jfree.data.xy.XYSeriesCollection;
052 import org.jfree.ui.RectangleInsets;
053
054
055 public abstract class Abstract2DChartRenderer<T> implements ChartRenderer {
056
057 public static final ImageFormat DEFAULT_IMAGE_FORMAT = ImageFormat.PNG;
058 public static final Dimension DEFAULT_DIMENSION = new Dimension(600, 400);
059
060 /** dimension of rendered image */
061 private Dimension dimension;
062
063 /** image format */
064
065 private ImageFormat format;
066
067 private XYPlot plot;
068 protected XYSeriesCollection dataset;
069
070 /** render the graph */
071 private XYItemRenderer renderer;
072
073 /** rendering info for interactive graphs **/
074 private ChartRenderingInfo renderingInfo;
075
076 /** possible categories */
077 private List<XYSeries> categories;
078
079 private XYSeries nextSeries;
080
081 /** text annotations */
082 private List<XYTextAnnotation> annots;
083
084 /** the x-axis interval */
085 protected Interval xAxisInterval;
086
087 protected Abstract2DChartRenderer(XYItemRenderer renderer) {
088 this(renderer, DEFAULT_IMAGE_FORMAT, DEFAULT_DIMENSION);
089 }
090
091 protected Abstract2DChartRenderer(XYItemRenderer renderer,
092 ImageFormat format, Dimension dim) {
093 this.format = format;
094 this.dimension = dim;
095 init(renderer, getXLegend(), getYLegend());
096 }
097
098 public void addCategory(XYSeries series) {
099 categories.add(series);
100 }
101
102 /**
103 * Set plot background color.
104 *
105 * @param color the background color.
106 */
107 public void setBackgroundColor(Paint color) {
108 plot.setBackgroundPaint(color);
109 }
110
111 public void setChartColor(int chartIndex, Paint color) {
112 renderer.setSeriesPaint(chartIndex, color);
113 }
114
115 public Paint getChartColor(int chartIndex) {
116 return renderer.getSeriesPaint(chartIndex);
117 }
118
119 /**
120 * Set image dimension.
121 *
122 * @param dim the image dimension.
123 */
124 public void setDimension(Dimension dim) {
125 this.dimension = dim;
126 }
127
128 public void setXAxisInterval(double from, double to) {
129 xAxisInterval = new Interval.Builder(from, to).build();
130 }
131
132 public void setXAxisDefaultInterval() {
133 xAxisInterval = null;
134 }
135
136 /**
137 * Set image format.
138 *
139 * @param format the image format (png or jpeg).
140 */
141 public void setImageFormat(ImageFormat format) {
142 this.format = format;
143 }
144
145 /**
146 * Get image format.
147 *
148 * @return format the image format (png or jpeg).
149 */
150 public ImageFormat getImageFormat() {
151 return format;
152 }
153
154 private void init(XYItemRenderer renderer, String xLegend, String yLegend) {
155 plot = new XYPlot();
156
157 NumberAxis domainAxis = new NumberAxis(xLegend);
158 domainAxis.setAutoRangeIncludesZero(false);
159
160 NumberAxis rangeAxis = new NumberAxis(yLegend);
161 rangeAxis.setAutoRangeIncludesZero(false);
162
163 plot.setDomainAxis(domainAxis);
164 plot.setRangeAxis(rangeAxis);
165 plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
166 plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
167 plot.setDatasetRenderingOrder(DatasetRenderingOrder.REVERSE);
168
169 this.renderer = renderer;
170 plot.setRenderer(renderer);
171
172 renderingInfo = new ChartRenderingInfo();
173 dataset = initDataset();
174
175 categories = new ArrayList<XYSeries>();
176
177 annots = new ArrayList<XYTextAnnotation>();
178 }
179
180 public abstract XYSeriesCollection initDataset();
181
182 public abstract String getXLegend();
183
184 public abstract String getYLegend();
185
186 /**
187 * Set the legend for the m/z axis.
188 *
189 * @param legend the x-axis legend.
190 */
191 public void setXAxisLegend(String legend) {
192 plot.setDomainAxis(new NumberAxis(legend));
193 }
194
195 /**
196 * Set the legend for the intensity axis.
197 *
198 * @param legend the y-axis legend.
199 */
200 public void setYAxisLegend(String legend) {
201 plot.setRangeAxis(new NumberAxis(legend));
202
203 }
204
205 /**
206 * Empty data set.
207 */
208 public void clearDataSet() {
209 dataset.removeAllSeries();
210 plot.clearAnnotations();
211 }
212
213 /**
214 * Add T-object data set
215 *
216 * @param data the data set.
217 * @param seriesCanals the map of series.
218 * @param annots the plot annotations.
219 */
220 public abstract void populateData(T data);
221
222 public void addDataInSeries(int i, double x, double y) {
223 categories.get(i).add(x, y);
224 }
225
226 public void addToCurrentDataSeries(double x, double y) {
227 nextSeries.add(x, y);
228 }
229
230 public void addAnnotInDefaultSeries(XYTextAnnotation textAnnot) {
231 annots.add(textAnnot);
232 }
233
234 public void addDataSet(T data, String seriesName) {
235 nextSeries = new XYSeries(seriesName);
236
237 populateData(data);
238
239 dataset.addSeries(nextSeries);
240 }
241
242 public void addMultiDataSet(T data) {
243 clearDataSet();
244 populateData(data);
245
246 if (annots.size() > 0) {
247 for (XYTextAnnotation annot : annots) {
248 plot.addAnnotation(annot);
249 }
250 }
251
252 for (XYSeries catego : categories) {
253 dataset.addSeries(catego);
254 }
255 }
256
257 /**
258 * @return a new chart that wrap data set.
259 */
260 private JFreeChart flushIntoChart() {
261 plot.setDataset(dataset);
262
263 if (annots.size() > 0) {
264 for (XYTextAnnotation annot : annots) {
265 plot.addAnnotation(annot);
266 }
267 }
268 annots.clear();
269
270 return new JFreeChart(plot);
271 }
272
273 /**
274 * Retrieve rendering info (for interactive graphs).
275 *
276 * @return the rendering information associated to the chart.
277 */
278 public ChartRenderingInfo getRenderingInfo() {
279 return renderingInfo;
280 }
281
282 /**
283 * Create an image (prerequisite: data sets have already been entered via
284 * {@code addDataSet} method).
285 *
286 * @return a new buffered image.
287 */
288 public BufferedImage render() {
289 JFreeChart chart = flushIntoChart();
290 return chart.createBufferedImage((int) dimension.getWidth(),
291 (int) dimension.getHeight(), renderingInfo);
292 }
293
294 /**
295 * Export a chart (prerequisite: data sets have already been entered via
296 * {@code addDataSet} method).
297 *
298 * @param filename the image file name without extension (defined in {@code
299 * ImageFormat}).
300 */
301 public void exportChart(String filename) {
302 JFreeChart chart = flushIntoChart();
303
304 try {
305 switch (format) {
306 case JPG:
307 ChartUtilities.saveChartAsJPEG(new File(filename + ".jpg"),
308 chart, (int) dimension.getWidth(), (int) dimension
309 .getHeight());
310 break;
311 case PNG:
312 ChartUtilities.saveChartAsPNG(new File(filename + ".png"),
313 chart, (int) dimension.getWidth(), (int) dimension
314 .getHeight());
315 }
316 } catch (IOException e) {
317 System.err.println(e.getMessage()
318 + ": Problem occurred while creating chart.");
319 }
320 }
321 }