001/*
002 * Copyright 2006 - 2013
003 *     Stefan Balev     <stefan.balev@graphstream-project.org>
004 *     Julien Baudry    <julien.baudry@graphstream-project.org>
005 *     Antoine Dutot    <antoine.dutot@graphstream-project.org>
006 *     Yoann Pigné      <yoann.pigne@graphstream-project.org>
007 *     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
008 * 
009 * This file is part of GraphStream <http://graphstream-project.org>.
010 * 
011 * GraphStream is a library whose purpose is to handle static or dynamic
012 * graph, create them from scratch, file or any source and display them.
013 * 
014 * This program is free software distributed under the terms of two licenses, the
015 * CeCILL-C license that fits European law, and the GNU Lesser General Public
016 * License. You can  use, modify and/ or redistribute the software under the terms
017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
019 * the Free Software Foundation, either version 3 of the License, or (at your
020 * option) any later version.
021 * 
022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
024 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
025 * 
026 * You should have received a copy of the GNU Lesser General Public License
027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
028 * 
029 * The fact that you are presently reading this means that you have had
030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
031 */
032package org.graphstream.algorithm.measure;
033
034import java.io.File;
035import java.io.IOException;
036
037import javax.swing.JFrame;
038
039import org.jfree.chart.ChartPanel;
040import org.jfree.chart.ChartUtilities;
041import org.jfree.chart.JFreeChart;
042import org.jfree.chart.plot.PlotOrientation;
043
044/**
045 * This is the base for high level measures. These measures allow to compute
046 * statistical values and plotting.
047 */
048public abstract class ChartMeasure {
049        /**
050         * Type of plot.s
051         */
052        public static enum PlotType {
053                /**
054                 * Points connected with lines.
055                 */
056                LINE,
057                /**
058                 * 
059                 */
060                BAR,
061                /**
062                 * 
063                 */
064                PIE,
065                /**
066                 * Cloud of points.
067                 */
068                SCATTER
069        }
070
071        /**
072         * Defines the support used for rendering : on screen or in a file.
073         */
074        public static enum PlotOutputType {
075                SCREEN, PNG, JPEG
076        }
077
078        /**
079         * Exception that can be raised when trying to plot measures.
080         */
081        public static class PlotException extends Exception {
082                private static final long serialVersionUID = -1158885472939044996L;
083
084                public PlotException(String message) {
085                        super(message);
086                }
087
088                public PlotException(Throwable cause) {
089                        super(cause);
090                }
091        }
092
093        /**
094         * Parameters defining how to plot measures.
095         */
096        public static class PlotParameters {
097                /**
098                 * Type of plot. This type is linked to the type of measure : LINE needs
099                 * series measures for example.
100                 */
101                public PlotType type;
102                /**
103                 * Defines if plotting is rendered on the screen or saved on a file.
104                 */
105                public PlotOutputType outputType;
106                /**
107                 * If rendering is saved on a file, this defines the path of this file.
108                 */
109                public String path;
110                /**
111                 * Title of the plot.
112                 */
113                public String title;
114                /**
115                 * Label of the x axis.
116                 */
117                public String xAxisLabel;
118                /**
119                 * Label of the y axis.
120                 */
121                public String yAxisLabel;
122                /**
123                 * Orientation of the plot.
124                 */
125                public PlotOrientation orientation;
126                /**
127                 * True if name of measures should be displayed on the plot.
128                 */
129                public boolean showLegend;
130                /**
131                 * Dimensions of the plot.
132                 */
133                public int width, height;
134
135                public PlotParameters() {
136                        type = PlotType.LINE;
137                        outputType = PlotOutputType.SCREEN;
138                        path = null;
139                        title = "plot";
140                        xAxisLabel = "x-axis";
141                        yAxisLabel = "y-axis";
142                        orientation = PlotOrientation.VERTICAL;
143                        showLegend = true;
144                        width = 600;
145                        height = 300;
146                }
147        }
148
149        /**
150         * Name of this measure. This name is used when plotting the measure.
151         */
152        protected String name;
153
154        /**
155         * Default constructor.
156         * 
157         * @param name
158         *            name of the new measure
159         */
160        protected ChartMeasure(String name) {
161                this.name = name;
162        }
163
164        /**
165         * Create a new plot with default plot parameters.
166         * 
167         * @see #getDefaultPlotParameters()
168         * @throws PlotException
169         */
170        public void plot() throws PlotException {
171                plot(getDefaultPlotParameters());
172        }
173
174        /**
175         * Create a default set of parameters to plot this measure.
176         * 
177         * @return a default PlotParameters adapted to this measure.
178         */
179        public abstract PlotParameters getDefaultPlotParameters();
180
181        /**
182         * Plot this measure using a set of parameters.
183         * 
184         * @param params
185         *            parameters that should be used to plot the measure
186         * @throws PlotException
187         */
188        public abstract void plot(PlotParameters params) throws PlotException;
189
190        /**
191         * Create a new chart of this measure according to a set of parameters.
192         * 
193         * @param params
194         *            the set of parameters used to create the chart
195         * @return a new chart
196         * @throws PlotException
197         */
198        public abstract JFreeChart createChart(PlotParameters params)
199                        throws PlotException;
200
201        /**
202         * Utility function to call
203         * {@link #outputPlot(PlotParameters, JFreeChart...)} with
204         * {@link org.graphstream.algorithm.measure.ChartMeasure} objects.
205         * 
206         * @see #outputPlot(PlotParameters, JFreeChart...)
207         * @param params
208         *            set of parameters used to output the plot
209         * @param measures
210         *            measures to plot
211         * @throws PlotException
212         */
213        public static void outputPlot(PlotParameters params,
214                        ChartMeasure... measures) throws PlotException {
215                if (measures == null || measures.length == 0)
216                        throw new PlotException("no measure");
217
218                JFreeChart[] charts = new JFreeChart[measures.length];
219
220                for (int i = 0; i < measures.length; i++)
221                        charts[i] = measures[i].createChart(params);
222
223                outputPlot(params, charts);
224        }
225
226        /**
227         * Output some charts according to a set of parameters. Actually, only one
228         * chart is supported. According to {@link PlotParameters#outputType}, plot
229         * is displayed on screen or saved in a file.
230         * 
231         * @param params
232         *            parameters used to plot
233         * @param charts
234         *            charts to output
235         * @throws PlotException
236         */
237        public static void outputPlot(PlotParameters params, JFreeChart... charts)
238                        throws PlotException {
239                if (charts == null || charts.length == 0)
240                        throw new PlotException("no chart");
241
242                if (charts.length > 1)
243                        throw new PlotException("multiple charts not yet supported");
244
245                JFreeChart chart = charts[0];
246
247                switch (params.outputType) {
248                case SCREEN:
249                        ChartPanel panel = new ChartPanel(chart, params.width,
250                                        params.height, params.width, params.height,
251                                        params.width + 50, params.height + 50, true, true, true,
252                                        true, true, true);
253
254                        JFrame frame = new JFrame(params.title);
255                        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
256                        frame.add(panel);
257                        frame.pack();
258                        frame.setVisible(true);
259
260                        break;
261                case JPEG:
262                        try {
263                                ChartUtilities.saveChartAsJPEG(new File(params.path), chart,
264                                                params.width, params.height);
265                        } catch (IOException e) {
266                                throw new PlotException(e);
267                        }
268
269                        break;
270                case PNG:
271                        try {
272                                ChartUtilities.saveChartAsPNG(new File(params.path), chart,
273                                                params.width, params.height);
274                        } catch (IOException e) {
275                                throw new PlotException(e);
276                        }
277
278                        break;
279                }
280
281        }
282}