/* * EuroCarbDB, a framework for carbohydrate bioinformatics * * Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * A copy of this license accompanies this distribution in the file LICENSE.txt. * * This program 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 Lesser General Public License * for more details. * * Last commit: $Rev: 1930 $ by $Author: david@nixbioinf.org $ on $Date:: 2010-07-29 #$ */ /** @author Alessio Ceroni (a.ceroni@imperial.ac.uk) */ package org.eurocarbdb.application.glycoworkbench.plugin; import org.eurocarbdb.application.glycanbuilder.*; import org.eurocarbdb.application.glycoworkbench.*; import java.io.File; import java.awt.*; import java.awt.geom.*; import java.awt.event.*; import java.awt.print.PrinterJob; import java.util.*; import javax.swing.*; import org.jfree.chart.JFreeChart; import org.jfree.chart.ChartPanel; import org.jfree.chart.plot.XYPlot; import org.jfree.data.Range; import org.jfree.data.xy.DefaultXYDataset; import org.jfree.data.xy.XYDataset; import org.jfree.chart.annotations.XYShapeAnnotation; import org.jfree.chart.annotations.XYTextAnnotation; import org.jfree.chart.renderer.xy.StandardXYItemRenderer; public class SpectraPanel extends DocumentPanel<SpectraDocument> implements ActionListener, MouseListener, MouseMotionListener { public interface SelectionChangeListener { public void selectionChanged(SelectionChangeEvent e); } public static class SelectionChangeEvent { private SpectraPanel src; public SelectionChangeEvent(SpectraPanel _src) { src = _src; } public SpectraPanel getSource() { return src; } } // components protected AnnotatedPeakList theSearchResults; protected DefaultXYDataset theDataset; protected DefaultXYDataset theIsotopesDataset; protected XYPlot thePlot; protected JFreeChart theChart; protected ChartPanel theChartPanel; protected JToolBar theToolBar; // data protected int current_ind; protected TreeMap<Double,Double> visibleData; // selection protected Peak current_peak; protected TreeSet<Peak> selected_peaks; // actions protected String shown_mslevel; protected JButton mslevel_button; protected boolean was_moving; protected boolean is_moving; protected Point2D mouse_start_point; protected Rectangle2D zoom_rectangle; protected Cursor hand_cursor; protected GlycanAction ms_action; protected GlycanAction msms_action; protected boolean update_isotope_curves; protected boolean automatic_update_isotope_curves; protected boolean show_all_isotopes; protected JButton isotopes_button; protected JButton ftmode_button; // protected Vector<SelectionChangeListener> listeners; // public SpectraPanel() { super(); } protected void initSingletons() { super.initSingletons(); theSearchResults=null; selected_peaks = new TreeSet<Peak>(); shown_mslevel = "msms"; current_ind = 0; visibleData = new TreeMap<Double,Double>(); update_isotope_curves = false; automatic_update_isotope_curves = true; show_all_isotopes = false; } protected void initComponents() { setLayout(new BorderLayout()); // create chart theDataset = new DefaultXYDataset(); theIsotopesDataset = new DefaultXYDataset(); theChart = org.jfree.chart.ChartFactory.createScatterPlot("Spectrum", "m/z ratio", "Intensity", theDataset, org.jfree.chart.plot.PlotOrientation.VERTICAL, false, false, false); thePlot = (XYPlot)theChart.getPlot(); thePlot.setRenderer(new StandardXYItemRenderer(StandardXYItemRenderer.LINES)); thePlot.setDataset(1, theIsotopesDataset); thePlot.setRenderer(1,new StandardXYItemRenderer(StandardXYItemRenderer.LINES)); theChartPanel = new ChartPanel(theChart); theChartPanel.setDomainZoomable(false); theChartPanel.setRangeZoomable(false); theChartPanel.setPopupMenu(null); //TODO: PAINT-RESTORE add(theChartPanel,BorderLayout.CENTER); // create toolbar theToolBar = createToolBar(); //TODO: PAINT-RESTORE add(theToolBar,BorderLayout.SOUTH); } protected void finalSettings() { // load cursors hand_cursor = FileUtils.createCursor("hand"); // add listeners listeners = new Vector<SelectionChangeListener>(); thePlot.getDomainAxis().addChangeListener(new org.jfree.chart.event.AxisChangeListener() { public void axisChanged(org.jfree.chart.event.AxisChangeEvent event) { updateChart(); } }); theChartPanel.addMouseMotionListener( this ); theChartPanel.addMouseListener( this ); was_moving = false; is_moving = false; mouse_start_point = null; zoom_rectangle = null; super.finalSettings(); } public SpectraDocument getDocumentFromWorkspace(GlycanWorkspace workspace) { return ( workspace!=null ) ?workspace.getSpectra() :null; } public void setDocumentFromWorkspace(GlycanWorkspace workspace) { if( theDocument!=null ) theDocument.removeDocumentChangeListener(this); if( theSearchResults!=null ) theSearchResults.removeDocumentChangeListener(this); theDocument = getDocumentFromWorkspace(workspace); if( theDocument==null ) theDocument = new SpectraDocument(); theSearchResults = (workspace!=null) ?workspace.getSearchResults() : null; theDocument.addDocumentChangeListener(this); if( theSearchResults!=null ) theSearchResults.addDocumentChangeListener(this); current_ind = 0; updateView(); updateActions(); } protected void createActions() { theActionManager.add("mslevel=ms",FileUtils.defaultThemeManager.getImageIcon("msms"),"Change current scan level",-1, "",this); theActionManager.add("mslevel=msms",FileUtils.defaultThemeManager.getImageIcon("ms"),"Change current scan level",-1, "",this); theActionManager.add("updateisotopecurves=true",FileUtils.defaultThemeManager.getImageIcon("isotopesoff"),"Automatic computation of isotopic distributions inactive",-1, "",this); theActionManager.add("updateisotopecurves=false",FileUtils.defaultThemeManager.getImageIcon("isotopeson"),"Automatic computation of isotopic distributions active",-1, "",this); theActionManager.add("showallisotopes=true",FileUtils.defaultThemeManager.getImageIcon("ftmodeoff"),"FTICR mode inactive",-1, "",this); theActionManager.add("showallisotopes=false",FileUtils.defaultThemeManager.getImageIcon("ftmodeon"),"FTICR mode active",-1, "",this); theActionManager.add("close",FileUtils.defaultThemeManager.getImageIcon("close"),"Close structure",KeyEvent.VK_S, "",this); theActionManager.add("previous",FileUtils.defaultThemeManager.getImageIcon("previous"),"Previous structure",KeyEvent.VK_L, "",this); theActionManager.add("next",FileUtils.defaultThemeManager.getImageIcon("next"),"Next structure",KeyEvent.VK_N, "",this); theActionManager.add("edit",FileUtils.defaultThemeManager.getImageIcon("edit"),"Edit scan data",-1, "",this); theActionManager.add("new",FileUtils.defaultThemeManager.getImageIcon("new"),"Clear",KeyEvent.VK_N, "",this); theActionManager.add("openspectra",FileUtils.defaultThemeManager.getImageIcon("openspectra"),"Open Spectra",KeyEvent.VK_O, "",this); theActionManager.add("print",FileUtils.defaultThemeManager.getImageIcon("print"),"Print...",KeyEvent.VK_P, "",this); theActionManager.add("addpeaks",FileUtils.defaultThemeManager.getImageIcon("addpeaks"),"Add selected peaks to list",-1, "",this); theActionManager.add("annotatepeaks",FileUtils.defaultThemeManager.getImageIcon("annotatepeaks"),"Find possible annotations for selected peaks",-1, "",this); theActionManager.add("baselinecorrection",FileUtils.defaultThemeManager.getImageIcon("baseline"),"Baseline correction of current spectrum", -1, "", this); theActionManager.add("noisefilter",FileUtils.defaultThemeManager.getImageIcon("noisefilter"),"Filter noise in current spectrum", -1, "", this); theActionManager.add("centroid",FileUtils.defaultThemeManager.getImageIcon("centroid"),"Compute peak centroids",-1, "",this); theActionManager.add("arrow",FileUtils.defaultThemeManager.getImageIcon("arrow"),"Activate zoom",-1, "",this); theActionManager.add("hand",FileUtils.defaultThemeManager.getImageIcon("hand"),"Activate moving",-1, "",this); theActionManager.add("zoomnone",FileUtils.defaultThemeManager.getImageIcon("zoomnone"),"Reset zoom",-1, "",this); theActionManager.add("zoomin",FileUtils.defaultThemeManager.getImageIcon("zoomin"),"Zoom in",-1, "",this); theActionManager.add("zoomout",FileUtils.defaultThemeManager.getImageIcon("zoomout"),"Zoom out",-1, "",this); } protected void updatePeakActions() { if( ms_action==null && theApplication.getPluginManager().getMsPeakActions().size()>0 ) ms_action = theApplication.getPluginManager().getMsPeakActions().iterator().next(); if( msms_action==null && theApplication.getPluginManager().getMsMsPeakActions().size()>0 ) msms_action = theApplication.getPluginManager().getMsMsPeakActions().iterator().next(); } protected void updateActions() { theActionManager.get("close").setEnabled(theDocument.getNoScans()!=0); theActionManager.get("previous").setEnabled(current_ind>0); theActionManager.get("next").setEnabled(current_ind<(theDocument.getNoScans()-1)); theActionManager.get("arrow").setEnabled(is_moving); theActionManager.get("hand").setEnabled(!is_moving); theActionManager.get("edit").setEnabled(theDocument.getNoScans()>0); theActionManager.get("zoomnone").setEnabled(theDocument.getNoScans()>0); theActionManager.get("zoomin").setEnabled(theDocument.getNoScans()>0); theActionManager.get("zoomout").setEnabled(theDocument.getNoScans()>0); theActionManager.get("addpeaks").setEnabled(selected_peaks.size()>0); theActionManager.get("annotatepeaks").setEnabled(selected_peaks.size()>0); theActionManager.get("baselinecorrection").setEnabled(theDocument.getNoScans()!=0); theActionManager.get("noisefilter").setEnabled(theDocument.getNoScans()!=0); theActionManager.get("centroid").setEnabled(theDocument.getNoScans()!=0); updateMsLevel(); } protected void updateData() { } private JToolBar createToolBar() { JToolBar toolbar = new JToolBar(); toolbar.setFloatable(false); toolbar.add(theActionManager.get("previous")); toolbar.add(theActionManager.get("close")); toolbar.add(theActionManager.get("next")); toolbar.addSeparator(); toolbar.add(theActionManager.get("new")); toolbar.add(theActionManager.get("openspectra")); toolbar.add(theActionManager.get("edit")); toolbar.addSeparator(); toolbar.add(theActionManager.get("print")); toolbar.addSeparator(); toolbar.add(theActionManager.get("arrow")); toolbar.add(theActionManager.get("hand")); toolbar.addSeparator(); toolbar.add(theActionManager.get("zoomnone")); toolbar.add(theActionManager.get("zoomin")); toolbar.add(theActionManager.get("zoomout")); toolbar.addSeparator(); toolbar.add(mslevel_button = new JButton(theActionManager.get("mslevel=msms")) ); mslevel_button.setText(null); toolbar.add(theActionManager.get("addpeaks")); toolbar.add(theActionManager.get("annotatepeaks")); toolbar.addSeparator(); toolbar.add(theActionManager.get("noisefilter")); toolbar.add(theActionManager.get("baselinecorrection")); toolbar.add(theActionManager.get("centroid")); toolbar.add(isotopes_button = new JButton(theActionManager.get("updateisotopecurves=false")) ); isotopes_button.setText(null); toolbar.add(ftmode_button = new JButton(theActionManager.get("showallisotopes=true")) ); ftmode_button.setText(null); return toolbar; } private JPopupMenu createPopupMenu(boolean over_peak) { JPopupMenu menu = new JPopupMenu(); if( over_peak ) { updatePeakActions(); menu.add(theActionManager.get("addpeaks")); ButtonGroup group = new ButtonGroup(); if( shown_mslevel.equals("ms") ) { for( GlycanAction a: theApplication.getPluginManager().getMsPeakActions() ) { JRadioButtonMenuItem last = new JRadioButtonMenuItem(new GlycanAction(a,"annotatepeaks",-1,"",this)); menu.add(last); last.setSelected(a == ms_action); group.add(last); } } else { for( GlycanAction a: theApplication.getPluginManager().getMsMsPeakActions() ) { JRadioButtonMenuItem last = new JRadioButtonMenuItem(new GlycanAction(a,"annotatepeaks",-1,"",this)); menu.add(last); last.setSelected(a == msms_action); group.add(last); } } menu.addSeparator(); } menu.add(theActionManager.get("zoomnone")); menu.add(theActionManager.get("zoomin")); menu.add(theActionManager.get("zoomout")); return menu; } //----------- // Visualization public double screenToDataX(double length) { Rectangle2D data_area = theChartPanel.getScreenDataArea(); double mz_unit = thePlot.getDomainAxis().lengthToJava2D(1.,data_area,thePlot.getDomainAxisEdge()); return length/mz_unit; } public double screenToDataY(double length) { Rectangle2D data_area = theChartPanel.getScreenDataArea(); double int_unit = thePlot.getRangeAxis().lengthToJava2D(1.,data_area,thePlot.getRangeAxisEdge()); return length/int_unit; } public Point2D screenToDataCoords(Point2D p) { Rectangle2D data_area = theChartPanel.getScreenDataArea(); double x = thePlot.getDomainAxis().java2DToValue(p.getX(),data_area,thePlot.getDomainAxisEdge()); double y = thePlot.getRangeAxis().java2DToValue(p.getY(),data_area,thePlot.getRangeAxisEdge()); return new Point2D.Double(x,y); } public double screenToDataCoordX(double x) { Rectangle2D data_area = theChartPanel.getScreenDataArea(); return thePlot.getDomainAxis().java2DToValue(x,data_area,thePlot.getDomainAxisEdge()); } public double screenToDataCoordY(double y) { Rectangle2D data_area = theChartPanel.getScreenDataArea(); return thePlot.getRangeAxis().java2DToValue(y,data_area,thePlot.getRangeAxisEdge()); } public void updateMZAxis() { if( theDocument.getNoScans()>0 ) thePlot.getDomainAxis().setRange(theDocument.getPeakDataAt(current_ind).getMZRange()); else thePlot.getDomainAxis().setRange(new Range(0.,1.)); } public void updateIntensityAxis() { double max_int = 0.; for( int d=0; d<thePlot.getDatasetCount(); d++ ) { XYDataset dataset = thePlot.getDataset(d); for( int s=0; s<dataset.getSeriesCount(); s++ ) for( int i=0; i<dataset.getItemCount(s); i++ ) max_int = Math.max(max_int,dataset.getYValue(s,i)); } if( max_int==0. ) { // no data return; } Range new_int_range = new Range(0.,max_int); // make space for annotations Rectangle2D data_area = theChartPanel.getScreenDataArea(); if( data_area.getHeight()>0 ) new_int_range = Range.expand(new_int_range,0.,12. / data_area.getHeight()); thePlot.getRangeAxis().setRange(new_int_range); } public void updateChart() { // auto zoom if( theDocument.getNoScans()>0 ) { Range mz_range = thePlot.getDomainAxis().getRange(); // update data double mz_toll = screenToDataX(1.); double[][] data = theDocument.getPeakDataAt(current_ind).getData(mz_range,mz_toll); // update visible data and compute intensity range visibleData.clear(); double min_int = (data[0].length>0) ?data[1][0] :0.; double max_int = (data[0].length>0) ?data[1][0] :0.; for( int i=0; i<data[0].length; i++ ) { min_int = Math.min(min_int,data[1][i]); max_int = Math.max(max_int,data[1][i]); visibleData.put(data[0][i],data[1][i]); } //Range new_int_range = new Range(min_int,max_int); Range new_int_range = new Range(0.,max_int); // make space for annotations Rectangle2D data_area = theChartPanel.getScreenDataArea(); if( data_area.getHeight()>0 ) new_int_range = Range.expand(new_int_range,0.,12. / data_area.getHeight()); // resize y axis thePlot.getRangeAxis().setRange(new_int_range); // reload dataset //theDataset.removeSeries("intensities"); theDataset.addSeries("intensities",data); /* for( int i=0; i<theDataset.getSeriesCount(); i++ ) { if( theDataset.getSeriesKey(i).equals("intensities") ) thePlot.getRenderer().setSeriesPaint(i,Color.red); else thePlot.getRenderer().setSeriesPaint(i,Color.blue); } */ } else { thePlot.getRangeAxis().setRange(new Range(0.,1.)); for( int i=0; i<theDataset.getSeriesCount(); i++ ) theDataset.removeSeries(theDataset.getSeriesKey(i)); } // restore annotation shapes showSelection(); } public void updateTitle() { if( theDocument.getNoScans()>0 ) { String title = "Spectrum " + theDocument.getScanNum(current_ind) + "/" + theDocument.getNoScans(); int ms_level; if( shown_mslevel.equals("ms") ) ms_level = 1; else { ms_level = theDocument.getScanDataAt(current_ind).getMSLevel(); if( ms_level==1 ) ms_level = 2; } if( ms_level==1 ) title += ", MS"; else if( ms_level==2 ) title += ", MS/MS"; else if( ms_level>2 ) title += ", MS" + ms_level; if( ms_level>1 ) title += ", precursor= " + new java.text.DecimalFormat("0.0000").format(theDocument.getScanDataAt(current_ind).getPrecursorMZ()) + " Da"; theChart.setTitle(title); } else { theChart.setTitle("Spectrum"); } } public void updateMsLevel() { if( theWorkspace.getCurrentScan()!=null ) onSetMsLevel(theWorkspace.getCurrentScan().isMsMs()?"msms" :"ms",false); else onSetMsLevel("msms",false); } public void updateView() { current_ind = Math.max(0,Math.min(current_ind,theDocument.getNoScans()-1)); // clear selection resetSelection(); // update title updateMZAxis(); updateChart(); updateTitle(); } //-------------- // manage selection private Peak findNearestPeak(double mz, double intensity, double mz_toll, double int_toll) { java.util.SortedMap<Double,Double> submap = visibleData.subMap(mz-mz_toll,mz+mz_toll); Peak found = null; double min_diff = 0.; for( Map.Entry<Double,Double> e : submap.entrySet() ) { double diff = Math.abs(e.getValue()-intensity); if( diff<=int_toll ) { if( found==null || diff<min_diff ) found = new Peak(e.getKey(),e.getValue()); } } return found; } public Peak findPeakAt(Point2D p) { if( theDocument.getNoScans()>0 ) { Point2D dp = screenToDataCoords(p); double mz_toll = screenToDataX(3.); double int_toll = screenToDataY(3.); return findNearestPeak(dp.getX(),dp.getY(),mz_toll,int_toll); } return null; } public boolean hasSelection() { return (selected_peaks.size()>0); } public boolean isSelected(Peak peak) { return (peak==null) ?false :selected_peaks.contains(peak); } public void resetSelection() { current_peak = null; selected_peaks.clear(); fireUpdatedSelection(); } public void setSelection(Peak peak) { if( peak!=null ) { selected_peaks.clear(); selected_peaks.add(peak); current_peak = peak; fireUpdatedSelection(); } else resetSelection(); } public void addSelection(Peak peak) { if( peak!=null ) { if( !isSelected(peak) ) selected_peaks.add(peak); else current_peak = peak; fireUpdatedSelection(); } } public void enforceSelection(Peak peak) { if( peak!=null ) { if( !isSelected(peak) ) setSelection(peak); else { current_peak = peak; fireUpdatedSelection(); } } else resetSelection(); } private void showSelection() { thePlot.clearAnnotations(); if( selected_peaks.size()>0 ) { double width = screenToDataX(6.); double height = screenToDataY(6.); double margin = screenToDataY(8.); for( Peak p : selected_peaks ) { // add annotation Shape shape = new Rectangle2D.Double(p.getMZ()-width/2.,p.getIntensity()-height/2.,width,height); if( p.equals(current_peak) ) { thePlot.addAnnotation( new XYShapeAnnotation(shape,new BasicStroke(2.f),Color.blue) ); thePlot.addAnnotation( new XYTextAnnotation(new java.text.DecimalFormat("0.0000").format(p.getMZ()), p.getMZ(), p.getIntensity() + margin ) ); } else thePlot.addAnnotation( new XYShapeAnnotation(shape,new BasicStroke(1.f),Color.black) ); } } } //----------------- // actions public int getCurrentInd() { return current_ind; } public void closeCurrent() { if( theDocument.getNoScans()>0 ) { int old_ind = current_ind; current_ind = Math.min(current_ind,theDocument.getNoScans()-2); current_ind = Math.max(current_ind,0); theDocument.removeScan(old_ind); updateActions(); updateView(); } } public void showPrevious() { if( theDocument.getNoScans()>0 && current_ind>0 ) { current_ind--; updateView(); } } public void showNext() { if( theDocument.getNoScans()>0 && current_ind<(theDocument.getNoScans()-1) ) { current_ind++; updateView(); } } public void showScan(int s_ind) { if( s_ind>=0 && s_ind<theDocument.getNoScans() ) { current_ind = s_ind; updateView(); } } public void onEditScanData() { if( theDocument.getNoScans()>0 ) new ScanDataPropertiesDialog(theApplication,theDocument.getScanDataAt(current_ind), theWorkspace).setVisible(true); } public void onPrint() { PrinterJob pj = theWorkspace.getPrinterJob(); if( pj==null ) return; try { pj.setPrintable(theChartPanel); if( pj.printDialog() ) pj.print(); } catch(Exception e) { LogUtils.report(e); } } public void onActivateZooming() { is_moving = false; theChartPanel.setCursor(Cursor.getDefaultCursor()); } public void onActivateMoving() { is_moving = true; //theChartPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); theChartPanel.setCursor(hand_cursor); } public void onZoomNone() { if( theDocument.getNoScans()>0 ) thePlot.getDomainAxis().setRange(theDocument.getPeakDataAt(current_ind).getMZRange()); } public void onZoomIn() { if( theDocument.getNoScans()>0 ) thePlot.getDomainAxis().resizeRange(0.5); } public void onZoomOut() { if( theDocument.getNoScans()>0 ) { thePlot.getDomainAxis().resizeRange(2.0); if( thePlot.getDomainAxis().getRange().contains(theDocument.getPeakDataAt(current_ind).getMinMZ()) || thePlot.getDomainAxis().getRange().contains(theDocument.getPeakDataAt(current_ind).getMaxMZ()) ) thePlot.getDomainAxis().setRange(theDocument.getPeakDataAt(current_ind).getMZRange()); } } public void onSetMsLevel(String mslevel, boolean changedoc) { shown_mslevel = mslevel; if( mslevel.equals("ms") ) { mslevel_button.setAction(theActionManager.get("mslevel=msms")); mslevel_button.setText(null); if( changedoc ) theWorkspace.setMsMs(theWorkspace.getCurrentScan(),false); } else { mslevel_button.setAction(theActionManager.get("mslevel=ms")); mslevel_button.setText(null); if( changedoc ) theWorkspace.setMsMs(theWorkspace.getCurrentScan(),true); } updateTitle(); } public void onSetUpdateIsotopeCurves(Boolean f) { automatic_update_isotope_curves = f; if( automatic_update_isotope_curves ) isotopes_button.setAction(theActionManager.get("updateisotopecurves=false")); else isotopes_button.setAction(theActionManager.get("updateisotopecurves=true")); isotopes_button.setText(null); } public void onSetShowAllIsotopes(Boolean f) { show_all_isotopes = f; if( show_all_isotopes ) ftmode_button.setAction(theActionManager.get("showallisotopes=false")); else ftmode_button.setAction(theActionManager.get("showallisotopes=true")); ftmode_button.setText(null); } public boolean onAddPeaks() { try { if( selected_peaks.size()>0 ) { // add selected peaks to list theApplication.getWorkspace().getPeakList().mergeData(selected_peaks); theApplication.getPluginManager().show("PeakList","PeakList"); return true; } return false; } catch(Exception e) { LogUtils.report(e); return false; } } public boolean onAnnotatePeaks(String parent_action) { try { if( selected_peaks.size()>0 ) { updatePeakActions(); if( shown_mslevel.equals("ms") ) { if( parent_action!=null ) ms_action = theApplication.getPluginManager().getMsPeakAction(parent_action); if( theApplication.getPluginManager().runAction(ms_action,new PeakList(selected_peaks)) ) { update_isotope_curves = automatic_update_isotope_curves; return true; } return false; } if( parent_action!=null ) msms_action = theApplication.getPluginManager().getMsMsPeakAction(parent_action); if( theApplication.getPluginManager().runAction(msms_action,new PeakList(selected_peaks)) ) { update_isotope_curves = automatic_update_isotope_curves; return true; } return false; } return false; } catch(Exception e) { LogUtils.report(e); return false; } } private void removeIsotopeCurves() { while( theIsotopesDataset.getSeriesCount()>0 ) theIsotopesDataset.removeSeries(theIsotopesDataset.getSeriesKey(0)); } private void updateIsotopeCurves() { update_isotope_curves = false; TreeMap<Peak,Collection<Annotation>> map = new TreeMap<Peak,Collection<Annotation>>(); for( PeakAnnotationMultiple pam : theSearchResults.getAnnotations() ) { if( map.get(pam.getPeak())==null ) map.put(pam.getPeak(),new Vector<Annotation>()); Collection<Annotation> dest = map.get(pam.getPeak()); for( Vector<Annotation> va : pam.getAnnotations() ) dest.addAll(va); } addIsotopeCurves(map); } public void addIsotopeCurves(TreeMap<Peak,Collection<Annotation>> annotations) { if( theDocument.size()==0 ) return; // remove old curves removeIsotopeCurves(); // add curves if( annotations!=null ) { // set renderer if( show_all_isotopes ) { thePlot.setRenderer(1,new StandardXYItemRenderer(StandardXYItemRenderer.SHAPES)); thePlot.getRenderer(1).setShape(new Ellipse2D.Double(0,0,7,7)); } else thePlot.setRenderer(1,new StandardXYItemRenderer(StandardXYItemRenderer.LINES)); MSUtils.IsotopeList isotope_list = new MSUtils.IsotopeList(show_all_isotopes); for(Map.Entry<Peak,Collection<Annotation>> pa : annotations.entrySet() ) { Peak p = pa.getKey(); double[] best_peak = theDocument.getPeakDataAt(current_ind).findNearestPeak(p.getMZ()); // get compositions HashSet<Molecule> compositions = new HashSet<Molecule>(); for( Annotation a : pa.getValue() ) { try { compositions.add(a.getFragmentEntry().fragment.computeIon()); } catch(Exception e) { e.printStackTrace(); } } // collect curves for this peak HashMap<String,double[][]> all_curves = new HashMap<String,double[][]>(); for( Molecule m : compositions ) { try { double[][] data = MSUtils.getIsotopesCurve(1,m,show_all_isotopes); // overlay the distribution with the existing list of isotopes isotope_list.adjust(data,best_peak[0],best_peak[1]); all_curves.put(m.toString(),data); } catch(Exception e) { LogUtils.report(e); } } // add average curve for this peak if( all_curves.size()>1 ) { double[][] data = MSUtils.average(all_curves.values(),show_all_isotopes); // add the average to the chart String name = "average-"+p.getMZ(); theIsotopesDataset.addSeries(name, data); thePlot.getRenderer(1).setSeriesPaint(theIsotopesDataset.indexOf(name),Color.magenta); thePlot.getRenderer(1).setSeriesStroke(theIsotopesDataset.indexOf(name),new BasicStroke(2)); // add the average to the isotope list isotope_list.add(data,false); } else if( all_curves.size()==1 ) { // add the only curve to the isotope list isotope_list.add(all_curves.values().iterator().next(),false); } // add the other curves for( Map.Entry<String,double[][]> e : all_curves.entrySet() ) { String name = e.getKey() + "-" + p.getMZ(); theIsotopesDataset.addSeries(name, e.getValue()); thePlot.getRenderer(1).setSeriesPaint(theIsotopesDataset.indexOf(name),Color.blue); } } } updateIntensityAxis(); } public void noiseFilter() { theDocument.noiseFilter(current_ind); } public void baselineCorrection() { theDocument.baselineCorrection(current_ind); } public void computeCentroids() { ((SpectraPlugin)theApplication.getPluginManager().get("Spectra")).computeCentroids(current_ind); } //----------- // listeners public void addSelectionChangeListener(SelectionChangeListener l) { if( l!=null ) listeners.add(l); } public void removeSelectionChangeListener(SelectionChangeListener l) { if( l!=null ) listeners.remove(l); } public void fireUpdatedSelection() { for( SelectionChangeListener l : listeners ) l.selectionChanged(new SelectionChangeEvent(this)); removeIsotopeCurves(); updateIntensityAxis(); showSelection(); updateActions(); } public void actionPerformed(ActionEvent e) { String action = GlycanAction.getAction(e); String param = GlycanAction.getParam(e); if( action.equals("previous") ) showPrevious(); else if( action.equals("next") ) showNext(); else if( action.equals("close") ) closeCurrent(); else if( action.equals("new") ) theApplication.onNew(theDocument); else if( action.equals("openspectra") ) theApplication.onOpen(null,theDocument,false); else if( action.equals("edit") ) onEditScanData(); else if( action.equals("print") ) onPrint(); else if( action.equals("arrow") ) onActivateZooming(); else if( action.equals("hand") ) onActivateMoving(); else if( action.equals("zoomnone") ) onZoomNone(); else if( action.equals("zoomin") ) onZoomIn(); else if( action.equals("zoomout") ) onZoomOut(); else if( action.equals("mslevel") ) onSetMsLevel(param,true); else if( action.equals("addpeaks") ) onAddPeaks(); else if( action.equals("annotatepeaks") ) onAnnotatePeaks(param); else if( action.equals("updateisotopecurves") ) onSetUpdateIsotopeCurves(Boolean.valueOf(param)); else if( action.equals("showallisotopes") ) onSetShowAllIsotopes(Boolean.valueOf(param)); else if( action.equals("noisefilter") ) noiseFilter(); else if( action.equals("baselinecorrection") ) baselineCorrection(); else if( action.equals("centroid") ) computeCentroids(); updateActions(); } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { if( MouseUtils.isPopupTrigger(e) ) { // open popup current_peak = findPeakAt(e.getPoint()); enforceSelection(current_peak); createPopupMenu(current_peak!=null).show(theChartPanel, e.getX(), e.getY()); } else { was_moving = is_moving; if( (MouseUtils.isPushTrigger(e) || MouseUtils.isMoveTrigger(e) ) && theChartPanel.getScreenDataArea().contains(e.getPoint()) ) { mouse_start_point = e.getPoint(); if( MouseUtils.isMoveTrigger(e) ) onActivateMoving(); } } } public void mouseMoved(MouseEvent e) { } public void mouseDragged(MouseEvent e) { if( mouse_start_point!=null && theDocument.getNoScans()>0 ) { if( is_moving ) { // moving double mz_delta = screenToDataX(mouse_start_point.getX() - e.getPoint().getX()); if( mz_delta>0. ) { double old_upper_bound = thePlot.getDomainAxis().getUpperBound(); double old_lower_bound = thePlot.getDomainAxis().getLowerBound(); double new_upper_bound = Math.min(old_upper_bound+mz_delta,theDocument.getPeakDataAt(current_ind).getMaxMZ()); double new_lower_bound = old_lower_bound + new_upper_bound - old_upper_bound; thePlot.getDomainAxis().setRange(new Range(new_lower_bound,new_upper_bound)); } else { double old_upper_bound = thePlot.getDomainAxis().getUpperBound(); double old_lower_bound = thePlot.getDomainAxis().getLowerBound(); double new_lower_bound = Math.max(old_lower_bound+mz_delta,theDocument.getPeakDataAt(current_ind).getMinMZ()); double new_upper_bound = old_upper_bound + new_lower_bound - old_lower_bound; thePlot.getDomainAxis().setRange(new Range(new_lower_bound,new_upper_bound)); } mouse_start_point = e.getPoint(); } else { // zooming Graphics2D g2 = (Graphics2D) theChartPanel.getGraphics(); g2.setXORMode(java.awt.Color.gray); // delete old rectangle if( zoom_rectangle!=null) g2.draw(zoom_rectangle); // create new rectangle double start_x = Math.min(e.getX(),mouse_start_point.getX()); double end_x = Math.max(e.getX(),mouse_start_point.getX()); Rectangle2D data_area = theChartPanel.getScreenDataArea((int)start_x,(int)mouse_start_point.getY()); double xmax = Math.min(end_x, data_area.getMaxX()); zoom_rectangle = new Rectangle2D.Double(start_x,data_area.getMinY(),xmax - start_x, data_area.getHeight()); // draw new rectangle g2.draw(zoom_rectangle); g2.dispose(); } } } public void mouseReleased(MouseEvent e) { if( MouseUtils.isPopupTrigger(e) ) { // clear all if( zoom_rectangle!=null ) { Graphics2D g2 = (Graphics2D) getGraphics(); g2.setXORMode(java.awt.Color.gray); g2.draw(zoom_rectangle); g2.dispose(); } mouse_start_point = null; zoom_rectangle = null; // open popup current_peak = findPeakAt(e.getPoint()); enforceSelection(current_peak); createPopupMenu(current_peak!=null).show(theChartPanel, e.getX(), e.getY()); } else { if( zoom_rectangle!=null && mouse_start_point!=null ) { if( Math.abs(e.getX() - mouse_start_point.getX()) > 10 ) { //if( e.getX() < mouse_start_point.getX() ) { // unzoom all // onZoomNone(); //} //else { // zoom area double start_x = Math.min(e.getX(),mouse_start_point.getX()); double end_x = Math.max(e.getX(),mouse_start_point.getX()); Rectangle2D data_area = theChartPanel.getScreenDataArea((int)start_x,(int)mouse_start_point.getY()); double new_lower_bound = screenToDataCoordX(start_x); double new_upper_bound = screenToDataCoordX(Math.min(end_x, data_area.getMaxX())); thePlot.getDomainAxis().setRange(new Range(new_lower_bound,new_upper_bound)); } else { // clear rectangle Graphics2D g2 = (Graphics2D) getGraphics(); g2.setXORMode(java.awt.Color.gray); g2.draw(zoom_rectangle); g2.dispose(); } } // restore zooming if( !was_moving && is_moving ) onActivateZooming(); zoom_rectangle = null; mouse_start_point = null; } } public void mouseClicked(MouseEvent e) { // find peak under mouse current_peak = findPeakAt(e.getPoint()); if( MouseUtils.isSelectTrigger(e) ) setSelection(current_peak); else if( MouseUtils.isAddSelectTrigger(e) ) addSelection(current_peak); else if( MouseUtils.isActionTrigger(e) ) { setSelection(current_peak); onAnnotatePeaks(null); } else if( MouseUtils.isCtrlActionTrigger(e) ) { setSelection(current_peak); onAddPeaks(); } } public void documentChanged(BaseDocument.DocumentChangeEvent e) { if( e.getSource()==theWorkspace.getSearchResults() ) { if( update_isotope_curves ) updateIsotopeCurves(); } else { removeIsotopeCurves(); super.documentChanged(e); } } public void internalDocumentChanged(GlycanWorkspace.Event e) { updateMsLevel(); } public void componentResized(ComponentEvent e) { if( !checkForUpdates() ) updateChart(); } public void componentShown(ComponentEvent e) { if( !checkForUpdates() ) updateChart(); } }