/* * Copyright 2006-2015 The MZmine 3 Development Team * * This file is part of MZmine 3. * * MZmine 3 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 3 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 3; if not, * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA */ package io.github.mzmine.modules.plots.msspectrum.datasets; import java.text.NumberFormat; import java.util.concurrent.ScheduledThreadPoolExecutor; import org.jfree.data.xy.AbstractXYDataset; import org.jfree.data.xy.XYDataset; import com.google.common.collect.Range; import io.github.msdk.datamodel.msspectra.MsSpectrum; import io.github.msdk.datamodel.msspectra.MsSpectrumType; import io.github.msdk.datamodel.rawdata.MsScan; import io.github.msdk.spectra.splash.SplashCalculationAlgorithm; import io.github.msdk.util.MsSpectrumUtil; import io.github.mzmine.main.MZmineCore; import io.github.mzmine.modules.plots.msspectrum.MsSpectrumPlotDataSet; import io.github.mzmine.util.MsScanUtils; import javafx.application.Platform; import javafx.beans.property.BooleanProperty; import javafx.beans.property.DoubleProperty; import javafx.beans.property.IntegerProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.scene.paint.Color; /** * MS spectrum data set. Implements IntervalXYDataset for centroid spectra support (rendered by * XYBarRenderer). */ public class MsSpectrumDataSet extends AbstractXYDataset implements MsSpectrumPlotDataSet { private static final long serialVersionUID = -3188441074323131747L; private static final ScheduledThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(1); private MsSpectrum spectrum; private double mzValues[]; private float intensityValues[]; private float topIndensity = 0f; private int numOfDataPoints = 0; private final StringProperty name = new SimpleStringProperty(this, "name", "MS spectrum"); private final DoubleProperty intensityScale = new SimpleDoubleProperty(this, "intensityScale", 0.0); private final DoubleProperty mzShift = new SimpleDoubleProperty(this, "mzShift", 0.0); private final IntegerProperty lineThickness = new SimpleIntegerProperty(this, "lineThickness", 1); private final ObjectProperty<MsSpectrumType> renderingType = new SimpleObjectProperty<>(this, "renderingType", MsSpectrumType.CENTROIDED); private final ObjectProperty<Color> color = new SimpleObjectProperty<>(this, "color", Color.BLUE); private final BooleanProperty showDataPoints = new SimpleBooleanProperty(this, "showDataPoints", false); public MsSpectrumDataSet(MsSpectrum spectrum, String datasetName) { // Listen for property changes mzShift.addListener(e -> { fireDatasetChanged(); }); intensityScale.addListener(e -> { fireDatasetChanged(); }); name.addListener(e -> { fireDatasetChanged(); }); setSpectrum(spectrum, datasetName); } public void setSpectrum(MsSpectrum spectrum, String datasetName) { // Load the actual data in a separate thread to avoid blocking the GUI threadPool.execute(() -> { // Turn notify to off, to avoid redrawing the plot after each // property change setNotify(false); // Remember if the current intensity scale was modified boolean modifiedIntensityScale = (getIntensityScale() != this.topIndensity); this.spectrum = spectrum; this.mzValues = spectrum.getMzValues(); this.intensityValues = spectrum.getIntensityValues(); this.numOfDataPoints = spectrum.getNumberOfDataPoints(); this.topIndensity = MsSpectrumUtil.getMaxIntensity(intensityValues, numOfDataPoints); // If the intensity scale was not modified by the user, set the new // scale to max intensity if (!modifiedIntensityScale) setIntensityScale((double) topIndensity); setName(datasetName); renderingType.get(); setRenderingType(spectrum.getSpectrumType()); // Finally, update the GUI Platform.runLater(() -> { setNotify(true); }); }); } public String getDescription() { StringBuilder sb = new StringBuilder(); if (spectrum instanceof MsScan) { MsScan scan = (MsScan) spectrum; String scanDesc = MsScanUtils.createFullMsScanDescription(scan); sb.append(scanDesc); } NumberFormat intensityFormat = MZmineCore.getConfiguration().getIntensityFormat(); NumberFormat mzFormat = MZmineCore.getConfiguration().getMZFormat(); sb.append("Spectrum type: "); sb.append(spectrum.getSpectrumType()); sb.append("\n"); sb.append("Number of data points: "); sb.append(numOfDataPoints); sb.append("\n"); Range<Double> mzRange = spectrum.getMzRange(); if (mzRange != null) { sb.append("m/z range: "); sb.append(mzFormat.format(mzRange.lowerEndpoint())); sb.append(" - "); sb.append(mzFormat.format(mzRange.upperEndpoint())); sb.append(" m/z\n"); } sb.append("Base peak intensity: "); sb.append(intensityFormat.format(topIndensity)); sb.append("\n"); sb.append("SPLASH ID: "); String splash = SplashCalculationAlgorithm.calculateSplash(spectrum); sb.append(splash); return sb.toString(); } public MsSpectrum getSpectrum() { return spectrum; } public String getName() { return name.get(); } public void setName(String newName) { name.set(newName); } public StringProperty nameProperty() { return name; } public Double getIntensityScale() { return intensityScale.get(); } public void setIntensityScale(Double newIntensityScale) { intensityScale.set(newIntensityScale); } public DoubleProperty intensityScaleProperty() { return intensityScale; } public void resetIntensityScale() { setIntensityScale((double) topIndensity); } public Double getMzShift() { return mzShift.get(); } public void setMzShift(Double newMzShift) { mzShift.set(newMzShift); } public DoubleProperty mzShiftProperty() { return mzShift; } public Integer getLineThickness() { return lineThickness.get(); } public void setLineThickness(Integer newLineThickness) { lineThickness.set(newLineThickness); } public IntegerProperty lineThicknessProperty() { return lineThickness; } public Boolean getShowDataPoints() { return showDataPoints.get(); } public void setShowDataPoints(Boolean newShowDataPoints) { showDataPoints.set(newShowDataPoints); } public BooleanProperty showDataPointsProperty() { return showDataPoints; } public MsSpectrumType getRenderingType() { return renderingType.get(); } public void setRenderingType(MsSpectrumType newType) { renderingType.set(newType); } public ObjectProperty<MsSpectrumType> renderingTypeProperty() { return renderingType; } public Color getColor() { return color.get(); } public void setColor(Color newColor) { color.set(newColor); } public ObjectProperty<Color> colorProperty() { return color; } @Override public int getItemCount(int series) { return numOfDataPoints; } @Override public Number getX(int series, int index) { return mzValues[index]; } @Override public Number getY(int series, int index) { return intensityValues[index] * (getIntensityScale() / topIndensity); } @Override public int getSeriesCount() { return 1; } @Override public Comparable<?> getSeriesKey(int series) { return getName(); } @Override public String generateLabel(XYDataset ds, int series, int index) { final double mz = mzValues[index] - mzShift.doubleValue(); NumberFormat mzFormat = MZmineCore.getConfiguration().getMZFormat(); String label = mzFormat.format(mz); return label; } @Override public String generateToolTip(XYDataset ds, int series, int index) { final double actualMz = mzValues[index]; final float scaledIntensity = getY(series, index).floatValue(); final float actualIntensity = intensityValues[index]; NumberFormat mzFormat = MZmineCore.getConfiguration().getMZFormat(); NumberFormat intensityFormat = MZmineCore.getConfiguration().getIntensityFormat(); StringBuilder sb = new StringBuilder(); if (mzShift.doubleValue() != 0.0) { final double displayMz = mzValues[index] - mzShift.doubleValue(); sb.append("Display m/z: "); sb.append(mzFormat.format(displayMz)); sb.append(" (shift "); sb.append(mzFormat.format(mzShift.doubleValue())); sb.append(" m/z)\n"); } sb.append("Data point m/z: "); sb.append(mzFormat.format(actualMz)); sb.append("\n"); if (intensityScale.get() != topIndensity) { sb.append("Scaled intensity: "); sb.append(intensityFormat.format(scaledIntensity)); sb.append("\n"); } sb.append("Data point intensity: "); sb.append(intensityFormat.format(actualIntensity)); return sb.toString(); } @Override public Number getStartX(int series, int item) { return getX(series, item); } @Override public double getStartXValue(int series, int item) { return getXValue(series, item); } @Override public Number getEndX(int series, int item) { return getX(series, item); } @Override public double getEndXValue(int series, int item) { return getXValue(series, item); } @Override public Number getStartY(int series, int item) { return getY(series, item); } @Override public double getStartYValue(int series, int item) { return getYValue(series, item); } @Override public Number getEndY(int series, int item) { return getY(series, item); } @Override public double getEndYValue(int series, int item) { return getYValue(series, item); } }