/*
* Copyright (c) 2003-2012 Fred Hutchinson Cancer Research Center
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fhcrc.cpl.viewer.gui;
import org.fhcrc.cpl.toolbox.datastructure.Pair;
import java.util.*;
import java.util.List;
import java.io.*;
import java.awt.event.ActionEvent;
import java.awt.*;
import org.fhcrc.cpl.toolbox.proteomics.feature.Feature;
import org.fhcrc.cpl.toolbox.proteomics.feature.FeatureSet;
import org.fhcrc.cpl.toolbox.proteomics.feature.FeaturePepXmlWriter;
import org.fhcrc.cpl.toolbox.proteomics.feature.matching.FeatureSetMatcher;
import org.fhcrc.cpl.toolbox.proteomics.feature.matching.ClusteringFeatureSetMatcher;
import org.fhcrc.cpl.toolbox.proteomics.feature.extraInfo.MS2ExtraInfoDef;
import org.fhcrc.cpl.toolbox.proteomics.MSRun;
import org.fhcrc.cpl.viewer.Localizer;
import org.fhcrc.cpl.viewer.Application;
import org.fhcrc.cpl.toolbox.proteomics.ProteinUtilities;
import org.fhcrc.cpl.viewer.util.SharedProperties;
import org.fhcrc.cpl.toolbox.proteomics.ProteomicsRegressionUtilities;
import org.fhcrc.cpl.toolbox.gui.chart.ChartDialog;
import org.fhcrc.cpl.toolbox.gui.ListenerHelper;
import org.fhcrc.cpl.viewer.amt.*;
import org.fhcrc.cpl.toolbox.TextProvider;
import org.fhcrc.cpl.toolbox.ApplicationContext;
import org.fhcrc.cpl.toolbox.proteomics.Protein;
import org.apache.log4j.Logger;
import org.jfree.chart.plot.FastScatterPlot;
import org.jfree.chart.axis.NumberAxis;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.ListSelectionEvent;
/**
* The idea is for this class to be as UI-oriented as possible. Any heavy lifting should be
* pushed down into ProteinMatcher or something
*/
public class ProteinMatcherFrame extends JDialog
{
private static Logger _log = Logger.getLogger(ProteinMatcherFrame.class);
public static final float DEFAULT_MIN_PEPTIDE_PROPHET_SCORE = .95f;
//menu action
public static class ProteinMatcherAction extends AbstractAction
{
public void actionPerformed(ActionEvent event)
{
ProteinMatcherFrame dialog = new ProteinMatcherFrame();
dialog.setModal(false);
dialog.setAlwaysOnTop(false);
}
}
FeatureSet _ms1Features = null;
FeatureSet _regressionMS2Features = null;
boolean loadedRegressionMS2Features = false;
FeatureSet _matchingMS2Features = null;
File _matchingMS2FeatureFile = null;
boolean loadedMatchingMS2Features = false;
File _fastaFile = null;
//variables related to hydrophobicity->retention time prediction
Map<String,Double> _regressionLineHydroToTime = null;
Map<String,Double> _regressionLineHydroToScan = null;
Map<String,Double> _regressionLineTimeToHydro = null;
Map<String,Double> _regressionLineScanToHydro = null;
protected int _scanOrTimeMode = ProteomicsRegressionUtilities.REGRESSION_MODE_TIME;
//TODO: actually control this somewhere. For now, always adaptive
protected int _peptideTimeToleranceMode =
PeptideMatcher.PEPTIDE_TIME_TOLERANCE_MODE_FIXED;
protected int _featureDisplayMode = ProteinDisplay.DISPLAY_MATCHED_FEATURES_MODE;
protected ArrayList<Protein> _matchedProteins = null;
protected ArrayList<Protein> _displayedProteins = null;
protected HashMap<Protein, Map<String,Feature>> _proteinMatchedMS1FeatureMap = null;
protected Map<Protein, Double> _proteinPercentCoverageMap = null;
protected HashMap<Protein, ArrayList<Feature>> _proteinSequenceMS2FeatureMap = null;
protected ArrayList<Pair<Feature,Feature>> _ms2ms1MatchedFeaturePairs = null;
protected HashMap<Protein,ArrayList<Feature>> _proteinMatchedMS1MS2FeatureMap = null;
protected AmtDatabase _amtDatabase = null;
protected ArrayList<Feature> _unmatchedMs2Features = null;
protected ArrayList<Feature> _currentProteinMS1AndMS2MatchedFeatures = null;
//initial filter is empty, show all proteins
protected String _proteinFilterString = "";
//menu
public JMenuItem showMS2MatchedProteinsMenuItem;
// public JMenuItem writePepXmlMs1Ms2MatchesMenuItem;
public JMenuItem writePepXmlMs2RegressionMenuItem;
public JMenuItem showPredictedHydroTimePlotMenuItem;
public Action saveFastaAction = new SaveFastaAction();
// public Action writePepXmlMs1Ms2Action = new WritePepXmlMatchedMs1Ms2Action();
public Action writePepXmlMs2RegressionAction = new WritePepXmlMs2RegressionAction();
public Action setParametersAction = new SetParametersAction();
public Action loadMS2RegressionAction = new LoadMS2RegressionAction();
public Action loadOffsetFeatureSetAction = new LoadOffsetFeatureSetAction();
public Action matchProteinsFromFastaAction = new MatchProteinsFromFastaAction();
public Action findProteinsMatchedInMS2Action = new FindProteinsMatchedInMS2Action();
public Action showPredictedHydroTimePlotAction = new ShowPredictedHydroTimePlotAction();
//protein display
public JLabel labelNumProteins;
public JLabel proteinLabel;
public JTable tblProteins;
public JTextField textProteinPrefix;
public JButton buttonFilterProteins;
protected ProteinTableModel _proteinTableModel = null;
protected Protein _selectedProtein = null;
//peptide display
public JComboBox displayMatchedUnmatchedComboBox;
protected ArrayList<Feature> _displayedFeatures = null;
protected ArrayList<Feature> _currentProteinMS2MatchedFeatures = null;
public JTable tblFeatures;
protected FeatureTableModel _featureTableModel = null;
protected ArrayList<Feature> _selectedFeatures = null;
//Transitory UI elements (referenced by CommandFileRunner)
public ParametersDialog mParametersDialog = null;
//matching parameters
float deltaMass = FeatureSetMatcher.DEFAULT_DELTA_MASS_ABSOLUTE;
int deltaMassType = FeatureSetMatcher.DEFAULT_DELTA_MASS_TYPE;
int deltaScan = FeatureSetMatcher.DEFAULT_DELTA_SCAN;
double deltaTime = FeatureSetMatcher.DEFAULT_DELTA_TIME;
double deltaHydrophobicity = FeatureSetMatcher.DEFAULT_DELTA_HYDROPHOBICITY;
float minPeptideProphet = DEFAULT_MIN_PEPTIDE_PROPHET_SCORE;
int minMatchedFeatures = 1;
int minPercentFeatureCoverage=0;
FeatureSetMatcher featureSetMatcher = null;
public ProteinMatcherFrame()
{
super(ApplicationContext.getFrame(), TextProvider.getText("AMT"));
initialize();
}
/**
* initial setup of UI and class variables
*/
public void initialize()
{
_ms1Features = getMS1Features();
if (_ms1Features == null)
{
ApplicationContext.infoMessage(TextProvider.getText(
"AMT_REQUIRES_DISPLAYED_FEATURES"));
this.setVisible(false);
this.dispose();
return;
}
this.setVisible(true);
//graphical stuff
try
{
JMenuBar jmenu = (JMenuBar) Localizer.getSwingEngine(this).render(
"org/fhcrc/cpl/viewer/gui/ProteinMatcherMenu.xml");
for (int i=0 ; i<jmenu.getMenuCount() ; i++)
jmenu.getMenu(i).getPopupMenu().setLightWeightPopupEnabled(false);
this.setJMenuBar(jmenu);
}
catch (Exception x)
{
ApplicationContext.errorMessage(TextProvider.getText("ERROR_LOADING_MENUS"), x);
throw new RuntimeException(x);
}
Container contentPanel;
try
{
contentPanel = Localizer.renderSwixml(
"org/fhcrc/cpl/viewer/gui/ProteinMatcherFrame.xml", this);
setContentPane(contentPanel);
pack();
}
catch (Exception x)
{
ApplicationContext.errorMessage(TextProvider.getText("ERROR_CREATING_DIALOG"), x);
throw new RuntimeException(x);
}
Dimension d = contentPanel.getPreferredSize();
setBounds(600, 100, (int)d.getWidth(), (int)d.getHeight());
ListenerHelper helper = new ListenerHelper(this);
helper.addListener(tblProteins.getSelectionModel(), "tblProteinsModel_valueChanged");
helper.addListener(buttonFilterProteins,"buttonFilterProteins_actionPerformed");
//hitting enter in the text field should act the same as hitting the filter button. Hack, focus, whatever
helper.addListener(textProteinPrefix,"buttonFilterProteins_actionPerformed");
helper.addListener(tblFeatures.getSelectionModel(), "tblFeaturesModel_valueChanged");
_proteinTableModel = new ProteinTableModel();
tblProteins.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
tblProteins.setAutoCreateColumnsFromModel(false);
tblProteins.setModel(_proteinTableModel);
tblProteins.setColumnModel(_proteinTableModel.columnModel);
if (null != displayMatchedUnmatchedComboBox)
{
//TODO: should really use TextProvider here, and use an internal value for determining state
displayMatchedUnmatchedComboBox.addItem("matched");
displayMatchedUnmatchedComboBox.addItem("unmatched peptides");
displayMatchedUnmatchedComboBox.addItem("unmatched ms2");
helper.addListener(displayMatchedUnmatchedComboBox,
"displayMatchedUnmatchedComboBox_actionPerformed");
}
_featureTableModel = new FeatureTableModel();
tblFeatures.setModel(_featureTableModel);
tblFeatures.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
tblFeatures.setAutoCreateColumnsFromModel(false);
ProteinTablePopupMenu proteinPopup = new ProteinTablePopupMenu();
tblProteins.setComponentPopupMenu(proteinPopup);
proteinLabel.setComponentPopupMenu(proteinPopup);
}
/**
* clean up and shut down this window
*/
protected void quit()
{
ApplicationContext.setProperty(SharedProperties.HIGHLIGHT_FEATURES, null);
ApplicationContext.setProperty(SharedProperties.HIGHLIGHT_FEATURES2, null);
ApplicationContext.setProperty(SharedProperties.HIGHLIGHT_FEATURES3, null);
this.setVisible(false);
this.dispose();
}
/**
* handler for the "display matched or unmatched features" combo box
* @param e
*/
public void displayMatchedUnmatchedComboBox_actionPerformed(ActionEvent e)
{
String comboBoxValue = (String) displayMatchedUnmatchedComboBox.getSelectedItem();
//TODO: the actual strings "matched" and "unmatched" should be internal values, not displayed
if ("matched".equals(comboBoxValue) &&
_featureDisplayMode != ProteinDisplay.DISPLAY_MATCHED_FEATURES_MODE)
{
_featureDisplayMode = ProteinDisplay.DISPLAY_MATCHED_FEATURES_MODE;
_displayedFeatures = new ArrayList<Feature>();
_displayedFeatures.addAll(_proteinMatchedMS1FeatureMap.get(_selectedProtein).values());
if (_displayedFeatures == null)
{
_displayedFeatures = new ArrayList<Feature>();
}
_featureTableModel.setDisplayedFeatures(_displayedFeatures);
updateMainWindowHighlight();
}
else if ("unmatched peptides".equals(comboBoxValue) &&
_featureDisplayMode != ProteinDisplay.DISPLAY_UNMATCHED_PROTEIN_PEPTIDES_MODE)
{
//TODO: no longer doing this, should remove
_featureDisplayMode = ProteinDisplay.DISPLAY_UNMATCHED_PROTEIN_PEPTIDES_MODE;
// _displayedFeatures = _unmatchedProteinPeptideMap.get(_selectedProtein);
if (_displayedFeatures == null)
{
_displayedFeatures = new ArrayList<Feature>();
}
_featureTableModel.setDisplayedFeatures(_displayedFeatures);
updateMainWindowHighlight();
}
else if ("unmatched ms2".equals(comboBoxValue) &&
_featureDisplayMode != ProteinDisplay.DISPLAY_UNMATCHED_MS2_FEATURES_MODE)
{
_featureDisplayMode = ProteinDisplay.DISPLAY_UNMATCHED_MS2_FEATURES_MODE;
_displayedFeatures = _unmatchedMs2Features;
_featureTableModel.setDisplayedFeatures(_displayedFeatures);
updateMainWindowHighlight();
}
}
/**
* Handler for protein selection
* @param e
*/
public void tblProteinsModel_valueChanged(ListSelectionEvent e)
{
int selectedRow = tblProteins.getSelectedRow();
if (selectedRow >= 0)
{
_selectedProtein = _proteinTableModel.getSelectedProtein(tblProteins.getSelectedRow());
/*
System.err.println("**Name="+_selectedProtein.getTextCode());
if (_selectedProtein.getAliases() != null)
for (int i=0; i<_selectedProtein.getAliases().length; i++) System.err.println("---alias="+_selectedProtein.getAliases()[i].getDescription());
System.err.println("**Header: "+ _selectedProtein.getHeader());
System.err.println("**OrigHeader: "+ _selectedProtein.getOrigHeader());
ProteinDisplay.openNCBIBrowserWindow(_selectedProtein);
*/
_selectedFeatures = null;
if (_featureDisplayMode == ProteinDisplay.DISPLAY_MATCHED_FEATURES_MODE)
{
_displayedFeatures = new ArrayList<Feature>();
_displayedFeatures.addAll(_proteinMatchedMS1FeatureMap.get(_selectedProtein).values());
if (_displayedFeatures == null)
{
_displayedFeatures = new ArrayList<Feature>();
}
_featureTableModel.setDisplayedFeatures(_displayedFeatures);
}
//TODO: no longer doing this, should remove
else if (_featureDisplayMode == ProteinDisplay.DISPLAY_UNMATCHED_PROTEIN_PEPTIDES_MODE)
{
// _displayedFeatures = _unmatchedProteinPeptideMap.get(_selectedProtein);
if (_displayedFeatures == null)
{
_displayedFeatures = new ArrayList<Feature>();
}
_featureTableModel.setDisplayedFeatures(_displayedFeatures);
}
else if (_featureDisplayMode == ProteinDisplay.DISPLAY_UNMATCHED_MS2_FEATURES_MODE)
{
_displayedFeatures = _unmatchedMs2Features;
}
_currentProteinMS2MatchedFeatures = getMatchedMS2Features(_selectedProtein);
//update protein sequence html
updateProteinSequence();
updateMainWindowHighlight();
}
}
/**
* update the main window feature highlighting
*/
protected void updateMainWindowHighlight()
{
//update highlighted features in main window
Feature[] displayedFeatureArray = null;
if (_displayedFeatures != null)
displayedFeatureArray = _displayedFeatures.toArray(new Feature[0]);
if (_featureDisplayMode == ProteinDisplay.DISPLAY_MATCHED_FEATURES_MODE)
{
Feature[] currentProteinMS2MatchedFeatureArray = null;
if (_currentProteinMS2MatchedFeatures != null)
currentProteinMS2MatchedFeatureArray = _currentProteinMS2MatchedFeatures.toArray(new Feature[0]);
ApplicationContext.setProperty(SharedProperties.HIGHLIGHT_FEATURES, displayedFeatureArray);
ApplicationContext.setProperty(SharedProperties.HIGHLIGHT_FEATURES2, currentProteinMS2MatchedFeatureArray);
ApplicationContext.setProperty(SharedProperties.HIGHLIGHT_FEATURES3, null);
}
else if (_featureDisplayMode == ProteinDisplay.DISPLAY_UNMATCHED_MS2_FEATURES_MODE ||
_featureDisplayMode == ProteinDisplay.DISPLAY_UNMATCHED_PROTEIN_PEPTIDES_MODE)
{
ApplicationContext.setProperty(SharedProperties.HIGHLIGHT_FEATURES,
displayedFeatureArray);
ApplicationContext.setProperty(SharedProperties.HIGHLIGHT_FEATURES2, null);
ApplicationContext.setProperty(SharedProperties.HIGHLIGHT_FEATURES3, null);
}
}
/**
* Update the protein sequence that's displayed in the middle of the window
*/
protected void updateProteinSequence()
{
_currentProteinMS1AndMS2MatchedFeatures =
getMatchedMS1AndMS2Features(_selectedProtein);
//update protein sequence html
proteinLabel.setText(ProteinDisplay.getProteinSequenceHtml(_selectedProtein,_displayedFeatures,
_currentProteinMS2MatchedFeatures,
_currentProteinMS1AndMS2MatchedFeatures,
_selectedFeatures, _featureDisplayMode));
}
/**
* get the matched ms1 features for a given protein. If none, return empty
* arraylist
* @param protein
* @return
*/
protected ArrayList<Feature> getMatchedMS1Features(Protein protein)
{
ArrayList<Feature> result = null;
if (_proteinMatchedMS1FeatureMap != null)
{
result.addAll(_proteinMatchedMS1FeatureMap.get(protein).values());
}
if (result == null)
result = new ArrayList<Feature>();
return result;
}
/**
* get the matched ms2 features for a given protein
* @param protein
* @return
*/
protected ArrayList<Feature> getMatchedMS2Features(Protein protein)
{
ArrayList<Feature> result = null;
if (_proteinSequenceMS2FeatureMap != null)
result = _proteinSequenceMS2FeatureMap.get(protein);
if (result == null)
result = new ArrayList<Feature>();
return result;
}
/**
* get the matched features that match both ms1 and ms2 for a given protein. Features are considered
* identical if they have the same peptide.
* NOTE: The actual Feature itself will be pulled from the MS2 feature list
* @param protein
* @return
*/
protected ArrayList<Feature> getMatchedMS1AndMS2Features(Protein protein)
{
/*
ArrayList<Pair> result = new ArrayList<Pair>();
ArrayList<Feature> ms1Features = getMatchedMS1Features(protein);
if (ms1Features == null || ms1Features.size() == 0)
return result;
ArrayList<Feature> ms2Features = getMatchedMS2Features(protein);
if (ms2Features == null || ms2Features.size() == 0)
return result;
//take no chances. Don't use collection methods to compare features, go right to the peptide
for (int i=0; i<ms1Features.size(); i++)
{
Feature ms1Feature = ms1Features.get(i);
for (int j=0; j<ms2Features.size(); j++)
{
if (ms1Feature.getPeptide() != null &&
ms1Feature.getPeptide().equalsIgnoreCase(ms2Features.get(j).getPeptide()))
{
result.add(ms2Features.get(j));
break;
}
}
}
return result;
*/
if (_proteinMatchedMS1MS2FeatureMap == null)
return new ArrayList<Feature>(0);
return _proteinMatchedMS1MS2FeatureMap.get(protein);
}
/**
* hide the choice of regression mode, time or scan
* @return
*/
protected Map<String,Double> getRegressionLineHydroToScanOrTime()
{
if (_scanOrTimeMode == ProteomicsRegressionUtilities.REGRESSION_MODE_TIME)
return _regressionLineHydroToTime;
else
return _regressionLineHydroToScan;
}
/**
* hide the choice of regression mode, time or scan
* @return
*/
protected Map<String,Double> getRegressionLineScanOrTimeToHydro()
{
if (_scanOrTimeMode == ProteomicsRegressionUtilities.REGRESSION_MODE_TIME)
return _regressionLineTimeToHydro;
else
return _regressionLineScanToHydro;
}
/**
* Query the user for an MS2 feature file to load for regression
*/
public void loadMS2RegressionFeatures()
{
File regressionFeatureFile = WorkbenchFileChooser.chooseExistingFile(
TextProvider.getText("MS2_FILE_FOR_REGRESSION"));
loadMS2RegressionFeatures(regressionFeatureFile);
}
/**
* load a specified MS2 feature file for regression. Calculate the regression line for both scan and time
* Note: any feature offsets found in the feature file will NOT be used in regression line
* calculation, as that line needs to be unmuddled by individual known feature offsets
* @param regressionFeatureFile
*/
public void loadMS2RegressionFeatures(File regressionFeatureFile)
{
if (regressionFeatureFile == null)
return;
try
{
_regressionMS2Features = new FeatureSet(regressionFeatureFile);
//Arrays.sort(_regressionMS2Features.getFeatures(),new Feature.MassAscComparator());
//for (int i=0; i<_regressionMS2Features.getFeatures().length; i++)
// System.err.println(_regressionMS2Features.getFeatures()[i].getMass() + ", " +_regressionMS2Features.getFeatures()[i].getPProphet());
FeatureSet.FeatureSelector peptideProphetFeatureSelector = new FeatureSet.FeatureSelector();
peptideProphetFeatureSelector.setMinPProphet(minPeptideProphet);
MSRun run = (MSRun) ApplicationContext.getProperty(SharedProperties.MS_RUN);
_regressionMS2Features.populateTimesForMS2Features(run);
_regressionMS2Features.filter(peptideProphetFeatureSelector);
_regressionLineHydroToScan = AmtUtilities.calculateHydrophobicityScanOrTimeRelationship(
_regressionMS2Features.getFeatures(), ProteomicsRegressionUtilities.REGRESSION_MODE_SCAN,
false);
_regressionLineHydroToTime = AmtUtilities.calculateHydrophobicityScanOrTimeRelationship(
_regressionMS2Features.getFeatures(), ProteomicsRegressionUtilities.REGRESSION_MODE_TIME,
false);
_regressionLineScanToHydro = AmtUtilities.calculateScanOrTimeHydrophobicityRelationship(
_regressionMS2Features.getFeatures(), ProteomicsRegressionUtilities.REGRESSION_MODE_SCAN,
false);
_regressionLineTimeToHydro = AmtUtilities.calculateScanOrTimeHydrophobicityRelationship(
_regressionMS2Features.getFeatures(), ProteomicsRegressionUtilities.REGRESSION_MODE_TIME,
false);
if (_regressionLineHydroToScan == null ||
_regressionLineHydroToTime == null)
{
ApplicationContext.infoMessage(TextProvider.getText(
"ERROR_LOADING_FEATURE_FILE_FILENAME",
regressionFeatureFile.getAbsolutePath()));
quit();
}
else
{
double[] coeffs = new double[2];
coeffs[1] = AmtUtilities.getSlopeFromRegressionLine(getRegressionLineScanOrTimeToHydro());
coeffs[0] = AmtUtilities.getInterceptFromRegressionLine(getRegressionLineScanOrTimeToHydro());
//build a map of known offsets from the features
AmtDatabaseBuilder.createAmtDatabaseForRun(_regressionMS2Features,
_scanOrTimeMode,
coeffs,
true, null, false
);
loadedRegressionMS2Features = true;
writePepXmlMs2RegressionMenuItem.setEnabled(true);
showPredictedHydroTimePlotMenuItem.setEnabled(true);
}
//System.err.println("***Parameters: " + _ms1Features.getFeatures().length + ", " + _regressionMS2Features.getFeatures().length + ", " + deltaMass + ", " + deltaMassType + ", " + deltaTime + ", " + Window2DFeatureSetMatcher.REGRESSION_MODE_TIME + ", " + minPeptideProphet);
//enable matching menu item, since we now have a basis for prediction
//System.err.println("****placeholder*** Hydro-scan relationship: Slope: " +
// _regressionLineHydroToScan.first + "; Intercept: " + _regressionLineHydroToScan.second +"\n" +
// "\nHydro-time relationship: Slope: " +
// _regressionLineHydroToTime.first + "; Intercept: " + _regressionLineHydroToTime.second +"\n");
}
catch (Exception e)
{
ApplicationContext.errorMessage(TextProvider.getText(
"ERROR_LOADING_FEATURE_FILE_FILENAME",
regressionFeatureFile.getAbsolutePath()), e);
quit();
}
}
public void buttonFilterProteins_actionPerformed(ActionEvent e)
{
_proteinFilterString = textProteinPrefix.getText();
filterDisplayedProteins();
}
/**
* handler for peptide selection
* @param e
*/
public void tblFeaturesModel_valueChanged(ListSelectionEvent e)
{
int selectedRow = tblFeatures.getSelectedRow();
if (selectedRow >= 0)
{
_selectedFeatures = _featureTableModel.getSelectedFeatures(tblFeatures.getSelectedRows());
updateProteinSequence();
ApplicationContext.setProperty(SharedProperties.HIGHLIGHT_FEATURES3, _selectedFeatures.toArray(new Feature[0]));
//select the feature -- scroll to it in the main window, and show its details
if (_selectedFeatures.size() == 1)
((WorkbenchFrame) (Application.getInstance().getFrame())).imageComponent.selectFeature(_selectedFeatures.get(0));
}
}
/**
* Narrow down the displayed proteins, and remove protein and peptide selections
*/
protected void filterDisplayedProteins()
{
if ("".equals(_proteinFilterString))
_displayedProteins = _matchedProteins;
else
{
String regexString = _proteinFilterString.toUpperCase();
//System.err.println("Before: " +regexString);
//wildcards
if (_proteinFilterString.contains("*"))
{
StringBuffer regexBuf = new StringBuffer();
for (int i=0; i<_proteinFilterString.length(); i++)
{
char currentChar = _proteinFilterString.charAt(i);
if (currentChar == '*')
{
regexBuf.append(".*");
}
else
regexBuf.append(Character.toUpperCase(currentChar));
}
regexString = regexBuf.toString();
}
//System.err.println("after: " +regexString);
_displayedProteins = new ArrayList<Protein>();
for (Protein protein : _matchedProteins)
{
String currentHeader = protein.getHeader();
if (currentHeader.toUpperCase().matches(regexString))
{
_displayedProteins.add(protein);
}
}
updateDisplayedProteins();
//clear out dependent fields
proteinLabel.setText("");
_displayedFeatures = new ArrayList<Feature>(0);
_featureTableModel.setDisplayedFeatures(_displayedFeatures);
}
}
/**
* Pick a featureset to represent the ms1 features. By convention this is the most
* recently chosen, visible featureset
* @return
*/
protected FeatureSet getMS1Features()
{
FeatureSet result = null;
//TODO: Does this do what it's supposed to?
List<FeatureSet> featureSets = (List<FeatureSet>) ApplicationContext.getProperty(
SharedProperties.FEATURE_SETS);
if (null == featureSets)
return null;
else
{
for (FeatureSet fs : featureSets)
{
if (fs.isDisplayed())
result = fs;
}
}
return result;
}
/**
* For CommandFileRunner
* @param fastaFile
*/
public void findMatchedMS1Proteins(File fastaFile)
{
_fastaFile = fastaFile;
findMatchedMS1Proteins();
}
/**
* Find all proteins in the loaded fasta file that match MS1 features
*/
public void findMatchedMS1Proteins()
{
try
{
ArrayList<Protein> proteinsInFasta = ProteinUtilities.loadProteinsFromFasta(_fastaFile);
//handling for no matches
if (proteinsInFasta.size() == 0)
{
ApplicationContext.infoMessage(TextProvider.getText("NO_PROTEINS_FOUND"));
return;
}
MSRun run = (MSRun)ApplicationContext.getProperty(SharedProperties.MS_RUN);
double deltaScanOrTime = deltaScan;
if (_scanOrTimeMode == ProteomicsRegressionUtilities.REGRESSION_MODE_TIME)
deltaScanOrTime = deltaTime;
Protein[] proteinArray = proteinsInFasta.toArray(new Protein[0]);
//TODO: the last argument in this call indicates that we should be matching peptides not
//TODO: found in the AMT database. this may not be the right thing to do in all cases...
//TODO: might need to provide control over this in the UI
_proteinMatchedMS1FeatureMap =
ProteinMatcher.findMatchesForAllProteins(_ms1Features, proteinArray,
MS2ExtraInfoDef.getFeatureSetModifications(_regressionMS2Features),
_amtDatabase,
minMatchedFeatures);
// _proteinPercentCoverageMap = ProteinMatcher.createProteinPercentCoverageMap(_proteinMatchedMS1FeatureMap);
HashMap<Protein, Map<String,Feature>> filteredProteinMatchedMS1FeatureMap =
new HashMap<Protein, Map<String,Feature>>();
for (Protein currentProtein : _proteinPercentCoverageMap.keySet())
{
if (_proteinPercentCoverageMap.get(currentProtein) >= minPercentFeatureCoverage)
{
filteredProteinMatchedMS1FeatureMap.put(currentProtein,
_proteinMatchedMS1FeatureMap.get(currentProtein));
}
}
_proteinMatchedMS1FeatureMap = filteredProteinMatchedMS1FeatureMap;
//Create a map of features to the number of peptide masses that match them
//TODO: restore this
// createProteinMS1FeatureNumberMassMatchesMap(proteinArray);
//Iterator<ArrayList<Feature>> featureArrayIterator = _proteinMatchedMS1FeatureMap.values().iterator();
//while (featureArrayIterator.hasNext())
//{
//ArrayList<Feature> bunchOFeatures = featureArrayIterator.next();
//for (int i=0; i<bunchOFeatures.size(); i++)
// System.err.println("Peptide: " + bunchOFeatures.get(i).getPeptide() +
// ", offset: " + bunchOFeatures.get(i).getProperty("PREDICTED_TIME_OFFSET"));
//}
//update UI
_displayedFeatures = new ArrayList<Feature>(0);
_featureTableModel.setDisplayedFeatures(_displayedFeatures);
Set<Protein> matchedProteinSet = _proteinMatchedMS1FeatureMap.keySet();
Iterator<Protein> matchedProteinIterator = matchedProteinSet.iterator();
_matchedProteins = new ArrayList<Protein>(matchedProteinSet.size());
while (matchedProteinIterator.hasNext())
_matchedProteins.add(matchedProteinIterator.next());
// Collections.sort(_matchedProteins, new Protein.HeaderComparator());
//sort by MS1 matches
Collections.sort(_matchedProteins, new ProteinMS1PercentCoverageComparator());
_displayedProteins = _matchedProteins;
updateDisplayedProteins();
_proteinTableModel.hideMS2Columns();
tblProteins.getSelectionModel().setSelectionInterval(0, 0);
tblProteinsModel_valueChanged(null);
showMS2MatchedProteinsMenuItem.setEnabled(true);
buttonFilterProteins.setEnabled(true);
}
catch (Exception e)
{
ApplicationContext.errorMessage(TextProvider.getText("ERROR_MATCHING_FEATURES"), e);
}
}
/**
* Write out a pepXml file containing the features in the regression MS2 file.
* Each feature will contain the observed offset from predicted elution time.
* NOTE: if a secondary offset file is loaded explicitly, those offsets will
* also get written out along with the offsets from the regression file
* @param outPepXmlFile
*/
public void writePepXmlMs2RegressionOffsetFile(File outPepXmlFile)
{
if (!loadedRegressionMS2Features)
return;
try
{
FeaturePepXmlWriter pepXmlWriter =
new FeaturePepXmlWriter(_regressionMS2Features.getFeatures(),
MS2ExtraInfoDef.getFeatureSetModifications(_regressionMS2Features));
pepXmlWriter.write(outPepXmlFile);
}
catch (Exception e)
{
e.printStackTrace(System.err);
}
}
/**
* Write out a pepXml file containing only the features that were matched in both MS1
* and MS2. Each feature will contain the observed offset from predicted elution time
* @param outPepXmlFile
*/
/*
public void writePepXmlMs1Ms2Matches(File outPepXmlFile)
{
if (!loadedMatchingMS2Features)
return;
ArrayList<Feature> allMatchedFeatures = new ArrayList<Feature>();
Iterator<Protein> proteinIterator = _proteinMatchedMS1MS2FeatureMap.keySet().iterator();
while (proteinIterator.hasNext())
{
ArrayList<Feature> currentProteinMatchedFeatures = getMatchedMS1AndMS2Features(proteinIterator.next());
allMatchedFeatures.addAll(currentProteinMatchedFeatures);
}
try
{
FeaturePepXmlWriter pepXmlWriter = new FeaturePepXmlWriter(allMatchedFeatures.toArray(new Feature[0]),
_matchingMS2Features.getModifications());
pepXmlWriter.write(outPepXmlFile);
}
catch (Exception e)
{
e.printStackTrace(System.err);
}
}
*/
/**
* Cover method passing in a file
* @param matchingMS2FeatureFile
*/
public void findMatchedMS2Proteins(File matchingMS2FeatureFile)
{
try
{
_matchingMS2Features = new FeatureSet(matchingMS2FeatureFile);
if (_matchingMS2Features.getLoadStatus() != FeatureSet.FEATURESET_LOAD_SUCCESS)
{
ApplicationContext.infoMessage(TextProvider.getText("" +
"ERROR_LOADING_FEATURE_FILE_FILENAME",
matchingMS2FeatureFile.getAbsolutePath()) +
": " + _matchingMS2Features.getLoadStatusMessage());
return;
}
FeatureSet.FeatureSelector peptideProphetFeatureSelector = new FeatureSet.FeatureSelector();
peptideProphetFeatureSelector.setMinPProphet(minPeptideProphet);
_matchingMS2Features.filter(peptideProphetFeatureSelector);
_matchingMS2FeatureFile = matchingMS2FeatureFile;
}
catch (Exception e)
{
ApplicationContext.errorMessage(TextProvider.getText(
"ERROR_LOADING_FEATURE_FILE_FILENAME",
matchingMS2FeatureFile.getAbsolutePath()), e);
}
findMatchedMS2Proteins();
}
/**
* Identify all matchingMS2 features with peptides that occur in the matched proteins.
* Match MS1 features with matchingMS2 Features
*/
public void findMatchedMS2Proteins()
{
MSRun run = (MSRun)ApplicationContext.getProperty(SharedProperties.MS_RUN);
//using the ms2 feature set for _matching_, find the features with peptides that are
//found in each protein. This is used for display of matched peptides.
//Only match if peptideprophet score above supplied cutoff
//TODO: restore this, or something
// _proteinSequenceMS2FeatureMap =
// ProteinMatcher.mapProteinsToFeatures(_matchedProteins,
// _matchingMS2Features.getFeatures(),
// minPeptideProphet);
//this arraylist will hold all the unmatched ms2 features
_unmatchedMs2Features = new ArrayList<Feature>();
ClusteringFeatureSetMatcher featureSetMatcher =
new ClusteringFeatureSetMatcher();
featureSetMatcher.init(deltaMass, deltaMassType,
(float) deltaHydrophobicity);
FeatureSetMatcher.FeatureMatchingResult featureMatchingResult =
featureSetMatcher.matchFeatures(_ms1Features,
_matchingMS2Features);
//associate ms1/ms2 matches with individual proteins based on peptide
//(may be multiply associated)
//TODO: should probably move this into ProteinMatcher for commandline use
_proteinMatchedMS1MS2FeatureMap = new HashMap<Protein,ArrayList<Feature>>();
Iterator<Protein> proteinIterator = _proteinMatchedMS1FeatureMap.keySet().iterator();
while (proteinIterator.hasNext())
{
Protein currentProtein = proteinIterator.next();
String currentProteinSequence = currentProtein.getSequenceAsString();
ArrayList<Feature> currentProteinMS1MS2Matches = new ArrayList<Feature>();
for (int i=0; i<_ms2ms1MatchedFeaturePairs.size(); i++)
{
Pair currentPair = _ms2ms1MatchedFeaturePairs.get(i);
Feature ms2Feature = (Feature) currentPair.first;
//null test shouldn't really be necessary. Paranoia
if (MS2ExtraInfoDef.getFirstPeptide(ms2Feature) != null &&
currentProteinSequence.contains(MS2ExtraInfoDef.getFirstPeptide(ms2Feature)))
{
currentProteinMS1MS2Matches.add(ms2Feature);
}
}
_proteinMatchedMS1MS2FeatureMap.put(currentProtein,currentProteinMS1MS2Matches);
}
//display changes
if (_selectedProtein != null)
_currentProteinMS2MatchedFeatures = getMatchedMS2Features(_selectedProtein);
tblProteinsModel_valueChanged(null);
loadedMatchingMS2Features = true;
_proteinTableModel.showMS2Columns();
_featureTableModel.fireTableDataChanged();
}
protected void updateDisplayedProteins()
{
_proteinTableModel.setDisplayedProteins(_displayedProteins);
labelNumProteins.setText(""+_displayedProteins.size());
}
/**
* Loads a FeatureSet from a file, solely for capturing a mapping between peptides and
* their observed offsets. Throws away the featureset
* @param offsetFeatureFile
*/
public void loadOffsetsFromFeatureFile(File offsetFeatureFile)
{
/*
FeatureSet features = null;
int numPreviousOffsets = _peptideOffsetMap.size();
try
{
features = new FeatureSet(offsetFeatureFile);
if (features.getLoadStatus() != FeatureSet.FEATURESET_LOAD_SUCCESS)
{
ApplicationContext.infoMessage(TextProvider.getText("ERROR_LOADING_FEATURE_FILE_FILENAME", offsetFeatureFile.getAbsolutePath()) +
": " + features.getLoadStatusMessage());
return;
}
}
catch (Exception e)
{
ApplicationContext.errorMessage(TextProvider.getText("ERROR_LOADING_FEATURE_FILE_FILENAME", offsetFeatureFile.getAbsolutePath()), e);
return;
}
//build a map of known offsets from the features
ProteinMatcher.augmentPeptideOffsetMap(_peptideOffsetMap, features.getFeatures());
// _regressionMS2FeaturesPeptideOffsetMap = new HashMap<String,Double>();
ApplicationContext.infoMessage(TextProvider.getText("LOADED_X_OFFSETS_FROM_FILE","" + (_peptideOffsetMap.size() - numPreviousOffsets)));
*/
}
protected void showPredictedHydroTimePlot()
{
//clone because we're sorting
Feature[] regressionMS2FeatureArray = _regressionMS2Features.getFeatures().clone();
Arrays.sort(regressionMS2FeatureArray, new Feature.ScanAscComparator());
int numQualifyingFeatures = 0;
for (int i=0; i<regressionMS2FeatureArray.length; i++)
{
if (MS2ExtraInfoDef.getPeptideProphet(regressionMS2FeatureArray[i]) >=
minPeptideProphet)
numQualifyingFeatures++;
}
float[][] scatterPlotData = new float[2][numQualifyingFeatures];
int[] sortedScanArray = new int[numQualifyingFeatures];
int arrayIndex = 0;
for (int i=0; i< regressionMS2FeatureArray.length; i++)
{
if (MS2ExtraInfoDef.getPeptideProphet(regressionMS2FeatureArray[i]) >=
minPeptideProphet)
{
Feature ms2Feature = regressionMS2FeatureArray[i];
scatterPlotData[0][arrayIndex] = (float)
AmtUtilities.calculateNormalizedHydrophobicity(
MS2ExtraInfoDef.getFirstPeptide(ms2Feature));
// scatterPlotData[1][arrayIndex] = ms2Feature.getScan();
sortedScanArray[arrayIndex] = ms2Feature.getScan();
arrayIndex++;
}
}
MSRun run = (MSRun) ApplicationContext.getProperty(SharedProperties.MS_RUN);
double[] timesArrayTemp = AmtUtilities.getTimesForSortedScanArray(run,
sortedScanArray);
float[] timesArray = new float[timesArrayTemp.length];
for (int i=0; i<timesArrayTemp.length; i++)
timesArray[i] = (float) timesArrayTemp[i];
scatterPlotData[1] = timesArray;
FastScatterPlot scatterPlot = new FastScatterPlot(scatterPlotData,
new NumberAxis(TextProvider.getText("CALCULATED_HYDROPHOBICITY")),
new NumberAxis(TextProvider.getText("TIME")));
scatterPlot.setPaint(Color.BLUE);
scatterPlot.setOutlineStroke(new BasicStroke(10));
ChartDialog chartDialog = new ChartDialog(scatterPlot);
chartDialog.setLocation(getLocation());
chartDialog.setVisible(true);
}
/**
* tablemodel for the protein list table
*/
private class ProteinTableModel extends DefaultTableModel
{
protected final String PROTEIN_COLUMN_NAME="PROTEIN";
protected final String MS2_FEATURES_COLUMN_NAME="MS2_FEATURES";
protected final String MS1_FEATURES_COLUMN_NAME="MS1_FEATURES";
protected final String MS1_MS2_FEATURES_COLUMN_NAME="MS1_AND_MS2";
protected final String MS1_PERCENT_FEATURE_COVERAGE_COLUMN_NAME="PERCENT_COVERAGE";
protected ArrayList<Protein> _displayedProteins = new ArrayList<Protein>();
protected TableColumnModel columnModel = null;
Hashtable<String,TableColumn> columnHash;
Hashtable<TableColumn,String> columnReverseHash;
public ProteinTableModel()
{
columnHash = new Hashtable<String,TableColumn>();
columnReverseHash = new Hashtable<TableColumn,String>();
TableColumn proteinColumn = new TableColumn();
proteinColumn.setHeaderValue(TextProvider.getText(PROTEIN_COLUMN_NAME));
proteinColumn.setModelIndex(0);
columnHash.put(PROTEIN_COLUMN_NAME, proteinColumn);
columnReverseHash.put(proteinColumn,PROTEIN_COLUMN_NAME);
TableColumn ms1Column = new TableColumn();
ms1Column.setHeaderValue(TextProvider.getText(MS1_FEATURES_COLUMN_NAME));
ms1Column.setModelIndex(1);
columnHash.put(MS1_FEATURES_COLUMN_NAME, ms1Column);
columnReverseHash.put(ms1Column,MS1_FEATURES_COLUMN_NAME);
TableColumn ms1FeatureCoverageColumn = new TableColumn();
ms1FeatureCoverageColumn.setHeaderValue(
TextProvider.getText(MS1_PERCENT_FEATURE_COVERAGE_COLUMN_NAME));
ms1FeatureCoverageColumn.setModelIndex(2);
columnHash.put(MS1_PERCENT_FEATURE_COVERAGE_COLUMN_NAME,
ms1FeatureCoverageColumn);
columnReverseHash.put(ms1FeatureCoverageColumn,
MS1_PERCENT_FEATURE_COVERAGE_COLUMN_NAME);
TableColumn ms2Column = new TableColumn();
ms2Column.setHeaderValue(TextProvider.getText(MS2_FEATURES_COLUMN_NAME));
ms2Column.setModelIndex(3);
columnHash.put(MS2_FEATURES_COLUMN_NAME, ms2Column);
columnReverseHash.put(ms2Column,MS2_FEATURES_COLUMN_NAME);
TableColumn ms1ms2Column = new TableColumn();
ms1ms2Column.setHeaderValue(TextProvider.getText(MS1_MS2_FEATURES_COLUMN_NAME));
ms1ms2Column.setModelIndex(4);
columnHash.put(MS1_MS2_FEATURES_COLUMN_NAME, ms1ms2Column);
columnReverseHash.put(ms1ms2Column,MS1_MS2_FEATURES_COLUMN_NAME);
columnModel = new DefaultTableColumnModel();
columnModel.addColumn(proteinColumn);
columnModel.addColumn(ms1Column);
columnModel.addColumn(ms1FeatureCoverageColumn);
}
public void showMS2Columns()
{
//just in case it's already there, don't show two copies
columnModel.removeColumn(columnHash.get(MS2_FEATURES_COLUMN_NAME));
columnModel.removeColumn(columnHash.get(MS1_MS2_FEATURES_COLUMN_NAME));
columnModel.addColumn(columnHash.get(MS2_FEATURES_COLUMN_NAME));
columnModel.addColumn(columnHash.get(MS1_MS2_FEATURES_COLUMN_NAME));
}
public void hideMS2Columns()
{
columnModel.removeColumn(columnHash.get(MS2_FEATURES_COLUMN_NAME));
columnModel.removeColumn(columnHash.get(MS1_MS2_FEATURES_COLUMN_NAME));
}
public void setDisplayedProteins(ArrayList<Protein> displayedProteins)
{
_displayedProteins = displayedProteins;
fireTableDataChanged();
}
public int getRowCount()
{
if (_displayedProteins == null)
return 0;
return _displayedProteins.size();
}
public Class getColumnClass(int c)
{
String columnName = getNameForColumn(c);
if (PROTEIN_COLUMN_NAME.equals(columnName))
return String.class;
else if (MS2_FEATURES_COLUMN_NAME.equals(columnName))
return Integer.class;
else if (MS1_FEATURES_COLUMN_NAME.equals(columnName))
return Integer.class;
else if (MS1_PERCENT_FEATURE_COVERAGE_COLUMN_NAME.equals(columnName))
return String.class;
else if (MS1_MS2_FEATURES_COLUMN_NAME.equals(columnName))
return Integer.class;
else
return Object.class;
}
public boolean isCellEditable(int row, int col)
{
return false;
}
protected String getNameForColumn(int col)
{
return columnReverseHash.get(columnModel.getColumn(col));
}
public Object getValueAt(int row, int col)
{
if (row >= _displayedProteins.size())
return null;
Protein protein = _displayedProteins.get(row);
String columnName = getNameForColumn(col);
if (PROTEIN_COLUMN_NAME.equals(columnName))
return protein.getLookup();
else if (MS2_FEATURES_COLUMN_NAME.equals(columnName))
return getMatchedMS2Features(protein).size();
else if (MS1_FEATURES_COLUMN_NAME.equals(columnName))
return getMatchedMS1Features(protein).size();
else if (MS1_PERCENT_FEATURE_COVERAGE_COLUMN_NAME.equals(columnName))
return round(ProteinDisplay.calculatePercentCovered(
getMatchedMS1Features(protein),
protein.getSequenceAsString()),2) + "%";
else if (MS1_MS2_FEATURES_COLUMN_NAME.equals(columnName))
return getMatchedMS1AndMS2Features(protein).size();
else
return "";
}
public Protein getSelectedProtein(int i)
{
return _displayedProteins.get(i);
}
}
/**
* tablemodel for the peptide display table
*/
private class FeatureTableModel extends AbstractTableModel
{
protected ArrayList<Feature> _displayedFeatures = new ArrayList<Feature>();
protected String[] _displayedFeatureHtmlStrings = null;
public void setDisplayedFeatures(ArrayList<Feature> displayedFeatures)
{
_displayedFeatures = displayedFeatures;
if (_displayedFeatures != null)
{
Collections.sort(_displayedFeatures,new Feature.MassAscComparator());
_displayedFeatureHtmlStrings =
ProteinDisplay.getHtmlForFeatures(_displayedFeatures,
_currentProteinMS1AndMS2MatchedFeatures,
_selectedFeatures, _featureDisplayMode);
}
fireTableDataChanged();
}
public int getRowCount()
{
return _displayedFeatures.size();
}
public int getColumnCount()
{
return columnNames.length;
}
public Class getColumnClass(int c)
{
switch (c)
{
case 0:
return Object.class;
case 1:
return Integer.class;
case 2:
return Float.class;
case 3:
return Float.class;
case 4:
return Integer.class;
default:
return Object.class;
}
}
public boolean isCellEditable(int row, int col)
{
return false;
}
public Object getValueAt(int row, int col)
{
if (row >= _displayedFeatures.size())
return null;
Feature feature = _displayedFeatures.get(row);
switch (col)
{
case 0:
return _displayedFeatureHtmlStrings[row];
// return feature.getPeptide();
case 1:
return feature.getScan();
case 2:
return feature.getMass();
case 3:
return feature.getTotalIntensity();
default:
return "";
}
}
private String[] columnNames = new String[]{
TextProvider.getText("PEPTIDE"),
TextProvider.getText("SCAN"),
TextProvider.getText("MASS"),
TextProvider.getText("TOTAL_INTENSITY"),
TextProvider.getText("MASS_MATCHES")
};
public String getColumnName(int i)
{
return i >= 0 && i < columnNames.length ? columnNames[i] : "";
}
public ArrayList<Feature> getSelectedFeatures(int[] indexes)
{
if (indexes == null || indexes.length == 0)
return null;
ArrayList<Feature> featureList = new ArrayList<Feature>(indexes.length);
for (int i=0; i<indexes.length; i++)
{
featureList.add(_displayedFeatures.get(indexes[i]));
}
return featureList;
}
}
/**
* menu action for saving a fasta file containing the currently displayed proteins
*/
public class SaveFastaAction extends AbstractAction
{
public void actionPerformed(ActionEvent evt)
{
if (_displayedProteins == null)
{
ApplicationContext.infoMessage(TextProvider.getText("NO_PROTEINS_TO_SAVE"));
return;
}
WorkbenchFileChooser chooser = new WorkbenchFileChooser();
int chooserStatus = chooser.showOpenDialog(ApplicationContext.getFrame());
//if user didn't hit OK, ignore
if (chooserStatus != JFileChooser.APPROVE_OPTION)
return;
File outFastaFile = chooser.getSelectedFile();
try
{
Protein.saveProteinArrayToFasta(_displayedProteins.toArray(new Protein[0]),
outFastaFile);
ApplicationContext.infoMessage(TextProvider.getText("SAVED_FASTA_FILE"));
}
catch (Exception e)
{
ApplicationContext.errorMessage(
TextProvider.getText("ERROR_SAVING_FASTA"), e);
}
}
}
/**
* menu action for loading an ms2 feature file for regression
*/
public class SetParametersAction extends AbstractAction
{
public void actionPerformed(ActionEvent evt)
{
mParametersDialog = new ParametersDialog();
mParametersDialog.setVisible(true);
}
}
//for accessing this action through CommandFileRunner
public SetParametersAction getSetParametersAction()
{
return new SetParametersAction();
}
/**
* menu action for loading an ms2 feature file for regression
*/
public class LoadMS2RegressionAction extends AbstractAction
{
public void actionPerformed(ActionEvent evt)
{
loadMS2RegressionFeatures();
}
}
/**
* menu action for loading a fasta file for protein matching
*/
public class MatchProteinsFromFastaAction extends AbstractAction
{
public void actionPerformed(ActionEvent evt)
{
_fastaFile = WorkbenchFileChooser.chooseExistingFile("CHOOSE_FASTA_FILE");
if (_fastaFile == null)
return;
findMatchedMS1Proteins();
}
}
/**
* menu action for loading an ms2 feature file for regression
*/
public class ShowPredictedHydroTimePlotAction extends AbstractAction
{
public void actionPerformed(ActionEvent evt)
{
showPredictedHydroTimePlot();
}
}
/**
* menu action for loading an ms2 feature file for regression
*/
public class FindProteinsMatchedInMS2Action extends AbstractAction
{
public void actionPerformed(ActionEvent evt)
{
File matchingFeatureFile =
WorkbenchFileChooser.chooseExistingFile("MATCHING_MS2_FILE");
if (matchingFeatureFile == null)
return;
findMatchedMS2Proteins(matchingFeatureFile);
}
}
/**
* menu action for
*/
public class LoadOffsetFeatureSetAction extends AbstractAction
{
public void actionPerformed(ActionEvent evt)
{
File offsetFeatureFile =
WorkbenchFileChooser.chooseExistingFile("OFFSET_FEATURE_FILE");
if (offsetFeatureFile == null)
return;
loadOffsetsFromFeatureFile(offsetFeatureFile);
}
}
/**
* menu action for writing out a pepxml file containing all the features matched
* between ms1 and ms2 feature sets
*/
/*
public class WritePepXmlMatchedMs1Ms2Action extends AbstractAction
{
public void actionPerformed(ActionEvent evt)
{
WorkbenchFileChooser chooser = new WorkbenchFileChooser();
chooser.setDialogTitle(TextProvider.getText("OUTPUT_PEPXML_FILE"));
chooser.showOpenDialog(ApplicationContext.getFrame());
File outPepXmlFile = chooser.getSelectedFile();
writePepXmlMs1Ms2Matches(outPepXmlFile);
}
}
*/
public class WritePepXmlMs2RegressionAction extends AbstractAction
{
public void actionPerformed(ActionEvent evt)
{
WorkbenchFileChooser chooser = new WorkbenchFileChooser();
chooser.setDialogTitle(TextProvider.getText("OUTPUT_PEPXML_FILE"));
int chooserStatus = chooser.showOpenDialog(ApplicationContext.getFrame());
//if user didn't hit OK, ignore
if (chooserStatus != JFileChooser.APPROVE_OPTION)
return;
File outPepXmlFile = chooser.getSelectedFile();
writePepXmlMs2RegressionOffsetFile(outPepXmlFile);
}
}
/**
* context menu for pulling up protein information
*/
protected class ProteinTablePopupMenu extends JPopupMenu
{
JMenuItem menuItemNCBI;
public ProteinTablePopupMenu()
{
super();
menuItemNCBI =
new JMenuItem(TextProvider.getText("NCBI_WEB_LOOKUP_SELECTED_PROTEIN"));
ListenerHelper helper = new ListenerHelper(this);
helper.addListener(menuItemNCBI,"menuItemNCBI_actionPerformed");
//layout
add(menuItemNCBI);
}
public void menuItemNCBI_actionPerformed(ActionEvent event)
{
if (_selectedProtein != null)
ProteinDisplay.openNCBIBrowserWindow(_selectedProtein);
}
}
/**
* Compare proteins based on how many MS1 matches they have. The one with fewer
* matches is deemed the greater. This is for display in the protein table
*/
protected class ProteinMS1MatchesComparator implements Comparator
{
public int compare(Object o1, Object o2)
{
int o1Features = getMatchedMS1Features((Protein) o1).size();
int o2Features = getMatchedMS1Features((Protein) o2).size();
return o1Features < o2Features ? 1 : o2Features < o1Features ? -1 : 0;
}
}
/*
* Compare proteins based on percent feature coverage. The one with fewer
* matches is deemed the greater. This is for display in the protein table
*/
protected class ProteinMS1PercentCoverageComparator implements Comparator
{
public int compare(Object o1, Object o2)
{
double o1Percent = _proteinPercentCoverageMap.get(o1);
double o2Percent = _proteinPercentCoverageMap.get(o2);
return o1Percent < o2Percent ? 1 : o2Percent < o1Percent ? -1 : 0;
}
}
/**
* dialog box for specifying parameters. This is also operated by CommandFileRunner
*/
public class ParametersDialog extends JDialog
{
public JTextField textDeltaMass;
public JComboBox comboBoxDaPpm;
public JTextField textDeltaScanTime;
public JComboBox comboBoxScanTime;
public JTextField textMinMatchedFeatures;
public JTextField textMinPercentFeatureCoverage;
public JTextField textMinPeptideProphet;
public JButton buttonCancel;
public JButton buttonOK;
protected ProteinMatcherFrame _proteinMatcherFrame = null;
public ParametersDialog()
{
super(ApplicationContext.getFrame(), TextProvider.getText("SET_PARAMETERS"));
//graphical stuff
Container contentPanel = null;
try
{
contentPanel =
Localizer.renderSwixml("org/fhcrc/cpl/viewer/gui/AMTParametersDialog.xml", this);
setContentPane(contentPanel);
pack();
}
catch (Exception x)
{
ApplicationContext.errorMessage(
TextProvider.getText("ERROR_CREATING_DIALOG"), x);
throw new RuntimeException(x);
}
//TODO: should really use TextProvider here, and use an internal value for determining state
comboBoxDaPpm.addItem("Daltons");
comboBoxDaPpm.addItem("PPM");
comboBoxScanTime.addItem("scans");
comboBoxScanTime.addItem("seconds");
textDeltaMass.setText(Double.toString(round((double)deltaMass,2)));
if (deltaMassType == FeatureSetMatcher.DELTA_MASS_TYPE_PPM)
comboBoxDaPpm.setSelectedItem(comboBoxDaPpm.getItemAt(1));
else
comboBoxDaPpm.setSelectedItem(comboBoxDaPpm.getItemAt(0));
if (_scanOrTimeMode == ProteomicsRegressionUtilities.REGRESSION_MODE_TIME)
{
comboBoxScanTime.setSelectedItem(comboBoxScanTime.getItemAt(1));
textDeltaScanTime.setText(Double.toString(round(deltaTime,2)));
}
else
{
comboBoxScanTime.setSelectedItem(comboBoxScanTime.getItemAt(0));
textDeltaScanTime.setText(Integer.toString(deltaScan));
}
textMinMatchedFeatures.setText(Integer.toString(minMatchedFeatures));
textMinPercentFeatureCoverage.setText(Integer.toString(minPercentFeatureCoverage));
textMinPeptideProphet.setText(Double.toString(round((double) minPeptideProphet,2)));
ListenerHelper helper = new ListenerHelper(this);
helper.addListener(buttonCancel,"buttonCancel_actionPerformed");
helper.addListener(buttonOK,"buttonOK_actionPerformed");
getRootPane().setDefaultButton(buttonOK);
}
public void buttonOK_actionPerformed(ActionEvent event)
{
//one big try block to catch all parsing problems. This could
//be broken up.
//Assign everything to temporary variables. Then, if everything is parsed
//ok, assign all the real variables
try
{
float tempDeltaMass = (float) Double.parseDouble(textDeltaMass.getText());
int tempDeltaMassType = FeatureSetMatcher.DELTA_MASS_TYPE_ABSOLUTE;
if ("PPM".equals(comboBoxDaPpm.getSelectedItem()))
tempDeltaMassType = FeatureSetMatcher.DELTA_MASS_TYPE_PPM;
int tempMinMatchedFeatures =
(int) Double.parseDouble(textMinMatchedFeatures.getText());
int tempMinPercentFeatureCoverage =
(int) Double.parseDouble(textMinPercentFeatureCoverage.getText());
float tempMinPeptideProphet =
(float) Double.parseDouble(textMinPeptideProphet.getText());
String comboBoxValue = (String) comboBoxScanTime.getSelectedItem();
//TODO: the actual strings "elution" and "scan" should be internal values, not displayed
int tempScanOrTimeMode = ProteomicsRegressionUtilities.REGRESSION_MODE_SCAN;
double tempDeltaTime = deltaTime;
int tempDeltaScan = deltaScan;
if ("seconds".equals(comboBoxValue))
{
tempScanOrTimeMode = ProteomicsRegressionUtilities.REGRESSION_MODE_TIME;
tempDeltaTime = (float) Double.parseDouble(textDeltaScanTime.getText());
}
else if ("scans".equals(comboBoxValue))
{
tempScanOrTimeMode = ProteomicsRegressionUtilities.REGRESSION_MODE_SCAN;
tempDeltaScan = (int) Double.parseDouble(textDeltaScanTime.getText());
}
//if we got here, we're ok, assign the real variables
deltaMass = tempDeltaMass;
deltaMassType = tempDeltaMassType;
minMatchedFeatures = tempMinMatchedFeatures;
minPercentFeatureCoverage = tempMinPercentFeatureCoverage;
minPeptideProphet = tempMinPeptideProphet;
_scanOrTimeMode = tempScanOrTimeMode;
if (_scanOrTimeMode == ProteomicsRegressionUtilities.REGRESSION_MODE_TIME)
deltaTime = tempDeltaTime;
else
deltaScan = tempDeltaScan;
if (_fastaFile != null)
findMatchedMS1Proteins();
if (_matchingMS2Features != null)
findMatchedMS2Proteins();
this.setVisible(false);
this.dispose();
}
catch (NumberFormatException e)
{
ApplicationContext.errorMessage(TextProvider.getText("BAD_PARAMETER_ERROR_MESSAGE"), e);
}
}
public void buttonCancel_actionPerformed(ActionEvent e)
{
this.setVisible(false);
this.dispose();
}
}
/** can't find a good way to use this yet
// This comparator is used to sort vectors of data
public static class ColumnSorter implements Comparator {
int colIndex;
boolean ascending;
ColumnSorter(int colIndex, boolean ascending) {
this.colIndex = colIndex;
this.ascending = ascending;
}
public int compare(Object a, Object b) {
Vector v1 = (Vector)a;
Vector v2 = (Vector)b;
Object o1 = v1.get(colIndex);
Object o2 = v2.get(colIndex);
// Treat empty strains like nulls
if (o1 instanceof String && ((String)o1).length() == 0) {
o1 = null;
}
if (o2 instanceof String && ((String)o2).length() == 0) {
o2 = null;
}
// Sort nulls so they appear last, regardless
// of sort order
if (o1 == null && o2 == null) {
return 0;
} else if (o1 == null) {
return 1;
} else if (o2 == null) {
return -1;
} else if (o1 instanceof Comparable) {
if (ascending) {
return ((Comparable)o1).compareTo(o2);
} else {
return ((Comparable)o2).compareTo(o1);
}
} else {
if (ascending) {
return o1.toString().compareTo(o2.toString());
} else {
return o2.toString().compareTo(o1.toString());
}
}
}
}
// Regardless of sort order (ascending or descending), null values always appear last.
// colIndex specifies a column in model.
public static void sortAllRowsBy(DefaultTableModel model, int colIndex, boolean ascending) {
Vector data = model.getDataVector();
Collections.sort(data, new ColumnSorter(colIndex, ascending));
model.fireTableStructureChanged();
}
*/
//TODO: this should really be a public static method in a common class somewhere
protected static final double factors[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
protected static double round(double n, int places)
{
if (places < 0 || places > 8) places = 8;
return Math.round(n * factors[places]) / factors[places];
}
}