Révision 137

tmp/org.txm.chartsengine.jfreechart.core/src/org/txm/chartsengine/jfreechart/core/JFCChartsEngine.java (revision 137)
1 1
package org.txm.chartsengine.jfreechart.core;
2 2

  
3
import java.awt.BasicStroke;
4
import java.awt.Color;
5 3
import java.awt.Graphics2D;
6 4
import java.awt.geom.Rectangle2D;
7 5
import java.awt.image.BufferedImage;
......
10 8
import java.io.FileOutputStream;
11 9
import java.io.FileWriter;
12 10
import java.io.IOException;
13
import java.text.DecimalFormat;
14 11
import java.util.ArrayList;
15
import java.util.Arrays;
16
import java.util.List;
17 12

  
18
import org.eclipse.core.runtime.Platform;
19 13
import org.jfree.chart.ChartFactory;
20 14
import org.jfree.chart.JFreeChart;
21
import org.jfree.chart.annotations.XYAnnotation;
22
import org.jfree.chart.annotations.XYLineAnnotation;
23
import org.jfree.chart.annotations.XYTextAnnotation;
24 15
import org.jfree.chart.axis.NumberAxis;
25 16
import org.jfree.chart.axis.ValueAxis;
26 17
import org.jfree.chart.plot.CategoryPlot;
27
import org.jfree.chart.plot.Marker;
28 18
import org.jfree.chart.plot.PlotOrientation;
29
import org.jfree.chart.plot.ValueMarker;
30 19
import org.jfree.chart.plot.XYPlot;
31 20
import org.jfree.data.category.CategoryDataset;
32 21
import org.jfree.data.category.DefaultCategoryDataset;
33 22
import org.jfree.data.general.DatasetUtilities;
34 23
import org.jfree.data.general.PieDataset;
35 24
import org.jfree.data.xy.IntervalXYDataset;
36
import org.jfree.data.xy.XYDataset;
37
import org.jfree.data.xy.XYSeries;
38 25
import org.jfree.data.xy.XYSeriesCollection;
39 26
import org.jfree.graphics2d.svg.SVGGraphics2D;
40
import org.jfree.ui.RectangleAnchor;
41
import org.jfree.ui.TextAnchor;
42 27
import org.txm.chartsengine.core.ChartsEngine;
43
import org.txm.chartsengine.jfreechart.core.datasets.FCAXYDataset;
44 28
import org.txm.chartsengine.jfreechart.core.preferences.JFCChartsEnginePreferences;
45
import org.txm.chartsengine.jfreechart.core.renderers.MultipleItemsSelector;
46
import org.txm.chartsengine.jfreechart.core.renderers.interfaces.IItemSelectionRenderer;
47 29
import org.txm.chartsengine.jfreechart.core.themes.base.ExtendedNumberAxis;
48 30
import org.txm.chartsengine.jfreechart.core.themes.base.SymbolAxisBetweenTicks;
49 31
import org.txm.chartsengine.jfreechart.core.themes.base.Theme;
50 32
import org.txm.chartsengine.jfreechart.core.themes.highcharts.defaulttheme.HighchartsDefaultTheme;
51
import org.txm.chartsengine.jfreechart.core.themes.highcharts.defaulttheme.renderers.FCAItemSelectionRenderer;
52
import org.txm.core.chartsengine.base.messages.ChartsEngineMessages;
53
import org.txm.core.chartsengine.jfreechart.messages.JFreeChartsEngineMessages;
54 33
import org.txm.core.preferences.TXMPreferences;
55
import org.txm.functions.ca.CA;
56
import org.txm.functions.classification.CAH;
57
import org.txm.functions.progression.Progression;
58
import org.txm.functions.specificities.SpecificitesResult;
59
import org.txm.searchengine.cqp.corpus.query.Query;
60
import org.txm.stat.StatException;
61
import org.txm.utils.logger.Log;
62 34

  
63 35
import com.lowagie.text.Document;
64 36
import com.lowagie.text.Rectangle;
......
88 60
	/**
89 61
	 * The charts engine description.
90 62
	 */
91
	public final static String DESCRIPTION = JFreeChartsEngineMessages.JFCChartsEngine_ENGINE_DESCRIPTION;
63
	public final static String DESCRIPTION = "Java";
92 64

  
93 65
	/**
94 66
	 * The rendering theme.
......
127 99
		this(TXMPreferences.getString(JFCChartsEnginePreferences.PREFERENCE_NODE, JFCChartsEnginePreferences.OUTPUT_FORMAT));
128 100
	}
129 101
	
130
	/**
131
	 * Add some borders to the limits of the specified XY plot.
132
	 * @param plot
133
	 */
134
	public static void createCAFactorialMapChartLimitsBorder(JFreeChart chart)	{
135 102

  
136
		XYPlot plot = chart.getXYPlot();
137 103

  
138
		// Remove all existent annotations
139
		for(int i = plot.getAnnotations().size() - 1; i >= 0; i--) {
140
			plot.removeAnnotation((XYAnnotation) plot.getAnnotations().get(i));
141
		}
142

  
143

  
144
        // Gets the extreme coordinates values
145
		double minX = 0, maxX = 0, minY = 0, maxY = 0;
146

  
147
		// FIXME: new version
148
//		minX = plot.getDataRange(plot.getDomainAxis()).getLowerBound();
149
//		maxX = plot.getDataRange(plot.getDomainAxis()).getUpperBound();
150
//
151
//		minY = plot.getDataRange(plot.getRangeAxis()).getLowerBound();
152
//		maxY = plot.getDataRange(plot.getRangeAxis()).getUpperBound();
153

  
154
		// FIXME: old version, to remove when new version will be validated
155
		// Rows
156
		if(plot.getRenderer().isSeriesVisible(0))	{
157
			minX = ((FCAXYDataset)plot.getDataset()).getMinX(0);
158
		}
159
		// Cols
160
		if(plot.getRenderer().isSeriesVisible(1))	{
161
			double tmpMinX = ((FCAXYDataset)plot.getDataset()).getMinX(1);
162
			if(tmpMinX < minX)	{
163
				minX = tmpMinX;
164
			}
165
		}
166

  
167
		// Rows
168
		if(plot.getRenderer().isSeriesVisible(0))	{
169
			maxX = ((FCAXYDataset)plot.getDataset()).getMaxX(0);
170
		}
171
		// Cols
172
		if(plot.getRenderer().isSeriesVisible(1))	{
173
			double tmpMaxX = ((FCAXYDataset)plot.getDataset()).getMaxX(1);
174
			if(tmpMaxX > maxX)	{
175
				maxX = tmpMaxX;
176
			}
177
		}
178

  
179
		// Rows
180
		if(plot.getRenderer().isSeriesVisible(0))	{
181
			minY = ((FCAXYDataset)plot.getDataset()).getMinY(0);
182
		}
183
		// Cols
184
		if(plot.getRenderer().isSeriesVisible(1))	{
185
			double tmpMinY = ((FCAXYDataset)plot.getDataset()).getMinY(1);
186
			if(tmpMinY < minY)	{
187
				minY = tmpMinY;
188
			}
189
		}
190

  
191
		// Rows
192
		if(plot.getRenderer().isSeriesVisible(0))	{
193
			maxY = ((FCAXYDataset)plot.getDataset()).getMaxY(0);
194
		}
195
		// Cols
196
		if(plot.getRenderer().isSeriesVisible(1))	{
197
			double tmpMaxY = ((FCAXYDataset)plot.getDataset()).getMaxY(1);
198
			if(tmpMaxY > maxY)	{
199
				maxY = tmpMaxY;
200
			}
201
		}
202

  
203
		// Add some margins to the border
204
		// FIXME : to compute according to the real series shape dimensions
205
		// The code below doesn't work
206
//		double shapeHalfWidth = chart.getXYPlot().getRenderer().getSeriesShape(0).getBounds2D().getWidth() / 2;
207
		double shapeHalfWidth = 0.02;
208
		minX -= shapeHalfWidth;
209
		maxX += shapeHalfWidth;
210
		minY -= shapeHalfWidth;
211
		maxY += shapeHalfWidth;
212

  
213

  
214
		// Create the border
215
		BasicStroke dashedStroke = new BasicStroke(0.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1f, new float[] {2f}, 0f);
216
		XYLineAnnotation annotation;
217
		Color borderColor = Color.GRAY;
218

  
219
		// Left border
220
		annotation = new XYLineAnnotation(minX, minY, minX, maxY, dashedStroke, borderColor);
221
        plot.addAnnotation(annotation);
222

  
223
        // Right border
224
		annotation = new XYLineAnnotation(maxX, minY, maxX, maxY, dashedStroke, borderColor);
225
        plot.addAnnotation(annotation);
226

  
227
		// Bottom border
228
		annotation = new XYLineAnnotation(minX, minY, maxX, minY, dashedStroke, borderColor);
229
        plot.addAnnotation(annotation);
230

  
231
        // Top border
232
		annotation = new XYLineAnnotation(minX, maxY, maxX, maxY, dashedStroke, borderColor);
233
        plot.addAnnotation(annotation);
234

  
235
	}
