/* * 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 org.pushingpixels.flamingo.api.ribbon.JRibbonBand; import org.pushingpixels.flamingo.api.ribbon.RibbonTask; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Vector; import javax.swing.ImageIcon; import javax.swing.JTabbedPane; import javax.swing.JOptionPane; import javax.swing.Timer; import javax.swing.ProgressMonitor; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; public class GAGPlugin implements Plugin, ActionListener { protected GAGDictionary theDictionary = null; protected GAGOptions theOptions = null; protected PluginManager theManager = null; protected GlycoWorkbench theApplication = null; protected GlycanWorkspace theWorkspace = null; protected boolean first_time_run = true; protected boolean annotate = false; protected boolean showTopResults = true; protected AnnotationThread theThread = null; protected ProgressMonitor progressDialog = null; protected Timer activityMonitor = null; public GAGPlugin(GlycoWorkbench bench) { this.theApplication=bench; theDictionary = new GAGDictionary("/conf/gag_backbones"); theOptions = new GAGOptions(); } public void init() { if( theWorkspace!=null ) theOptions.retrieve(theWorkspace.getConfiguration()); } public void exit() { if( theWorkspace!=null ) theOptions.store(theWorkspace.getConfiguration()); } public String getName() { return "GAGs"; } public int getMnemonic() { return KeyEvent.VK_G; } public ImageIcon getIcon() { return ThemeManager.getEmptyIcon(ICON_SIZE.TINY); } public int getViewPosition(String view) { return PluginManager.VIEW_NONE; } public java.awt.Component getLeftComponent() { return null; } public java.awt.Component getRightComponent() { return null; } public java.awt.Component getBottomComponent() { return null; } public Collection<String> getViews() { Vector<String> views = new Vector<String>(); return views; } public Collection<GlycanAction> getActions() { Vector<GlycanAction> actions = new Vector<GlycanAction>(); actions.add(new GlycanAction("options",ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),"Set plugin options",KeyEvent.VK_O,"",this)); actions.add(null); actions.add(new GlycanAction("computeStructures",ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),"Compute all the possible structures for a given family",KeyEvent.VK_M,"",this)); actions.add(new GlycanAction("findStructures",ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),"Find all the structures of a given family with a certain m/z value",KeyEvent.VK_F,"",this)); actions.add(new GlycanAction("matchStructures",ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),"Annotate peaks with structures from a given family",KeyEvent.VK_N,"",this)); actions.add(null); actions.add(new GlycanAction("findSulfationsCurrent",ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),"Find the sulfation patterns of the current structures with a given m/z value",KeyEvent.VK_C,"",this)); actions.add(new GlycanAction("findSulfationsSelected",ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),"Find the sulfation patterns of the selected structures with a given m/z value",KeyEvent.VK_S,"",this)); actions.add(new GlycanAction("findSulfationsAll",ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),"Find the sulfation patterns of all structures with a given m/z value",KeyEvent.VK_A,"",this)); actions.add(null); actions.add(new GlycanAction("matchSulfationsCurrent",ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),"Annotate peaks with sulfation patterns of the current structures",KeyEvent.VK_U,"",this)); actions.add(new GlycanAction("matchSulfationsSelected",ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),"Annotate peaks with sulfation patterns of the selected structures",KeyEvent.VK_E,"",this)); actions.add(new GlycanAction("matchSulfationsAll",ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),"Annotate peaks with sulfation patterns of all structures",KeyEvent.VK_L,"",this)); return actions; } public Collection<GlycanAction> getToolbarActions() { Vector<GlycanAction> actions = new Vector<GlycanAction>(); return actions; } public Collection<GlycanAction> getObjectActions(Object prototype, ActionListener al) { Vector<GlycanAction> actions = new Vector<GlycanAction>(); return actions; } public void setManager(PluginManager manager) { theManager = manager; if( theManager!=null ) theManager.addMsPeakAction(new GlycanAction("findStructures",ThemeManager.getResizableEmptyIcon(ICON_SIZE.L3),"Find all GAG structures matching the peaks",KeyEvent.VK_F,"",this)); } public void setApplication(GlycoWorkbench application) { theApplication = application; } public void setWorkspace(GlycanWorkspace workspace) { theWorkspace = workspace; if( theWorkspace!=null ) theOptions.retrieve(theWorkspace.getConfiguration()); } public PluginManager getManager() { return theManager; } public GlycoWorkbench getApplication() { return theApplication; } public GlycanWorkspace getWorkspace() { return theWorkspace; } public void show(String view) throws Exception { throw new Exception("Invalid view: " + view); } public boolean runAction(String action) throws Exception{ if( action.startsWith("find") ) { String m_z = JOptionPane.showInputDialog(theApplication, "Insert m/z value"); if( m_z!=null ) return runAction(true,action,new PeakList(Double.valueOf(m_z))); return false; } return runAction(true,action,theWorkspace.getPeakList()); } public boolean runAction(String action, Object params) throws Exception{ if( !(params instanceof PeakList) ) throw new Exception("Invalid param object: PeakList needed"); if( runAction(first_time_run,action,(PeakList)params) ) { first_time_run = false; return true; } return false; } public boolean runAction(boolean ask, String action, PeakList peaks) throws Exception{ if( action.equals("options") ) return setOptions(); if( action.equals("computeStructures") ) { if( computeAllStructures(ask) ) { theManager.show("Fragments","Details"); return true; } return false; } if( action.equals("findStructures") ) { annotate = false; if( matchStructures(ask,peaks) ) { theManager.show("Search",(theWorkspace.getSearchResults().getNoStructures()>1) ?"Summary" :"Details"); return true; } return false; } if( action.equals("matchStructures") ) { annotate = true; if( matchStructures(ask,peaks) ) { theManager.show("Annotation",(theWorkspace.getAnnotatedPeakList().getNoStructures()>1) ?"Summary" :"Details"); return true; } return false; } if( action.equals("findSulfationsCurrent") ) { annotate = false; theApplication.getCanvas().enforceSelection(); if( matchAllSulfations(ask,theApplication.getCanvas().getCurrentStructure(),peaks) ) { theManager.show("Search",(theWorkspace.getSearchResults().getNoStructures()>1) ?"Summary" :"Details"); return true; } return false; } if( action.equals("findSulfationsSelected") ) { annotate = false; theApplication.getCanvas().enforceSelection(); if( matchAllSulfations(ask,theApplication.getCanvas().getSelectedStructures(),peaks) ) { theManager.show("Search",(theWorkspace.getSearchResults().getNoStructures()>1) ?"Summary" :"Details"); return true; } return false; } if( action.equals("findSulfationsAll") ) { annotate = false; if( matchAllSulfations(ask,theWorkspace.getStructures().getStructures(),peaks) ) { theManager.show("Search",(theWorkspace.getSearchResults().getNoStructures()>1) ?"Summary" :"Details"); return true; } return false; } if( action.equals("matchSulfationsCurrent") ) { annotate = true; theApplication.getCanvas().enforceSelection(); if( matchAllSulfations(ask,theApplication.getCanvas().getCurrentStructure(),peaks) ) { theManager.show("Annotation","Stats"); return true; } return false; } if( action.equals("matchSulfationsSelected") ) { annotate = true; theApplication.getCanvas().enforceSelection(); if( matchAllSulfations(ask,theApplication.getCanvas().getSelectedStructures(),peaks) ) { theManager.show("Annotation","Stats"); return true; } return false; } if( action.equals("matchSulfationsAll") ) { annotate = true; if( matchAllSulfations(ask,theWorkspace.getStructures().getStructures(),peaks) ) { theManager.show("Annotation","Stats"); return true; } return false; } throw new Exception("Invalid action: " + action); } public void actionPerformed(ActionEvent e) { try { runAction(GlycanAction.getAction(e)); } catch(Exception ex) { LogUtils.report(ex); } } public void updateViews() { } public void updateMasses() { } //------------ // ACTIONS public boolean setOptions() { GAGOptionsDialog dlg = new GAGOptionsDialog(theApplication,theDictionary,theOptions); dlg.setVisible(true); if( !dlg.getReturnStatus().equals("OK") ) return false; return true; } public boolean computeAllStructures(boolean ask_options) { if( ask_options ) { // show options dialog GAGOptionsDialog dlg = new GAGOptionsDialog(theApplication,theDictionary,theOptions); dlg.setVisible(true); if( !dlg.getReturnStatus().equals("OK") ) return false; } // halt interactions theApplication.haltInteractions(); // compute structures FragmentDocument results = theDictionary.generateStructures(theOptions); theWorkspace.getFragments().copy(results); // restore interactions theApplication.restoreInteractions(); return true; } public boolean matchStructures(boolean ask_options, PeakList peaks) { FragmentOptions frag_opt = theWorkspace.getFragmentOptions(); AnnotationOptions ann_opt = theWorkspace.getAnnotationOptions(); if( ask_options ) { // show gag options dialog GAGOptionsDialog gdlg = new GAGOptionsDialog(theApplication,theDictionary,theOptions); gdlg.setVisible(true); if( !gdlg.getReturnStatus().equals("OK") ) return false; // show annotation options dialog AnnotationOptionsDialog adlg = new AnnotationOptionsDialog(theApplication,frag_opt,ann_opt,false,false); adlg.setVisible(true); if( !adlg.getReturnStatus().equals("OK") ) return false; } // halt interactions theApplication.haltInteractions(); // match structures theDictionary.setOptions(theOptions); theThread = new AnnotationThread(peaks,theDictionary,ann_opt); return runAnnotation(); } public boolean matchAllSulfations(boolean ask_options, Glycan structure, PeakList peaks) { if( structure!=null ) return matchAllSulfations(ask_options,Collections.singleton(structure),peaks); return false; } public boolean matchAllSulfations(boolean ask_options, Collection<Glycan> structures, PeakList peaks) { // show annotation options dialog FragmentOptions frag_opt = theWorkspace.getFragmentOptions(); AnnotationOptions ann_opt = theWorkspace.getAnnotationOptions(); if( ask_options ) { AnnotationOptionsDialog adlg = new AnnotationOptionsDialog(theApplication,frag_opt,ann_opt,false,false); adlg.setVisible(true); if( !adlg.getReturnStatus().equals("OK") ) return false; } // halt interactions theApplication.haltInteractions(); // compute structures FragmentDocument fd = Fragmenter.generateLabilesConfigurations(structures); // match structures theThread = new AnnotationThread(peaks,fd,ann_opt); return runAnnotation(); } private boolean runAnnotation() { theThread.start(); // launch progress dialog progressDialog = new ProgressMonitor(theApplication, "Matching peaks with fragments", null, 0, theThread.getTarget()); // set up the timer action activityMonitor = new Timer(200, new ActionListener() { public void actionPerformed (ActionEvent event) { int progress = theThread.getProgress(); // show progress progressDialog.setProgress(progress); // check if task is completed or canceled if( progress==theThread.getTarget() || theThread.isInterrupted() || progressDialog.isCanceled ()) { activityMonitor.stop(); progressDialog.close(); if( progress!=theThread.getTarget() ) { theThread.interrupt(); onAnnotationAborted(theThread); } else { onAnnotationCompleted(theThread); } } } }); activityMonitor.start(); // return control return true; } public void onAnnotationCompleted(AnnotationThread t) { // show annotations AnnotatedPeakList dest = null; if( annotate ) dest = theWorkspace.getAnnotatedPeakList(); else dest = theWorkspace.getSearchResults(); if( showTopResults ) dest.copy(t.getAnnotatedPeaks().getFirst(20)); else dest.copy(t.getAnnotatedPeaks()); // restore interactions theApplication.restoreInteractions(); // show status if( t.getNonEmptyStructures()>0 ) { if( t.hasFuzzyStructures() ) { if( t.getNonEmptyStructures()==1 ) JOptionPane.showMessageDialog(theApplication, "Cannot compute fragments for structures with uncertain terminals", "Error", JOptionPane.ERROR_MESSAGE); else if( t.hasNonFuzzyStructures() ) JOptionPane.showMessageDialog(theApplication, "Cannot compute fragments for some structures with uncertain terminals", "Error", JOptionPane.ERROR_MESSAGE); else JOptionPane.showMessageDialog(theApplication, "Cannot compute fragments, all structures have uncertain terminals", "Error", JOptionPane.ERROR_MESSAGE); } } } public void onAnnotationAborted(AnnotationThread t) { // restore interactions theApplication.restoreInteractions(); } @Override public void completeSetup() { // TODO Auto-generated method stub } @Override public List<JRibbonBand> getBandsForToolBar() { // TODO Auto-generated method stub return null; } @Override public RibbonTask getRibbonTask() { // TODO Auto-generated method stub return null; } }