/* * Copyright 2006-2020 The MZmine Development Team * * This file is part of MZmine. * * MZmine is free software; you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * MZmine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along with MZmine; if not, * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA */ package io.github.mzmine.modules.visualization.productionfilter; import com.google.common.collect.Range; import io.github.mzmine.datamodel.RawDataFile; import io.github.mzmine.gui.chartbasics.gui.javafx.EChartViewer; import io.github.mzmine.gui.chartbasics.listener.ZoomHistory; import io.github.mzmine.main.MZmineCore; import io.github.mzmine.modules.visualization.spectra.simplespectra.SpectraVisualizerModule; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Shape; import java.awt.geom.Ellipse2D; import java.text.NumberFormat; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; import javafx.scene.control.SeparatorMenuItem; import javafx.scene.input.MouseButton; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.event.ChartProgressEvent; import org.jfree.chart.fx.interaction.ChartMouseEventFX; import org.jfree.chart.fx.interaction.ChartMouseListenerFX; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.SeriesRenderingOrder; import org.jfree.chart.plot.ValueMarker; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.title.TextTitle; class ProductIonFilterPlot extends EChartViewer { private JFreeChart chart; private XYPlot plot; private ProductIonFilterDataPointRenderer defaultRenderer; private boolean showSpectrumRequest = false; private ProductIonFilterVisualizerWindow visualizer; // crosshair (selection) color private static final Color crossHairColor = Color.gray; // crosshair stroke private static final BasicStroke crossHairStroke = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1.0f, new float[]{5, 3}, 0); // title font private static final Font titleFont = new Font("SansSerif", Font.PLAIN, 11); // Item's shape, small circle private static final Shape dataPointsShape = new Ellipse2D.Double(-1, -1, 2, 2); private static final Shape dataPointsShape2 = new Ellipse2D.Double(-1, -1, 3, 3); // Series colors private static final Color pointColor = Color.blue; private static final Color searchPrecursorColor = Color.green; private static final Color searchNeutralLossColor = Color.orange; private TextTitle chartTitle; private Range<Double> highlightedPrecursorRange = Range.singleton(Double.NEGATIVE_INFINITY); private Range<Double> highlightedNeutralLossRange = Range.singleton(Double.NEGATIVE_INFINITY); public ProductIonFilterPlot(ProductIonFilterVisualizerWindow visualizer) { super(ChartFactory.createXYLineChart("", "", "", null, PlotOrientation.VERTICAL, true, true, false), true, true, false, false, true); resetZoomHistory(); setMouseZoomable(false); this.visualizer = visualizer; // set the renderer properties defaultRenderer = new ProductIonFilterDataPointRenderer(false, true); defaultRenderer.setTransparency(0.4f); setSeriesColorRenderer(0, pointColor, dataPointsShape); setSeriesColorRenderer(1, searchPrecursorColor, dataPointsShape2); setSeriesColorRenderer(2, searchNeutralLossColor, dataPointsShape2); // chart properties chart = getChart(); chart.setBackgroundPaint(Color.white); // set the plot properties plot = chart.getXYPlot(); plot.setBackgroundPaint(Color.white); plot.setSeriesRenderingOrder(SeriesRenderingOrder.FORWARD); // title chartTitle = chart.getTitle(); chartTitle.setMargin(5, 0, 0, 0); chartTitle.setFont(titleFont); // set crosshair (selection) properties plot.setDomainCrosshairVisible(true); plot.setRangeCrosshairVisible(true); plot.setDomainCrosshairPaint(crossHairColor); plot.setRangeCrosshairPaint(crossHairColor); plot.setDomainCrosshairStroke(crossHairStroke); plot.setRangeCrosshairStroke(crossHairStroke); plot.addRangeMarker(new ValueMarker(0)); // add items to popup menu ContextMenu popupMenu = getContextMenu(); popupMenu.getItems().add(new SeparatorMenuItem()); this.addChartMouseListener(new ChartMouseListenerFX() { @Override public void chartMouseClicked(ChartMouseEventFX event) { requestFocus(); javafx.scene.input.MouseEvent mouseEvent = event.getTrigger(); if ((mouseEvent.getClickCount() == 2) && (mouseEvent.getButton() == MouseButton.PRIMARY)) { // showSpectrum(); showSpectrumRequest = true; } } @Override public void chartMouseMoved(ChartMouseEventFX event) { } }); this.setOnKeyTyped(keyEvent -> { if (keyEvent.getCharacter().equals(" ")) { showSpectrum(); } }); chart.addProgressListener(event -> { if (event.getType() == ChartProgressEvent.DRAWING_FINISHED) { visualizer.updateTitle(); if (showSpectrumRequest) { showSpectrumRequest = false; showSpectrum(); } } }); resetZoomHistory(); } public void showSpectrum() { ProductIonFilterDataSet dataset = (ProductIonFilterDataSet) plot.getDataset(); double xValue = plot.getDomainCrosshairValue(); double yValue = plot.getRangeCrosshairValue(); ProductIonFilterDataPoint pos = dataset.getDataPoint(xValue, yValue); RawDataFile dataFile = visualizer.getDataFile(); if (pos != null) { SpectraVisualizerModule.showNewSpectrumWindow(dataFile, pos.getScanNumber()); } resetZoomHistory(); } public void resetZoomHistory() { ZoomHistory history = getZoomHistory(); if (history != null) { history.clear(); } } public void setAxisTypes(Object xAxisType) { NumberFormat rtFormat = MZmineCore.getConfiguration().getRTFormat(); NumberFormat mzFormat = MZmineCore.getConfiguration().getMZFormat(); // set the X axis (retention time) properties final NumberAxis xAxis = (NumberAxis) this.plot.getDomainAxis(); if (xAxisType.equals(ProductIonFilterParameters.xAxisPrecursor)) { xAxis.setLabel("Precursor ion m/z"); xAxis.setNumberFormatOverride(mzFormat); } else { xAxis.setLabel("Retention time"); xAxis.setNumberFormatOverride(rtFormat); } xAxis.setUpperMargin(0); xAxis.setLowerMargin(0); xAxis.setAutoRangeIncludesZero(false); // set the Y axis (intensity) properties final NumberAxis yAxis = (NumberAxis) this.plot.getRangeAxis(); yAxis.setLabel("Product ion m/z"); yAxis.setAutoRangeIncludesZero(false); yAxis.setNumberFormatOverride(mzFormat); yAxis.setUpperMargin(0); yAxis.setLowerMargin(0); } public void addProductionFilterDataSet(ProductIonFilterDataSet dataset) { plot.setDataset(dataset); defaultRenderer.setDefaultToolTipGenerator(dataset); plot.setRenderer(defaultRenderer); } public void setMenuItems() { final ContextMenu popupMenu = getContextMenu(); MenuItem highlightPrecursorMenuItem = new MenuItem("Highlight precursor m/z range..."); highlightPrecursorMenuItem.setOnAction(event -> { ProductIonFilterSetHighlightDialog dialog = new ProductIonFilterSetHighlightDialog(visualizer, this, "HIGHLIGHT_PRECURSOR"); dialog.show(); }); popupMenu.getItems().add(highlightPrecursorMenuItem); MenuItem highlightNLMenuItem = new MenuItem("Highlight neutral loss m/z range..."); highlightNLMenuItem.setOnAction(event -> { ProductIonFilterSetHighlightDialog dialog = new ProductIonFilterSetHighlightDialog(visualizer, this, "HIGHLIGHT_NEUTRALLOSS"); dialog.show(); }); popupMenu.getItems().add(highlightNLMenuItem); popupMenu.getItems().add(new SeparatorMenuItem()); } private void setSeriesColorRenderer(int series, Color color, Shape shape) { defaultRenderer.setSeriesPaint(series, color); defaultRenderer.setSeriesFillPaint(series, color); defaultRenderer.setSeriesShape(series, shape); } void setTitle(String title) { chartTitle.setText(title); } /** * @return Returns the highlightedPrecursorRange. */ Range<Double> getHighlightedPrecursorRange() { return highlightedPrecursorRange; } /** * @param range The highlightedPrecursorRange to set. */ void setHighlightedPrecursorRange(Range<Double> range) { this.highlightedPrecursorRange = range; } /** * @return Returns the highlightedNeutralLossRange. */ Range<Double> getHighlightedNeutralLossRange() { return highlightedNeutralLossRange; } /** * @param range The highlightedNeutralLossRange to set. */ void setHighlightedNeutralLossRange(Range<Double> range) { this.highlightedNeutralLossRange = range; } XYPlot getXYPlot() { return plot; } }