236

  
237

  
238

  
239 104
	/**
240 105
	 * Creates an XY line chart from the specified dataset.
241 106
	 * @param dataset
......
529 394

  
530 395
    	// Domain axis symbols instead of values
531 396
    	if(domainAxisSymbols != null)	{
532
            chart.getXYPlot().setDomainAxis(new SymbolAxisBetweenTicks(ChartsEngineMessages.ChartsEngine_PARTITION_DIMENSIONS_X_AXIS_LABEL, domainAxisSymbols));
397
            chart.getXYPlot().setDomainAxis(new SymbolAxisBetweenTicks(xAxisLabel, domainAxisSymbols));
533 398
    	}
534 399

  
535 400
		// Apply theme to the chart
......
556 421
	}
557 422

  
558 423

  
559
	/**
560
	 * Creates a FCA scatter plot from the specified dataset.
561
	 * @param dataset
562
	 * @return the JFreeChart chart
563
	 */
564
	public JFreeChart createCAFactorialMapChart(FCAXYDataset dataset, String title, String xAxisLabel, String yAxisLabel) {
565 424

  
566
		JFreeChart chart = ChartFactory.createScatterPlot(title, xAxisLabel, yAxisLabel, dataset, PlotOrientation.VERTICAL, true, false, false);
567 425

  
568
		// Add some borders to the limits of the CA
569
		JFCChartsEngine.createCAFactorialMapChartLimitsBorder(chart);
570 426

  
571
		// Custom renderer
572
		chart.getXYPlot().setRenderer(this.theme.createFCARenderer());
573 427

  
574
		return chart;
575
	}
576 428

  
577

  
578
	@Override
579
	public JFreeChart createCAFactorialMapChart(CA ca) {
580

  
581
		JFreeChart chart  = null;
582

  
583
		try {
584
			FCAXYDataset dataset = new FCAXYDataset(ca);
585

  
586
			DecimalFormat f = new DecimalFormat("###.00"); //$NON-NLS-1$
587
			double singularValuesSum = ca.getValeursPropresSum();
588

  
589
			String percent1 = f.format(100 * ca.getValeursPropres()[ca.getFirstDimension() - 1] / singularValuesSum);
590
			String axis1 = ChartsEngineMessages.ChartsEngine_CA_FACTORIAL_MAP_AXIS_LABEL_PREFIX + " " + ca.getFirstDimension() + " (" + percent1 + "%)";
591
			String percent2 = f.format(100 * ca.getValeursPropres()[ca.getSecondDimension() - 1] / singularValuesSum);
592
			String axis2 = ChartsEngineMessages.ChartsEngine_CA_FACTORIAL_MAP_AXIS_LABEL_PREFIX  + " " + ca.getSecondDimension() + " (" + percent2 + "%)";
593
			chart = this.createCAFactorialMapChart(dataset, this.createCAFactorialMapChartTitle(ca), axis1, axis2);
594

  
595
		}
596
		catch(StatException e) {
597
			Log.severe("Can't create CA factorial map scatter plot" + e);
598
		}
599

  
600
		// Apply theme to the chart
601
		this.theme.apply(chart);
602

  
603
		return chart;
604
	}
605

  
606
	@Override
607
	public File createCAFactorialMapChartFile(CA ca, File file) {
608
		return this.export(this.createCAFactorialMapChart(ca), file);
609
	}
610

  
611

  
612
	@Override
613
	public JFreeChart createCASingularValuesBarChart(CA ca) {
614

  
615
		JFreeChart chart = null;
616

  
617
		try {
618
			// Creating the data set from the CA result
619
			DefaultCategoryDataset dataset = new DefaultCategoryDataset();
620
			double[] singularValues = ca.getValeursPropres();
621

  
622
			for(int i = 0; i < singularValues.length; i++) {
623
				dataset.setValue(singularValues[i], ChartsEngineMessages.ChartsEngine_CA_SINGULAR_VALUES_TOOLTIP_Y_LABEL, ChartsEngineMessages.ChartsEngine_CA_SINGULAR_VALUES_X_LABELS_PREFIX + String.valueOf(i + 1));
624
			}
625

  
626
			// Create the chart
627
			chart = this.createCategoryBarChart(dataset, ChartsEngineMessages.ChartsEngine_CA_SINGULAR_VALUES_TITLE, ChartsEngineMessages.ChartsEngine_CA_SINGULAR_VALUES_X_AXIS_LABEL, ChartsEngineMessages.ChartsEngine_CA_SINGULAR_VALUES_Y_AXIS_LABEL, false, false, false);
628

  
629
			// Custom renderer
630
			chart.getCategoryPlot().setRenderer(this.theme.createCASingularValuesRenderer());
631
	        ((IItemSelectionRenderer) chart.getCategoryPlot().getRenderer()).getItemsSelector().setResultData(ca);
632

  
633
	        // Custom range axis for ticks drawing options
634
	        chart.getCategoryPlot().setRangeAxis(new ExtendedNumberAxis((NumberAxis) chart.getCategoryPlot().getRangeAxis(), false, true, 0, DatasetUtilities.findMaximumRangeValue(chart.getCategoryPlot().getDataset()).doubleValue()));
635

  
636
		}
637
		catch(StatException e) {
638
			Log.severe(ChartsEngineMessages.ChartsEngine_CA_SINGULAR_VALUES_CANT_CREATE_CHART + e);
639
		}
640

  
641
		// Apply theme to the chart
642
		this.theme.apply(chart);
643

  
644
		return chart;
645
	}
646

  
647

  
648
	@Override
649
	public File createCASingularValuesBarChartFile(CA ca, File file) {
650
		return this.export(this.createCASingularValuesBarChart(ca), file);
651
	}
652

  
653

  
654
	// FIXME: old version with bar plot renderer
655
	@Override
