Array Matrix used for XYZDataset?

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
kimba516
Posts: 4
Joined: Mon May 19, 2008 11:52 pm

Array Matrix used for XYZDataset?

Post by kimba516 » Tue May 20, 2008 11:06 pm

I'm trying to create a spectral plot, very similar to the XYBlockChart demos. Using a XYZDataset seems the easiest to implement, but I keep running into some issues. I've put the data of my plot into a 2-dim array, making a matrix (Mxy) where an element at position (x,y) describes the Z-value. Is there anyway to incorporate this with the XYZDataset?

I've seen this :

Code: Select all

        double[] xvalues = new double[totalRows * totalColumns]; 
        double[] yvalues = new double[totalRows * totalColumns];        
        double[] zvalues = new double[totalRows * totalColumns]; 
        double[][] data = new double[][] {xvalues, yvalues, zvalues};
But my matrix already inherently takes into account the x and y values by position, so basically, can my matrix somehow be used instead?

Thanks for any help!

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Re: Array Matrix used for XYZDataset?

Post by paradoxoff » Fri May 23, 2008 8:26 am

Hi kimba,
there was somebody asking for something similar. See http://www.jfree.org/phpBB2/viewtopic.php?t=23541
In general, if you already have your data structure, there are two ways in which you can use that as a data source in JFreeChart:
1. Put your data in one of the available dataset implementations. Drawback: you have to store your data in two places: in your custom structure and in the dataset. If your data structure changes you would have to do the entire data transport again.
2. Write your own class that implements/extends one of the available dataset interfaces/classes and exposes your data to JFreeChart in the right way. In this way you only have to store your data in one place. If the data in your data structure changes, you can simple fire an event.
Displaying a 2D number array in a plot is a situation somewhere in between an XYPlot and a CategoryPlot.
a) we have a discrete number of equally spaced x values (somehow like in a CategoryPlot). The number of the x values could e. g. stem from an analysis device that records data with a given frequency over a defined time span or that observes a given range in space with a given resolution in datapoints/length unit.
b) for each x-value we have a discrete number of equally spaced y-values. Each x-value has the same number of y-values (again somewhat like a CategoryPlot).
c) for each point in the chart given by the integer coordinates described in a) and b) we have a z-value that we want to show. That is a clear case of an XYZDataset and an XYBlockRenderer.
Let the number of x-values be columnCount and the number of y-values rowCount. Then we can design an XYZData implementation based on the following:
- The number of data points is columnCount*rowCount.
- For the first rowCount data points the x-index is 0, for the next rowCount data points the x-index is 1 an so forth.
- For x-index = 0, the y index is equal to the index of the data point in your value list. After we have displayed the first rowCount data points we are resetting the y-index to zero. In general, the y-index of a data point is the modulus of its index in the data point list divided by the columns displayed so far
- The measurand can be retrieved from an array via [xindex][yindex].

Enough theory, here is a smaple program that will hopefully make the whole thing clearer.
Regards, paradoxoff

Code: Select all

package demo;
import java.awt.Color;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.LookupPaintScale;
import org.jfree.chart.renderer.xy.*;
import org.jfree.data.xy.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.title.*;
import org.jfree.ui.*;

