src/core/net/sf/basedb/util/plot/ScatterPlot.java

Code
Comments
Other
Rev Date Author Line
2087 17 Mar 06 nicklas 1 /*
2087 17 Mar 06 nicklas 2   $Id$
2087 17 Mar 06 nicklas 3
4889 06 Apr 09 nicklas 4   Copyright (C) 2006 Jari Häkkinen, Nicklas Nordborg
2087 17 Mar 06 nicklas 5
2304 22 May 06 jari 6   This file is part of BASE - BioArray Software Environment.
2304 22 May 06 jari 7   Available at http://base.thep.lu.se/
2087 17 Mar 06 nicklas 8
2087 17 Mar 06 nicklas 9   BASE is free software; you can redistribute it and/or
2087 17 Mar 06 nicklas 10   modify it under the terms of the GNU General Public License
4479 05 Sep 08 jari 11   as published by the Free Software Foundation; either version 3
2087 17 Mar 06 nicklas 12   of the License, or (at your option) any later version.
2087 17 Mar 06 nicklas 13
2087 17 Mar 06 nicklas 14   BASE is distributed in the hope that it will be useful,
2087 17 Mar 06 nicklas 15   but WITHOUT ANY WARRANTY; without even the implied warranty of
2087 17 Mar 06 nicklas 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2087 17 Mar 06 nicklas 17   GNU General Public License for more details.
2087 17 Mar 06 nicklas 18
2087 17 Mar 06 nicklas 19   You should have received a copy of the GNU General Public License
4515 11 Sep 08 jari 20   along with BASE. If not, see <http://www.gnu.org/licenses/>.
2087 17 Mar 06 nicklas 21 */
2087 17 Mar 06 nicklas 22 package net.sf.basedb.util.plot;
2087 17 Mar 06 nicklas 23
2137 31 Mar 06 nicklas 24 import net.sf.basedb.core.BaseException;
2087 17 Mar 06 nicklas 25 import net.sf.basedb.core.query.SqlResult;
2131 30 Mar 06 nicklas 26 import net.sf.basedb.core.query.SqlResultIterator;
4128 05 Feb 08 nicklas 27 import net.sf.basedb.core.signal.ThreadSignalHandler;
2087 17 Mar 06 nicklas 28
2087 17 Mar 06 nicklas 29 import org.jfree.chart.JFreeChart;
2087 17 Mar 06 nicklas 30 import org.jfree.chart.axis.NumberAxis;
2131 30 Mar 06 nicklas 31 import org.jfree.chart.plot.SeriesRenderingOrder;
2087 17 Mar 06 nicklas 32 import org.jfree.chart.plot.XYPlot;
2087 17 Mar 06 nicklas 33 import org.jfree.chart.renderer.xy.XYDotRenderer;
2087 17 Mar 06 nicklas 34 import org.jfree.data.xy.XYSeries;
2087 17 Mar 06 nicklas 35 import org.jfree.data.xy.XYSeriesCollection;
2087 17 Mar 06 nicklas 36
2087 17 Mar 06 nicklas 37 import java.sql.SQLException;
2137 31 Mar 06 nicklas 38 import java.util.ArrayList;
2137 31 Mar 06 nicklas 39 import java.util.Collection;
2137 31 Mar 06 nicklas 40 import java.util.HashMap;
2137 31 Mar 06 nicklas 41 import java.util.List;
2137 31 Mar 06 nicklas 42 import java.util.Map;
2087 17 Mar 06 nicklas 43
2087 17 Mar 06 nicklas 44
2087 17 Mar 06 nicklas 45 /**
2327 24 May 06 nicklas 46   A simple plot utility for generating scatter plots without
2327 24 May 06 nicklas 47   the need to delve deep into the JFreePlot package. Note! This class
2327 24 May 06 nicklas 48   is experimental and it is likely that the implementation will change 
2327 24 May 06 nicklas 49   in the future.
2087 17 Mar 06 nicklas 50
2087 17 Mar 06 nicklas 51   @author Nicklas
2087 17 Mar 06 nicklas 52   @version 2.0
2087 17 Mar 06 nicklas 53   @base.modified $Date$
2087 17 Mar 06 nicklas 54 */
2087 17 Mar 06 nicklas 55 public class ScatterPlot
2087 17 Mar 06 nicklas 56 {
2087 17 Mar 06 nicklas 57   
2087 17 Mar 06 nicklas 58   private XYPlot plot;
2087 17 Mar 06 nicklas 59   private XYSeriesCollection allSeries;
2087 17 Mar 06 nicklas 60   private JFreeChart chart;
2087 17 Mar 06 nicklas 61
2327 24 May 06 nicklas 62   /**
2327 24 May 06 nicklas 63     Create a new ScatterPlot.
2327 24 May 06 nicklas 64     @param nameX The label on the X-axis
2327 24 May 06 nicklas 65     @param nameY The label on the Y-axis
2327 24 May 06 nicklas 66   */
2087 17 Mar 06 nicklas 67   public ScatterPlot(String nameX, String nameY)
2087 17 Mar 06 nicklas 68   {
2087 17 Mar 06 nicklas 69     allSeries = new XYSeriesCollection();
2087 17 Mar 06 nicklas 70     NumberAxis domainAxis = new NumberAxis(nameX);
2087 17 Mar 06 nicklas 71       domainAxis.setAutoRangeIncludesZero(false);
2087 17 Mar 06 nicklas 72
2087 17 Mar 06 nicklas 73       NumberAxis rangeAxis = new NumberAxis(nameY);
2087 17 Mar 06 nicklas 74     rangeAxis.setAutoRangeIncludesZero(true);
2087 17 Mar 06 nicklas 75
2087 17 Mar 06 nicklas 76       plot = new XYPlot(allSeries, domainAxis, rangeAxis, new XYDotRenderer());
2131 30 Mar 06 nicklas 77       plot.setSeriesRenderingOrder(SeriesRenderingOrder.FORWARD);
2087 17 Mar 06 nicklas 78     chart = new JFreeChart(plot);
2087 17 Mar 06 nicklas 79     chart.setAntiAlias(false);
2087 17 Mar 06 nicklas 80   }
2137 31 Mar 06 nicklas 81   
2327 24 May 06 nicklas 82   /**
2327 24 May 06 nicklas 83     Add data to the plot. The <code>SqlResultIterator</code> should return
2327 24 May 06 nicklas 84     the x value as a float in the first position, ie. <code>data.getFloat(1)</code>
2327 24 May 06 nicklas 85     and y values in the positions 2 and up.
2327 24 May 06 nicklas 86
2327 24 May 06 nicklas 87     @param data The data to plot
2327 24 May 06 nicklas 88     @param names An array of series names, x-value for series 'i' is found
2327 24 May 06 nicklas 89       in <code>data.getFloat(2+i)</code>
2327 24 May 06 nicklas 90   */
2131 30 Mar 06 nicklas 91   public void addData(SqlResultIterator data, String... names)
2087 17 Mar 06 nicklas 92     throws SQLException
2087 17 Mar 06 nicklas 93   {
2131 30 Mar 06 nicklas 94     XYSeries[] series = new XYSeries[names.length];
2131 30 Mar 06 nicklas 95     for (int i = 0; i < names.length; ++i)
2131 30 Mar 06 nicklas 96     {
2137 31 Mar 06 nicklas 97       XYSeries s = new XYSeries(names[i]);
2137 31 Mar 06 nicklas 98       s.setNotify(false);
2137 31 Mar 06 nicklas 99       series[i] = s;
2131 30 Mar 06 nicklas 100     }
2087 17 Mar 06 nicklas 101     while (data.hasNext())
2087 17 Mar 06 nicklas 102     {
4128 05 Feb 08 nicklas 103       ThreadSignalHandler.checkInterrupted();
2087 17 Mar 06 nicklas 104       SqlResult r = data.next();
2131 30 Mar 06 nicklas 105       float x = r.getFloat(1);
2131 30 Mar 06 nicklas 106       for (int i = 0; i < series.length; ++i)
2131 30 Mar 06 nicklas 107       {
2131 30 Mar 06 nicklas 108         series[i].add(x, r.getFloat(2+i));
2131 30 Mar 06 nicklas 109       }
2087 17 Mar 06 nicklas 110     }
2131 30 Mar 06 nicklas 111     for (int i = 0; i < series.length; ++i)
2131 30 Mar 06 nicklas 112     {
2131 30 Mar 06 nicklas 113       allSeries.addSeries(series[i]);
2131 30 Mar 06 nicklas 114     }
2087 17 Mar 06 nicklas 115   }
2087 17 Mar 06 nicklas 116   
2327 24 May 06 nicklas 117   /**
2327 24 May 06 nicklas 118     Add data to the plot. The SqlResultIterator must return at least 3 columns.
2327 24 May 06 nicklas 119     The first column in the result is used to determine which annotation/series 
2327 24 May 06 nicklas 120     the spot belongs to. The second column is the x value and the third column 
2327 24 May 06 nicklas 121     is the y value. Additional columns are not used.
2327 24 May 06 nicklas 122     <p>
2327 24 May 06 nicklas 123     The annotations collection contains the mappings from the actual value to
2327 24 May 06 nicklas 124     the annotation. Ie. if the result contains a 1 in the first column we
2327 24 May 06 nicklas 125     check which annotation returns a 1 in it's {@link PlotAnnotation#getValues()}
2327 24 May 06 nicklas 126     method. One value may not be used by more than one annotation.
2327 24 May 06 nicklas 127     
2327 24 May 06 nicklas 128     @param data The data to plot
2327 24 May 06 nicklas 129     @param annotations Annotation information that maps each data spot to 
2327 24 May 06 nicklas 130       an annotation
2327 24 May 06 nicklas 131   */
2137 31 Mar 06 nicklas 132   public void addData(SqlResultIterator data, Collection<PlotAnnotation> annotations)
2137 31 Mar 06 nicklas 133     throws SQLException
2137 31 Mar 06 nicklas 134   {
2137 31 Mar 06 nicklas 135     Map<Integer, XYSeries> series = new HashMap<Integer, XYSeries>(annotations.size());
2137 31 Mar 06 nicklas 136     List<XYSeries> newSeries = new ArrayList<XYSeries>(annotations.size());
2137 31 Mar 06 nicklas 137     for (PlotAnnotation pa : annotations)
2137 31 Mar 06 nicklas 138     {
2137 31 Mar 06 nicklas 139       XYSeries s = new XYSeries(pa.getName());
2137 31 Mar 06 nicklas 140       s.setNotify(false);
2137 31 Mar 06 nicklas 141       newSeries.add(s);
2327 24 May 06 nicklas 142       for (Integer value : pa.getValues())
2137 31 Mar 06 nicklas 143       {
2327 24 May 06 nicklas 144         if (series.containsKey(value))
2137 31 Mar 06 nicklas 145         {
2327 24 May 06 nicklas 146           throw new BaseException("Value " + value + " has already been mapped to another series");
2137 31 Mar 06 nicklas 147         }
2327 24 May 06 nicklas 148         series.put(value, s);
2137 31 Mar 06 nicklas 149       }
2137 31 Mar 06 nicklas 150     }
2137 31 Mar 06 nicklas 151     while (data.hasNext())
2137 31 Mar 06 nicklas 152     {
4128 05 Feb 08 nicklas 153       ThreadSignalHandler.checkInterrupted();
2137 31 Mar 06 nicklas 154       SqlResult r = data.next();
2137 31 Mar 06 nicklas 155       XYSeries s = series.get(r.getInt(1));
2137 31 Mar 06 nicklas 156       s.add(r.getFloat(2), r.getFloat(3));
2137 31 Mar 06 nicklas 157     }
2137 31 Mar 06 nicklas 158     for (XYSeries s : newSeries)
2137 31 Mar 06 nicklas 159     {
2137 31 Mar 06 nicklas 160       allSeries.addSeries(s);
3015 11 Dec 06 nicklas 161       plot.getRenderer().setSeriesVisibleInLegend(allSeries.getSeriesCount()-1, !s.getKey().equals(""));
2137 31 Mar 06 nicklas 162     }
2137 31 Mar 06 nicklas 163   }
2137 31 Mar 06 nicklas 164   
2327 24 May 06 nicklas 165   /**
2327 24 May 06 nicklas 166      Get the underlying JFreeChar object. Use this method to polish up 
2327 24 May 06 nicklas 167      everything and save the image.
2327 24 May 06 nicklas 168   */
2087 17 Mar 06 nicklas 169   public JFreeChart getChart()
2087 17 Mar 06 nicklas 170   {
2087 17 Mar 06 nicklas 171     return chart;
2087 17 Mar 06 nicklas 172   }
2087 17 Mar 06 nicklas 173 }