656
	public JFreeChart createCAH2dChart(CAH cah) {
657

  
658

  
659
		JFreeChart chart = null;
660

  
661
		// Creating the data set from the result
662
		DefaultCategoryDataset dataset = new DefaultCategoryDataset();
663
		String category = "cluster ";
664

  
665

  
666

  
667
		int[] clusterNumbers = cah.getClusterNumbers();
668
		String[] rowNames = cah.getClusterRowNames();
669
		String[] orderedRowNames = cah.getClusterOrderedRowNames();
670
		double[] clusterHeights = cah.getClusterTreeHeights();
671
		double[][] clusterMerges = cah.getClusterTreeMerges();
672
		double[][] clusterCoords = cah.getClusterCoords();
673

  
674
		double[] yValuesByOrderedRowNames = new double[rowNames.length];
675
		double[] clusterNumbersValuesByOrderedRowNames = new double[rowNames.length];
676

  
677

  
678

  
679
		// FIXME: Sort the cluster numbers in reverse order
680
//			Arrays.sort(clusterNumbers);
681
//			ArrayUtils.reverse(clusterNumbers);
682
//			System.out.println(Arrays.toString(clusterNumbers));
683

  
684

  
685
		// FIXME: tests row names
686
		//System.err.println("JFCChartsEngine.createCAH2dChart(): cluster row names: \t\t" + Arrays.toString(rowNames));
687

  
688
		// FIXME: tests ordered row names
689
		//System.err.println("JFCChartsEngine.createCAH2dChart(): cluster ordered row names: \t" + Arrays.toString(orderedRowNames));
690

  
691
		// FIXME: tests, ordered cluster numbers
692
		//System.err.println("JFCChartsEngine.createCAH2dChart(): cluster numbers: \t\t" + Arrays.toString(clusterNumbers));
693

  
694
		// FIXME: tests, cluster tree merges
695
		//System.err.println("JFCChartsEngine.createCAH2dChart(): cluster tree merges: \t\t" + Arrays.toString(clusterMerges));
696

  
697
		// FIXME: tests, heights
698
//		System.err.println("JFCChartsEngine.createCAH2dChart(): cluster heights: \t\t" + Arrays.toString(clusterHeights));
699

  
700

  
701
		// FIXME: tests
702
		System.err.println("JFCChartsEngine.createCAH2dChart(): tests: \t\t" + Arrays.toString(cah.getInertiaGains()));
703

  
704

  
705

  
706
		System.out.println("JFCChartsEngine.createCAH2dChart() cluster heights count: " + clusterHeights.length);
707
		for(int i = 0; i < clusterHeights.length; i++) {
708
			System.out.println("JFCChartsEngine.createCAH2dChart() cluster height: " + new DecimalFormat("0.00000000000000000").format(clusterHeights[i]));
709
		}
710

  
711 429
//
712
//		String[] clusterUnorderedRowNames = cah.getClusterRowNames();
713
//		for(int i = 0; i < clusterUnorderedRowNames.length; i++) {
714
//			System.out.println("JFCChartsEngine.createCAH2dChart() unordered row names " + i + " : " + clusterUnorderedRowNames[i]);
715
//		}
716

  
717
		// Parse the merge pairs
718
		// A negative number in the FactoMineR tree merge table means a singleton
719
		for (int i = 0 ; i < clusterMerges.length ; i++) {
720

  
721
			// FIXME: debug
722
			//for (int j = 0 ; j < clusterMerges.length ; j++) {
723
				System.err.println("JFCChartsEngine.createCAH2dChart(): cluster tree merges: \t\t" + Arrays.toString(clusterMerges[i]));
724
				System.err.println("JFCChartsEngine.createCAH2dChart(): row names: \t\t" + rowNames[(int) Math.abs(clusterMerges[i][0]) - 1] + " | " + rowNames[(int) Math.abs(clusterMerges[i][1]) - 1]);
725

  
726

  
727
			//}
728

  
729
			// Leaves pair
730
			if(clusterMerges[i][0] < 0)	{
731

  
732
				//System.err.print("JFCChartsEngine.createCAH2dChart(): merging: " + rowNames[(int) Math.abs(clusterMerge[i][0]) - 1]);
733

  
734
				// Put the height in the ordered by names values table
735
				for(int j = 0; j < orderedRowNames.length; j++) {
736
					if(orderedRowNames[j].equals(rowNames[(int) Math.abs(clusterMerges[i][0]) - 1]))	{
737
						yValuesByOrderedRowNames[j] = clusterHeights[i];
738
						//clusterNumbersValuesByOrderedRowNames[j] = clusterNumbers[(int) Math.abs(clusterMerge[i][0]) - 1];
739
					}
740
				}
741

  
742
			}
743
			// Non-singleton
744
//				else	{
745
//					//System.err.print("JFCChartsEngine.createCAH2dChart(): merging aggregation: " +  clusterMerge[i][0]);
746
//				}
747

  
748
			// Leaves pair
749
			if(clusterMerges[i][1] < 0)	{
750
				//System.err.print(" with: " + rowNames[(int) Math.abs(clusterMerge[i][1]) - 1]);
751

  
752
				// Put the height in the ordered by names values table
753
				for(int j = 0; j < orderedRowNames.length; j++) {
754
					if(orderedRowNames[j].equals(rowNames[(int) Math.abs(clusterMerges[i][1]) - 1]))	{
755
						yValuesByOrderedRowNames[j] = clusterHeights[i];
756
						//clusterNumbersValuesByOrderedRowNames[j] = clusterNumbers[(int) Math.abs(clusterMerge[i][1]) - 1];
757
					}
758

  
759
				}
760

  
761
			}
762
			// Non-singleton
763
//				else	{
764
//					//System.err.print(" with aggregation: " + clusterMerge[i][1]);
765
//				}
766

  
767
			//System.err.println(" and height: " + clusterHeights[i] + " as aggregation: " + (i + 1));
768

  
769
		}
770

  
771

  
772
		//
773
//		for (int i = 0 ; i <  cah.getClusterTreeMerges().length; i++) {
774
//			System.err.println("JFCChartsEngine.createCAH2dChart() merges : ");
775
//			for(int j = 0; j < cah.getClusterTreeMerges()[i].length; j++) {
776
//				System.err.print(" : " + cah.getClusterTreeMerges()[i][j]);
777
//			}
778
//		}
779

  
780

  
781

  
782
//		ArrayList<Double> middlePoints = cah.getClusterTreeMiddlePoints();
430
//	@Override
431
//	public File createCAH2dChartFile(CAH cah, File file) {
432
//		return this.export(this.createCAH2dChart(cah), file);
433
//	}
783 434
//
784
//		for (int i = 0 ; i <  middlePoints.size(); i++) {
785
//			System.err.println("JFCChartsEngine.createCAH2dChart() middle points X: " + middlePoints.get(i));
786
//		}
787

  
788

  
789

  
790
//		for (int i = 0 ; i < cah.getClusterCoords().length ; i++) {
791
//			for(int j = 0; j < cah.getClusterCoords()[i].length; j++) {
792
//				//System.err.println("JFCChartsEngine.createCAH2dChart(): " + cah.getClusterCoords()[i][j]);
793
//				dataset.setValue(cah.getClusterCoords()[i][j], category + clusterNumbers[i], rownames[i]);
794
//			}
795
//		}
796

  
797

  
798

  
799
		// Create chart title
800
		String title = "title";
801
		String xAxisLabel = "Column";
802
		if(!cah.isColumnsComputing())	{
803
			xAxisLabel = "Row";
804
		}
805

  
806

  
807

  
808
		// Create the data set
809
		// FIXME: bar plot test
810
//		for(int i = 0; i < yValuesByOrderedRowNames.length; i++) {
811
//			//dataset.setValue(yValuesByOrderedRowNames[i], category + clusterNumbers[clusterNumbers.length - 1 - i], orderedRowNames[i]);
812 435
//
813
//
814
//			dataset.setValue(yValuesByOrderedRowNames[i], category + clusterNumbers[yValuesByOrderedRowNames.length - 1 - i], orderedRowNames[i]);
815
//			//dataset.setValue(yValuesByOrderedRowNames[i], category + clusterNumbers[i], orderedRowNames[i]);
816
//
817
//			//dataset.setValue(yValuesByOrderedRowNames[i], category + clusterNumbersValuesByOrderedRowNames[i], orderedRowNames[i]);
818
//		}
819
//
820
//		// Create the chart
821
//        chart = this.createCategoryBarChart(dataset, title, xAxisLabel, "Height", false, false, false);
822
//        ((IItemSelectionRenderer) chart.getCategoryPlot().getRenderer()).setChartType(ChartsEngine.CHART_TYPE_CAH_2D);
823
//
824
//        // Draw tree
825
//        for(int j = 0; j < chart.getCategoryPlot().getDataset().getColumnCount() - 1; j++) {
826
//			//System.err.println("JFCChartsEngine.createCAH2dChart(): " + chart.getCategoryPlot().getDataset().getColumnKey(j));
827
//
828
//
829
//        	// Non-singleton pairs lines
830
//			if(yValuesByOrderedRowNames[j] == yValuesByOrderedRowNames[j + 1])	{
831
//				chart.getCategoryPlot().addAnnotation(new CategoryLineAnnotation(chart.getCategoryPlot().getDataset().getColumnKey(j), yValuesByOrderedRowNames[j],
832
//						chart.getCategoryPlot().getDataset().getColumnKey(j + 1), yValuesByOrderedRowNames[j + 1], Color.red, new BasicStroke(2.0f)));
833
//			}
834
//
835
//
836
//			//chart.getCategoryPlot().addAnnotation(new Cate
837
//
838
//
839
//
840
//		}
841

  
842

  
843

  
844
		// Create the data set
845
		// FIXME: step chart test
846
//		for(int i = 0; i < yValuesByOrderedRowNames.length - 1; i++) {
847
//			if(yValuesByOrderedRowNames[i] == yValuesByOrderedRowNames[i + 1])	{
848
//				dataset.setValue(yValuesByOrderedRowNames[i], category + clusterNumbers[yValuesByOrderedRowNames.length - 1 - i], orderedRowNames[i]);
849
//			}
850
//		}
851
////		dataset.addValue(0, "test", "truc 1");
852
////		dataset.addValue(0.5, "test", "truc 1");
853
////		dataset.addValue(0.9, "test", "truc 1");
854
//		// Create the chart
855
//        chart = this.createCategoryStepChart(dataset, title, xAxisLabel, "Height", false, false);
856
//        ((IItemSelectionRenderer) chart.getCategoryPlot().getRenderer()).setChartType(ChartsEngine.CHART_TYPE_CAH_2D);
857

  
858

  
859
		// Create the data set
860
		// FIXME: XY category bar chart test
861
		XYSeriesCollection dataset2 = new XYSeriesCollection();
862

  
863
		// Last tree level (leaves level)
864
		XYSeries series = new XYSeries("leaves");
865
		for(int i = 0; i < yValuesByOrderedRowNames.length - 1; i++) {
866
			series.add(i, 0);
867
			series.add(i, yValuesByOrderedRowNames[i]);
868
			if(yValuesByOrderedRowNames[i] == yValuesByOrderedRowNames[i + 1])	{
869
				series.add(i + 1, yValuesByOrderedRowNames[i]);
870
				series.add(i + 1, 0);
871
			}
872
			else	{
873
				series.add(i + 1, null);
874
			}
875
		}
876
		dataset2.addSeries(series);
877

  
878

  
879
		// Link singletons to non singleton
880
		series = new XYSeries("singleton to non singleton links");
881
		for(int i = clusterHeights.length; i >= 0; i--) {
882

  
883
			// Skip non singletons case
884
			if(i > 3 && yValuesByOrderedRowNames[i] == yValuesByOrderedRowNames[i - 1] && yValuesByOrderedRowNames[i - 2] == yValuesByOrderedRowNames[i - 3])	{
885
				continue;
886
			}
887

  
888
			// Link singletons to non singleton
889
			if(i > 1 && yValuesByOrderedRowNames[i] == yValuesByOrderedRowNames[i - 1] && yValuesByOrderedRowNames[i - 1] != yValuesByOrderedRowNames[i - 2]) {
890
				series.add(i - 0.5, yValuesByOrderedRowNames[i - 2]);
891
				series.add(i - 0.5, yValuesByOrderedRowNames[i]);
892
				series.add(i - 0.5, null);
893
				series.add(i - 2, yValuesByOrderedRowNames[i - 2]);
894
			}
895
		}
896
		dataset2.addSeries(series);
897

  
898
		// Link singletons to newly created pairs
899
		series = new XYSeries("singleton to newly created pairs");
900
		for(int i = clusterHeights.length; i >= 0; i--) {
901

  
902
			// Skip non singletons case
903
			if(i > 0 && yValuesByOrderedRowNames[i] == yValuesByOrderedRowNames[i - 1])	{
904
				series.add(i, null);
905
				continue;
906
			}
907

  
908
			// Link singletons to newly created pairs
909
			if(i < clusterHeights.length - 1 && yValuesByOrderedRowNames[i] != yValuesByOrderedRowNames[i + 1]
910
					&& yValuesByOrderedRowNames[i + 1] != yValuesByOrderedRowNames[i + 2]
911

  
912
//						&& i > 1 &&
913

  
914
							) {
915

  
916
				series.add(i, null);
917

  
918
				series.add(i, yValuesByOrderedRowNames[i]);
919

  
920
				series.add(i + 1.75, yValuesByOrderedRowNames[i]);
921
				series.add(i + 1.75, yValuesByOrderedRowNames[i + 1]);
922

  
923

  
924
				//series.add(i - 2, yValuesByOrderedRowNames[i - 2]);
925
			}
926
		}
927
		dataset2.addSeries(series);
928

  
929

  
930

  
931
		// Link singletons; test 2
932
//		series = new XYSeries("singleton links");
933
//		for(int i = 0; i <  clusterHeights.length - 2; i++) {
934
//			if(i > 0 && i < clusterHeights.length - 2 && yValuesByOrderedRowNames[i] != yValuesByOrderedRowNames[i + 1] && yValuesByOrderedRowNames[i] != yValuesByOrderedRowNames[i - 1]) {
935
//				series.add(i, yValuesByOrderedRowNames[i]);
936
//				series.add(i + 1.5, yValuesByOrderedRowNames[i]);
937
//				series.add(i + 1.5, yValuesByOrderedRowNames[i + 1]);
938
//				series.add(i + 1.5, null);
939
//			}
940
//		}
941
//		dataset2.addSeries(series);
942

  
943

  
944
//		// Other clusters
945
//		ArrayList<Double> otherClusters = new ArrayList<Double>();
946
//		//series = new XYSeries("other clusters");
947
//		for(int i = 0; i < clusterHeights.length; i++) {
948
//			// If not a leaf
949
//			boolean done = false;
950
//			for(int j = 0; j < clusterNumbersValuesByOrderedRowNames.length; j++) {
951
//				if(clusterHeights[i] == yValuesByOrderedRowNames[j])	{
952
//					done = true;
953
//					break;
954
//				}
955
//			}
956
//			if(done)	{
957
//				continue;
958
//			}
959
//			System.err.println("JFCChartsEngine.createCAH2dChart() other clusters: " + new DecimalFormat("0.0000000000000000").format(clusterHeights[i]));
960
//		}
961
//		//dataset2.addSeries(series);
962

  
963

  
964

  
965
//		dataset.addValue(0, "test", "truc 1");
966
//		dataset.addValue(0.5, "test", "truc 1");
967
//		dataset.addValue(0.9, "test", "truc 1");
968
		// Create the chart
969
        //chart = this.createXYBarChart(dataset2, title, xAxisLabel, "Height", false, false);
970
        chart = ChartFactory.createXYLineChart(
971
        		title,      // chart title
972
        		xAxisLabel,                      // x axis label
973
                "height",                      // y axis label
974
                dataset2,                  // data
975
                PlotOrientation.VERTICAL,
976
                true,                     // include legend
977
                true,                     // tooltips
978
                false                     // urls
979
            );
980

  
981

  
982

  
983

  
984
        chart.getXYPlot().setRenderer(this.theme.createXYLineAndShapeRenderer(true, false));
985
        ((IItemSelectionRenderer) chart.getXYPlot().getRenderer()).setChartType(ChartsEngine.CHART_TYPE_CAH_2D);
986

  
987

  
988
        //chart.getXYPlot().addAnnotation(new XYLineAnnotation(0.5,  yValuesByOrderedRowNames[0], 0.5,  yValuesByOrderedRowNames[0] + 0.002));
989

  
990

  
991

  
992

  
993

  
994

  
995

  
996

  
997
        //System.err.println("JFCChartsEngine.createCAH2dChart() " + chart.getCategoryPlot().getCategories().get(0));
998
        //chart.getCategoryPlot().addAnnotation(new CategoryLineAnnotation("1970-12-31", .0002, "1965-12-31", .00005, Color.red, new BasicStroke(2.0f)));
999

  
1000
        // Custom range axis for ticks drawing options
1001
        //chart.getCategoryPlot().setRangeAxis(new ExtendedNumberAxis((NumberAxis) chart.getCategoryPlot().getRangeAxis(), false, true, 0, DatasetUtilities.findMaximumRangeValue(chart.getCategoryPlot().getDataset()).doubleValue()));
1002

  
1003

  
1004

  
1005
		// Apply theme to the chart
1006
		this.theme.apply(chart);
1007

  
1008

  
1009

  
1010
		// FIXME: test algo R
1011
		int dimens = 2;
1012
		int ax1 = 0;
1013
		int ax2 = 1;
1014
		double x1, y1, x2, y2, w1, w2;
1015

  
1016
		double h1, h2; // FIXME: when using 3 dimensions
1017

  
1018

  
1019
		double[][] aa = new double[clusterMerges.length][4];
1020
		for(int i = 0; i < clusterMerges.length; i++) {
1021
			for(int j = 0; j < 4; j++) {
1022
				aa[i][j] = 0;
1023
			}
1024
		}
1025

  
1026

  
1027
		   //aa=matrix(ncol=4, nrow=nrow(merge))
1028

  
1029

  
1030

  
1031

  
1032
		// Decrement/increment the cluster merge value because the R algorithm uses 1 as first table index
1033

  
1034
		for(int i = 0; i < clusterMerges.length; i++) {
1035
			if(clusterMerges[i][0] < 0)	{
1036
				clusterMerges[i][0]++;
1037
			}
1038
			else	{
1039
				clusterMerges[i][0]--;
1040
			}
1041

  
1042
			if(clusterMerges[i][1] < 0)	{
1043
				clusterMerges[i][1]++;
1044
			}
1045
			else	{
1046
				clusterMerges[i][1]--;
1047
			}
1048
		}
1049

  
1050

  
1051
		for(int i = 0; i < clusterMerges.length; i++) {
1052

  
1053
//		    for(i in 1:nrow(merge)){
1054
			     // if(merge[i,1]<0){
1055
			// Singleton
1056
			if(clusterMerges[i][0] < 0)	{
1057

  
1058

  
1059
			        x1 = clusterCoords[(int) -clusterMerges[i][0]][ax1];
1060
			        y1 = clusterCoords[(int) -clusterMerges[i][0]][ax2];
1061

  
1062

  
1063
			        h1 = 0;
1064
			        w1 = 1;
1065
			      }
1066
			      else{
1067
			        x1 = aa[(int) clusterMerges[i][0]][0];
1068
			        y1 = aa[(int) clusterMerges[i][0]][1];
1069
			        w1 = aa[(int) clusterMerges[i][0]][3];
1070
			        h1 = aa[(int) clusterMerges[i][0]][2];
1071
			      }
1072
			// Singleton
1073
			if(clusterMerges[i][1] < 0)	{
1074
			      //if(merge[i,2]<0){
1075
			        x2 = clusterCoords[-(int) clusterMerges[i][1]][ax1];
1076
			        y2 = clusterCoords[-(int) clusterMerges[i][1]][ax2];
1077
			        h2 = 0;
1078
			        w2 = 1;
1079
			      }
1080
			      else{
1081
			        x2 = aa[(int) clusterMerges[i][1]][0];
1082
			        y2 = aa[(int) clusterMerges[i][1]][1];
1083
			        w2 = aa[(int) clusterMerges[i][1]][3];
1084
			        h2 = aa[(int) clusterMerges[i][1]][2];
1085
			      }
1086
			      aa[i][0] = (w1 * x1 + w2 * x2) / (w1 + w2);
1087
			      aa[i][1] = (w1 * y1 + w2 * y2) / (w1 + w2);
1088

  
1089
			      //if(i<=nrow(merge)-t.level+1)
1090
			      if(i <= clusterMerges.length)	{
1091
			    	  clusterHeights[i] = 0;
1092
			      }
1093

  
1094
			      aa[i][2] = clusterHeights[i];
1095
			      aa[i][3] = w1 + w2;
1096

  
1097
//			      if(i>(nrow(merge)-t.level+1)){
1098
//			      if(i > clusterMerges[i][1]){ // FIXME: this test is strange
1099
//			        if(dimens==3) s$points3d(rbind(c(x1,y1,h1),c(x1,y1,height[i]), c(x2,y2,height[i]),c(x2,y2,h2)), lty=1, type="o", pch="")
1100
			        if(dimens == 2)	{
1101
			        //	lines(c(x1,x2), c(y1,y2), lwd=(height[i]/max(height))*3)
1102

  
1103
			        	//chart.getXYPlot().addAnnotation(new XYLineAnnotation(x1, y1, x2, y2));
1104
			        	// tests with steps lines
1105
			        	x1 *= 10;
1106
			        	x2 *= 10;
1107
			        	y1 /= 100;
1108
			        	y2 /= 100;
1109

  
1110
			        	chart.getXYPlot().addAnnotation(new XYLineAnnotation(x1, y1, x1, y2));
1111
			        	chart.getXYPlot().addAnnotation(new XYLineAnnotation(x1, y2, x2, y2));
1112
			        	chart.getXYPlot().addAnnotation(new XYLineAnnotation(x2, y2, x2, y1));
1113

  
1114

  
1115
			        	// FIXME: labels tests
1116
			        	chart.getXYPlot().addAnnotation(new XYTextAnnotation(rowNames[(int) Math.abs(clusterMerges[i][0])], x1, y1));
1117
			        	chart.getXYPlot().addAnnotation(new XYTextAnnotation(rowNames[(int) Math.abs(clusterMerges[i][1])], x2, y1));
1118

  
1119

  
1120

  
1121
//			        	chart.getXYPlot().addAnnotation(new XYLineAnnotation(y2, x1, y1, x1));
1122

  
1123

  
1124
			        	//chart.getXYPlot().addAnnotation(new XYLineAnnotation(x2, y2, x2, y2));
1125

  
1126

  
1127
			        	System.err.println("JFCChartsEngine.createCAH2dChart(): draw line " + x1 + ", " + y1 + " | " + x2 + "," + y2);
1128
			        }
1129
//			      }
1130
		//	    }
1131

  
1132

  
1133
		}
1134

  
1135

  
1136
		// FIXME: test symbol axis
1137
		//chart.getXYPlot().setDomainAxis(new SymbolAxis("test symbol axis", new String[]{"A", "b", "c"}));
1138

  
1139
		// FIXME: for cluster boxes we may use XYBoxAnnotation()
1140

  
1141

  
1142
		//chart.getXYPlot().addAnnotation(new XYLineAnnotation(x1, y1, x2, y2));
1143

  
1144

  
1145
        return chart;
1146

  
1147
	}