public class XYZChartDemo {
    public XYZChartDemo(String title) {
        JFrame frame = new JFrame(title);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JFreeChart chart = createXYZChart();
        int width = 600;
        int height = 600;
        ChartPanel chartPanel = new ChartPanel(chart,width,height,16,16,width*10,height*10,true,true,true,true,true,true);
        frame.setContentPane(chartPanel);
        frame.pack();
 		frame.setVisible(true);       
    }
    private JFreeChart createXYZChart() {
        NumberAxis xAxis = new NumberAxis("x Axis");
        NumberAxis yAxis = new NumberAxis("y Axis");
        double[][] data = new double[][]{{10.0,15.0,20.0,25.0,30.0},{35.0,40.0,45.0,50.0,55.0},{60.0,65.0,70.0,75.0,80.0}};
		XYZDataset xyzset = new XYZArrayDataset(data);
        XYPlot plot = new XYPlot(xyzset, xAxis, yAxis, null);
        XYBlockRenderer r = new XYBlockRenderer();
        LookupPaintScale ps = new LookupPaintScale(0.0,100.0,Color.GRAY);
		ps.add(10.0,new Color(255,192,192));
		ps.add(15.0,new Color(255,128,128));
		ps.add(20.0,new Color(255,0,0));
		ps.add(25.0,new Color(192,0,0));
		ps.add(30.0,new Color(128,0,0));
		
		ps.add(35.0,new Color(128,255,128));
		ps.add(40.0,new Color(64,255,64));
		ps.add(45.0,new Color(0,224,0));
		ps.add(50.0,new Color(0,160,0));
		ps.add(55.0,new Color(0,96,0));
		
		ps.add(60.0,new Color(192,192,255));
		ps.add(65.0,new Color(128,128,255));
		ps.add(70.0,new Color(0,0,255));
		ps.add(75.0,new Color(0,0,192));
		ps.add(80.0,new Color(0,0,128));
        r.setPaintScale(ps);
        r.setBlockHeight(1.0f);
        r.setBlockWidth(1.0f);
        plot.setRenderer(r);
		JFreeChart chart = new JFreeChart("Chart Title",JFreeChart.DEFAULT_TITLE_FONT,plot,false);
        NumberAxis scaleAxis = new NumberAxis("Scale");
        scaleAxis.setUpperBound(100);
        scaleAxis.setAxisLinePaint(Color.white);
        scaleAxis.setTickMarkPaint(Color.white);
        scaleAxis.setTickLabelFont(new Font("Dialog", Font.PLAIN, 12));
        PaintScaleLegend legend = new PaintScaleLegend(ps, 
                scaleAxis);
        legend.setAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
        legend.setPadding(new RectangleInsets(5, 5, 5, 5));
        legend.setStripWidth(50);
        legend.setPosition(RectangleEdge.RIGHT);
        legend.setBackgroundPaint(Color.WHITE);
        chart.addSubtitle(legend);
        chart.setBackgroundPaint(Color.white);
        return chart;
    }
	private static class XYZArrayDataset extends AbstractXYZDataset{
		double[][] data;
		int rowCount = 0;
		int columnCount = 0;
		
		XYZArrayDataset(double[][] data){
			this.data = data;
			rowCount = data.length;
			columnCount = data[0].length;
		}
		public int getSeriesCount(){
			return 1;
		}
		public Comparable getSeriesKey(int series){
			return "serie";
		}
		public int getItemCount(int series){
			return rowCount*columnCount;
		}
		public double getXValue(int series,int item){
			return (int)(item/columnCount);
		}
		public double getYValue(int series,int item){
			return item % columnCount;
		}
		public double getZValue(int series,int item){
			return data[(int)(item/columnCount)][item % columnCount];
		}
		public Number getX(int series,int item){
			return new Double((int)(item/columnCount));
		}
		public Number getY(int series,int item){
			return new Double(item % columnCount);
		}
		public Number getZ(int series,int item){
			return new Double(data[(int)(item/columnCount)][item % columnCount]);
		}
	}
    public static void main(String[] args) {
        XYZChartDemo demo = new XYZChartDemo(
                "XYZ Demo");
    }
}

kimba516
Posts: 4
Joined: Mon May 19, 2008 11:52 pm

Post by kimba516 » Fri May 23, 2008 3:11 pm

Wow thanks a lot! I'm definitely going to give that a go, but it looks like this should get the job done!

benito
Posts: 4
Joined: Wed Jun 04, 2008 7:11 pm

Post by benito » Wed Jun 04, 2008 7:20 pm

Hi,

I was having trouble with updating the chart when the XYZArrayDataset data changes (or is updated).
I'm trying to create a dynamic XYZBlockRenderer chart to which values can be added.
Any suggestions?


Thanks , greatly appreciated.

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

Post by david.gilbert » Wed Jun 04, 2008 7:47 pm

If you add a new method to the class that allows the data to be updated, make sure the method fires a DatasetChangeEvent to all registered listeners. The plot listens for this, and sets off a chain of events that leads to the ChartPanel being repainted (which redraws the chart with the new data).
David Gilbert
JFreeChart Project Leader

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

benito
Posts: 4
Joined: Wed Jun 04, 2008 7:11 pm

Post by benito » Wed Jun 04, 2008 10:23 pm

Thank you very much, and thanks for the quick response.

My chart is working great.

allensmith
Posts: 2
Joined: Thu Jan 29, 2015 8:31 am
antibot: No, of course not.

Re: Array Matrix used for XYZDataset?

Post by allensmith » Wed Mar 04, 2015 7:22 am

Hi,i am a designer of code128 of java barcode project.I'm using XYBlockRenderer with XYZDataset.when I run my code, my Java program runs at almost 55% of my CPU. Does anyone have any suggestions on how to improve the performance of this?

Locked