/***************************************************************************** * Copyright (c) 2008 Bioclipse Project * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * *****************************************************************************/ package spok.guicomponents; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.text.DecimalFormat; import java.util.Iterator; import java.util.List; import net.bioclipse.spectrum.editor.ChartPage; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.part.WorkbenchPart; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.annotations.XYLineAnnotation; import org.jfree.chart.labels.XYItemLabelGenerator; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.StandardXYItemRenderer; import org.jfree.chart.renderer.xy.XYItemRenderer; import org.jfree.data.xy.XYBarDataset; import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import org.xmlcml.cml.base.CMLElement; import org.xmlcml.cml.element.CMLPeak; import org.xmlcml.cml.element.CMLSpectrum; import spok.utils.SpectrumUtils; /** * Factory class for building spectrum charts * * @author Stefan Kuhn * @created 4/Aug/08 */ public class SpectrumChartFactory { /** The Buttons of the Chart Properties Popup Window */ // public static JButton buttonSetChanges, buttonApply, buttonCancel; static double[] xData; static double[] yData; static double continuousUpperDomainBound; static double continuousLowerDomainBound; private static XYSeries SERIEShigh = null; private static XYSeries SERIESlow = null; private static JFreeChart lastPeakchart = null; public final static String LABELTHRESHOLD="labelthreshold"; private static double minx; private static double maxx; /** * Method for creating a peak chart. * * @param spectrum The SpokSpectrum for which the chart should be created * @param matches These peaks will be highlighted in the chart * @param page The SpectrumCompareView or ChartPage this chart is in * @return the ChartPanel containing the peak chart */ public static JFreeChart createPeakChart(CMLSpectrum spectrum, List<CMLElement> matches, WorkbenchPart page) { return SpectrumChartFactory.createPeakChart(spectrum,matches,page,false); } /** * Method for creating a peak chart. * * @param spectrum The SpokSpectrum for which the chart should be created * @param matches These peaks will be highlighted in the chart * @param page The SpectrumCompareView or ChartPage this chart is in * @param minx * @param maxx The limits to be used for the chart (normally the peaks determine this, you can override this by these values) * @return the ChartPanel containing the peak chart */ public static JFreeChart createPeakChart(CMLSpectrum spectrum, List<CMLElement> matches, WorkbenchPart page, double minx, double maxx) { SpectrumChartFactory.minx=minx; SpectrumChartFactory.maxx=maxx; return SpectrumChartFactory.createPeakChart(spectrum,matches,page,true); } /** * Method for creating a peak chart. * * @param spectrum The SpokSpectrum for which the chart should be created * @param matches These peaks will be highlighted in the chart * @param page The SpectrumCompareView or ChartPage this chart is in * @param externalLimits Shall external limits be used? * @return the ChartPanel containing the peak chart */ public static JFreeChart createPeakChart(CMLSpectrum spectrum, List<CMLElement> matches, IWorkbenchPart page, boolean externalLimits) { JFreeChart peakChart; String xAxisLabel = null; String yAxisLabel = null; try{ if (spectrum != null) { if (spectrum.getPeakListElements().size() != 0) { //not sure how this can happen, but it does and causes npe if(spectrum.getPeakListElements().get(0).getPeakElements().get(0)!=null){ CMLPeak peak = spectrum.getPeakListElements().get(0) .getPeakElements().get(0); xAxisLabel = peak.getXUnits(); yAxisLabel = peak.getYUnits(); } } else if ( spectrum.getSpectrumDataElements().size()>0){ xAxisLabel = spectrum.getSpectrumDataElements().get(0) .getXaxisElements().get(0).getArrayElements().get(0) .getUnits(); yAxisLabel = spectrum.getSpectrumDataElements().get(0) .getYaxisElements().get(0).getArrayElements().get(0) .getUnits(); }else{ MessageBox mb = new MessageBox(page.getSite().getShell(),SWT.ICON_INFORMATION); mb.setText( "No Data" ); mb.setMessage( "We found neither peaks nor continuous data in your spectrum. This might be a problem with the file or the parsing. We will still display, but don't be suprised!" ); mb.open(); } if(xAxisLabel==null) xAxisLabel=""; if(yAxisLabel==null) yAxisLabel=""; //if label are namespaced, remove namespace if (xAxisLabel != null && xAxisLabel.indexOf(":") != -1) { xAxisLabel = xAxisLabel.substring(xAxisLabel.indexOf(":")+1); yAxisLabel = yAxisLabel.substring(yAxisLabel.indexOf(":")+1); } String title = getSpectrumTitle(spectrum); List<CMLElement> peaks = SpectrumUtils.getPeakElements(spectrum); if(peaks!=null){ if(net.bioclipse.spectrum.Activator.getDefault().getPluginPreferences().isDefault(LABELTHRESHOLD)) net.bioclipse.spectrum.Activator.getDefault().getPluginPreferences().setValue(LABELTHRESHOLD,-1); SERIEShigh = new XYSeries("high Peak"); SERIESlow = new XYSeries("low Peak"); boolean allYVal0 = checkIfAllYVal0(peaks); Iterator<CMLElement> it = peaks.iterator(); while (it.hasNext()) { CMLPeak peak = (CMLPeak)it.next(); int tresholdMultiplicator = 0; //dependent on the threshold sort peaks into to series - SERIEShigh will have the y-value as label if (net.bioclipse.spectrum.Activator.getDefault().getPluginPreferences().getInt(LABELTHRESHOLD) != -1) { tresholdMultiplicator = net.bioclipse.spectrum.Activator.getDefault().getPluginPreferences().getInt(LABELTHRESHOLD); } double threshold = (SpectrumUtils.getHighestY(spectrum)/100)*tresholdMultiplicator; if (!allYVal0 && peak.getYValue() > threshold || (Double.isNaN(peak.getYValue()) && net.bioclipse.spectrum.Activator.getDefault().getPluginPreferences().getInt(LABELTHRESHOLD) != -1)) { if(Double.isNaN(peak.getYValue())) SERIEShigh.add(peak.getXValue(), 1); else SERIEShigh.add(peak.getXValue(), peak.getYValue()); } else { if(Double.isNaN(peak.getYValue())) SERIESlow.add(peak.getXValue(), 1); else if (allYVal0) { SERIEShigh.add(peak.getXValue(), 100); } else SERIESlow.add(peak.getXValue(), peak.getYValue()); } } XYSeriesCollection collection = new XYSeriesCollection(SERIEShigh); collection.addSeries(SERIESlow); XYBarDataset dataset = new XYBarDataset(collection, 0); //create the chart peakChart = ChartFactory.createXYBarChart(title, xAxisLabel, false, yAxisLabel, dataset, PlotOrientation.VERTICAL, false, true, false); peakChart.setAntiAlias(false); XYPlot peakPlot = peakChart.getXYPlot(); //highlight peaks which are in matches if (peaks != null && peaks.size() > 0) { for (int i=0; i<peaks.size(); i++) { if(matches!=null){ for(int k=0;k<matches.size();k++){ if(((CMLPeak)peaks.get(i)).getXValue()==((CMLPeak)matches.get(k)).getXValue()){ CMLPeak peak = (CMLPeak)peaks.get(i); double xval = peak.getXValue(); double yval = peak.getYValue(); //if peak has no y-value assigned set y value to upperBound of the chart if (yval == 0 || Double.isNaN(yval)) { yval = peakPlot.getRangeAxis().getUpperBound(); } //create the XYKLineAnnotation and add it to the plot XYLineAnnotation lineAnno = new XYLineAnnotation(xval, 0, xval, yval, new BasicStroke(1f), Color.GREEN); peakPlot.addAnnotation(lineAnno); break; } } } } } //invert x-axis if nmr or ir spectrum if (spectrum.getType()!=null && (spectrum.getType().equals(SpectrumUtils.NMRSPECTRUMTYPE) || spectrum.getType().equals(SpectrumUtils.IRSPECTRUMTYPE))) { peakPlot.getDomainAxis().setInverted(true); } //y-axis increase upperBound by 20%, so that the label of the highest peak can be seen as well... peakPlot.getRangeAxis().setUpperBound(peakPlot.getRangeAxis().getUpperBound() * 1.2); peakPlot.getDomainAxis().addChangeListener(externalLimits ? new SpectrumAxisListener(page, peakChart,minx,maxx) : new SpectrumAxisListener(page, peakChart)); XYItemRenderer renderer = peakPlot.getRenderer(); //paint both series in black, so they cant be distiguished anymore :) renderer.setSeriesPaint(0, Color.black); renderer.setSeriesPaint(1, Color.black); //make first Series item labels visible and hide second Series ones if (net.bioclipse.spectrum.Activator.getDefault().getPluginPreferences().getInt(LABELTHRESHOLD)!=-1){ renderer.setItemLabelsVisible(null); renderer.setSeriesItemLabelsVisible(0, true); renderer.setSeriesItemLabelsVisible(1, false); XYItemLabelGenerator labelGenerator = new MyXYItemLabelGenerator("{2}", new DecimalFormat("0.00"), new DecimalFormat("0.00")); renderer.setItemLabelGenerator(labelGenerator); renderer.setItemLabelFont(new Font("Arial", Font.BOLD, 9)); for (int i=0; i<SERIEShigh.getItemCount(); i++) { labelGenerator.generateLabel(dataset, 0, i); } } if (spectrum.getSpectrumDataElements() != null && spectrum.getSpectrumDataElements().size() != 0) { peakPlot.getDomainAxis().setUpperBound( continuousUpperDomainBound); peakPlot.getDomainAxis().setLowerBound( continuousLowerDomainBound); } lastPeakchart = peakChart; } else{ peakChart = ChartFactory.createXYBarChart(null, xAxisLabel, false, yAxisLabel, null, PlotOrientation.VERTICAL, false, true, false); lastPeakchart = null; } } else { peakChart = ChartFactory.createXYBarChart(null, xAxisLabel, false, yAxisLabel, null, PlotOrientation.VERTICAL, false, true, false); lastPeakchart = null; } }catch(Exception e){ e.printStackTrace(); return null; } return peakChart; } private static boolean checkIfAllYVal0(List<CMLElement> peaks) { Iterator<CMLElement> it = peaks.iterator(); while (it.hasNext()) { CMLPeak peak = (CMLPeak) it.next(); double yValue = peak.getYValue(); if (yValue != 0) { return false; } } return true; } /** * Method for creating a continuous chart * * @param cmlSpectrum * The CMLSpectrum for which the chart should be created * the Workbench page containing the ContinuousSpectrumView and * the PeakSpectrumView * @param page The SpectrumCompareView or ChartPage this chart is in * @return the ChartPanel containing the continuous chart * @throws CMLException */ public static JFreeChart createContinousChart(CMLSpectrum cmlSpectrum, ChartPage page) { JFreeChart continuousChart; String xAxisLabel = null; String yAxisLabel = null; if (cmlSpectrum != null && cmlSpectrum.getSpectrumDataElements().size()>0 && cmlSpectrum.getSpectrumDataElements().get(0).getXaxisElements().size()>0) { xAxisLabel = cmlSpectrum.getSpectrumDataElements().get(0) .getXaxisElements().get(0).getTitle(); yAxisLabel = cmlSpectrum.getSpectrumDataElements().get(0) .getYaxisElements().get(0).getTitle(); // if label are namespaced, remove namespace if (xAxisLabel != null && xAxisLabel.indexOf(":") != -1) { xAxisLabel = xAxisLabel.substring(xAxisLabel.indexOf(":")+1); yAxisLabel = yAxisLabel.substring(yAxisLabel.indexOf(":")+1); } String title = getSpectrumTitle(cmlSpectrum); double[] xDataArray = null; double[] yDataArray = null; xDataArray = cmlSpectrum.getSpectrumDataElements().get(0) .getXaxisElements().get(0).getArrayElements().get(0) .getDoubles(); yDataArray = cmlSpectrum.getSpectrumDataElements().get(0) .getYaxisElements().get(0).getArrayElements().get(0) .getDoubles(); XYSeries series = new XYSeries("Signal"); for (int i = 0; i < xDataArray.length; i++) { series.add(xDataArray[i], yDataArray[i]); } XYDataset xyDataset = new XYSeriesCollection(series); continuousChart = ChartFactory.createXYLineChart(title, xAxisLabel, yAxisLabel, xyDataset, PlotOrientation.VERTICAL, false, true, false); continuousChart.setAntiAlias(false); XYPlot continuousPlot = continuousChart.getXYPlot(); // invert x-axis if nmr or ir spectrum if (cmlSpectrum.getType().equals(SpectrumUtils.NMRSPECTRUMTYPE) || cmlSpectrum.getType().equals(SpectrumUtils.IRSPECTRUMTYPE)) { continuousPlot.getDomainAxis().setInverted(true); } continuousPlot.setRenderer(new StandardXYItemRenderer()); continuousPlot.getDomainAxis().addChangeListener( new SpectrumAxisListener(page, continuousChart)); continuousUpperDomainBound = continuousPlot.getDomainAxis() .getUpperBound(); continuousLowerDomainBound = continuousPlot.getDomainAxis() .getLowerBound(); syncronizeLastPeakChart(); } else { continuousChart = ChartFactory.createXYBarChart(null, xAxisLabel, false, yAxisLabel, null, PlotOrientation.VERTICAL, false, true, false); } return continuousChart; } private static String getSpectrumTitle(CMLSpectrum spectrum) { String title; if (spectrum.getTitle() != null && spectrum.getTitle().length() > 0) { title = spectrum.getTitle(); } else { title = spectrum.getId(); } return title; } private static void syncronizeLastPeakChart() { if (lastPeakchart != null) { lastPeakchart.getXYPlot().getDomainAxis().setUpperBound( continuousUpperDomainBound); lastPeakchart.getXYPlot().getDomainAxis().setLowerBound( continuousLowerDomainBound); } } }