1148

  
1149
	// FIXME: new version with category step renderer
1150 436
//	@Override
1151
//	public JFreeChart createCAH2dChart(CAH cah) {
437
//	public JFreeChart createCAH3dChart(CAH cah) {
438
//		// FIXME : tests CAH 3d
439
//		return null;
440
//	}
1152 441
//
1153 442
//
1154
//			JFreeChart chart = null;
1155
//
1156
//			// Creating the data set from the result
1157
//			DefaultCategoryDataset dataset = new DefaultCategoryDataset();
1158
//			String category = "cluster ";
1159
//
1160
//
1161
//
1162
//			int[] clusterNumbers = cah.getClusterNumbers();
1163
//			String[] rowNames = cah.getClusterRowNames();
1164
//			String[] orderedRowNames = cah.getClusterOrderedRowNames();
1165
//			double[] clusterHeights = cah.getClusterTreeHeights();
1166
//			double[][] clusterMerge = cah.getClusterTreeMerges();
1167
//
1168
//
1169
//			double[] yValuesByOrderedRowNames = new double[rowNames.length];
1170
//			double[] clusterNumbersValuesByOrderedRowNames = new double[rowNames.length];
1171
//
1172
//
1173
//
1174
//			// FIXME: Sort the cluster numbers in reverse order
1175
////			Arrays.sort(clusterNumbers);
1176
////			ArrayUtils.reverse(clusterNumbers);
1177
////			System.out.println(Arrays.toString(clusterNumbers));
1178
//
1179
//
1180
//			// FIXME: tests row names
1181
//			//System.err.println("JFCChartsEngine.createCAH2dChart(): cluster row names: \t\t" + Arrays.toString(rowNames));
1182
//
1183
//			// FIXME: tests ordered row names
1184
//			//System.err.println("JFCChartsEngine.createCAH2dChart(): cluster ordered row names: \t" + Arrays.toString(orderedRowNames));
1185
//
1186
//			// FIXME: tests, ordered cluster numbers
1187
//			//System.err.println("JFCChartsEngine.createCAH2dChart(): cluster number: \t\t" + Arrays.toString(clusterNumbers));
1188
//
1189
//
1190
//
1191
//			for (int i = 0 ; i < clusterMerge.length ; i++) {
1192
//
1193
//				// Singleton
1194
//				if(clusterMerge[i][0] < 0)	{
1195
//
1196
//					//System.err.print("JFCChartsEngine.createCAH2dChart(): merging: " + rowNames[(int) Math.abs(clusterMerge[i][0]) - 1]);
1197
//
1198
//					// Put the height in the ordered by names values table
1199
//					for(int j = 0; j < orderedRowNames.length; j++) {
1200
//						if(orderedRowNames[j].equals(rowNames[(int) Math.abs(clusterMerge[i][0]) - 1]))	{
1201
//							yValuesByOrderedRowNames[j] = clusterHeights[i];
1202
//							//clusterNumbersValuesByOrderedRowNames[j] = clusterNumbers[(int) Math.abs(clusterMerge[i][0]) - 1];
1203
//						}
1204
//					}
1205
//
1206
//				}
1207
//				// Non-singleton
1208
//				else	{
1209
//					//System.err.print("JFCChartsEngine.createCAH2dChart(): merging aggregation: " +  clusterMerge[i][0]);
1210
//				}
1211
//
1212
//				// Singleton
1213
//				if(clusterMerge[i][1] < 0)	{
1214
//					//System.err.print(" with: " + rowNames[(int) Math.abs(clusterMerge[i][1]) - 1]);
1215
//
1216
//					// Put the height in the ordered by names values table
1217
//					for(int j = 0; j < orderedRowNames.length; j++) {
1218
//						if(orderedRowNames[j].equals(rowNames[(int) Math.abs(clusterMerge[i][1]) - 1]))	{
1219
//							yValuesByOrderedRowNames[j] = clusterHeights[i];
1220
//							//clusterNumbersValuesByOrderedRowNames[j] = clusterNumbers[(int) Math.abs(clusterMerge[i][1]) - 1];
1221
//						}
1222
//
1223
//					}
1224
//
1225
//				}
1226
//				// Non-singleton
1227
//				else	{
1228
//					//System.err.print(" with aggregation: " + clusterMerge[i][1]);
1229
//				}
1230
//
1231
//				//System.err.println(" and height: " + clusterHeights[i] + " as aggregation: " + (i + 1));
1232
//
1233
//			}
1234
//
1235
//
1236
//			// Create the data set
1237
//
1238
//			for(int i = 0; i < yValuesByOrderedRowNames.length; i++) {
1239
//				//dataset.setValue(yValuesByOrderedRowNames[i], category + clusterNumbers[clusterNumbers.length - 1 - i], orderedRowNames[i]);
1240
//
1241
//				dataset.setValue(yValuesByOrderedRowNames[i], category + clusterNumbers[yValuesByOrderedRowNames.length - 1 - i], orderedRowNames[i]);
1242
//				//dataset.setValue(yValuesByOrderedRowNames[i], category, orderedRowNames[i]);
1243
//
1244
//				//dataset.setValue(yValuesByOrderedRowNames[i], category + clusterNumbersValuesByOrderedRowNames[i], orderedRowNames[i]);
1245
//			}
1246
//
1247
////
1248
////			for (int i = 0 ; i <  cah.getClusterTreeMerges().length; i++) {
1249
////				System.err.println("JFCChartsEngine.createCAH2dChart() merges : ");
1250
////				for(int j = 0; j < cah.getClusterTreeMerges()[i].length; j++) {
1251
////					System.err.print(" : " + cah.getClusterTreeMerges()[i][j]);
1252
////				}
1253
////			}
1254
//
1255
//
1256
//
1257
////			ArrayList<Double> middlePoints = cah.getClusterTreeMiddlePoints();
1258
////
1259
////			for (int i = 0 ; i <  middlePoints.size(); i++) {
1260
////				System.err.println("JFCChartsEngine.createCAH2dChart() middle points X: " + middlePoints.get(i));
1261
////			}
1262
//
1263
//
1264
//
1265
////			for (int i = 0 ; i < cah.getClusterCoords().length ; i++) {
1266
////				for(int j = 0; j < cah.getClusterCoords()[i].length; j++) {
1267
////					//System.err.println("JFCChartsEngine.createCAH2dChart(): " + cah.getClusterCoords()[i][j]);
1268
////					dataset.setValue(cah.getClusterCoords()[i][j], category + clusterNumbers[i], rownames[i]);
1269
////				}
1270
////			}
1271
//
1272
//
1273
//
1274
//			// Create chart title
1275
//			String title = "title";
1276
//			String xAxisLabel = "Column";
1277
//			if(!cah.isColumnsComputing())	{
1278
//				xAxisLabel = "Row";
1279
//			}
1280
//
1281
//
1282
//			// Create the chart
1283
//	        chart = this.createCategoryStepChart(dataset, title, xAxisLabel, "Height", false, false);
1284
//
1285
//
1286
//	        ((IItemSelectionRenderer) chart.getCategoryPlot().getRenderer()).setChartType(ChartsEngine.CHART_TYPE_CAH_2D);
1287
//
1288
//
1289
//	        // Draw tree
1290
//	        chart.getCategoryPlot().addAnnotation(new CategoryLineAnnotation(chart.getCategoryPlot().getDataset().getColumnKey(0), 5.0,
1291
//	        		chart.getCategoryPlot().getDataset().getColumnKey(1), 8.0, Color.red, new BasicStroke(2.0f)));
1292
//
1293
//	        // Custom range axis for ticks drawing options: cut the range to minimum and maximum values
1294
//	        chart.getCategoryPlot().setRangeAxis(new ExtendedNumberAxis((NumberAxis) chart.getCategoryPlot().getRangeAxis(), false, true, 0, DatasetUtilities.findMaximumRangeValue(chart.getCategoryPlot().getDataset()).doubleValue()));
1295
//
1296
//
1297
//		return chart;
1298
//
1299
//
1300
//
1301
//
443
//	@Override
444
//	public File createCAH3dChartFile(CAH cah, File file) {
445
//		return this.export(this.createCAH3dChart(cah), file);
1302 446
//	}
1303 447

  
1304 448

  
1305
	@Override
