Adding x values and y values as separate series 1.0.13

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
84923331
Posts: 8
Joined: Fri Jun 12, 2009 2:04 pm

Adding x values and y values as separate series 1.0.13

Post by 84923331 » Wed Jun 24, 2009 2:23 pm

Is it possible to create a series with only 1 parameter, as in one list of numbers for use in either xy series or time series. Right now to plot a series I add data to to a xy series with .add(x, y) where x and y are the x and y values to be plotted. I would like to know if you can create a series with just 1 parameter, and create say series A series B with an add function with just 1 value like .add(value) so that when you choose to create the graph you can select which series you would like to plot as the x (say series A) values against another (say series B) as the y values. I've looked at the api and in xy series and time series you can create you can only add data points with two values. However I am asking if anyone knows any way around this. The reason why I am asking this is that when I read in the data for the time series/xy series graphs I do not know which values will be the x and y values because the user should be able to select which tracks of data to plot as the x and y values. Now, I can read in the data first, storing it into my own data structures ( which takes approximately 5 - 10 seconds depending on the size of the data ) and then when the user selects which tracks to plot, add the data from my own data structure into the series object in jfreechart in a big for loop. However, adding the values into the series objects take just about as much time as it takes to load the data in originally, which is why I would like to store the data into the series objects as soon as I read the data instead of into my own data structure, and then when the user wants a graph the graphing will almost be instant, that way the user only ever has to wait while loading a file. However, since the add function in series only accepts two values, one of which I do not know which one of the data tracks to load into yet, this is not possible for me. That is why I would like series with only 1 value (or a solution like this), so I can quickly plot the graphs after I get the data and only wait once for the data to load. If anything is unclear feel free to say so and I will explain. I did not post any pictures or example code because neither are relevant to my question.

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: Adding x values and y values as separate series 1.0.13

Post by david.gilbert » Wed Jun 24, 2009 2:28 pm

Stick with your own data structure, but wrap it in your own class that implements the XYDataset interface. Your class should have a flag that determines whether the first or second series is used as the x-values (and then obviously the other series is used for the y-values).
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

84923331
Posts: 8
Joined: Fri Jun 12, 2009 2:04 pm

Re: Adding x values and y values as separate series 1.0.13

Post by 84923331 » Wed Jun 24, 2009 2:42 pm

This sounds like a sound solution, I will try to use this method. Thanks for the fast reply!

84923331
Posts: 8
Joined: Fri Jun 12, 2009 2:04 pm

Re: Adding x values and y values as separate series 1.0.13

Post by 84923331 » Wed Jun 24, 2009 4:51 pm

For those interested I'll post what I have so far:

The implemented XYDataset:

Code: Select all

import java.util.Vector;
import org.jfree.data.DomainOrder;
import org.jfree.data.general.DatasetChangeListener;
import org.jfree.data.general.DatasetGroup;
import org.jfree.data.xy.XYDataset;
/**
 * Holds all of the information read from a raw file and interfaced with JFreeChart.
 * Implements methods from XYDataset interface, which specify how to get x and y-values and the
 * size of such collections. Holds all of the data read from a raw file in the "data" field
 * and the y-values to be plotted in the "yValues" vector and the x-values in the "xValues" field.
 * Changing or adding values should change the graph through observer pattern.
 * @author	
 * @since	June 24, 2009
 */
