/***************************************************************************** * 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 net.bioclipse.spectrum.views; import java.awt.BorderLayout; import java.awt.Frame; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import net.bioclipse.spectrum.Activator; import net.bioclipse.spectrum.business.ISpectrumManager; import net.bioclipse.spectrum.domain.JumboSpectrum; import org.eclipse.core.resources.IFile; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.awt.SWT_AWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.part.ViewPart; import org.jfree.chart.JFreeChart; import org.xmlcml.cml.base.CMLElement; import org.xmlcml.cml.element.CMLPeak; import org.xmlcml.cml.element.CMLSpectrum; import spok.guicomponents.SpectrumChartFactory; import spok.guicomponents.SpokChartPanel; import spok.utils.SpectrumUtils; /** * View displaying a JFreeChart based peak chart as an embedded swing container. * * @author Tobias Helmus * @created 19. Dezember 2005 * */ public class SpectrumCompareView extends ViewPart implements ISelectionListener { public static final String ID = "net.bioclipse.spectrum.views.SpectrumCompareView"; private ArrayList<Composite> controls=new ArrayList<Composite>(); private Composite parent; private List<JFreeChart> charts=new ArrayList<JFreeChart>(); public List<JFreeChart> getCharts() { return charts; } /** * This is a callback that will allow us to create the viewer and initialize * it. */ public void createPartControl(Composite parent) { this.parent=parent; GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.verticalSpacing = 2; layout.marginWidth = 0; layout.marginHeight = 2; parent.setLayout(layout); GridData layoutData = new GridData(); layoutData.grabExcessHorizontalSpace = true; layoutData.grabExcessVerticalSpace=true; parent.setLayoutData(layoutData); getSite().getWorkbenchWindow().getSelectionService().addSelectionListener("net.bioclipse.navigator",this); } public void setFocus() { parent.setFocus(); parent.redraw(); } /* * (non-Javadoc) * * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, * org.eclipse.jface.viewers.ISelection) */ public void selectionChanged(IWorkbenchPart part, ISelection selection) { if(!parent.isDisposed()) this.reactOnSelection(selection); } /* * (non-Javadoc) * * @see org.eclipse.ui.IWorkbenchPart#dispose() */ @Override public void dispose() { super.dispose(); } private void cleanComposite() { for(int i=0;i<controls.size();i++) { Display.getCurrent().syncExec(new MyRunnable (controls.get(i))); } controls.clear(); } public List<CMLElement> getMatchingSearchShift(List<CMLElement> originalSpectrum, List<CMLElement> searchSpectrum) { List<CMLElement> peakList = new ArrayList<CMLElement>(); if(searchSpectrum.size()==0 || originalSpectrum.size()==0) return peakList; boolean signalsUsed[] = new boolean[originalSpectrum.size()]; double threshold=100/originalSpectrum.size(); if(searchSpectrum.size()>originalSpectrum.size()) threshold=100/searchSpectrum.size(); for (int i = 0; i < searchSpectrum.size(); i++) { int nearestSignal = -1; double difference = Double.MAX_VALUE; for (int m = 0; m < originalSpectrum.size(); m++) { if (java.lang.Math.abs(((CMLPeak)originalSpectrum.get(m)).getXValue() - ((CMLPeak)searchSpectrum.get(i)).getXValue()) < threshold && java.lang.Math.abs(((CMLPeak)originalSpectrum.get(m)).getXValue() - ((CMLPeak)searchSpectrum.get(i)).getXValue()) < difference && signalsUsed[m] == false) { difference = java.lang.Math.abs(((CMLPeak)originalSpectrum.get(m)).getXValue() - ((CMLPeak)searchSpectrum.get(i)).getXValue()); nearestSignal = m; } } if(nearestSignal>-1){ signalsUsed[nearestSignal] = true; peakList.add(searchSpectrum.get(i)); peakList.add(originalSpectrum.get(nearestSignal)); } } return (peakList); } public void update(final ArrayList<CMLSpectrum> spectra, final double minx, final double maxx) { parent.getDisplay().syncExec(new Runnable(){ public void run() { try{ //look for matching peaks if more than one spectrum List<CMLElement> matches=new ArrayList<CMLElement>(); if(spectra.size()>1) { matches=getMatchingSearchShift(SpectrumUtils.getPeakElements(spectra.get(0)),SpectrumUtils.getPeakElements(spectra.get(1))); for(int i=2;i<spectra.size();i++){ matches=getMatchingSearchShift(matches,SpectrumUtils.getPeakElements(spectra.get(i))); } } cleanComposite(); for(int i=0;i<spectra.size();i++){ Composite peakChartcomposite = new Composite(parent, SWT.EMBEDDED); GridLayout layout = new GridLayout(); peakChartcomposite.setLayout(layout); GridData layoutData = new GridData(GridData.FILL_BOTH); peakChartcomposite.setLayoutData(layoutData); Frame fileTableFrame = SWT_AWT.new_Frame(peakChartcomposite); fileTableFrame.setLayout(new BorderLayout()); JFreeChart chart = SpectrumChartFactory.createPeakChart(spectra.get(i), matches, SpectrumCompareView.this,minx*.8,maxx*1.2); chart.getXYPlot().getDomainAxis().setUpperBound(maxx*1.2); chart.getXYPlot().getDomainAxis().setLowerBound(minx*.8); charts.add(chart); SpectrumCompareView.this.charts.add(chart); SpokChartPanel chartPanel = new SpokChartPanel(chart, "peak", spectra.get(i),null); fileTableFrame.add(chartPanel, BorderLayout.CENTER); controls.add(peakChartcomposite); } parent.layout(true,true); }catch(Exception ex){ ex.printStackTrace(); } } }); } private void reactOnSelection(ISelection selection) { if (!selection.isEmpty()) { ISpectrumManager spectrumManager = Activator.getDefault() .getJavaSpectrumManager(); if (selection instanceof IStructuredSelection) { Iterator it=((IStructuredSelection)selection).iterator(); ArrayList<CMLSpectrum> al=new ArrayList<CMLSpectrum>(1); double minx=Double.MAX_VALUE; double maxx=Double.MIN_VALUE; while(it.hasNext()){ Object o=it.next(); if (o instanceof IFile) { try { if(SpectrumUtils.isSpectrum( (IFile)o )){ JumboSpectrum js=spectrumManager.loadSpectrum((IFile)o); if (SpectrumUtils.spectrumHasPeaks(js.getJumboObject())) { al.add(js.getJumboObject()); List<CMLElement> peaks = SpectrumUtils.getPeakElements(js.getJumboObject()); Iterator<CMLElement> it2 = peaks.iterator(); double maxy=Double.MIN_VALUE; while (it2.hasNext()) { CMLPeak peak = (CMLPeak) it2.next(); if (peak.getXValue() > maxx) { maxx = peak.getXValue(); } if (peak.getXValue() < minx) { minx = peak.getXValue(); } if(peak.getYValue() > maxy) maxy = peak.getYValue(); } //this is to have same y range and a label to ensure uniform //width of graphics it2 = peaks.iterator(); while (it2.hasNext()) { CMLPeak peak = (CMLPeak) it2.next(); if(Double.isNaN( peak.getYValue() )) peak.setYValue( 100 ); else peak.setYValue( (peak.getYValue()/maxy)*100 ); } if(js.getJumboObject().getPeakListElements().get(0) .getPeakElements().get(0).getXUnits()==null) js.getJumboObject().getPeakListElements().get(0) .getPeakElements().get(0).setXUnits("Unspecified"); if(js.getJumboObject().getPeakListElements().get(0) .getPeakElements().get(0).getYUnits()==null) js.getJumboObject().getPeakListElements().get(0) .getPeakElements().get(0).setYUnits("Unspecified"); } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } this.update(al,minx, maxx); } } } class MyRunnable implements Runnable{ private Composite control; public MyRunnable(Composite control){ this.control=control; } public void run () { control.dispose(); } } }