1306
	public File createCAH2dChartFile(CAH cah, File file) {
1307
		return this.export(this.createCAH2dChart(cah), file);
1308
	}
1309 449

  
1310 450

  
1311
	@Override
1312
	public JFreeChart createCAH3dChart(CAH cah) {
1313
		// FIXME : tests CAH 3d
1314
		return null;
1315
	}
1316

  
1317

  
1318
	@Override
1319
	public File createCAH3dChartFile(CAH cah, File file) {
1320
		return this.export(this.createCAH3dChart(cah), file);
1321
	}
1322

  
1323

  
1324

  
1325

  
1326 451
//	@Override
1327 452
//	public JFreeChart createPartitionDimensionsChart(Partition partition, boolean sortPartsBySize) {
1328 453
//
......
2235 1360

  
2236 1361

  
2237 1362

  
2238
	@Override
2239
	public void updateChartCAFactorialMapSetRowsVisible(Object chart, CA ca, boolean visible)	{
2240
		super.updateChartCAFactorialMapSetRowsVisible(chart, ca, visible);
2241 1363

  
2242
		((JFreeChart) chart).getXYPlot().getRenderer().setSeriesVisible(0, visible);
2243

  
2244
		// Update the limits border
2245
		JFCChartsEngine.createCAFactorialMapChartLimitsBorder((JFreeChart) chart);
2246

  
2247
	}
