package com.compomics.util.gui.spectrum; import com.compomics.util.experiment.identification.matches.IonMatch; import com.compomics.util.experiment.massspectrometry.MSnSpectrum; import java.awt.Color; import java.util.ArrayList; import javax.swing.JPanel; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.labels.StandardXYToolTipGenerator; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.DefaultXYItemRenderer; import org.jfree.data.xy.DefaultXYDataset; /** * Creates a MassErrorPlot displaying the mz values vs the mass error. * * @author Harald Barsnes */ public class MassErrorPlot extends JPanel { /** * The complete list of possible spectrum annotations. */ private ArrayList<IonMatch> annotations; /** * The chart panel. */ private ChartPanel chartPanel; /** * Creates a new MassErrorPlot. * * @param annotations the full list of spectrum annotations * @param currentSpectrum the current spectrum * @param massTolerance the mass error tolerance * * @throws java.lang.InterruptedException exception thrown if the thread is * interrupted */ public MassErrorPlot( ArrayList<IonMatch> annotations, MSnSpectrum currentSpectrum, double massTolerance) throws InterruptedException { this(annotations, currentSpectrum, massTolerance, false); } /** * Creates a new MassErrorPlot. * * @param annotations the full list of spectrum annotations * @param currentSpectrum the current spectrum * @param massTolerance the mass error tolerance * @param useRelativeError if true the relative error (ppm) is used instead * of the absolute error (Da) * * @throws java.lang.InterruptedException exception thrown if the thread is * interrupted */ public MassErrorPlot( ArrayList<IonMatch> annotations, MSnSpectrum currentSpectrum, double massTolerance, boolean useRelativeError) throws InterruptedException { super(); setOpaque(false); setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.LINE_AXIS)); this.annotations = annotations; if (annotations.size() > 0) { boolean useIntensityGrading = false; // @TODO: make this selectable by the user? DefaultXYDataset xyDataset = new DefaultXYDataset(); ArrayList<Color> colors = new ArrayList<Color>(); // find the most intense annotated peak double maxAnnotatedIntensity = 0.0; for (IonMatch annotation : annotations) { IonMatch ionMatch = (IonMatch) annotation; if (ionMatch.peak.intensity > maxAnnotatedIntensity) { maxAnnotatedIntensity = ionMatch.peak.intensity; } } double maxError = 0.0; for (IonMatch annotation : annotations) { double[][] dataXY = new double[2][1]; IonMatch ionMatch = (IonMatch) annotation; dataXY[0][0] = ionMatch.peak.mz; if (useRelativeError) { dataXY[1][0] = ionMatch.getRelativeError(); } else { dataXY[1][0] = ionMatch.getAbsoluteError(); } if (Math.abs(dataXY[1][0]) > maxError) { maxError = Math.abs(dataXY[1][0]); } xyDataset.addSeries(ionMatch.getPeakAnnotation(true), dataXY); // use the two lines below if all points ought to have the same color //int alphaLevel = Double.valueOf((ionMatch.peak.intensity / totalIntensity) / (maxAnnotatedIntensity / totalIntensity) * 255).intValue(); //colors.add(new Color(255, 0, 0, alphaLevel)); // @TODO: make color selectable by the user? // use the same colors as for the SpectrumPanel annotation colors.add(SpectrumPanel.determineFragmentIonColor(ionMatch.ion, false)); } JFreeChart chart = ChartFactory.createScatterPlot(null, null, null, xyDataset, PlotOrientation.VERTICAL, false, false, false); // fine tune the chart properites XYPlot plot = chart.getXYPlot(); DefaultXYItemRenderer renderer = new DefaultXYItemRenderer(); renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator()); // set the colors and shape for the datapoints for (int i = 0; i < colors.size(); i++) { if (useIntensityGrading) { // @TODO: implement itensity color grading? renderer.setSeriesPaint(i, colors.get(i)); renderer.setSeriesShape(i, renderer.getBaseShape()); } else { renderer.setSeriesPaint(i, colors.get(i)); renderer.setSeriesShape(i, renderer.getBaseShape()); } } plot.setRenderer(renderer); // remove space before/after the domain axis plot.getDomainAxis().setUpperMargin(0); plot.getDomainAxis().setLowerMargin(0); // set the mass error range plot.getRangeAxis().setLowerBound(-massTolerance); plot.getRangeAxis().setUpperBound(massTolerance); plot.setRangeGridlinePaint(Color.black); ValueAxis domainAxis = plot.getDomainAxis(); domainAxis.setRange(0, currentSpectrum.getMaxMz()); // hide unwanted chart details plot.setDomainGridlinesVisible(false); chart.getPlot().setOutlineVisible(false); // set background color chart.getPlot().setBackgroundPaint(Color.WHITE); chart.setBackgroundPaint(Color.WHITE); chartPanel = new ChartPanel(chart); chartPanel.setBackground(Color.WHITE); this.add(chartPanel); } } /** * Returns the current number of data points in the mass error plot. * * @return the current number of data points */ public int getNumberOfDataPointsInPlot() { return annotations.size(); } /** * Returns the chart panel. * * @return the chart panel */ public ChartPanel getChartPanel() { return chartPanel; } }