package org.signalml.method.bookaverage; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.image.BufferedImage; import javax.swing.JComboBox; import javax.swing.JPanel; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.XYPlot; import org.jfree.data.xy.XYSeriesCollection; import org.signalml.app.view.book.wignermap.WignerMapImageProvider; import org.signalml.app.view.book.wignermap.WignerMapPalette; import org.signalml.app.view.book.wignermap.WignerMapPaletteComboBoxCellRenderer; import org.signalml.app.view.book.wignermap.WignerMapScaleComboBoxCellRenderer; import org.signalml.domain.book.WignerMapScaleType; /** * @author ptr@mimuw.edu.pl */ public class TimeFrequencyMapPanel extends JPanel { private final XYPlot plot; private final int width, height; private final double[][] normed, scaled; private final JComboBox paletteComboBox; private final JComboBox scaleComboBox; public TimeFrequencyMapPanel(double[][] data, double freqMin, double freqMax, double timeRange) { super(new BorderLayout()); ItemListener refresh = new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { refreshImage(); } }; this.width = data.length; this.height = data[0].length; this.normed = new double[width][height]; this.scaled = new double[width][height]; this.scaleComboBox = createScaleComboBox(refresh); this.paletteComboBox = createPaletteComboBox(refresh); this.plot = createPlot(freqMin, freqMax, timeRange); double min = Double.POSITIVE_INFINITY; double max = Double.NEGATIVE_INFINITY; for (int ix=0; ix<width; ++ix) for (int iy=0; iy<height; ++iy) { min = Math.min(min, data[ix][iy]); max = Math.max(max, data[ix][iy]); } double range = max - min; for (int ix=0; ix<width; ++ix) for (int iy=0; iy<height; ++iy) { normed[ix][iy] = (data[ix][iy] - min) / range; } refreshImage(); ChartPanel chartPanel = new ChartPanel(new JFreeChart(plot)); JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING)); topPanel.add(scaleComboBox); topPanel.add(paletteComboBox); this.add(chartPanel, BorderLayout.CENTER); this.add(topPanel, BorderLayout.PAGE_START); } private static XYPlot createPlot(double freqMin, double freqMax, double timeRange) { ValueAxis ax = new NumberAxis("time (s)"); ax.setRange(0, timeRange); ValueAxis ay = new NumberAxis("frequency (Hz)"); ay.setRange(freqMin, freqMax); XYPlot result = new XYPlot(new XYSeriesCollection(), ax, ay, null) { @Override public boolean isDomainZoomable() { return false; } @Override public boolean isRangeZoomable() { return false; } }; result.setBackgroundImageAlpha(1.0f); return result; } private static JComboBox createPaletteComboBox(ItemListener itemListener) { JComboBox result = new JComboBox(WignerMapPalette.values()); result.setRenderer(new WignerMapPaletteComboBoxCellRenderer()); result.addItemListener(itemListener); return result; } private static JComboBox createScaleComboBox(ItemListener itemListener) { JComboBox result = new JComboBox(WignerMapScaleType.values()); result.setRenderer(new WignerMapScaleComboBoxCellRenderer()); result.addItemListener(itemListener); return result; } private void refreshImage() { final WignerMapScaleType scale = (WignerMapScaleType) scaleComboBox.getSelectedItem(); final WignerMapPalette palette = (WignerMapPalette) paletteComboBox.getSelectedItem(); WignerMapImageProvider mip = new WignerMapImageProvider(); if (scale == WignerMapScaleType.SQRT) { for (int ix=0; ix<width; ++ix) for (int iy=0; iy<height; ++iy) { scaled[ix][iy] = Math.sqrt(normed[ix][iy]); } } else if (scale == WignerMapScaleType.LOG) { double log2 = Math.log(2.0); for (int ix=0; ix<width; ++ix) for (int iy=0; iy<height; ++iy) { scaled[ix][iy] = Math.log(1.0 + normed[ix][iy]) / log2; } } else { for (int ix=0; ix<width; ++ix) for (int iy=0; iy<height; ++iy) { scaled[ix][iy] = normed[ix][iy]; } } BufferedImage image = mip.getImage(scaled, width, height, palette); plot.setBackgroundImage(image); } }