2248

  
2249

  
2250
	@Override
2251
	public void updateChartCAFactorialMapSetColumnsVisible(Object chart, CA ca, boolean visible)	{
2252
		super.updateChartCAFactorialMapSetColumnsVisible(chart, ca, visible);
2253

  
2254
		((JFreeChart) chart).getXYPlot().getRenderer().setSeriesVisible(1, visible);
2255

  
2256
		// Update the limits border
2257
		JFCChartsEngine.createCAFactorialMapChartLimitsBorder((JFreeChart) chart);
2258

  
2259
	}
2260

  
2261

  
2262

  
2263
	@Override
2264
	public void updateChartCAFactorialMapSetDimensions(Object chart, CA ca, int dimension1, int dimension2)	{
2265
		 super.updateChartCAFactorialMapSetDimensions(chart, ca, dimension1, dimension2);
2266

  
2267
		 // Modify data set
2268
		 ((FCAXYDataset) ((JFreeChart) chart).getXYPlot().getDataset()).setAxis1(dimension1);
2269
		 ((FCAXYDataset) ((JFreeChart) chart).getXYPlot().getDataset()).setAxis2(dimension2);
2270

  
2271
		 // Update axis labels
2272
		 // FIXME : create a method in CA to directly get a singular value as percent ?
2273
		 try {
2274
			 double sinuglarValuesSum = ca.getValeursPropresSum();
2275
			 DecimalFormat f = new DecimalFormat("###.00"); //$NON-NLS-1$
2276
			 ((JFreeChart) chart).getXYPlot().getDomainAxis().setLabel(ChartsEngineMessages.ChartsEngine_CA_FACTORIAL_MAP_AXIS_LABEL_PREFIX + " " + dimension1 + " (" + f.format(100 * ca.getValeursPropres()[dimension1 - 1] / sinuglarValuesSum) + "%)");
2277
			 ((JFreeChart) chart).getXYPlot().getRangeAxis().setLabel(ChartsEngineMessages.ChartsEngine_CA_FACTORIAL_MAP_AXIS_LABEL_PREFIX + " " + dimension2 + " (" + f.format(100 * ca.getValeursPropres()[dimension2 - 1] / sinuglarValuesSum) + "%)");
2278

  
2279
			 // Refresh data set
2280
			 // FIXME : any way to fire a data set event rather than reassign the same data set ?
2281
			 ((JFreeChart) chart).getXYPlot().setDataset(((JFreeChart) chart).getXYPlot().getDataset());
2282
			// the code below doesn't neither center the view nor update the axes ticks of the new chart, continue tests
2283
			//((JFreeChart) chart).setNotify(true);
2284

  
2285

  
2286
			// Update the limits border
2287
			JFCChartsEngine.createCAFactorialMapChartLimitsBorder((JFreeChart) chart);
2288

  
2289
		}
2290
		catch(StatException e) {
2291
			// TODO Auto-generated catch block
2292
			e.printStackTrace();
2293
		}
2294
	 }
2295

  
2296

  
2297
	@Override
2298
	public void updateChartCAFactorialMapHighlightPoints(Object chart, boolean rows, String[] labels) {
2299

  
2300
		MultipleItemsSelector selector = (MultipleItemsSelector) ((FCAItemSelectionRenderer)((JFreeChart) chart).getXYPlot().getRenderer()).getItemsSelector();
2301

  
2302
		// Rows
2303
		int series = 0;
2304
		// Columns
2305
		if(!rows)	{
2306
			series = 1;
2307
		}
2308
		selector.removeAllSelectedItems(series);
2309
		int[] items = ((FCAXYDataset)((JFreeChart) chart).getXYPlot().getDataset()).getLabelIndices(series, labels);
2310

  
2311
		for(int i = 0; i < items.length; i++) {
2312
			selector.addSelectedItem(series, items[i]);
2313
		}
2314

  
2315
		((JFreeChart) chart).setNotify(true);
2316
	}
2317

  
2318

  
2319
	@Override
2320
	public ArrayList<String> getCAFactorialMapChartSelectedRowPoints(Object chart) {
2321
		return this.getCAFactorialMapChartSelectedPoints(chart, 0);
2322
	}
2323

  
2324
	@Override
2325
	public ArrayList<String> getCAFactorialMapChartSelectedColumnPoints(Object chart) {
2326
		return this.getCAFactorialMapChartSelectedPoints(chart, 1);
2327
	}
2328

  
2329
	/**
2330
	 * Gets the currently selected item in the specified series in the chart.
2331
	 * @param chart
2332
	 * @param series
2333
	 * @return
2334
	 */
2335
	public ArrayList<String> getCAFactorialMapChartSelectedPoints(Object chart, int series) {
2336

  
2337
		MultipleItemsSelector selector = (MultipleItemsSelector) ((FCAItemSelectionRenderer)((JFreeChart) chart).getXYPlot().getRenderer()).getItemsSelector();
2338
		ArrayList<String> pointLabels = new ArrayList<String>(selector.getSelectedItemsCount(series));
2339

  
2340
		if(selector.getSelectedItemsCount(series) > 0)	{
2341

  
2342
			FCAXYDataset dataset = (FCAXYDataset) ((JFreeChart) chart).getXYPlot().getDataset();
2343
			int[] selectedItems = selector.getSelectedItems(series);
2344

  
2345
			for(int i = 0; i < selectedItems.length; i++) {
2346
				pointLabels.add(dataset.getLabel(series, selectedItems[i]));
2347
			}
2348
		}
2349
		return pointLabels;
2350
	}
2351

  
2352

  
2353
	@Override
