package pl.edu.fuw.fid.signalanalysis.dtf; import java.awt.BorderLayout; import java.awt.GridLayout; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingConstants; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartMouseEvent; import org.jfree.chart.ChartMouseListener; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; /** * Panel displaying precomputed spectral features of the AR model, * all at once (in rectangular grid), or one at a time. * * @author ptr@mimuw.edu.pl */ public class DtfPlotsPanel extends JPanel { private final int dimension; private final ChartPanel[] charts; private final boolean[] normalizable; // if >= 0, only one chart is visible private int chartSelected = -1; public DtfPlotsPanel(XYSeries[][] series) { super(new BorderLayout()); dimension = series.length; charts = new ChartPanel[dimension * dimension]; normalizable = new boolean[dimension * dimension]; // add placeholder which shall be visible until the user selects model order add(new JLabel("select AR model order to display graphs", SwingConstants.CENTER), BorderLayout.CENTER); // prepare charts to be displayed int index = 0; for (int i=0; i<series.length; ++i) { if (series[i].length != dimension) { throw new RuntimeException("series[][] is not a square array"); } for (int j=0; j<series.length; ++j) { XYSeries serie = series[i][j]; if (serie != null) { final int indexFinal = index; JFreeChart chart = ChartFactory.createXYAreaChart(serie.getDescription(), "frequency [Hz]", null, new XYSeriesCollection(serie), PlotOrientation.VERTICAL, false, false, false); ChartPanel panel = new ChartPanel(chart); panel.setDomainZoomable(false); panel.setRangeZoomable(false); panel.addChartMouseListener(new ChartMouseListener() { @Override public void chartMouseMoved(ChartMouseEvent cme) { // nothing here } @Override public void chartMouseClicked(ChartMouseEvent cme) { if (chartSelected == indexFinal) { showAllCharts(); } else { showSingleChart(indexFinal); } } }); charts[index] = panel; normalizable[index] = (i != j); } index++; } } } public void rescaleCharts() { double max = 0.0; for (int i=0; i<charts.length; ++i) { if (normalizable[i]) { XYDataset data = charts[i].getChart().getXYPlot().getDataset(); int length = data.getItemCount(0); for (int f=0; f<length; ++f) { max = Math.max(max, data.getYValue(0, f)); } } } for (int i=0; i<charts.length; ++i) { if (normalizable[i]) { charts[i].getChart().getXYPlot().getRangeAxis().setRange(0, max); } } } public void showAllCharts() { this.removeAll(); chartSelected = -1; setLayout(new GridLayout(dimension, dimension)); for (int i=0; i<charts.length; ++i) { if (charts[i] != null) { this.add(charts[i], i); } } revalidate(); } public void showSingleChart(int index) { this.removeAll(); chartSelected = index; setLayout(new BorderLayout()); this.add(charts[index], BorderLayout.CENTER); revalidate(); } }