/* * Software Name : ATK * * Copyright (C) 2007 - 2012 France Télécom * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * ------------------------------------------------------------------ * File Name : GraphGenerator.java * * Created : 28/03/2008 * Author(s) : France Telecom */ package com.orange.atk.results.logger.documentGenerator; import java.awt.image.BufferedImage; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Date; import javax.imageio.ImageIO; import org.apache.log4j.Logger; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.DateAxis; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import com.orange.atk.graphAnalyser.RelativeDateFormat; import com.orange.atk.platform.Platform; import com.orange.atk.results.measurement.PlotList; public class GraphGenerator { /** * Generate a graph in png from the provided plot list. The X axis of the * graph is in minutes. * * @param plotList * plotlist to save. Xvalues must be stored in milliseconds. * @param associatedName * kind of the list * @param folderWhereResultsAreSaved * folder where graph while be saved * @param yLabel * name of the y label * @param pictureFile * name of the file where the picture would be saved (path should * be absolute) * @param yDivisor divisor of the measurements */ public static void generateGraph(PlotList plotList, String associatedName, String folderWhereResultsAreSaved, String yLabel, String pictureFile, float yDivisor) { Logger.getLogger("generateGraph"). debug(folderWhereResultsAreSaved + associatedName + ".cmd"); // Store measurements in a file try { dumpInFile(plotList, folderWhereResultsAreSaved + associatedName + ".csv"); // Create gnuplot scripts used to generate graphs if (plotList.isEmpty()) { Logger.getLogger(GraphGenerator.class ) .warn(associatedName + " plot list is empty"); return; } // create a .cmd which will be given to the gnuplot program File commandFile = new File(folderWhereResultsAreSaved + associatedName + ".cmd"); BufferedWriter bufferedWriter = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(commandFile))); // Picture will be saved in png bufferedWriter.write("set terminal png" + Platform.LINE_SEP); // Name of the picture bufferedWriter.write("set output '" + folderWhereResultsAreSaved + associatedName + ".png'" + Platform.LINE_SEP); // format of the number on the y-axis bufferedWriter.write("set format y \"%.3s\"" + Platform.LINE_SEP); // Names of the axis bufferedWriter.write("set xlabel \"Time\"" + Platform.LINE_SEP); bufferedWriter.write("set ylabel \"" + yLabel + "\"" + Platform.LINE_SEP); // Set the range on y axis bufferedWriter.write("set yrange [" + (plotList.getMin() / yDivisor) * 0.9998 + ":" + (plotList.getMax() / yDivisor) * 1.0002 + "]" + Platform.LINE_SEP); bufferedWriter.write("set xtics autofreq" + Platform.LINE_SEP); bufferedWriter.write("set ytics autofreq" + Platform.LINE_SEP); bufferedWriter.write("plot '" + folderWhereResultsAreSaved + associatedName + ".csv' with lines" + Platform.LINE_SEP); bufferedWriter.flush(); bufferedWriter.close(); // call gnuplot for generating graphs Runtime runtime = Runtime.getRuntime(); String gnuplotName = null; if (Platform.OS_NAME.toLowerCase().contains("windows")) { gnuplotName = "wgnuplot"; } else { gnuplotName = "gnuplot"; } String[] cmdsCpu1 = { gnuplotName, folderWhereResultsAreSaved + associatedName + ".cmd" }; if (!plotList.isEmpty()) { // Call gnuplot int returnValue = runtime.exec(cmdsCpu1).waitFor(); if (returnValue != 0) { Logger.getLogger(GraphGenerator.class ) .warn("Problem while creating graph. Does " + gnuplotName + " program belongs to PATH?"); } } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } /** * This function creates the measurement graph by using the JFreeChart * library. The X axis of the graph is in minutes. * * @param plotList * plotlist to save. Xvalues must be stored in milliseconds. * @param associatedName * Name of the list * @param folderWhereResultsAreSaved * folder where results are saved * @param yLabel * Name of the y label * @param pictureFile * name of the file * @param yDivisor * use to divide measurements stored in the plotlist by yDivisor */ public static void generateGraphWithJFreeChart(PlotList plotList, String associatedName, String folderWhereResultsAreSaved, String yLabel, String pictureFile, float yDivisor) { // Create a new XYSeries // XYSeries are used to represent couples of (x,y) values. XYSeries data = new XYSeries(associatedName); int size = plotList.getSize(); if (size == 0) { // no element in graphics, exit //Logger.getLogger(this.getClass() ).warn("Nothing in graph"); return; } // Find the initial value of the time // Due to the fact that getX(i) <= getX(i+1), // min({0<=i<size / getX(i)}) = getX(0) long initialValue = plotList.getX(0); XYSeriesCollection series = new XYSeriesCollection(data); if(!plotList.getunit().equals("")) yLabel+=" ("+plotList.getunit()+")"; // Create a new XY graph. //JFreeChart chart = ChartFactory.createXYLineChart("", "Time", yLabel, series, PlotOrientation.VERTICAL, true, true, false); JFreeChart chart = ChartFactory.createTimeSeriesChart("", "Time (min:sec)", yLabel, series, true, true, false); // Set the graph format XYPlot plot = chart.getXYPlot(); plot.setOrientation(PlotOrientation.VERTICAL); DateAxis axis = (DateAxis) plot.getDomainAxis(); //axis.setTickUnit(new DateTickUnit(DateTickUnit.SECOND, 10)); RelativeDateFormat rdf = new RelativeDateFormat(initialValue); rdf.setSecondFormatter(new DecimalFormat("00")); axis.setDateFormatOverride(rdf); // Fill the JFreeChart object which will be used to create the Graph for (int i = 0; i < size; i++) { // xvalue must be in double xval = ((Long) plotList.getX(i)).doubleValue(); float yval = plotList.getY(i).floatValue() / yDivisor; // Logger.getLogger(this.getClass() ).debug(associatedName + " [" + (((Long) // plotList.getX(i)).floatValue() - initialValue) // / XDIVISOR +"] "+ yval); data.add(xval, yval); } ValueAxis rangeAxis = plot.getRangeAxis(); Long min = plotList.getMin(); Long max = plotList.getMax(); double diff = (max-min)*0.02; if(diff == 0) diff = max * 0.0001; rangeAxis.setLowerBound((min-diff) / yDivisor); rangeAxis.setUpperBound((max+diff) / yDivisor); // Logger.getLogger(this.getClass() ).debug("(" + (min / yDivisor) * 0.98 + " - " // + (min / yDivisor) * 0.98 + ")"); // Logger.getLogger(this.getClass() ).debug("Bound = " + rangeAxis.getLowerBound() + " - " // + rangeAxis.getUpperBound()); // Logger.getLogger(this.getClass() ).debug("Margin = " + rangeAxis.getLowerMargin() + " - " // + rangeAxis.getUpperMargin()); // Logger.getLogger(this.getClass() ).debug("NB AXIS = " + plot.getRangeAxisCount()); // save the chart in a picture file. BufferedImage bufImage = chart.createBufferedImage(640, 480); File fichier = new File(pictureFile); try { if (!ImageIO.write(bufImage, "png", fichier)) { return; } } catch (IOException e) { e.printStackTrace(); } } /** * Save the data of a plot list into a file. A divisor value coould be apply * to X, ie values would be dived by Xdivisor value are * stored on each line as :<br/> (x_i-x_0)/Xdivisor \t y <br/> * format, the first value is shifted to 0. * * @param plotList * plot list to save * @param fileName * file name where plot list would be saved * @param Xdivisor * divisor for the X axis * @param Ydivisor * divisor for the Y axis * @throws ArrayIndexOutOfBoundsException * @throws IOException */ public static void dumpInFile(PlotList plotList, String fileName) throws ArrayIndexOutOfBoundsException, IOException { int iXListSize = plotList.getSize(); if (iXListSize > 0) { // get the first value to translate the x scale // x rep SimpleDateFormat spf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); SimpleDateFormat year = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat hour = new SimpleDateFormat("HH:mm:ss"); SimpleDateFormat ms = new SimpleDateFormat("SSS"); // double initialValue = ((Long) plotList.getX(0)).doubleValue(); File fichier = new File(fileName); BufferedWriter bufferedWriter = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(fichier))); bufferedWriter.write("# "+ spf.format(new Date(plotList.getX(0)))+ "-" + Platform.LINE_SEP); bufferedWriter.write("# yyyy-MM-dd, HH:mm:ss:SSS,value"+ Platform.LINE_SEP); for (int i = 0; i < iXListSize; i++) { // Logger.getLogger(this.getClass() ).debug(((plotList.getX(i)).floatValue()) + " - " // + initialValue); long xval = (((Long) plotList.getX(i))); float yval = plotList.getY(i).floatValue(); bufferedWriter.write(year.format(new Date(xval))+", " +hour.format(new Date(xval)) +":"+ms.format(new Date(xval))+"," + yval + Platform.LINE_SEP); // Logger.getLogger(this.getClass() ).debug(xval + "\t" + yval ); } bufferedWriter.close(); } } }