2354
	public ArrayList<Integer> getProgressionChartSelectedPointPositions(Object chart) {
2355

  
2356
		MultipleItemsSelector selector = (MultipleItemsSelector) ((IItemSelectionRenderer)((JFreeChart) chart).getXYPlot().getRenderer()).getItemsSelector();
2357
		ArrayList<Integer> pointPositionsInCorpora = new ArrayList<Integer>();
2358

  
2359

  
2360
		// FIXME: returns all the point positions
2361
		XYDataset dataset = ((JFreeChart) chart).getXYPlot().getDataset();
2362
		for(int i = 0; i < selector.getSelectedSeries().length; i++) {
2363
			int selectedSeries = selector.getSelectedSeries()[i];
2364
			int[] selectedItemsInSeries = selector.getSelectedItems(selectedSeries) ;
2365
			for(int j = 0; j < selectedItemsInSeries.length; j++) {
2366
				// if it's the dummy last chart point, get the previous point position instead of ther last one
2367
				if(selectedItemsInSeries[j] == dataset.getItemCount(selectedSeries) - 1)	{
2368
					pointPositionsInCorpora.add((int) (dataset.getXValue(selectedSeries, selectedItemsInSeries[j] - 1)));
2369
				}
2370
				else	{
2371
					pointPositionsInCorpora.add((int) (dataset.getXValue(selectedSeries, selectedItemsInSeries[j])));
2372
				}
2373
			}
2374
			
2375
		}
2376

  
2377
		// put the last selected point at the end of the list
2378
		if(selector.getLastSelectedSeries() != -1 && selector.getLastSelectedItem() != -1)	{
2379
			int item = selector.getLastSelectedItem();
2380
			// if it's the dummy last chart point, get the previous point position instead of ther last one
2381
			if(item == dataset.getItemCount(selector.getLastSelectedSeries()) - 1)	{
2382
				item--;
2383
			}
2384
			
2385
			Integer lastSelectedPointPosition = (int) (dataset.getXValue(selector.getLastSelectedSeries(), item));
2386
			pointPositionsInCorpora.remove(lastSelectedPointPosition);
2387
			pointPositionsInCorpora.add(lastSelectedPointPosition);
2388
		}
2389
		
2390
		
2391
		// FIXME: old version which returns only 1 point position
2392
//		if(selector.getMultipleSelectedSeries().length > 0)	{
2393
//			int selectedSeries = selector.getMultipleSelectedSeries()[0];
2394
//			if(selector.getMouseOverItemInSeries(selectedSeries) != -1)	{
2395
//				XYDataset dataset = ((JFreeChart) chart).getXYPlot().getDataset();
2396
//				// if it's the dummy last chart point, get the previous point position instead of ther last one
2397
//				if(selector.getMouseOverItemInSeries(selectedSeries) == dataset.getItemCount(selector.getMultipleSelectedSeries()[0]) - 1)	{
2398
//					pointPositionsInCorpora.add((int) (dataset.getXValue(selector.getMultipleSelectedSeries()[0], selector.getMouseOverItemInSeries(selectedSeries) - 1)));
2399
//				}
2400
//				else	{
2401
//					pointPositionsInCorpora.add((int) (dataset.getXValue(selector.getMultipleSelectedSeries()[0], selector.getMouseOverItemInSeries(selectedSeries))));
2402
//				}
2403
//				
2404
//			}
1364
//
1365
//
1366
//	@Override
1367
//	public void updateChartCAFactorialMapSetDimensions(Object chart, CA ca, int dimension1, int dimension2)	{
1368
//		 super.updateChartCAFactorialMapSetDimensions(chart, ca, dimension1, dimension2);
1369
//
1370
//		 // Modify data set
1371
//		 ((FCAXYDataset) ((JFreeChart) chart).getXYPlot().getDataset()).setAxis1(dimension1);
1372
//		 ((FCAXYDataset) ((JFreeChart) chart).getXYPlot().getDataset()).setAxis2(dimension2);
1373
//
1374
//		 // Update axis labels
1375
//		 // FIXME : create a method in CA to directly get a singular value as percent ?
1376
//		 try {
1377
//			 double sinuglarValuesSum = ca.getValeursPropresSum();
1378
//			 DecimalFormat f = new DecimalFormat("###.00"); //$NON-NLS-1$
1379
//			 ((JFreeChart) chart).getXYPlot().getDomainAxis().setLabel(ChartsEngineMessages.ChartsEngine_CA_FACTORIAL_MAP_AXIS_LABEL_PREFIX + " " + dimension1 + " (" + f.format(100 * ca.getValeursPropres()[dimension1 - 1] / sinuglarValuesSum) + "%)");
1380
//			 ((JFreeChart) chart).getXYPlot().getRangeAxis().setLabel(ChartsEngineMessages.ChartsEngine_CA_FACTORIAL_MAP_AXIS_LABEL_PREFIX + " " + dimension2 + " (" + f.format(100 * ca.getValeursPropres()[dimension2 - 1] / sinuglarValuesSum) + "%)");
1381
//
1382
//			 // Refresh data set
1383
//			 // FIXME : any way to fire a data set event rather than reassign the same data set ?
1384
//			 ((JFreeChart) chart).getXYPlot().setDataset(((JFreeChart) chart).getXYPlot().getDataset());
1385
//			// the code below doesn't neither center the view nor update the axes ticks of the new chart, continue tests
1386
//			//((JFreeChart) chart).setNotify(true);
1387
//
1388
//
1389
//			// Update the limits border
1390
//			JFCChartsEngine.createCAFactorialMapChartLimitsBorder((JFreeChart) chart);
1391
//
2405 1392
//		}
2406
		
2407
		return pointPositionsInCorpora;
2408
	}
1393
//		catch(StatException e) {
1394
//			// TODO Auto-generated catch block
1395
//			e.printStackTrace();
1396
//		}
1397
//	 }
1398
//
1399
//
1400
//	@Override
1401
//	public void updateChartCAFactorialMapHighlightPoints(Object chart, boolean rows, String[] labels) {
1402
//
1403
//		MultipleItemsSelector selector = (MultipleItemsSelector) ((FCAItemSelectionRenderer)((JFreeChart) chart).getXYPlot().getRenderer()).getItemsSelector();
1404
//
1405
//		// Rows
1406
//		int series = 0;
1407
//		// Columns
1408
//		if(!rows)	{
1409
//			series = 1;
1410
//		}
1411
//		selector.removeAllSelectedItems(series);
1412
//		int[] items = ((FCAXYDataset)((JFreeChart) chart).getXYPlot().getDataset()).getLabelIndices(series, labels);
1413
//
1414
//		for(int i = 0; i < items.length; i++) {
1415
//			selector.addSelectedItem(series, items[i]);
1416
//		}
1417
//
1418
//		((JFreeChart) chart).setNotify(true);
1419
//	}
1420
//
2409 1421

  
2410
	@Override
2411
	public ArrayList<Integer> getProgressionChartSelectedPointNumbers(Object chart) {
2412 1422

  
2413
		MultipleItemsSelector selector = (MultipleItemsSelector) ((IItemSelectionRenderer)((JFreeChart) chart).getXYPlot().getRenderer()).getItemsSelector();
2414
		ArrayList<Integer> pointNumbers = new ArrayList<Integer>();
2415
		XYDataset dataset = ((JFreeChart) chart).getXYPlot().getDataset();
2416
		
2417
		for(int i = 0; i < selector.getSelectedSeriesCount(); i++) {
2418
			int series = selector.getSelectedSeries()[i];
2419
			int[] items = selector.getSelectedItems(series);
2420
			int lastDummyItem = dataset.getItemCount(series) - 1; 
2421
			for(int j = 0; j < items.length; j++) {
2422
				int item = items[j];
2423
				// manage the first dummy point
2424
				if(item == 0)	{
2425
					item++;
2426
				}
2427
				// manage the last dummy point
2428
				else if(item == lastDummyItem)	 {
2429
					item--;
2430
				}
2431
				
2432
				pointNumbers.add(item);
2433
			}
2434
		}
2435
		
2436
		return pointNumbers;
2437
	}
2438
	
2439 1423

  
2440
	
2441
	@Override
2442
	public ArrayList<Integer> getProgressionChartAllPointPositions(Object chart) {
2443

  
2444
		ArrayList<Integer> pointPositionsInCorpora = new ArrayList<Integer>();
2445
		XYDataset dataset = ((JFreeChart) chart).getXYPlot().getDataset();
2446
		
2447
		for(int i = 0; i < dataset.getSeriesCount(); i++) {
2448
			for(int j = 0; j < dataset.getItemCount(i) - 1; j++) { // -1 to skip the last dummy point of the step chart
2449
				pointPositionsInCorpora.add((int) dataset.getXValue(i, j));
2450
			}
2451
		}
2452
		
2453
		return pointPositionsInCorpora;
2454
	}
2455
	
2456
	@Override
2457
	public ArrayList<Integer> getProgressionChartSelectedSeries(Object chart) {
2458
		ArrayList<Integer> selectedSeries = new ArrayList<Integer>();
2459
		MultipleItemsSelector selector = (MultipleItemsSelector) ((IItemSelectionRenderer)((JFreeChart) chart).getXYPlot().getRenderer()).getItemsSelector();
2460
		Integer[] multipleSelectedSeries = selector.getSelectedSeries();
2461
		for(int i = 0; i < multipleSelectedSeries.length; i++) {
2462
			selectedSeries.add(multipleSelectedSeries[i]);
2463
		}
2464
		return selectedSeries;
2465
	}
2466

  
2467

  
2468
	@Override
2469
	public int getProgressionChartLastSelectedSeries(Object chart) {
2470
		return ((MultipleItemsSelector) ((IItemSelectionRenderer)((JFreeChart) chart).getXYPlot().getRenderer()).getItemsSelector()).getLastSelectedSeries();
2471
	}
2472

  
2473
	
