/*
* 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.proteomics.feature.AnalyzeICAT;
import org.fhcrc.cpl.toolbox.proteomics.feature.Feature;
import org.fhcrc.cpl.viewer.feature.FeatureExtractor;
import org.fhcrc.cpl.toolbox.proteomics.feature.FeatureSet;
import org.fhcrc.cpl.toolbox.proteomics.MSRun;
import org.fhcrc.cpl.viewer.feature.extraction.FeatureFinder;
import org.fhcrc.cpl.viewer.feature.extraction.PeakCombiner;
import org.fhcrc.cpl.viewer.feature.extraction.FeatureFindingBroker;
import org.fhcrc.cpl.viewer.feature.extraction.PeakExtractor;
import org.fhcrc.cpl.viewer.Localizer;
import org.fhcrc.cpl.viewer.commandline.modules.FindPeptidesCommandLineModule;
import org.fhcrc.cpl.viewer.util.SharedProperties;
import org.fhcrc.cpl.toolbox.ApplicationContext;
import org.fhcrc.cpl.toolbox.datastructure.FloatRange;
import org.fhcrc.cpl.toolbox.TextProvider;
import org.fhcrc.cpl.toolbox.gui.ListenerHelper;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.*;
/**
* User: mbellew
* Date: May 26, 2004
* Time: 2:58:14 PM
*
* dhmay changing 2009/01/02: adding default filtering of minimum 2 peaks and maximum KL 3.0
*
*/
public class ExtractFeatureRangesAction extends AbstractAction implements PropertyChangeListener
{
public ExtractFeatureRangesAction()
{
super(TextProvider.getText("FIND_ALL_FEATURES_DOTDOTDOT"));
ApplicationContext.addPropertyChangeListener(SharedProperties.MS_RUN, this);
}
public void actionPerformed(ActionEvent event)
{
MSRun run;
run = (MSRun)ApplicationContext.getProperty(SharedProperties.MS_RUN);
if (null == run)
return;
FeatureScanner scanner = new FeatureScanner(run, null, true);
ExtractFeatureRangesDialog dialog = new ExtractFeatureRangesDialog(scanner);
dialog.setModal(true);
dialog.setVisible(true);
if (dialog.action == ExtractFeatureRangesDialog.ACTION_CANCEL || null == scanner._file)
return;
File file = scanner._file;
if (dialog.action == ExtractFeatureRangesDialog.ACTION_LOAD)
{
if (file.exists())
{
FeatureSelectionFrame.FeatureSelectionDialog.getInstance().addFeatureSet(file);
FeatureSelectionFrame.FeatureSelectionDialog.getInstance().setVisible(true);
}
else
ApplicationContext.errorMessage(TextProvider.getText("FILE_FILE_DOES_NOT_EXIST","FILEPATH", file.getPath()), null);
}
else
{
//Don't have the information cached in a file, so do this on a background thread..
Thread t = new Thread(scanner);
t.setPriority(Thread.MIN_PRIORITY);
t.start();
}
}
public static File getFeatureRangeFile(MSRun run)
{
File runFile = run.getFile();
return getFeatureRangeFile(runFile);
}
public static File getFeatureRangeFile(File runFile)
{
return new File(runFile.getAbsolutePath() + ".peptideRanges.tsv");
}
public static File getFeatureFile(MSRun run)
{
File featureRangeFile = run.getFile();
String path = featureRangeFile.getAbsolutePath();
if (path.toLowerCase().endsWith(".mzxml"))
path = path.substring(0, path.length() - 6);
String featureRangeFileName = path + ".peptides.tsv";
return new File(featureRangeFileName);
}
public static File getFeatureFile(File runFile)
{
String featureRangeFileName = runFile.getAbsolutePath() + ".peptides.tsv";
return new File(featureRangeFileName);
}
public static Feature[] ExtractScanFeatures(MSRun.MSScan scan, MSRun run)
{
try
{
FloatRange range = FeatureExtractor.getMzExtractionRange(scan);
FeatureSet features = FeatureExtractor.getDefault(run, scan.getNum(), 1, 6, range, 2.0).analyze();
return features.getFeatures();
}
catch (InterruptedException x)
{
return null;
}
}
public void propertyChange(PropertyChangeEvent event)
{
setEnabled(null != ApplicationContext.getProperty(SharedProperties.MS_RUN));
}
public static class FeatureScanner implements Runnable
{
protected MSRun _run;
protected boolean _updateUI = true;
protected File _file = null;
protected int _startScan = 1;
protected int _endScan = -1;
protected boolean _outputZeroCharge = false;
protected boolean _deconvolute = false;
protected boolean _quant = false;
protected float _lightTagWeight = -1.f;
protected float _heavyTagWeight = -1.f;
protected char _labeledResidue = ' ';
protected int _maxLabelCount = AnalyzeICAT.DEFAULT_MAX_LABEL_COUNT;
public FeatureScanner(MSRun run, File file)
{
_run = run;
_file = file;
_endScan = run.getScanCount();
_startScan = 1;
// Default label params for ICAT
_lightTagWeight = AnalyzeICAT.icatLabel.getLight();
_heavyTagWeight = AnalyzeICAT.icatLabel.getHeavy() + _lightTagWeight; // getHeavy() gives delta
_labeledResidue = AnalyzeICAT.icatLabel.getResidue();
_maxLabelCount = AnalyzeICAT.icatLabel.getMaxLabelCount();
}
public FeatureScanner(MSRun run, File file, boolean updateUI)
{
this(run, file);
_updateUI = updateUI;
}
public FeatureScanner(MSRun run, File file, boolean updateUI, int startScanNum, int endScanNum, boolean outputZeroCharge)
{
this(run, file, updateUI);
setStartScan(startScanNum);
setEndScan(endScanNum);
_outputZeroCharge = outputZeroCharge;
}
public void run()
{
PrintWriter pw = null;
FeatureSet fs = null;
try
{
pw = new PrintWriter(new FileOutputStream(_file));
pw.flush(); // test printwriter
FloatRange range = FeatureExtractor.getMzExtractionRange(_run);
int scanCount = _endScan - _startScan + 1;
int maxCharge = PeakCombiner.DEFAULT_MAX_CHARGE;
Class featureStrategyClass = FeatureExtractor.getDefaultClass();
fs = FeatureFindingBroker.findPeptides(_run, _startScan, scanCount,
maxCharge, range, 0,
FeatureFinder.DEFAULT_ACCURATE_MASS_ADJUSTMENT_SCANS,
featureStrategyClass, true,
PeakExtractor.DEFAULT_PEAK_RIDGE_WALK_SMOOTHED, false);
//default filtering. No way to turn this off in the GUI
FeatureSet.FeatureSelector sel = new FeatureSet.FeatureSelector();
sel.setMinPeaks(FindPeptidesCommandLineModule.DEFAULT_MIN_PEAKS);
sel.setMaxKL(FindPeptidesCommandLineModule.DEFAULT_MAX_KL);
fs = fs.filter(sel);
if (!_outputZeroCharge)
{
Feature[] features = fs.getFeatures();
ArrayList collect = new ArrayList(features.length);
for (int i = 0; i < features.length; i++)
{
if (features[i].charge == 0)
continue;
collect.add(features[i]);
}
features = (Feature[])collect.toArray(new Feature[0]);
fs.setFeatures(features);
}
if (_deconvolute)
{
// TODO: add to GUI as parameters
int scanWindow = 6;
double massWindow = .4;
boolean sumIntensities = true;
fs = fs.deconvolute(scanWindow, massWindow, sumIntensities);
}
//dhmay changing
if (_quant)
fs = fs.quant(_lightTagWeight, _heavyTagWeight, _labeledResidue, _maxLabelCount, _run);
fs.save(pw);
pw.close();
pw = null;
}
catch (Exception x1)
{
ApplicationContext.errorMessage(TextProvider.getText("ERROR_WRITING_FEATURE_FILE"), x1);
return;
}
catch (java.lang.OutOfMemoryError ome)
{
ApplicationContext.errorMessage(TextProvider.getText("FEATURE_SCANNER_OME"), ome);
return;
}
finally
{
if (null != pw)
pw.close();
}
if (_updateUI)
{
Arrays.sort(fs.getFeatures(), new Feature.MzScanAscComparator());
fs.setColor(FeatureSelectionFrame.FeatureSelectionDialog.nextColor());
final FeatureSet finalSet = fs;
fs.setSourceFile(_file);
EventQueue.invokeLater(new Runnable()
{
public void run()
{
FeatureSelectionFrame.FeatureSelectionDialog.getInstance().addFeatureSet(finalSet);
}
});
}
ApplicationContext.setMessage(TextProvider.getText("FINDING_FEATURES_COMPLETE_SEE_FILE","FILEPATH",_file.getAbsolutePath()));
}
public int getStartScan()
{
return _startScan;
}
public void setStartScan(int startScanNum)
{
_startScan = _run.getIndexForScanNum(startScanNum);
if (_startScan < 0)
_startScan = -(_startScan + 1);
}
public int getEndScan()
{
return _endScan;
}
public void setEndScan(int endScanNum)
{
_endScan = _run.getIndexForScanNum(endScanNum);
if (_endScan < 0)
_endScan = -(_endScan + 1);
_endScan = Math.min(_run.getScanCount(),_endScan);
}
public void setOutputZeroCharge(boolean outputZeroCharge)
{
this._outputZeroCharge = outputZeroCharge;
}
public void setDeconvolute(boolean deconvolute)
{
this._deconvolute = deconvolute;
}
public void setLightTagWeight(float lightTagWeight)
{
this._lightTagWeight = lightTagWeight;
}
public void setHeavyTagWeight(float heavyTagWeight)
{
this._heavyTagWeight = heavyTagWeight;
}
public void setLabeledResidue(char labeledResidue)
{
this._labeledResidue = labeledResidue;
}
public void setMaxLabelCount(int maxLabelCount)
{
this._maxLabelCount = maxLabelCount;
}
}
public static class ExtractFeatureRangesDialog extends JDialog
{
public static final int ACTION_CANCEL = 0;
public static final int ACTION_LOAD = 1;
public static final int ACTION_FIND = 2;
public int action = ACTION_CANCEL;
/* public String fileName = null;
public int startScan = 1;
public int endScan = 2000;
public boolean outputZeroCharge = false;
public boolean icat = false;
public boolean deconvolute = false; */
FeatureScanner scanner = null;
public JLabel labelAlgorithm;
public JButton buttonCancel;
public JButton buttonLoadFile;
public JButton buttonFindFeatures;
public JButton buttonBrowse;
public JTextField textFileName;
public JTextField textEndScan;
public JTextField textStartScan;
public JCheckBox checkboxZeroCharge;
public JCheckBox checkboxDeconvolute;
public JCheckBox checkboxQuant;
public JComboBox comboboxTagSelect;
public JTextField textLightTagWeight;
public JTextField textHeavyTagWeight;
public JTextField textLabeledResidue;
public JTextField textMaxLabelCount;
public ExtractFeatureRangesDialog(FeatureScanner scanner)
{
super(ApplicationContext.getFrame(), TextProvider.getText("EXTRACT_FEATURES"));
this.scanner = scanner;
try
{
Container content = Localizer.renderSwixml("org/fhcrc/cpl/viewer/gui/ExtractFeatureRanges.xml",this);
setContentPane(content);
pack();
}
catch (Exception x)
{
ApplicationContext.errorMessage(TextProvider.getText("ERROR_CREATING_DIALOG"), x);
throw new RuntimeException(x);
}
final MSRun run = (MSRun)ApplicationContext.getProperty(SharedProperties.MS_RUN);
if (null == run)
throw new IllegalStateException();
String start = "1";
String end = "1";
if (run.getScanCount() > 0)
{
start = String.valueOf(run.getScan(0).getNum());
end = String.valueOf(run.getScan(run.getScanCount() - 1).getNum());
}
Class<?> c = (Class<?>)ApplicationContext.getProperty(FeatureExtractor.DEFAULT_EXTRACTOR_PROPERTYNAME);
String name = c.getName();
name = name.substring(name.lastIndexOf('.')+1);
labelAlgorithm.setText(name);
textStartScan.setText(start);
textEndScan.setText(end);
populateTagSelectComboBox(comboboxTagSelect);
comboboxTagSelect.setEnabled(false);
textLightTagWeight.setText(String.valueOf(scanner._lightTagWeight));
textLightTagWeight.setEnabled(false);
textHeavyTagWeight.setText(String.valueOf(scanner._heavyTagWeight));
textHeavyTagWeight.setEnabled(false);
textLabeledResidue.setText(String.valueOf(scanner._labeledResidue));
textLabeledResidue.setEnabled(false);
textMaxLabelCount.setText(String.valueOf(scanner._maxLabelCount));
textMaxLabelCount.setEnabled(false);
if (null == scanner._file)
scanner._file = new File(ExtractFeatureRangesAction.getFeatureFile(run).getAbsolutePath());
textFileName.setText(scanner._file.getPath());
buttonLoadFile.setEnabled(scanner._file.exists());
ListenerHelper helper = new ListenerHelper(this);
helper.addListener(buttonCancel, "buttonCancel_actionPerformed");
helper.addListener(buttonFindFeatures, "buttonFindFeatures_actionPerformed");
helper.addListener(buttonLoadFile, "buttonLoadFile_actionPerformed");
helper.addListener(buttonBrowse, "buttonBrowse_actionPerformed");
helper.addListener(textFileName, "textFileName_keyTyped");
helper.addListener(textFileName, "textFileName_actionPerformed");
helper.addListener(textFileName.getDocument(), "textFileName_insertUpdate");
helper.addListener(textFileName.getDocument(), "textFileName_removeUpdate");
helper.addListener(textFileName.getDocument(), "textFileName_changedUpdate");
helper.addListener(checkboxQuant, "checkboxQuant_actionPerformed");
helper.addListener(comboboxTagSelect, "comboboxTagSelect_actionPerformed");
}
private void updateButtonState()
{
scanner._file = new File(textFileName.getText());
buttonLoadFile.setEnabled(scanner._file.exists());
}
public void buttonCancel_actionPerformed(ActionEvent event)
{
action = ACTION_CANCEL;
ExtractFeatureRangesDialog.this.dispose();
}
public void buttonFindFeatures_actionPerformed(ActionEvent event)
{
action = ACTION_FIND;
try
{
scanner.setEndScan(Integer.parseInt(textEndScan.getText()));
scanner.setStartScan(Integer.parseInt(textStartScan.getText()));
scanner._outputZeroCharge = checkboxZeroCharge.isSelected();
scanner._deconvolute = checkboxDeconvolute.isSelected();
scanner._quant = checkboxQuant.isSelected();
scanner.setLightTagWeight(Float.parseFloat(textLightTagWeight.getText()));
scanner.setHeavyTagWeight(Float.parseFloat(textHeavyTagWeight.getText()));
scanner.setLabeledResidue(textLabeledResidue.getText().charAt(0));
try
{
scanner.setMaxLabelCount(Integer.parseInt(textMaxLabelCount.getText()));
}
catch (Exception e)
{
ApplicationContext.infoMessage(TextProvider.getText("BAD_VALUE_MAX_LABEL_USING_DEFAULT",
Integer.toString(AnalyzeICAT.DEFAULT_MAX_LABEL_COUNT)));
scanner.setMaxLabelCount(AnalyzeICAT.DEFAULT_MAX_LABEL_COUNT);
}
}
catch (NumberFormatException x)
{
}
ExtractFeatureRangesDialog.this.dispose();
}
public void buttonLoadFile_actionPerformed(ActionEvent event)
{
action = ACTION_LOAD;
ExtractFeatureRangesDialog.this.dispose();
}
public void buttonBrowse_actionPerformed(ActionEvent event)
{
JFileChooser chooser = new WorkbenchFileChooser();
int chooserStatus = chooser.showOpenDialog(ExtractFeatureRangesDialog.this);
//if user didn't hit OK, ignore
if (chooserStatus != JFileChooser.APPROVE_OPTION)
return;
File file = chooser.getSelectedFile();
if (null != file)
{
textFileName.setText(file.getAbsolutePath());
}
}
public void textFileName_keyTyped(KeyEvent event)
{
updateButtonState();
}
public void textFileName_actionPerformed(ActionEvent event)
{
updateButtonState();
}
public void textFileName_insertUpdate(DocumentEvent event)
{
updateButtonState();
}
public void textFileName_removeUpdate(DocumentEvent event)
{
updateButtonState();
}
public void textFileName_changedUpdate(DocumentEvent event)
{
updateButtonState();
}
public void checkboxQuant_actionPerformed(ActionEvent event)
{
boolean enabled = checkboxQuant.isSelected();
textLightTagWeight.setEnabled(enabled);
textHeavyTagWeight.setEnabled(enabled);
comboboxTagSelect.setEnabled(enabled);
textLabeledResidue.setEnabled(enabled);
textMaxLabelCount.setEnabled(enabled);
}
/**
* event handler for the prepopulated tag combobox.
* Not very efficient at matching the selected label, but that list will never be big,
* because it's displayed in the UI.
* @param event
*/
public void comboboxTagSelect_actionPerformed(ActionEvent event)
{
ArrayList tagArrayList = AnalyzeICAT.getPrePopulatedLabels();
ListIterator tagArrayListIterator = tagArrayList.listIterator();
String selectedTagName = (String) comboboxTagSelect.getSelectedItem();
while (tagArrayListIterator.hasNext())
{
AnalyzeICAT.IsotopicLabel currentLabel =
(AnalyzeICAT.IsotopicLabel) tagArrayListIterator.next();
if (currentLabel.getName().equals(selectedTagName))
{
textLightTagWeight.setText(String.valueOf(currentLabel.getLight()));
textHeavyTagWeight.setText(String.valueOf(currentLabel.getHeavy() + currentLabel.getLight()));
textLabeledResidue.setText(String.valueOf(currentLabel.getResidue()));
textMaxLabelCount.setText(String.valueOf(currentLabel.getMaxLabelCount()));
break;
}
}
}
}
/**
* Populates the label name selection combobox from the prepopulated labels stored in
* AnalyzeICAT
* @param comboBox
*/
protected static void populateTagSelectComboBox(JComboBox comboBox)
{
if (comboBox == null)
return;
ArrayList tagArrayList = AnalyzeICAT.getPrePopulatedLabels();
ListIterator tagArrayListIterator = tagArrayList.listIterator();
while (tagArrayListIterator.hasNext())
{
AnalyzeICAT.IsotopicLabel currentLabel =
(AnalyzeICAT.IsotopicLabel) tagArrayListIterator.next();
comboBox.addItem(currentLabel.getName());
}
}
}