public class MyDataset implements XYDataset{
	/**
	 * The total set of data.
	 * Not for giving JFreeChart for plotting but just for storing.
	 */
	private Vector<DataTrack> data;
	/**
	 * The list of DataTrack objects to be plotted as y-values.
	 * To be given to JFreeChart to be plotted.
	 */
	private Vector<DataTrack> yValues;
	/**
	 * The DataTrack representing the list of numbers to be plotted as
	 * the x values.
	 */
	private DataTrack xValues;
	/**
	 * Constructor.
	 */
	public MyDataset(){
		data = new Vector<DataTrack>();
		yValues = new Vector<DataTrack>();
		xValues = null;
	}
	/**
	 * Adds a new data track with given name.
	 * @param	name	The name of the track to be added.
	 */
	public void addTrack(String name){
		data.add(new DataTrack(name));
	}
	/**
	 * Returns the domain order.
	 * @return	The order.
	 */
	public DomainOrder getDomainOrder() {
		// TODO Auto-generated method stub
		return null;
	}
	/**
	 * Returns the item count for a selected series.
	 * @param	series	The series selected.
	 * @return	The item count for a series. Returns 0 if the series index is wrong.
	 */
	public int getItemCount(int series) {
		if(series < 0 || series > yValues.size()) return 0;
		return yValues.get(series).getSize();
	}
	/**
	 * Adds a data value to selected parameter track.
	 * Example: add(2, 10.54) adds the value 10.54 to the 2nd data track.
	 * @param	index	The index.
	 * @param	value	The value to be added.
	 * @return	True if successfully added.
	 * 			False, if the index given was out of bounds.
	 */
	public boolean add(int index, Float value){
		if(index < 0 || index > data.size()){
			return false;
		}
		data.get(index).add(value);
		notifyAll();
		return true;
	}
	/**
	 * Returns the name of a data track.
	 * @param	index	The index.
	 * @return	The name of the data track.
	 * 			Null if the index doesn't exist.
	 */
	public String getName(int index){
		if(index < 0 || index > data.size()){
			System.err.println("DataBuffer.getName(int index): index out of bounds.");
			return null;
		}
		return data.get(index).getName();
	}
	/**
	 * Returns the size of the parameter data track selected.
	 * @param	index	The index of the vector of DataTrack objects.
	 * @return	The size of the DataTrack.
	 * 			Returns -1 if the index does not exist.
	 */
	public int getSize(int index){
		if(index < 0 || index > data.size()) return -1;
		return data.get(index).getSize();
	}
	/**
	 * Sets which of the data tracks to plot as the x-values.
	 * @param	index	The index.
	 * @return	True if successfully set a track as the x-values.
	 * 			False if index does not exist.
	 */
	public boolean setXValues(int index){
		if(index < 0 || index > data.size()) return false;
		xValues = data.get(index);
		notifyAll();
		return true;
	}
	/**
	 * Sets which data tracks to plot as the y-values.
	 * @param	index	The index.
	 * @return	True if successfully set a track to plot.
	 * 			False if index does not exist.
	 */
	public boolean setToPlot(int index){
		if(index < 0 || index > data.size()) return false;
		yValues.add(data.get(index));
		notifyAll();
		return true;
	}
	/**
	 * Returns the number of data tracks.
	 * @return	Number of data tracks.
	 */
	public int getSize(){
		return data.size();
	}
	/**
	 * Returns the x-value.
	 * @param	series	Not used since the y-values will be the same for all tracks.
	 * @param	index	I'm assuming this index means the index through the list of x-values.
	 * 					JFreeChart documentation calls this "item".
	 * @return	The x-value. Returns 0 if there is nothing to return yet.
	 */
	public Number getX(int series, int index) {
		if(xValues == null) return null;
		return xValues.get(index);
	}
	/**
	 * Returns the y-value as a double primitive.
	 * @param	series	I assume this is the index of one of the multiple series a XYDataset can hold.
	 * @param	index	I assume this is the index for the list of y-values for a series in XYDataset.
	 * 					JFreeChart documentation calls this "item".
	 * @return	The y-value. Return 0 if the index is incorrect.
	 */
	public double getXValue(int series, int index) {
		if(xValues == null) return 0;
		return xValues.get(index);
	}
	/**
	 * Returns the y-value.
	 * @param	series	I assume this is the index of one of the multiple series a XYDataset can hold.
	 * @param	index	I assume this is the index for the list of y-values for a series in XYDataset.
	 * 					JFreeChart documentation calls this "item".
	 * @return	The y-value. Return 0 if the index is incorrect.
	 */
	public Number getY(int series, int index) {
		if(index < 0 || index > yValues.size()) return 0;
		return yValues.get(series).get(index);
	}
	/**
	 * Returns the y-value as a double primitive.
	 * @param	series	I assume this is the index of one of the multiple series a XYDataset can hold.
	 * @param	index	I assume this is the index for the list of y-values for a series in XYDataset.
	 * 					JFreeChart documentation calls this "item".
	 * @return	The y-value. Return 0 if the index is incorrect.
	 */
	public double getYValue(int series, int index) {
		if(index < 0 || index > yValues.size()) return 0;
		return yValues.get(series).get(index);
	}
	/**
	 * Returns the number of series in the dataset or in this case the
	 * number of data tracks that are set to be plotted.
	 */
	public int getSeriesCount() {
		return yValues.size();
	}
	public Comparable getSeriesKey(int arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	public int indexOf(Comparable arg0) {
		// TODO Auto-generated method stub
		return 0;
	}

	public void addChangeListener(DatasetChangeListener arg0) {
		// TODO Auto-generated method stub
		
	}

	public DatasetGroup getGroup() {
		// TODO Auto-generated method stub
		return null;
	}

	public void removeChangeListener(DatasetChangeListener arg0) {
		// TODO Auto-generated method stub
		
	}

	public void setGroup(DatasetGroup arg0) {
		// TODO Auto-generated method stub
		
	}

}
My data structure used:

Code: Select all

import java.util.Vector;
/**
 * A data track.  Which is essentially a list of numbers with a name label so I know what these
 * numbers represent.
 * @autho
 * @since	June 24, 2009
 */
public class DataTrack {
	/**
	 * The list of values the data track has. (example: 10.24, 23.09, 7.89 ...).
	 */
	private Vector<Float> values;
	/**
	 * The name of the data track (example: "SysTime")
	 */
	private String name;
	/**
	 * Constructor specifying the name of the data track.
	 * @param	name	The name of this track.
	 */
	public DataTrack(String name){
		this.name = name;
		values = new Vector<Float>();
	}
	/**
	 * Add a value to the track.
	 * @param	value	The value to add.
	 */
	public void add(Float value){
		values.add(value);
	}
	/**
	 * Returns a value.
	 * @param	index	The index.
	 * @return	The value.
	 */
	public Float get(int index){
		return values.get(index);
	}
	/**
	 * Returns the size of the list of values.
	 * @return	Number of values in the list.
	 */
	public int getSize(){
		return values.size();
	}
	/**
	 * Returns the name.
	 * @return	The name of this list of values.
	 */
	public String getName(){
		return name;
	}
}
I also have concerns about real-time large-dataset: I have tried using large datasets and real-time, the real-time seems to work fine with version 1.0.13, large data sets still load slow when first loading data but plots almost instantly after all the data is loaded, even when adding data the refresh is almost instant (I guess you guys have incorporated a lot of the fast classes discussed in the mentioned thread, also I saw references to fast classes in the 1.0.13 api). My concern is If I use my own version of an implemented XYDataset will this affect the real-time large-dataset abilities of JFreeChart? Is it okay to keep notifyAll() in my method which adds new data to the dataset? Thanks for reading, comments welcome.

Locked