Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.compomics.cell_coord.gui.controller.summary; import com.compomics.cell_coord.entity.Sample; import com.compomics.cell_coord.entity.Track; import com.compomics.cell_coord.gui.controller.load.LoadTracksController; import com.compomics.cell_coord.gui.summary.VisualizeTracksPanel; import com.compomics.cell_coord.utils.GuiUtils; import com.compomics.cell_coord.utils.JFreeChartUtils; import java.awt.GridBagConstraints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.ButtonGroup; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.data.Range; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; /** * A controller component to visualize the cell tracks. * * @author Paola */ @Controller("visualizeTracksController") public class VisualizeTracksController { // model private Double[][] coordRanges; private Double[][] shiftedCoordRange; private List<XYSeriesCollection> xYSeriesCollections; // view private VisualizeTracksPanel visualizeTracksPanel; private List<ChartPanel> tracksChartPanels; // parent controller @Autowired private LoadTracksController loadTracksController; // services private GridBagConstraints gridBagConstraints; /** * Initialize controller */ public void init() { gridBagConstraints = GuiUtils.getDefaultGridBagConstraints(); xYSeriesCollections = new ArrayList<>(); tracksChartPanels = new ArrayList<>(); // init main view initVisualizeTracksPanel(); } /** * Compute both the raw and the shifted-to-zero coordinates ranges. */ public void computeRanges() { coordRanges = new Double[2][2]; shiftedCoordRange = new Double[2][2]; List<Double> xRawMinList = new ArrayList<>(); List<Double> xRawMaxList = new ArrayList<>(); List<Double> yRawMinList = new ArrayList<>(); List<Double> yRawMaxList = new ArrayList<>(); List<Double> xShiftMinList = new ArrayList<>(); List<Double> xShiftMaxList = new ArrayList<>(); List<Double> yShiftMinList = new ArrayList<>(); List<Double> yShiftMaxList = new ArrayList<>(); List<Sample> samples = loadTracksController.getSamples(); for (Sample sample : samples) { List<Track> tracks = sample.getTracks(); for (Track track : tracks) { Double[][] coordinateRanges = track.getCoordinateRanges(); Double[][] shiftedCoordinateRanges = track.getShiftedCoordinateRanges(); xRawMinList.add(coordinateRanges[0][0]); xRawMaxList.add(coordinateRanges[0][1]); yRawMinList.add(coordinateRanges[1][0]); yRawMaxList.add(coordinateRanges[1][1]); xShiftMinList.add(shiftedCoordinateRanges[0][0]); xShiftMaxList.add(shiftedCoordinateRanges[0][1]); yShiftMinList.add(shiftedCoordinateRanges[1][0]); yShiftMaxList.add(shiftedCoordinateRanges[1][1]); } } Double xRawMin = Collections.min(xRawMinList); Double xRawMax = Collections.max(xRawMaxList); Double yRawMin = Collections.min(yRawMinList); Double yRawMax = Collections.max(yRawMaxList); coordRanges[0] = new Double[] { xRawMin, xRawMax }; coordRanges[1] = new Double[] { yRawMin, yRawMax }; Double xShiftMin = Collections.min(xShiftMinList); Double xShiftMax = Collections.max(xShiftMaxList); Double yShiftMin = Collections.min(yShiftMinList); Double yShiftMax = Collections.max(yShiftMaxList); shiftedCoordRange[0] = new Double[] { xShiftMin, xShiftMax }; shiftedCoordRange[1] = new Double[] { yShiftMin, yShiftMax }; } /** * Initialize main view */ private void initVisualizeTracksPanel() { // create new view object visualizeTracksPanel = new VisualizeTracksPanel(); // add radiobuttons to a button group ButtonGroup scaleAxesButtonGroup = new ButtonGroup(); scaleAxesButtonGroup.add(visualizeTracksPanel.getDoNotScaleAxesRadioButton()); scaleAxesButtonGroup.add(visualizeTracksPanel.getScaleAxesRadioButton()); // another button group for the shifted/unshifted coordinates ButtonGroup shiftedCoordinatesButtonGroup = new ButtonGroup(); shiftedCoordinatesButtonGroup.add(visualizeTracksPanel.getRawCoordRadioButton()); shiftedCoordinatesButtonGroup.add(visualizeTracksPanel.getRosePlotRadioButton()); /** * Action Listeners. */ // do not scale the axes visualizeTracksPanel.getDoNotScaleAxesRadioButton().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int nCols = Integer.parseInt((String) visualizeTracksPanel.getnColumnsComboBox().getSelectedItem()); boolean useRawData = visualizeTracksPanel.getRawCoordRadioButton().isSelected(); resetPlotLogic(); generateDataForPlots(useRawData); // use the data to set the charts setChartsWithCollections(nCols); } }); // scale the axes (use a common scale for all the samples) visualizeTracksPanel.getScaleAxesRadioButton().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { boolean useRawData = visualizeTracksPanel.getRawCoordRadioButton().isSelected(); for (ChartPanel chartPanel : tracksChartPanels) { scaleAxes(chartPanel.getChart(), useRawData); } } }); // plot the raw tracks visualizeTracksPanel.getRawCoordRadioButton().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int nCols = Integer.parseInt((String) visualizeTracksPanel.getnColumnsComboBox().getSelectedItem()); resetPlotLogic(); generateDataForPlots(true); // use the data to set the charts setChartsWithCollections(nCols); } }); // make the Rose plot: shift coordinates to origin (zero, zero) visualizeTracksPanel.getRosePlotRadioButton().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int nCols = Integer.parseInt((String) visualizeTracksPanel.getnColumnsComboBox().getSelectedItem()); resetPlotLogic(); generateDataForPlots(false); // use the data to set the charts setChartsWithCollections(nCols); } }); // replot with a different number of columns visualizeTracksPanel.getnColumnsComboBox().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int nCols = Integer.parseInt((String) visualizeTracksPanel.getnColumnsComboBox().getSelectedItem()); boolean useRawData = visualizeTracksPanel.getRawCoordRadioButton().isSelected(); resetPlotLogic(); generateDataForPlots(useRawData); // use the data to set the charts setChartsWithCollections(nCols); } }); visualizeTracksPanel.getDoNotScaleAxesRadioButton().setSelected(true); visualizeTracksPanel.getRawCoordRadioButton().setSelected(true); visualizeTracksPanel.getTracksGraphicsParentPanel().revalidate(); visualizeTracksPanel.getTracksGraphicsParentPanel().repaint(); // add view to parent controller loadTracksController.getMainFrame().getVisualizeTracksParentPanel().add(visualizeTracksPanel, gridBagConstraints); } /** * Scale the axes to the experiment coordinates ranges. * * @param chart */ private void scaleAxes(JFreeChart chart, boolean useRawData) { XYPlot xYPlot = chart.getXYPlot(); Double[][] coordinatesRanges; if (useRawData) { coordinatesRanges = coordRanges; } else { coordinatesRanges = shiftedCoordRange; } Double[] xCoords = coordinatesRanges[0]; Double[] yCoords = coordinatesRanges[1]; xYPlot.getDomainAxis().setRange(new Range(yCoords[0], yCoords[1])); xYPlot.getRangeAxis().setRange(new Range(xCoords[0], xCoords[1])); } /** * This will reset the plot logic. */ private void resetPlotLogic() { for (ChartPanel chartPanel : tracksChartPanels) { visualizeTracksPanel.getTracksGraphicsParentPanel().remove(chartPanel); } visualizeTracksPanel.getTracksGraphicsParentPanel().revalidate(); visualizeTracksPanel.getTracksGraphicsParentPanel().repaint(); if (!xYSeriesCollections.isEmpty()) { xYSeriesCollections.clear(); } if (!tracksChartPanels.isEmpty()) { tracksChartPanels.clear(); } } /** * Generate the data for the plots. * * @param useRawData * @return */ private void generateDataForPlots(boolean useRawData) { for (Sample sample : loadTracksController.getSamples()) { XYSeriesCollection xYSeriesCollection = new XYSeriesCollection(); // this is not the best way to fix this multiple locations issue, but for the moment fair enough !! int counter = 0; for (Track track : sample.getTracks()) { // the matrix to use is either the raw coordinates matrix or the shifted matrix Double[][] coordinatesMatrix; if (useRawData) { coordinatesMatrix = track.getCoordinates(); } else { coordinatesMatrix = track.getShiftedCoordinates(); } XYSeries xySeries = JFreeChartUtils.generateXYSeries(coordinatesMatrix); Long trackid = track.getTrackid(); String key; key = "track " + trackid; // we check here if the collection already contains this key int seriesIndex = xYSeriesCollection.getSeriesIndex(key); if (seriesIndex == -1) { key = "track " + trackid; } else { // should be able to get the number of the series already present !! key = "track " + trackid + ", " + (counter + 1); counter++; } xySeries.setKey(key); xYSeriesCollection.addSeries(xySeries); } xYSeriesCollections.add(xYSeriesCollection); } } /** * Given the number of columns to use, set the charts with the * xySeriesCollections generated. * * @param nCols */ private void setChartsWithCollections(int nCols) { List<Sample> samples = loadTracksController.getSamples(); int nPlots = xYSeriesCollections.size(); for (int i = 0; i < nPlots; i++) { XYSeriesCollection collection = xYSeriesCollections.get(i); int numberTracks = collection.getSeries().size(); String title = numberTracks + " tracks" + " - " + samples.get(i).getName(); // create a chart for each plate condition JFreeChart coordinatesChart = ChartFactory.createXYLineChart(title, "x (m)", "y (m)", collection, PlotOrientation.VERTICAL, false, true, false); // and a new chart panel as well ChartPanel coordinatesChartPanel = new ChartPanel(null); coordinatesChartPanel.setOpaque(false); // compute the constraints GridBagConstraints specialGBC = getGridBagConstraints(nPlots, i, nCols); visualizeTracksPanel.getTracksGraphicsParentPanel().add(coordinatesChartPanel, specialGBC); if (visualizeTracksPanel.getScaleAxesRadioButton().isSelected()) { scaleAxes(coordinatesChart, visualizeTracksPanel.getRawCoordRadioButton().isSelected()); } coordinatesChartPanel.setChart(coordinatesChart); // add the chart panels to the list tracksChartPanels.add(coordinatesChartPanel); visualizeTracksPanel.getTracksGraphicsParentPanel().revalidate(); visualizeTracksPanel.getTracksGraphicsParentPanel().repaint(); } } /** * Given the amount of plots to render, and the index of the current plot, * as well as the number of columns to use, get the appropriate * GridBagConstraints. * * @param nPlots * @param index * @param nCols * @return the GridBagConstraints */ private GridBagConstraints getGridBagConstraints(int nPlots, int index, int nCols) { GridBagConstraints specialGBC = new GridBagConstraints(); int nRows = (int) Math.ceil(nPlots / nCols); specialGBC.fill = GridBagConstraints.BOTH; specialGBC.weightx = 1.0 / nCols; specialGBC.weighty = 1.0 / nRows; specialGBC.gridy = (int) Math.floor(index / nCols); if (index < nCols) { specialGBC.gridx = index; } else { specialGBC.gridx = index - ((index / nCols) * nCols); } return specialGBC; } }