2474

  
2475 1424
	/**
2476 1425
	 * Defines the theme to use for rendering charts.
2477 1426
	 * @param theme the theme to set
......
2840 1789
//	}
2841 1790
	
2842 1791
	
2843
	@Override
2844
	public void updateChartCAFactorialMapSetLabelItemsSelectionOrder(Object chart, String[] rowLabels, String[] colLabels) {
2845
		
2846
		MultipleItemsSelector selector = (MultipleItemsSelector) ((FCAItemSelectionRenderer)((JFreeChart) chart).getXYPlot().getRenderer()).getItemsSelector();
2847
		selector.setCyclicItemsOrder(selector.getItemsAndSeriesOrderedByLabels((FCAXYDataset)((JFreeChart) chart).getXYPlot().getDataset(), rowLabels, colLabels)); 
2848
	}
2849 1792

  
2850

  
2851

  
2852 1793
	
2853 1794
}
tmp/org.txm.chartsengine.jfreechart.core/src/org/txm/chartsengine/jfreechart/core/JFCChartCreator.java (revision 137)
1 1
package org.txm.chartsengine.jfreechart.core;
2 2

  
3
import java.awt.Color;
3 4
import java.io.File;
5
import java.util.ArrayList;
4 6

  
5 7
import org.jfree.chart.JFreeChart;
6 8
import org.txm.chartsengine.core.ChartCreator;
......
53 55
		
54 56
	}
55 57
	
58
	
56 59
	@Override
60
	public ArrayList<Color> getSeriesShapesColors(Object chart) {
61
		ArrayList<Color> colors = new ArrayList<Color>();
62
		JFreeChart c = (JFreeChart) chart;
63

  
64
		// XY plot
65
		if(c.getXYPlot() != null)	{
66
			for(int i = 0; i < c.getXYPlot().getSeriesCount(); i++) {
67
				colors.add((Color) c.getXYPlot().getRenderer().getSeriesPaint(i));
68
			}
69
		}
70
		// category plot
71
		else if(c.getCategoryPlot() != null)	{
72
			for(int i = 0; i < c.getCategoryPlot().getCategories().size(); i++) {
73
				colors.add((Color) c.getCategoryPlot().getRenderer().getSeriesPaint(i));
74
			}
75
		}
76
		return colors;
77
	}
78

  
79

  
80

  
81
	
82
	@Override
57 83
	public Class getChartsEngineClass() {
58 84
		return JFCChartsEngine.class;
59 85
	}
tmp/org.txm.chartsengine.jfreechart.core/src/org/txm/chartsengine/jfreechart/core/themes/highcharts/defaulttheme/renderers/CASingularValuesItemSelectionRenderer.java (revision 137)
1
package org.txm.chartsengine.jfreechart.core.themes.highcharts.defaulttheme.renderers;
2

  
3
import java.awt.Color;
4
import java.text.DecimalFormat;
5
import java.util.List;
6

  
7
import org.jfree.chart.labels.CategoryToolTipGenerator;
8
import org.jfree.data.category.CategoryDataset;
9
import org.jfree.data.category.DefaultCategoryDataset;
10
import org.txm.chartsengine.jfreechart.core.renderers.interfaces.IItemSelectionRenderer;
11
import org.txm.chartsengine.jfreechart.core.themes.highcharts.defaulttheme.swing.CustomHTMLToolTip;
12
import org.txm.core.chartsengine.base.___ChartsEngine;
13
import org.txm.core.chartsengine.base.messages.ChartsEngineMessages;
14
import org.txm.functions.ca.CA;
15

  
16
/**
17
 * Renderer providing item selection system and drawing features for selected item and custom rendering for CA singular values bar charts.
18
 * @author sjacquot
19
 *
20
 */
21
public class CASingularValuesItemSelectionRenderer extends ItemSelectionCategoryBarRenderer {
22

  
23

  
24

  
25

  
26
	/**
27
	 * Percent values number format.
28
	 */
29
	protected DecimalFormat percentValuesNumberFormat;
30

  
31

  
32
	/**
33
	 * Creates a renderer dedicated to CA charts.
34
	 */
35
	public CASingularValuesItemSelectionRenderer() {
36
		super();
37
		this.setChartType(___ChartsEngine.CHART_TYPE_CA_SINGULAR_VALUES);
38

  
39
		this.percentValuesNumberFormat = new DecimalFormat("#.00");
40
	}
41

  
42

  
43

  
44
	@Override
45
	public void initToolTipGenerator(final IItemSelectionRenderer renderer)	{
46
		this.setBaseToolTipGenerator(new CategoryToolTipGenerator() {
47

  
48
			@Override
49
			public String generateToolTip(CategoryDataset dataset, int row, int column) {
50

  
51
				// Hexadecimal color
52
				Color color = (Color) getSeriesPaint(row);
53
				String hex = "#" + Integer.toHexString(color.getRGB()).substring(2);
54

  
55
				DefaultCategoryDataset catDataset = (DefaultCategoryDataset) dataset;
56
				Number value = catDataset.getValue(row, column);
57

  
58

  
59
				CA ca = (CA) getItemsSelector().getResultData();
60
				List<List<Object>> singularValuesData = ca.getSingularValuesInfos();
61

  
62
				return CustomHTMLToolTip.getDefaultHTMLBody(renderer, hex) + "<p>#" + catDataset.getColumnKey(column) + "</p>"
63
						+ "<p><span style=\"color: " + hex + ";\">" + catDataset.getRowKey(row) + ChartsEngineMessages.ChartsEngine_LABEL_VALUE_SEPARATORS
64
							+ " </span><b>" + valuesNumberFormat.format(value) + "</b></p>"
65
						+ "<p><span style=\"color: " + hex + ";\">" + ChartsEngineMessages.ChartsEngine_CA_SINGULAR_VALUES_TOOLTIP_PERCENT + ChartsEngineMessages.ChartsEngine_LABEL_VALUE_SEPARATORS
66
							+ " </span><b>" + percentValuesNumberFormat.format(singularValuesData.get(column).get(2)) + "</b></p>"
67
						+ "<p><span style=\"color: " + hex + ";\">" + ChartsEngineMessages.ChartsEngine_CA_SINGULAR_VALUES_TOOLTIP_SUM + ChartsEngineMessages.ChartsEngine_CA_SINGULAR_VALUES_TOOLTIP_PERCENT
68
							+ ChartsEngineMessages.ChartsEngine_LABEL_VALUE_SEPARATORS
69
							+ " </span><b>" + percentValuesNumberFormat.format(singularValuesData.get(column).get(3)) + "</b></p>"
70
						+ "</body><html>";
71
			}
72
		});
73
	}
74

  
75

  
76

  
77
}
tmp/org.txm.chartsengine.jfreechart.core/src/org/txm/chartsengine/jfreechart/core/themes/highcharts/defaulttheme/renderers/FCAItemSelectionRenderer.java (revision 137)
1
package org.txm.chartsengine.jfreechart.core.themes.highcharts.defaulttheme.renderers;
2

  
3
import java.awt.Color;
4
import java.awt.Font;
5
import java.awt.Graphics2D;
6
import java.awt.Paint;
7
import java.awt.Shape;
8
import java.awt.geom.AffineTransform;
9
import java.awt.geom.Area;
10
import java.awt.geom.Rectangle2D;
11
import java.awt.geom.RoundRectangle2D;
12
import java.text.DecimalFormat;
13
import java.util.ArrayList;
14

  
15
import org.jfree.chart.ChartPanel;
16
import org.jfree.chart.labels.XYItemLabelGenerator;
17
import org.jfree.chart.labels.XYToolTipGenerator;
18
import org.jfree.data.xy.XYDataset;
19
import org.txm.chartsengine.jfreechart.core.datasets.FCAXYDataset;
20
import org.txm.chartsengine.jfreechart.core.renderers.interfaces.IItemSelectionRenderer;
21
import org.txm.chartsengine.jfreechart.core.themes.highcharts.defaulttheme.swing.CustomHTMLToolTip;
22
import org.txm.core.chartsengine.base.___ChartsEngine;
23
import org.txm.core.chartsengine.base.messages.ChartsEngineMessages;
24

  
25
/**
26
 * Renderer providing item selection system and drawing features for selected item and custom rendering for CA charts.
27
 * @author sjacquot
28
 *
29
 */
30
public class FCAItemSelectionRenderer extends ItemSelectionXYLineAndShapeRenderer {
31

  
32

  
33
	/**
34
	 * Needed to get the Graphics2D object to use in getItemShape() to compute the label text bounds and draw a background rectangle.
35
	 */
36
	protected ChartPanel chartPanel;
37

  
38
	/**
39
	 * Stack to store selected items to draw at last, over other items.
40
	 */
41
	protected ArrayList itemsToDrawAtLast; 
42
	
43

  
44
	/**
45
	 * Creates a renderer dedicated to CA charts.
46
	 */
47
	public FCAItemSelectionRenderer() {
48
		super();
49
		this.setChartType(___ChartsEngine.CHART_TYPE_CA_FACTORIAL_MAP);
50
	}
51

  
52

  
53

  
54
	@Override
55
	public void initToolTipGenerator(final IItemSelectionRenderer renderer)	{
56
		// Rows
57
		this.setSeriesToolTipGenerator(0, new XYToolTipGenerator() {
58

  
59
			@Override
60
			public String generateToolTip(XYDataset dataset, int series, int item) {
61

  
62
				// Coordinates format
63
				String pattern = new String("#.##");
64
				DecimalFormat format = new DecimalFormat(pattern);
65

  
66
				// Hexadecimal color
67
				Color color = (Color) getSeriesPaint(series);
... Ce différentiel a été tronqué car il excède la taille maximale pouvant être affichée.

Formats disponibles : Unified diff