/*
* 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.viewer.Localizer;
import org.fhcrc.cpl.toolbox.proteomics.MSRun;
import org.fhcrc.cpl.viewer.ViewerUserManualGenerator;
import org.fhcrc.cpl.viewer.Application;
import org.fhcrc.cpl.toolbox.commandline.CommandLineModule;
import org.fhcrc.cpl.viewer.commandline.ViewerCommandLineModuleDiscoverer;
import org.fhcrc.cpl.viewer.mrm.commandline.MRMCommandLineModule;
import org.fhcrc.cpl.toolbox.proteomics.Clusterer2D;
import org.fhcrc.cpl.viewer.util.ElutionDataPoint;
import org.fhcrc.cpl.toolbox.filehandler.TempFileManager;
import org.fhcrc.cpl.toolbox.gui.chart.PanelWithChart;
import org.fhcrc.cpl.toolbox.gui.HtmlViewerPanel;
import org.fhcrc.cpl.toolbox.gui.ListenerHelper;
import org.fhcrc.cpl.viewer.mrm.*;
import org.fhcrc.cpl.viewer.mrm.utilities.*;
import org.fhcrc.cpl.toolbox.ApplicationContext;
import org.fhcrc.cpl.toolbox.TextProvider;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.annotations.XYLineAnnotation;
import org.jfree.chart.annotations.XYTextAnnotation;
import org.jfree.chart.axis.Axis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.event.AxisChangeEvent;
import org.jfree.chart.event.AxisChangeListener;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.Range;
import org.jfree.data.xy.XYDataItem;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.*;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.event.*;
import java.awt.geom.Line2D;
import java.io.*;
import java.text.NumberFormat;
import java.util.*;
import java.util.List;
/**
* GUI
*/
public class MRMDialog extends JFrame implements Serializable {
protected JLabel titleText;
protected JLabel elutionTableLabel;
protected MRMTransition[] _mrmTransitions;
protected int currentTransitionIndex = 0;
protected MSRun _run;
protected float _precursorDiscoveryMzTolerance;
protected float _daughterMzTolerance;
protected float _precursorChromatogramWindow;
protected File _mzXMLFile;
protected JFileChooser _mzXMLFileChooser;
protected JFileChooser _outputFileChooser;
protected JFileChooser _inputTSVFileChooser;
protected JFileChooser _imageOutputFileChooser;
protected boolean _traceAllFragments;
protected ListSelectionListener _ptmlsl;
protected transitionListSelectionListener _tlsl;
protected boolean _synclh;
//Widgets
public JList listTransition;
public JScrollPane listScrollPane;
public JScrollPane peaksScrollPane;
public static JTable peaksTable;
public JLabel fileNameLabel;
public JPanel precursorContainerPanel;
public JPanel precursorContainerContainerPanel;
public JPanel daughterContainerContainerPanel;
public JPanel daughterContainerPanel;
public JLabel topGraphLabel;
public JButton buttonZC;
public JButton buttonPrev;
public JButton buttonNext;
public JButton buttonSave;
public JButton buttonAccept;
public JButton buttonReject;
public JButton buttonZoom;
public JButton buttonFindMate;
public JButton buttonBoost;
public JButton buttonTiming;
public JButton buttonRejectGroup;
public JMenuBar menuBarMain;
public JMenu menuFile;
public JMenuItem menuItemQuit;
public JMenuItem menuItemOpen;
public JMenuItem menuItemLoadTSV;
public JMenu menuOptions;
public JMenu menuHelp;
public JMenuItem menuItemArguments;
public JMenuItem menuItemOptions;
public JMenuItem menuItemDefinitions;
public JMenuItem menuItemTips;
public JMenuItem menuItemSICtolerance;
public JMenuItem menuItemPrecDiscTol;
public JMenuItem menuItemDaughterDiscTol;
public JMenuItem menuItemTraceAllFragments;
public JMenuItem menuItemChangeStrategy;
public JMenuItem menuItemSyncLH;
public JMenuItem menuItemPMin;
public JMenuItem menuItemAMin;
public JMenuItem menuItemSaveImage;
ListenerHelper helper = null;
public boolean _sim = false;
public boolean _conn = false;
public float _sictol = 0.0f;
public Class _ecurveclass = null;
public Container contentPanel = null;
public MRMTransition transitionOnPlot = null;
public TransitionDefinitionHeader transDefHeader = null;
public float _minPeakCutoff;
public float _minAreaCutoff;
/* todo: these are totally hokey and needs to be re-thought */
private static enum whichGraph{Precursor,Daughter};
private static enum whichAxis{Domain,Range};
private void menuBarInitializations() {
menuBarMain = new JMenuBar();
this.setJMenuBar(menuBarMain);
menuFile = new JMenu("File");
menuBarMain.add(menuFile);
menuItemOpen = new JMenuItem("Open mzXML");
menuFile.add(menuItemOpen);
menuItemSaveImage = new JMenuItem("Save Chromatogram");
menuItemQuit = new JMenuItem("Quit");
menuItemLoadTSV = new JMenuItem("Load TSV table");
menuFile.add(menuItemLoadTSV);
menuFile.add(menuItemSaveImage);
menuFile.add(menuItemQuit);
menuOptions = new JMenu("Options");
menuItemSICtolerance = new JMenuItem("SIC Tolerance");
menuOptions.add(menuItemSICtolerance);
menuItemPrecDiscTol = new JMenuItem("Precursor Tolerance");
menuOptions.add(menuItemPrecDiscTol);
menuItemDaughterDiscTol = new JMenuItem("Product Tolerance");
menuOptions.add(menuItemDaughterDiscTol);
menuItemTraceAllFragments = new JMenuItem("Trace Chromats");
menuOptions.add(menuItemTraceAllFragments);
menuItemChangeStrategy = new JMenuItem("Curve Strategy");
menuOptions.add(menuItemChangeStrategy);
menuItemSyncLH = new JMenuItem("Synchronize L/H label elution regions");
menuOptions.add(menuItemSyncLH);
menuItemPMin = new JMenuItem("Refilter Min Peak Height");
menuOptions.add(menuItemPMin);
menuItemAMin = new JMenuItem("Refilter Min Curve Area");
menuOptions.add(menuItemAMin);
menuBarMain.add(menuOptions);
menuHelp = new JMenu("Help");
menuItemArguments = new JMenuItem("Java commandline options");
menuItemOptions = new JMenuItem("Options help");
menuHelp.add(menuItemOptions);
menuItemDefinitions = new JMenuItem("Definitions");
menuHelp.add(menuItemDefinitions);
menuItemTips = new JMenuItem("User Tips");
menuHelp.add(menuItemTips);
menuHelp.add(menuItemArguments);
menuBarMain.add(menuHelp);
}
private void listenerHelperInitializations() {
helper.addListener(menuItemSICtolerance,"buttonSICUpdate_actionPerformed");
helper.addListener(menuItemPrecDiscTol,"buttonPDT_actionPerformed");
helper.addListener(menuItemDaughterDiscTol,"buttonDTOL_actionPerformed");
helper.addListener(menuItemTraceAllFragments,"menuItemTraceAllFragments_actionPerformed");
helper.addListener(menuItemChangeStrategy,"menuItemChangeStrategy_actionPerformed");
helper.addListener(menuItemSyncLH,"menuItemSyncLH_actionPerformed");
helper.addListener(buttonZC, "buttonZC_actionPerformed");
helper.addListener(menuItemPMin,"menuItemPMin_actionPerformed");
helper.addListener(menuItemAMin,"menuItemAMin_actionPerformed");
helper.addListener(buttonNext, "buttonNext_actionPerformed");
helper.addListener(buttonPrev, "buttonPrev_actionPerformed");
helper.addListener(buttonSave, "buttonSave_actionPerformed");
helper.addListener(buttonAccept,"buttonAccept_actionPerformed");
helper.addListener(buttonBoost,"buttonBoost_actionPerformed");
helper.addListener(buttonTiming,"buttonTiming_actionPerformed");
helper.addListener(buttonReject,"buttonReject_actionPerformed");
helper.addListener(buttonRejectGroup,"buttonRejectGroup_actionPerformed");
helper.addListener(contentPanel,"contentPanel_mouseClicked");
helper.addListener(menuItemQuit,"menuItemQuit_actionPerformed");
helper.addListener(menuItemTips,"menuItemTips_actionPerformed");
helper.addListener(menuItemDefinitions,"menuItemDefinitions_actionPerformed");
helper.addListener(menuItemOptions,"menuItemOptions_actionPerformed");
helper.addListener(menuItemArguments,"menuItemArguments_actionPerformed");
helper.addListener(menuItemLoadTSV,"menuItemLoadTSV_actionPerformed");
helper.addListener(menuItemOpen,"menuItemOpen_actionPerformed");
helper.addListener(buttonZoom,"buttonZoom_actionPerformed");
helper.addListener(buttonFindMate,"buttonFindMate_actionPerformed");
helper.addListener(menuItemSaveImage,"menuItemSaveImage_actionPerformed");
}
/**
* Initialize the GUI and show the first transition
* @param mzXMLFile
*/
public MRMDialog(File mzXMLFile, float precDiscTol, float daughterTol, float chromTol, Class ECurveStrat, boolean traceAllFragments, boolean synclh,float minP, float minA)
{
super();
this.setTitle(TextProvider.getText("MRMer")+" v. "+TextProvider.getText("MRMER_VERSION")+" (build "+ (String) ApplicationContext.getProperty("REVISION")+")");
//frameInit();
_precursorDiscoveryMzTolerance =precDiscTol;
_daughterMzTolerance = daughterTol;
_precursorChromatogramWindow = chromTol;
_mzXMLFile = mzXMLFile;
_ecurveclass = ECurveStrat;
currentTransitionIndex = 0;
_traceAllFragments = traceAllFragments;
_synclh = synclh;
_minPeakCutoff = minP;
_minAreaCutoff = minA;
//graphical stuff
contentPanel = null;
helper = new ListenerHelper(this);
try
{
contentPanel =
Localizer.renderSwixml("org/fhcrc/cpl/viewer/gui/MRMDialog.xml",this);
contentPanel.setBackground(new Color(255,255,153));
menuBarInitializations();
_mzXMLFileChooser = new JFileChooser();
_mzXMLFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
_mzXMLFileChooser.setMultiSelectionEnabled(false);
_mzXMLFileChooser.setFileFilter(
new javax.swing.filechooser.FileFilter() {
public boolean accept(File f) {
if(f.isDirectory()) return true;
String fname = f.getName();
String parts[] = fname.split("\\.");
if(parts.length != 2) return false;
return parts[1].equalsIgnoreCase("mzXML");
}
public String getDescription() {
return "mzXML files";
}
}
);
_outputFileChooser = new JFileChooser();
_outputFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
_outputFileChooser.setMultiSelectionEnabled(false);
_outputFileChooser.setFileFilter(
new javax.swing.filechooser.FileFilter() {
public boolean accept(File f)
{return f.toString().endsWith(".tsv") || f.isDirectory();}
public String getDescription()
{return "TSV files";}
}
);
_imageOutputFileChooser = new JFileChooser();
_imageOutputFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
_imageOutputFileChooser.setMultiSelectionEnabled(false);
_imageOutputFileChooser.setFileFilter(
new javax.swing.filechooser.FileFilter() {
public boolean accept(File f)
{return f.toString().endsWith(".png") || f.isDirectory();}
public String getDescription()
{return "PNG graphics files";}
}
);
_inputTSVFileChooser = new JFileChooser();
_inputTSVFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
_inputTSVFileChooser.setMultiSelectionEnabled(false);
_inputTSVFileChooser.setFileFilter(
new javax.swing.filechooser.FileFilter() {
public boolean accept(File f)
{return f.toString().endsWith(".tsv") || f.isDirectory();}
public String getDescription()
{return "TSV files";}
}
);
this.add(contentPanel);
setResizable(true);
}
catch (Exception x)
{
System.err.println("Failed in MRMDialog initializer: "+x);
ApplicationContext.errorMessage(TextProvider.getText("ERROR_CREATING_DIALOG"), x);
throw new RuntimeException(x);
}
initStuff();
listenerHelperInitializations();
}
private void transitionListInitializations() {
listTransition = new JList();
listTransition.setCellRenderer(new coloredMRMListRenderer());
listTransition.setModel(new DefaultListModel());
listTransition.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
_tlsl = new transitionListSelectionListener();
listTransition.addListSelectionListener(_tlsl);
listTransition.addMouseWheelListener(
new MouseWheelListener(){
public void mouseWheelMoved(MouseWheelEvent event){
int move = event.getWheelRotation();
int curIndex = listTransition.getSelectedIndex();
int newIndex = curIndex;
if(move > 0) {
newIndex = Math.min(curIndex+move,listTransition.getModel().getSize());
listTransition.setSelectedIndex(newIndex);
}
if(move < 0) {
newIndex = Math.max(curIndex+move,0);
listTransition.setSelectedIndex(newIndex);
}
listTransition.ensureIndexIsVisible(newIndex);
}
}
);
for (MRMTransition curTran : _mrmTransitions)
((DefaultListModel)listTransition.getModel()).addElement(curTran);
listTransition.setVisible(true);
listScrollPane.getViewport().setView(listTransition);
listScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
listScrollPane.getVerticalScrollBar().addAdjustmentListener(
new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent ae) {
if(!ae.getValueIsAdjusting()) {
listTransition.repaint();
}
}
}
);
}
private void peaksDataInitializations() {
String classElements[] = _ecurveclass.getName().split("\\.");
elutionTableLabel.setText("<html><body><center>Elution Data<br><font size='-1'>("+classElements[classElements.length-1]+")</font></center></body></html>");
elutionTableLabel.setHorizontalAlignment(JLabel.CENTER);
elutionTableLabel.setHorizontalTextPosition(JLabel.CENTER);
if(transDefHeader == null || transDefHeader.getAQUApairs() == null || transDefHeader.getAQUApairs().size() == 0){
buttonFindMate.setVisible(false);
} else {
buttonFindMate.setVisible(true);
}
peaksScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
peaksScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
peaksTable = new JTable(new PeaksTableModel() );
//peaksTable.setPreferredScrollableViewportSize(new Dimension(500, 700));
peaksTable.setSelectionModel(new peaksTableSelectionModel());
peaksTable.setAutoscrolls(true);
peaksTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
int totalTableRows = 1;
for(MRMTransition curTrans: _mrmTransitions) totalTableRows += (1+ curTrans.getDaughters().size());
((PeaksTableModel)(peaksTable.getModel())).data = new Object[totalTableRows-1][peaksData.values().length];
for(peaksData pd: EnumSet.allOf(peaksData.class)) {
peaksTable.getColumnModel().getColumn(pd.colno).setPreferredWidth(pd.colWidth);
}
peaksTable.doLayout();
((DefaultCellEditor)peaksTable.getDefaultEditor(peaksData.Accept.colClass)).setClickCountToStart(1);
int i = 0;
for(MRMTransition curTrans: _mrmTransitions) {
curTrans.setGraphData(makeParentSeries(curTrans));
int curPrecursorIndex = i;
curTrans.setTableRow(curPrecursorIndex);
for(peaksData pd: EnumSet.allOf(peaksData.class)) {
((PeaksTableModel)(peaksTable.getModel())).data[i][pd.colno] = null;
pd.makeVisible(true);
}
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Accept.colno] = null;
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Precursor.colno] = curTrans;
for(MRMDaughter d: curTrans.getDaughters().values()) {
i++;
d.setGraphData(d.makeDaughterSeries());
d.setContinDaughterData(d.makeDaughterSeries(d,true));
d.setElutionDataTableRow(i);
ElutionCurveStrategy bes = ElutionCurveStrategy.getInstance(curTrans,d,_ecurveclass);
bes.calculateParentElutionCurves(null);
bes.calculateDaughterElutionCurves(null);
bes.calculateBestCurves();
d.calculateQuality();
curTrans.getElutionCurves().put(d, bes);
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Accept.colno] = new Boolean(!Utils.allYsAre0(d));
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Peptide.colno] ="";
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Precursor.colno] = curTrans;
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Daughter.colno] = d;
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.CoStart.colno] = null;
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.CoEnd.colno] = null;
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.CoDelta.colno] = null;
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.AUC.colno] = null;
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.MaxPeak.colno] = null;
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.MidTime.colno] = null;
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Quality.colno] = null;
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Label.colno] = "";
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Code.colno] = null;
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.LHRatio.colno] = null;
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Comment.colno] = "";
if(transDefHeader != null && transDefHeader.getDToTD() != null && transDefHeader.getDToTD().get(d) != null) {
TransitionDefinition td = transDefHeader.getDToTD().get(d);
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Peptide.colno] =td.getPeptide();
((PeaksTableModel)(peaksTable.getModel())).data[curPrecursorIndex][peaksData.Peptide.colno] =td.getPeptide();
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Code.colno] = new Integer(td.getAQUAcode());
}
ElutionCurve bestPrecursorCurve = bes.getBestParentCurve();
if(bestPrecursorCurve == null || bestPrecursorCurve.getMinElutionTimeSecs() <= 0.0){
((PeaksTableModel)(peaksTable.getModel())).data[curPrecursorIndex][peaksData.AUC.colno] = new Float(-1);
((PeaksTableModel)(peaksTable.getModel())).data[curPrecursorIndex][peaksData.MaxPeak.colno] = new Float(-1);
((PeaksTableModel)(peaksTable.getModel())).data[curPrecursorIndex][peaksData.Quality.colno] = new Float(-1);
((PeaksTableModel)(peaksTable.getModel())).data[curPrecursorIndex][peaksData.MidTime.colno] = new Float(-1);
} else {
((PeaksTableModel)(peaksTable.getModel())).data[curPrecursorIndex][peaksData.AUC.colno] = new Float(bestPrecursorCurve.getAUC());
((PeaksTableModel)(peaksTable.getModel())).data[curPrecursorIndex][peaksData.MaxPeak.colno] = new Float(bestPrecursorCurve.getHighestPointY());
((PeaksTableModel)(peaksTable.getModel())).data[curPrecursorIndex][peaksData.Quality.colno] = new Float(curTrans.getQuality());
}
ElutionCurve bestDaughterCurve = bes.getBestDaughterCurve();
if(bestDaughterCurve == null || bestDaughterCurve.getMinElutionTimeSecs() <= 0.0) {
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Accept.colno] = new Boolean(false);
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.AUC.colno] = new Float(-1);
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.MaxPeak.colno] = new Float(-1);
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Quality.colno] = new Float(-1);
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.MidTime.colno] = new Float(-1);
} else {
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.AUC.colno] = new Float(bestDaughterCurve.getAUC());
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.MaxPeak.colno] = new Float(bestDaughterCurve.getHighestPointY());
d.setBestElutionCurve(bestDaughterCurve);
((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Quality.colno] = new Float(d.getQuality());
if(_minPeakCutoff > 0 && bestDaughterCurve.getHighestPointY() < _minPeakCutoff) ((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Accept.colno] = new Boolean(false);
if(_minAreaCutoff > 0 && bestDaughterCurve.getAUC() < _minAreaCutoff) ((PeaksTableModel)(peaksTable.getModel())).data[i][peaksData.Accept.colno] = new Boolean(false);
}
}
curTrans.setElutionRegionStart(curTrans.calculateMinOfAllBestDaughterCurves());
curTrans.setElutionRegionEnd(curTrans.calculateMaxOfAllBestDaughterCurves());
curTrans.calcMaxYofAllDaughters();
for(int j=curPrecursorIndex; j<=i; j++){
((PeaksTableModel)(peaksTable.getModel())).data[j][peaksData.CoStart.colno] = new Float(curTrans.getElutionRegionStart());
((PeaksTableModel)(peaksTable.getModel())).data[j][peaksData.CoEnd.colno] = new Float(curTrans.getElutionRegionEnd());
((PeaksTableModel)(peaksTable.getModel())).data[j][peaksData.CoDelta.colno] = new Float(curTrans.getElutionRegionEnd()-curTrans.getElutionRegionStart());
((PeaksTableModel)(peaksTable.getModel())).data[j][peaksData.MidTime.colno] = new Float(curTrans.getCalcXatMaxYAllDaughters());
}
i++;
}
peaksTable.setDefaultRenderer(MRMTransition.class, new MRMTransitionTableRenderer(false));
peaksTable.setDefaultRenderer(MRMDaughter.class, new MRMDaughterTableRenderer(false));
peaksTable.setDefaultRenderer(Number.class, new MRMNumberTableRenderer());
peaksTable.setDefaultRenderer(Integer.class, new MRMNumberTableRenderer());
peaksTable.setDefaultRenderer(Boolean.class, new MRMBooleanRenderer());
peaksTable.getColumnModel().getColumn(peaksData.CoStart.colno).setCellEditor(new NumberTableCellEditor());
peaksTable.getColumnModel().getColumn(peaksData.CoEnd.colno).setCellEditor(new NumberTableCellEditor());
peaksTable.getColumnModel().getColumn(peaksData.Code.colno).setCellEditor(new NumberTableCellEditor());
peaksTable.getColumnModel().getColumn(peaksData.LHRatio.colno).setCellEditor(new NumberTableCellEditor());
peaksScrollPane.getViewport().setView(peaksTable);
if(transDefHeader == null) {
peaksData.Peptide.makeVisible(false);
peaksData.Label.makeVisible(false);
peaksData.LHRatio.makeVisible(false);
peaksData.Code.makeVisible(false);
} else {
if(transDefHeader.getAQUApairs() == null || transDefHeader.getAQUApairs().isEmpty()) {
peaksData.Label.makeVisible(false);
peaksData.LHRatio.makeVisible(false);
peaksData.Code.makeVisible(false);
}
}
// "Quality" column, currently unused, is invisible unless one or more of its
// values is not -1
peaksData.Quality.makeVisible(!Utils.qualColIsEmpty());
peaksScrollPane.getVerticalScrollBar().addAdjustmentListener(
new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent ae) {
if(!ae.getValueIsAdjusting()) {
peaksTable.repaint();
}
}
}
);
peaksTable.getModel().addTableModelListener(new peaksTableListener());
_ptmlsl = new PeaksTableListSelectionListener();
peaksTable.getSelectionModel().addListSelectionListener(_ptmlsl);
}
public void AQUAinitializations() {
if(transDefHeader == null || transDefHeader.getAQUApairs() == null) return;
for(TransitionDefinitionHeader.AQUApair aqp: transDefHeader.getAQUApairs().values()) {
if(aqp.getHeavyMember().getAssociatedProduct() == null || aqp.getLightMember().getAssociatedProduct() == null) continue;
MRMDaughter light = aqp.getLightMember().getAssociatedProduct();
MRMDaughter heavy = aqp.getHeavyMember().getAssociatedProduct();
if(light.getBestElutionCurve() == null || heavy.getBestElutionCurve() == null) continue;
ElutionCurve lec = light.getBestElutionCurve();
ElutionCurve hec = heavy.getBestElutionCurve();
Float lhratio = new Float(lec.getAUC()/hec.getAUC());
((PeaksTableModel)(peaksTable.getModel())).setValueAt(new Character(aqp.getLightMember().getLowOrHigh()).toString(),light.getElutionDataTableRow(),peaksData.Label.colno);
((PeaksTableModel)(peaksTable.getModel())).setValueAt(new Character(aqp.getHeavyMember().getLowOrHigh()).toString(),heavy.getElutionDataTableRow(),peaksData.Label.colno);
((PeaksTableModel)(peaksTable.getModel())).setValueAt(lhratio,light.getElutionDataTableRow(),peaksData.LHRatio.colno);
((PeaksTableModel)(peaksTable.getModel())).setValueAt(lhratio,heavy.getElutionDataTableRow(),peaksData.LHRatio.colno);
}
}
public void initStuff()
{
transDefHeader = null;
transitionOnPlot = null;
try {
//long start = System.currentTimeMillis();
_run = MSRun.load(_mzXMLFile.getAbsolutePath());
//long end = System.currentTimeMillis();
//System.out.println("time to read mzXML (ms): "+(end-start));
//System.exit(0);
_mrmTransitions = loadMRMTransitions(_run);
if(_mrmTransitions == null) {
throw new RuntimeException("_mrmTransitions is null MRMDialog");
}
} catch (Exception e) {
System.err.println("Failed in initstuff: "+e);
ApplicationContext.errorMessage(TextProvider.getText("ERROR_CREATING_DIALOG"), e);
}
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String _transitionDefFilePath = _mzXMLFile.getAbsolutePath().replaceAll("\\.mzXML$",".transition.tsv");
if((new File(_transitionDefFilePath)).exists()){
transDefHeader = new TransitionDefinitionHeader(_transitionDefFilePath,new TSVTransitionDefinitionParser());
try {
transDefHeader.getParser().setTransitionDefFile(_transitionDefFilePath);
transDefHeader.doParse();
if(transDefHeader==null || transDefHeader.getTransitionDefs() == null || transDefHeader.getTransitionDefs().size()==0) {
transDefHeader = null;
} else {
transDefHeader.linkUpToTransitionList(_mrmTransitions,_precursorDiscoveryMzTolerance,_daughterMzTolerance);
transDefHeader.determinePairs();
}
} catch (Exception e) {
System.err.println(e);
}
}
if(transDefHeader != null && transDefHeader.getComment() != null && !transDefHeader.getComment().equals("")) {
fileNameLabel.setText("<html><body><center>"+_mzXMLFile.getName()+"<br>"+transDefHeader.getComment()+"</center></body></html>");
fileNameLabel.setHorizontalAlignment(JLabel.CENTER);
fileNameLabel.setHorizontalTextPosition(JLabel.CENTER);
fileNameLabel.setMinimumSize(new Dimension(1200,30));
}
else {
fileNameLabel.setText(_mzXMLFile.getName());
}
if(transDefHeader != null && transDefHeader.getMzXMLFile() != null && !transDefHeader.getMzXMLFile().equals("")) {
if(!transDefHeader.getMzXMLFile().trim().equals(_mzXMLFile.getName().trim())) {
ApplicationContext.infoMessage("Note: current mzXML ("+_mzXMLFile.getName()+") does not match mzXML file name in transition.tsv file ("+transDefHeader.getMzXMLFile()+")");
}
}
helper.addListener(this, "contentPanel_componentResized");
transitionListInitializations();
peaksDataInitializations();
AQUAinitializations();
String mzToleranceText = "" + (double) _precursorChromatogramWindow;
//this is kind of arbitrary: one digit after decimal. It also doesn't support
//comma-radix. Whatever.
if (mzToleranceText.contains("."))
mzToleranceText = mzToleranceText.substring(0,mzToleranceText.indexOf(".") + 2);
_mzXMLFileChooser.setCurrentDirectory(_mzXMLFile.getAbsoluteFile().getParentFile());
_outputFileChooser.setCurrentDirectory(_mzXMLFile.getAbsoluteFile().getParentFile());
_inputTSVFileChooser.setCurrentDirectory(_mzXMLFile.getAbsoluteFile().getParentFile());
listTransition.setSelectedIndex(0);
//updateChartsAndFields(false);
peaksScrollPane.updateUI();
listScrollPane.updateUI();
pack();
//debug
// System.out.println(Runtime.getRuntime().freeMemory()+" bytes available before freeing _run");
_run.close();
_run = null;
for(MRMTransition mrmt: _mrmTransitions ) mrmt.setRun(null);
System.gc();
// System.out.println(Runtime.getRuntime().freeMemory()+" bytes available after freeing _run");
}
// Listeners
private volatile boolean _kludge_listener_removal = false;
public class transitionListSelectionListener implements ListSelectionListener {
public void valueChanged(ListSelectionEvent e)
{
if(e.getValueIsAdjusting()) return;
if(_kludge_listener_removal) return;
MRMTransition curTrans = null;
try
{
listTransition.getSelectionModel().removeListSelectionListener(this);
int indices[]=listTransition.getSelectedIndices();
DefaultListModel dlm = (DefaultListModel) listTransition.getModel();
for(int i=0; i<indices.length;i++) {
curTrans = (MRMTransition)dlm.get(indices[i]);
curTrans.setCurrentDaughterIndex(0);
int dataIndex = -1;
Object[][] tableData = ((PeaksTableModel)(peaksTable.getModel())).data;
for(int j = 0; j<tableData.length; j++)
{
if(curTrans == (MRMTransition)(tableData[j][peaksData.Precursor.colno]))
{
dataIndex = j;
}
}
if(dataIndex > -1)
{
ListSelectionListener curlsl = null;
ListSelectionListener larr[] = ((peaksTableSelectionModel)peaksTable.getSelectionModel()).getListSelectionListeners();
for(int ii = 0; ii<larr.length; ii++) {
if(larr[ii] instanceof PeaksTableListSelectionListener) {
curlsl = larr[ii];
peaksTable.getSelectionModel().removeListSelectionListener(curlsl);
//break;
}
}
scrollPeakTableToRow(curTrans.getCurrentDaughter().getElutionDataTableRow());
if(curlsl != null) peaksTable.getSelectionModel().addListSelectionListener(curlsl);
}
}
transitionOnPlot = curTrans;
updateChartsAndFields(false);
listTransition.getSelectionModel().addListSelectionListener(this);
} catch (Exception ee) {
ApplicationContext.infoMessage("Can't plot selected index: "+ee);
}
}
}
public class PeaksTableListSelectionListener implements ListSelectionListener {
public void valueChanged(ListSelectionEvent event) {
if(event.getValueIsAdjusting())return;
try{
((ListSelectionModel)(event.getSource())).removeListSelectionListener(this);
// Switch transitions table to appropriate transition
int oldIndex = transitionOnPlot.getCurrentDaughter().getElutionDataTableRow();
int index = -1;
if(event.getLastIndex()!=oldIndex) {
index = event.getLastIndex();
} else {
if(event.getFirstIndex() != oldIndex) {
index = event.getFirstIndex();
} else {
System.err.println("Failed in peakstablelistselectionlistener: can't find row index ");
ApplicationContext.errorMessage("Problem in PeaksTableListener: can't find correct row index", null);
((ListSelectionModel)(event.getSource())).addListSelectionListener(this);
return;
}
}
// The transition we selected
MRMTransition curTrans =(MRMTransition)((PeaksTableModel)(peaksTable.getModel())).data[index][peaksData.Precursor.colno];
//Get currently selected daughter. If we aren't positioned on a row
//that contains a daughter, assume the first daughter of the transition
MRMDaughter curD =(MRMDaughter)((PeaksTableModel)(peaksTable.getModel())).data[index][peaksData.Daughter.colno];
if(curD == null) curD = curTrans.getDaughters().values().iterator().next();
//Set transition's current daughter to the daughter on the table row
Object dArr[] = curTrans.getDaughters().values().toArray();
for(int i = 0; i<dArr.length; i++) {
if(dArr[i] == (Object) curD) {
curTrans.setCurrentDaughterIndex(i);
break;
}
}
//Move the transition list (left table on screen) to the correct index
//if we have moved from one transition to another
//Make sure to remove and replace listener, so it won't do any
//mischief. Then replace it afterward *only if it had been there before*!
//find listTransition listener of the proper variety, if there is one
ListSelectionListener curlsl = null;
ListSelectionListener larr[] = listTransition.getListSelectionListeners();
for(int i = 0; i<larr.length; i++) {
if(larr[i] instanceof transitionListSelectionListener) {
curlsl = larr[i];
listTransition.removeListSelectionListener(curlsl);
//break;
}
}
//todo: find out why removal of transitionListSelectionListener isn't working
_kludge_listener_removal = true;
if(curTrans != listTransition.getSelectedValues()[0]){
listTransition.setSelectedValue(curTrans,true);
}
_kludge_listener_removal = false;
//replace listener if it had been there before
if(transDefHeader != null) {
buttonFindMate.setEnabled(transDefHeader.getMatchingDaughter(curD) != null);
}
if(curlsl != null) listTransition.addListSelectionListener(curlsl);
// redisplay graph
transitionOnPlot = curTrans;
updateChartsAndFields(false);
//put current selection model back
((ListSelectionModel)(event.getSource())).addListSelectionListener(this);
} catch (Exception e) {
ApplicationContext.infoMessage("Can't set MRMer to selected row: "+e+"\nPlease contact maintainers.");
e.printStackTrace();
((ListSelectionModel)(event.getSource())).addListSelectionListener(this);
}
}
}
public class domainAxisZoomCoordinator implements AxisChangeListener
{
public CenterZoomNumberAxis getMyAxis() {
return myAxis;
}
public void setMyAxis(CenterZoomNumberAxis myAxis) {
this.myAxis = myAxis;
}
CenterZoomNumberAxis myAxis;
public domainAxisZoomCoordinator(CenterZoomNumberAxis na)
{
myAxis = na;
}
public void axisChanged(AxisChangeEvent ace)
{
if(precursorChromatogramEmpty(transitionOnPlot)) return;
CenterZoomNumberAxis theOtherAxis = null;
domainAxisZoomCoordinator theOtherCoordinator = null;
if(getMyAxis() == findAxisOfPanel(precursorContainerPanel,whichAxis.Domain)){
theOtherAxis = (CenterZoomNumberAxis) findAxisOfPanel(daughterContainerPanel, whichAxis.Domain);
} else {
theOtherAxis = (CenterZoomNumberAxis) findAxisOfPanel(precursorContainerPanel,whichAxis.Domain);
}
theOtherCoordinator = theOtherAxis.getTheListener();
theOtherAxis.removeChangeListener(theOtherCoordinator);
getMyAxis().removeChangeListener(this);
theOtherAxis.setLowerBound(getMyAxis().getLowerBound());
theOtherAxis.setUpperBound(getMyAxis().getUpperBound());
getMyAxis().addChangeListener(this);
theOtherAxis.addChangeListener(theOtherCoordinator);
// theOtherCoordinator.axisChanged(new AxisChangeEvent(theOtherAxis));
}
}
public class daughterRangeAxisChangeListener implements AxisChangeListener {
public void axisChanged(AxisChangeEvent ace) {
XYPlot xyp = (XYPlot) ace.getAxis().getPlot();
if(xyp != null && ace.getAxis() == xyp.getRangeAxis())
{
ValueAxis precursorRangeAxis = (ValueAxis)findAxisOfPanel(precursorContainerPanel,whichAxis.Range);
ValueAxis daughterRangeAxis = (ValueAxis) ace.getAxis();
precursorRangeAxis.setLowerBound(daughterRangeAxis.getLowerBound());
precursorRangeAxis.setUpperBound(daughterRangeAxis.getUpperBound());
}
}
}
public class peaksTableSelectionModel extends DefaultListSelectionModel {
public ListSelectionListener[] getListSelectionListeners() {
return (ListSelectionListener[])listenerList.getListeners(
ListSelectionListener.class);
}
}
public class peaksTableListener implements TableModelListener {
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
int column = e.getColumn();
TableModel model = (TableModel)e.getSource();
String columnName = model.getColumnName(column);
if(!columnName.equalsIgnoreCase("Start") &&
!columnName.equalsIgnoreCase("End") &&
!columnName.equalsIgnoreCase("Accept")
) return;
Object data = model.getValueAt(row, column);
if(columnName.equalsIgnoreCase("Accept")){
if(data != null) {
boolean accepted = (Boolean) data;
if(!accepted) {
//model.setValueAt(new Float(-1),row,peaksData.AUC.colno);
} else {
MRMDaughter curD = (MRMDaughter)model.getValueAt(row,peaksData.Daughter.colno);
ElutionCurve curEC = null;
if(curD != null) curEC = curD.getBestElutionCurve();
if(curEC != null) {
model.setValueAt(
new Float(curEC.getAUC()),
row,
peaksData.AUC.colno
);
}
}
}
updateDaughterCharts(false);
return;
}
float colVal = Float.parseFloat(data.toString());
float otherVal = 0.0f;
float start = 0f;
float end = 0f;
// Is this a daughter or parent?
// assume daughter first
MRMTransition mrt = null;
MRMDaughter mrd = (MRMDaughter)model.getValueAt(row,peaksData.Daughter.colno);
if(mrd == null){
mrt = (MRMTransition)model.getValueAt(row,peaksData.Precursor.colno);
} else {
mrt = mrd.getPrecursor();
}
if(columnName.equalsIgnoreCase("Start")) {
start = colVal;
otherVal = Float.parseFloat(model.getValueAt(row,peaksData.CoEnd.colno).toString());
end = otherVal;
if(colVal >= otherVal) {
JOptionPane.showMessageDialog(null,"Starting elution time must be less than ending elution time","Elution Range Error",JOptionPane.ERROR_MESSAGE);
model.removeTableModelListener(this);
model.setValueAt(new Float(0.0f),row, column);
model.addTableModelListener(this);
return;
}
mrt.setElutionRegionStart(start);
} else {
end = colVal;
otherVal = Float.parseFloat(model.getValueAt(row,peaksData.CoStart.colno).toString());
start = otherVal;
if(colVal <= otherVal){
JOptionPane.showMessageDialog(null,"End elution time must be greater than starting elution time","Elution Range Error",JOptionPane.ERROR_MESSAGE);
model.removeTableModelListener(this);
model.setValueAt(new Float(100000000.0f),row, column);
model.addTableModelListener(this);
return;
}
mrt.setElutionRegionEnd(end);
}
// elution boundaries have been changed manually
// change all daughter columns
model.removeTableModelListener(this);
model.setValueAt(new Float(start),mrt.getTableRow(),peaksData.CoStart.colno);
model.setValueAt(new Float(end),mrt.getTableRow(),peaksData.CoEnd.colno);
float delta = end-start;
model.setValueAt(new Float(delta),mrt.getTableRow(),peaksData.CoDelta.colno);
for(MRMDaughter mrmd: mrt.getDaughters().values()){
model.setValueAt(new Float(start),mrmd.getElutionDataTableRow(),peaksData.CoStart.colno);
model.setValueAt(new Float(end),mrmd.getElutionDataTableRow(),peaksData.CoEnd.colno);
model.setValueAt(new Float(delta),mrmd.getElutionDataTableRow(),peaksData.CoDelta.colno);
}
Vector<MRMDaughter> matchingDaughters = null;
//if synchronize low-high is set, and this is an AQUA-like assay, synchronize the matching
//low row and high row to the same new elution range
if(transDefHeader != null && _synclh) {
matchingDaughters = new Vector<MRMDaughter>();
for(MRMDaughter mrmd: mrt.getDaughters().values()){
MRMDaughter matchingDaughter = transDefHeader.getMatchingDaughter(mrmd);
if(matchingDaughter != null) {
model.setValueAt(new Float(start),matchingDaughter.getElutionDataTableRow(),peaksData.CoStart.colno);
model.setValueAt(new Float(end),matchingDaughter.getElutionDataTableRow(),peaksData.CoEnd.colno);
model.setValueAt(new Float(delta),matchingDaughter.getElutionDataTableRow(),peaksData.CoDelta.colno);
matchingDaughters.add(matchingDaughter);
}
}
}
// recalculate all curves??
// or reselect region as elution curve?
// seems like a dumb idea
mrt.getElutionCurves().clear();
for(MRMDaughter d: mrt.getDaughters().values()){
d.setBestElutionCurve(null);
ElutionCurveStrategy ecs =
ElutionCurveStrategy.getInstance(mrt,d,_ecurveclass);
ecs.calculateParentElutionCurves(null);
ecs.calculateDaughterElutionCurves(null);
ecs.calculateBestCurves();
d.setBestElutionCurve(ecs.getBestDaughterCurve());
mrt.getElutionCurves().put(d,ecs);
ElutionCurve bestPrecursorCurve = ecs.getBestParentCurve();
ElutionCurve bestDaughterCurve = ecs.getBestDaughterCurve();
if(bestPrecursorCurve == null ||
bestPrecursorCurve.getMinElutionTimeSecs()<=0.0) {
model.setValueAt(new Float(-1),mrt.getTableRow(),peaksData.AUC.colno);
} else {
model.setValueAt(new Float(bestPrecursorCurve.getAUC()),mrt.getTableRow(),peaksData.AUC.colno);
}
if(bestDaughterCurve == null ||
bestDaughterCurve.getMinElutionTimeSecs()<=0.0
) {
model.setValueAt(new Float(-1),d.getElutionDataTableRow(),peaksData.AUC.colno);
model.setValueAt(new Float(-1),d.getElutionDataTableRow(),peaksData.MaxPeak.colno);
model.setValueAt(new Float(-1),d.getElutionDataTableRow(),peaksData.Quality.colno);
model.setValueAt(new Float(-1),d.getElutionDataTableRow(),peaksData.MidTime.colno);
} else {
model.setValueAt(new Float(bestDaughterCurve.getAUC()),d.getElutionDataTableRow(),peaksData.AUC.colno);
model.setValueAt(new Float(bestDaughterCurve.getHighestPointY()),d.getElutionDataTableRow(),peaksData.MaxPeak.colno);
model.setValueAt(new Float(d.getQuality()),d.getElutionDataTableRow(),peaksData.Quality.colno);
}
}
//Can't do this until all daughter curves have be recalculated
mrt.calcMaxYofAllDaughters();
model.setValueAt(new Float(mrt.getCalcXatMaxYAllDaughters()),mrt.getTableRow(),peaksData.MidTime.colno);
for(MRMDaughter d: mrt.getDaughters().values()){
model.setValueAt(new Float(mrt.getCalcXatMaxYAllDaughters()),d.getElutionDataTableRow(),peaksData.MidTime.colno);
}
//For AQUA assays, etc.
if(matchingDaughters != null && !matchingDaughters.isEmpty()) {
MRMTransition otherMRT = matchingDaughters.get(0).getPrecursor();
otherMRT.getElutionCurves().clear();
model.setValueAt(new Float(start),otherMRT.getTableRow(),peaksData.CoStart.colno);
model.setValueAt(new Float(end),otherMRT.getTableRow(),peaksData.CoEnd.colno);
model.setValueAt(new Float(delta),otherMRT.getTableRow(),peaksData.CoDelta.colno);
otherMRT.setElutionRegionStart(mrt.getElutionRegionStart());
otherMRT.setElutionRegionEnd(mrt.getElutionRegionEnd());
for(MRMDaughter md: matchingDaughters) {
md.setBestElutionCurve(null);
ElutionCurveStrategy mecs = ElutionCurveStrategy.getInstance(otherMRT,md,_ecurveclass);
mecs.calculateParentElutionCurves(null);
mecs.calculateDaughterElutionCurves(null);
mecs.calculateBestCurves();
md.setBestElutionCurve(mecs.getBestDaughterCurve());
otherMRT.getElutionCurves().put(md,mecs);
ElutionCurve bestPrecursorCurve = mecs.getBestParentCurve();
ElutionCurve bestDaughterCurve = mecs.getBestDaughterCurve();
if(bestPrecursorCurve == null || bestPrecursorCurve.getMinElutionTimeSecs()<=0.0) {
model.setValueAt(new Float(-1),otherMRT.getTableRow(),peaksData.AUC.colno);
} else {
model.setValueAt(new Float(bestPrecursorCurve.getAUC()),otherMRT.getTableRow(),peaksData.AUC.colno);
}
if(bestDaughterCurve == null || bestDaughterCurve.getMinElutionTimeSecs()<=0.0) {
model.setValueAt(new Float(-1),md.getElutionDataTableRow(),peaksData.AUC.colno);
} else {
model.setValueAt(new Float(bestDaughterCurve.getAUC()),md.getElutionDataTableRow(),peaksData.AUC.colno);
}
}
}
// redisplay AUCs
if(mrt == transitionOnPlot){
updateChartsAndFields(new defaultGraphZone());
}
if(transDefHeader != null) AQUAinitializations();
model.addTableModelListener(this);
}
}
public void buttonPostPressTasks() {
listTransition.requestFocus();
}
public void buttonSICUpdate_actionPerformed(ActionEvent event)
{
try
{
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
String answer = nf.format(_precursorChromatogramWindow);
String newAnswer = JOptionPane.showInputDialog("New value for MS1 SIC tolerance:",answer);
_precursorChromatogramWindow = (float) Double.parseDouble(newAnswer);
for(MRMTransition t : _mrmTransitions)
{
t.setGraphData(null);
for(MRMDaughter d : t.getDaughters().values())
{
d.setGraphData(null);
}
}
updateChartsAndFields(false);
}
catch (Exception e)
{
ApplicationContext.infoMessage("Bad value for MZ tolerance, please try again");
}
}
public void buttonPDT_actionPerformed(ActionEvent event)
{
try
{
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
String answer = nf.format(_precursorDiscoveryMzTolerance);
String newAnswer = JOptionPane.showInputDialog("New value for precursor tolerance:",answer);
_precursorDiscoveryMzTolerance = (float) Double.parseDouble(newAnswer);
initStuff();
}
catch (Exception e)
{
ApplicationContext.infoMessage("Bad value for precursor tolerance.");
}
}
public void buttonDTOL_actionPerformed(ActionEvent event)
{
try
{
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(4);
nf.setMinimumFractionDigits(4);
String answer = nf.format(_daughterMzTolerance);
String newAnswer = JOptionPane.showInputDialog("New value for product tolerance:",answer);
_daughterMzTolerance = (float) Double.parseDouble(newAnswer);
initStuff();
}
catch (Exception e)
{
ApplicationContext.infoMessage("Bad value for product tolerance.");
}
}
public void menuItemPMin_actionPerformed(ActionEvent event) {
try {
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
nf.setGroupingUsed(false);
String answer = nf.format(_minPeakCutoff);
String newAnswer = JOptionPane.showInputDialog("New value for min peak cutoff:",answer);
if(newAnswer == null) return;
float newCutoff = Float.parseFloat(newAnswer);
if(newCutoff > 0.0f) {
for(MRMTransition mrt: _mrmTransitions) {
for(MRMDaughter curd: mrt.getDaughters().values()) {
if(curd.getBestElutionCurve() != null && curd.getBestElutionCurve().getHighestPointY() < newCutoff) {
((PeaksTableModel)(peaksTable.getModel())).setValueAt(new Boolean(false),curd.getElutionDataTableRow(),peaksData.Accept.colno);
}
}
}
}
_minPeakCutoff = newCutoff;
} catch (Exception e) {
ApplicationContext.infoMessage("Failed to change min acceptable peak height: "+e);
}
}
public void menuItemAMin_actionPerformed(ActionEvent event) {
try {
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
nf.setGroupingUsed(false);
String answer = nf.format(_minAreaCutoff);
String newAnswer = JOptionPane.showInputDialog("New value for min AUC cutoff:",answer);
if(newAnswer == null) return;
float newCutoff = Float.parseFloat(newAnswer);
if(newCutoff > 0.0f) {
for(MRMTransition mrt: _mrmTransitions) {
for(MRMDaughter curd: mrt.getDaughters().values()) {
if(curd.getBestElutionCurve() != null && curd.getBestElutionCurve().getAUC() < newCutoff) {
((PeaksTableModel)(peaksTable.getModel())).setValueAt(new Boolean(false),curd.getElutionDataTableRow(),peaksData.Accept.colno);
}
}
}
}
_minAreaCutoff = newCutoff;
} catch (Exception e) {
ApplicationContext.infoMessage("Failed to change min acceptable AUC: "+e);
}
}
public void menuItemQuit_actionPerformed(ActionEvent event)
{
try {
System.err.println("Normal exit");
System.exit(0);
} catch (Exception e)
{
ApplicationContext.infoMessage("Cannot quit: "+e);
}
}
public void menuItemTraceAllFragments_actionPerformed(ActionEvent event) {
try {
int newTraceAllCode = JOptionPane.showConfirmDialog(this,"Trace over elution curves of ALL fragments?","Trace All Fragments",JOptionPane.YES_NO_CANCEL_OPTION);
if(newTraceAllCode != JOptionPane.YES_OPTION && newTraceAllCode != JOptionPane.NO_OPTION) return;
boolean newTraceAll = (newTraceAllCode == JOptionPane.YES_OPTION);
if(newTraceAll != _traceAllFragments) {
_traceAllFragments = newTraceAll;
updateChartsAndFields(false);
}
_traceAllFragments = newTraceAll;
} catch (Exception e) {
ApplicationContext.infoMessage("Cannot change 'Trace All' mode: "+e);
}
}
public void menuItemSyncLH_actionPerformed(ActionEvent event) {
try {
int newsync = JOptionPane.showConfirmDialog(this,"Synchronize L/H Elution Regions","Sync Label Elution Regions",JOptionPane.YES_NO_CANCEL_OPTION);
if(newsync != JOptionPane.YES_OPTION && newsync != JOptionPane.NO_OPTION) return;
boolean newsyncbool = (newsync == JOptionPane.YES_OPTION);
_synclh = newsyncbool;
} catch (Exception e) {
ApplicationContext.infoMessage("Cannot change 'Synchronize L/H' mode: "+e);
}
}
public void menuItemChangeStrategy_actionPerformed(ActionEvent event){
try {
String newStrategyName =
(String) JOptionPane.showInputDialog(
this,
"Which elution curve strategy would you like to use?",
"Elution Strategy",
JOptionPane.PLAIN_MESSAGE,
null,
MRMCommandLineModule.strategies,
MRMCommandLineModule.strategies[0]
);
newStrategyName = "org.fhcrc.cpl.viewer.mrm." + newStrategyName;
if(newStrategyName != _ecurveclass.getName()) {
Class newClass = Class.forName(newStrategyName);
_ecurveclass = newClass;
initStuff();
}
} catch (Exception e) {
ApplicationContext.infoMessage("Cannot change elution curve strategy: "+e);
}
}
public void menuItemOpen_actionPerformed(ActionEvent event)
{
try {
int returnVal = _mzXMLFileChooser.showOpenDialog(this);
if(returnVal == JFileChooser.APPROVE_OPTION) {
_mzXMLFile =_mzXMLFileChooser.getSelectedFile();
initStuff();
}
} catch (Exception e)
{
ApplicationContext.infoMessage("Cannot open file '"+_mzXMLFileChooser.getName()+"': "+e);
}
}
public void menuItemLoadTSV_actionPerformed(ActionEvent event) {
boolean result;
try {
/*
_inputTSVFileChooser.setCurrentDirectory(_mzXMLFile.getParentFile());
System.err.println("restore file directory="+_inputTSVFileChooser.getCurrentDirectory());
System.err.println("derived from "+_mzXMLFile.getParent());
*/
int returnVal = _inputTSVFileChooser.showOpenDialog(this);
if(returnVal == JFileChooser.APPROVE_OPTION) {
File restoreFile = _inputTSVFileChooser.getSelectedFile();
result = ((PeaksTableModel) peaksTable.getModel()).restoreModelFromTSV(restoreFile);
if(!result)JOptionPane.showMessageDialog(this,"TSV file is not correct for this MRMer data.");
}
} catch (Exception e) {
ApplicationContext.infoMessage("Cannot restore from TSV: "+e);
e.printStackTrace();
}
}
public void menuItemTips_actionPerformed(ActionEvent event)
{
try {
HtmlViewerPanel.showURLInDialog("http://proteomics.fhcrc.org/CPL/mrm_user_tips.html","Tips for Using MRMer");
} catch (Exception e)
{
ApplicationContext.infoMessage("Cannot display TIPS help:"+e);
}
}
public void menuItemDefinitions_actionPerformed(ActionEvent event)
{
try {
HtmlViewerPanel.showURLInDialog("http://proteomics.fhcrc.org/CPL/MRMer_help.html#mrmcomopt","OPTION menu commands");
} catch (Exception e)
{
ApplicationContext.infoMessage("Cannot display Definitions help:"+e);
}
}
public void menuItemOptions_actionPerformed(ActionEvent event)
{
try {
HtmlViewerPanel.showURLInDialog("http://proteomics.fhcrc.org/CPL/MRMer_help.html#mrmmenopt","OPTION menu commands");
} catch (Exception e)
{
ApplicationContext.infoMessage("Cannot display OPTIONS help:"+e);
}
}
public void menuItemArguments_actionPerformed(ActionEvent event)
{
try {
CommandLineModule module = ViewerCommandLineModuleDiscoverer.getSingletonInstance().getCommandLineModule("MRM");
String dummyCaller = "dummy_help_caller";
File tempHelpFile = TempFileManager.createTempFile("help_mrm", dummyCaller);
PrintWriter outPW = new PrintWriter(tempHelpFile);
new ViewerUserManualGenerator().generateCommandManualEntry(module, outPW);
outPW.flush();
outPW.close();
HtmlViewerPanel.showFileInDialog(tempHelpFile,"Java command line options");
} catch (Exception e)
{
ApplicationContext.infoMessage("Cannot show ARGUMENTS help:"+e);
}
}
public void buttonSave_actionPerformed(ActionEvent event)
{
//System.err.println("save file directory="+_mzXMLFile.getAbsoluteFile().getParent());
int returnVal = _outputFileChooser.showSaveDialog(this);
if(returnVal == JFileChooser.APPROVE_OPTION) {
PeaksTableModel ptm = (PeaksTableModel) peaksTable.getModel();
if(!ptm.saveSaveModelAsTSV(_outputFileChooser.getSelectedFile()))
ApplicationContext.infoMessage("Cannot save data to '"+_outputFileChooser.getName()+"'");
} else {
ApplicationContext.infoMessage("Cannot save data to '"+_outputFileChooser.getName()+"', returnVal="+returnVal);
}
buttonPostPressTasks();
}
public void menuItemSaveImage_actionPerformed(ActionEvent event)
{
int returnVal = _imageOutputFileChooser.showSaveDialog(this);
if(returnVal == JFileChooser.APPROVE_OPTION) {
File imfi = _imageOutputFileChooser.getSelectedFile();
if(imfi != null && !imfi.toString().toUpperCase().endsWith(".PNG")){
imfi = new File(imfi.toString()+".png");
}
if (imfi == null) {
ApplicationContext.infoMessage("Cannot save chromatogram image.");
} else {
int width = daughterContainerPanel.getWidth();
int height = daughterContainerPanel.getHeight();
BufferedImage dataForFile = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = dataForFile.createGraphics();
daughterContainerPanel.paint(g2d);
g2d.dispose();
try {
ImageIO.write(dataForFile,"png",imfi);
} catch (Exception e) {
ApplicationContext.infoMessage("Cannot save chromatogram image: "+e);
buttonPostPressTasks();
}
}
} else {
ApplicationContext.infoMessage("Cannot save chromatogram image to '"+_imageOutputFileChooser.getName()+"', returnVal="+returnVal);
}
buttonPostPressTasks();
}
public void buttonZC_actionPerformed(ActionEvent event)
{
try
{
if(((PeaksTableModel)(peaksTable.getModel())).data[peaksTable.getSelectedRow()][peaksData.Daughter.colno] == null)return;
updateChartsAndFields(new zoomToCurveGraphZone());
}
catch (Exception e)
{
ApplicationContext.infoMessage("Can't zoom to current curve");
}
buttonPostPressTasks();
}
public void buttonZoom_actionPerformed(ActionEvent event) {
try
{
updateChartsAndFields(new zoomedGraphZone());
}
catch (Exception e)
{
System.err.println("Failed in ZOOM: "+e);
e.printStackTrace();
ApplicationContext.errorMessage("Can't zoom:"+e,e);
}
buttonPostPressTasks();
}
public void buttonNext_actionPerformed(ActionEvent event) {
try {
int newIndex = transitionOnPlot.getCurrentDaughter().getElutionDataTableRow() + 1;
//what if we're positioned on a precursor line?
if(((PeaksTableModel)(peaksTable.getModel())).data[peaksTable.getSelectedRow()][peaksData.Daughter.colno] == null) newIndex--;
//what if we've moved out of the current group?
if(((PeaksTableModel) peaksTable.getModel()).data[newIndex][peaksData.Daughter.colno] == null) {
newIndex++;
}
if (newIndex < ((PeaksTableModel) peaksTable.getModel()).data.length) {
scrollPeakTableToRow(newIndex);
}
//updateChartsAndFields(false);
}
catch (ArrayIndexOutOfBoundsException aioobe) {
System.gc();
}
catch (Exception e) {
ApplicationContext.infoMessage("Can't display NEXT plot");
}
buttonPostPressTasks();
}
public void buttonPrev_actionPerformed(ActionEvent event)
{
try
{
int newIndex = transitionOnPlot.getCurrentDaughter().getElutionDataTableRow()-1;
if(((PeaksTableModel)peaksTable.getModel()).data[newIndex][peaksData.Daughter.colno] == null) {
newIndex--;
}
if(newIndex > 0) {
scrollPeakTableToRow(newIndex);
} else {
System.gc();
}
//updateChartsAndFields(false);
}
catch(Exception e)
{
ApplicationContext.infoMessage("Can't display PREVIOUS plot");
}
buttonPostPressTasks();
}
public void buttonReject_actionPerformed(ActionEvent event)
{
try
{
int selectedIndex = peaksTable.getSelectedRow();
if(selectedIndex >= 0) {
if(((PeaksTableModel)(peaksTable.getModel())).data[selectedIndex][peaksData.Daughter.colno] == null) return;
((PeaksTableModel)(peaksTable.getModel())).data[selectedIndex][peaksData.Accept.colno] = new Boolean(false);
((PeaksTableModel)(peaksTable.getModel())).fireTableCellUpdated(selectedIndex,peaksData.Accept.colno);
buttonNext.doClick();
}
} catch (Exception e) {
ApplicationContext.infoMessage("Can't REJECT peak: "+e);
}
buttonPostPressTasks();
}
public void buttonRejectGroup_actionPerformed(ActionEvent event)
{
try
{
int selectedIndex = peaksTable.getSelectedRow();
if(selectedIndex >= 0) {
int maxIndex = -1;
MRMTransition curTrans =
((PeaksTableModel)(peaksTable.getModel())).data[selectedIndex][peaksData.Daughter.colno] != null
? ((MRMDaughter)((PeaksTableModel)(peaksTable.getModel())).data[selectedIndex][peaksData.Daughter.colno]).getPrecursor()
: ((MRMTransition)((PeaksTableModel)(peaksTable.getModel())).data[selectedIndex][peaksData.Precursor.colno]);
for(MRMDaughter curd: curTrans.getDaughters().values()) {
int curIndex = curd.getElutionDataTableRow();
((PeaksTableModel)(peaksTable.getModel())).data[curIndex][peaksData.Accept.colno] = new Boolean(false);
((PeaksTableModel)(peaksTable.getModel())).fireTableCellUpdated(curIndex,peaksData.Accept.colno);
if(curIndex > maxIndex) maxIndex = curIndex;
}
peaksTable.getSelectionModel().setSelectionInterval(maxIndex,maxIndex);
buttonNext.doClick();
}
} catch (Exception e) {
ApplicationContext.infoMessage("Can't REJECT group: "+e);
}
buttonPostPressTasks();
}
public void buttonAccept_actionPerformed(ActionEvent event)
{
try
{
int selectedIndex = peaksTable.getSelectedRow();
if(selectedIndex >= 0) {
if(((PeaksTableModel)(peaksTable.getModel())).data[selectedIndex][peaksData.Daughter.colno] == null) return;
((PeaksTableModel)(peaksTable.getModel())).data[selectedIndex][peaksData.Accept.colno] = new Boolean(true);
((PeaksTableModel)(peaksTable.getModel())).fireTableCellUpdated(selectedIndex,peaksData.Accept.colno);
buttonNext.doClick();
}
} catch (Exception e) {
ApplicationContext.infoMessage("Can't ACCEPT peak: "+e);
}
buttonPostPressTasks();
}
public void buttonBoost_actionPerformed(ActionEvent event)
{
try
{
int selectedIndex = peaksTable.getSelectedRow();
if(selectedIndex >= 0) {
String comVal = (String) ((PeaksTableModel)(peaksTable.getModel())).data[selectedIndex][peaksData.Comment.colno];
if(comVal.startsWith("D ")) return;
((PeaksTableModel)(peaksTable.getModel())).data[selectedIndex][peaksData.Comment.colno] = "D "+comVal;
((PeaksTableModel)(peaksTable.getModel())).fireTableCellUpdated(selectedIndex,peaksData.Comment.colno);
buttonAccept.doClick();
}
} catch (Exception e) {
ApplicationContext.infoMessage("Can't add Dwell comment to product: "+e);
}
buttonPostPressTasks();
}
public void buttonTiming_actionPerformed(ActionEvent event)
{
try
{
int selectedIndex = peaksTable.getSelectedRow();
PeaksTableModel model = (PeaksTableModel)peaksTable.getModel();
String tmp;
tmp = ((String)model.data[transitionOnPlot.getTableRow()][MRMDialog.peaksData.Comment.colno]);
if(tmp == null) tmp = "";
if(!tmp.startsWith("T ")){
tmp = "T "+tmp;
model.data[transitionOnPlot.getTableRow()][peaksData.Comment.colno] = tmp;
}
for(MRMDaughter d: transitionOnPlot.getDaughters().values()) {
tmp = ((String)model.data[d.getElutionDataTableRow()][peaksData.Comment.colno]);
if(tmp == null) tmp = "";
if(!tmp.startsWith("T ")){
tmp = "T "+tmp;
model.setValueAt(tmp,d.getElutionDataTableRow(),peaksData.Comment.colno);
}
}
tmp = ((String)model.data[transitionOnPlot.getTableRow()][MRMDialog.peaksData.Comment.colno]);
if(tmp == null) tmp = "";
if(!tmp.startsWith("T ")){
tmp = "T "+tmp;
}
model.setValueAt(tmp,transitionOnPlot.getTableRow(),peaksData.Comment.colno);
peaksTable.getSelectionModel().setSelectionInterval(selectedIndex,selectedIndex);
} catch (Exception e) {
ApplicationContext.infoMessage("Can't add TIMING comment to product: "+e);
}
buttonPostPressTasks();
}
public void buttonFindMate_actionPerformed(ActionEvent event)
{
try
{
if(transDefHeader == null || transDefHeader.getAQUApairs() == null)
throw new Exception("No transitions defined.");
MRMDaughter curMRMD = transitionOnPlot.getCurrentDaughter();
if(curMRMD == null) throw new Exception("Can't find current daughter");
TransitionDefinition curTD = transDefHeader.getDToTD().get(curMRMD);
if(curTD == null) throw new Exception("Can't find transition definition for "+curMRMD.toString());
TransitionDefinitionHeader.AQUApair curAQUA = transDefHeader.getAQUApairs().get(curTD.getAQUAcode());
if(curAQUA == null) throw new Exception("Can't find AQUA or SILAC pair");
MRMDaughter matchingDaughter = null;
if(curTD.isHigh()){
matchingDaughter = curAQUA.getLightMember().getAssociatedProduct();
} else {
if(curTD.isLow()) {
matchingDaughter = curAQUA.getHeavyMember().getAssociatedProduct();
}
}
if(matchingDaughter == null) throw new Exception("Can't find opposite labeled product");
scrollPeakTableToRow(matchingDaughter.getElutionDataTableRow());
} catch (Exception e) {
ApplicationContext.errorMessage("Can't find matching label: ",e);
}
buttonPostPressTasks();
}
public void contentPanel_componentResized(ComponentEvent event)
{
try
{
updateChartsAndFields(false);
}
catch (Exception e)
{
System.err.println("Failed to resize chart: "+e);
e.printStackTrace();
ApplicationContext.infoMessage("Cannot resize chart");
}
}
public void contentPanel_mouseClicked(MouseEvent event) {
if(event.getButton() == MouseEvent.BUTTON3) {
contentPanel.setBackground(
JColorChooser.showDialog(this,"Choose Background Color",contentPanel.getBackground())
);
}
}
// Renderers
public class coloredMRMListRenderer extends JPanel implements ListCellRenderer
{
public coloredMRMListRenderer() {
super();
}
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus)
{
this.removeAll();
this.setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(3);
nf.setMinimumFractionDigits(3);
JLabel precursor = new JLabel(((MRMTransition)value).getName()+"\u00B1"+nf.format(_precursorDiscoveryMzTolerance));
Font tmpFont = precursor.getFont();
tmpFont=tmpFont.deriveFont(tmpFont.getSize()+4.0F);
tmpFont=tmpFont.deriveFont(Font.BOLD);
precursor.setFont(tmpFont);
this.add(precursor);
for(MRMDaughter d : ((MRMTransition)value).getDaughters().values()){
JLabel dname = new JLabel(" "+d.getName());
dname.setFont(tmpFont);
Color dcolor = (Color)d.getGraphColor();
dname.setForeground(dcolor);
this.add(dname);
}
setBackground(isSelected ? Color.LIGHT_GRAY : Color.WHITE);
this.setVisible(true);
return this;
}
}
public class MRMTransitionTableRenderer extends JLabel
implements TableCellRenderer
{
Border unselectedBorder = null;
Border selectedBorder = null;
boolean isBordered = true;
public MRMTransitionTableRenderer(boolean isBordered)
{
super();
this.isBordered = isBordered;
setOpaque(true); //MUST do this for background to show up.
}
public Component getTableCellRendererComponent(
JTable table, Object transition,
boolean isSelected, boolean hasFocus,
int row, int column)
{
setText("");
this.setHorizontalAlignment(JLabel.RIGHT);
Color newColor = Color.BLACK;
setForeground(newColor);
if (isBordered) {
if (isSelected) {
if (selectedBorder == null) {
selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
table.getSelectionBackground());
}
setBorder(selectedBorder);
} else {
if (unselectedBorder == null) {
unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
table.getBackground());
}
setBorder(unselectedBorder);
}
}
if(transition != null){
this.setText(((MRMTransition)transition).getName());
Font tmpFont = this.getFont();
tmpFont = tmpFont.deriveFont(tmpFont.getSize()+4.0f);
}
super.setBackground(UIManager.getColor("Table.focusCellBackground"));
return this;
}
}
protected DrawingSupplier getDrawingSupplierForPlot(MRMTransition plot)
{
Paint colorseq[];
if(plot != null)
{
int nColors = 0;
nColors += plot.getDaughters().size();
colorseq = new Paint[nColors];
int i=0;
for(MRMDaughter d : plot.getDaughters().values()) {
if(d == plot.getCurrentDaughter())
{
colorseq[i]= Utils.paleColor((Color)plot.getCurrentDaughter().getGraphColor());
} else {
colorseq[i] = Color.LIGHT_GRAY;
}
i++;
}
} else {
colorseq = new Paint[1];
colorseq[0] = Color.WHITE;
}
return new DefaultDrawingSupplier(
colorseq,
DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE,
DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE,
DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,
DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE
);
}
public enum peaksData {
Accept,
Peptide,
Precursor,
Daughter {public String toString(){return "Product";}},
CoStart {public String toString(){return "Start";}},
CoEnd {public String toString(){return "End";}},
CoDelta {public String toString(){return "Width";}},
AUC,
MaxPeak,
MidTime,
Quality,
Label,
Code,
LHRatio,
Comment;
public static NumberFormat floatFormat = NumberFormat.getNumberInstance();
public int colno = -1;
public Class colClass = null;
public int colWidth = -1;
protected boolean visible = true;
protected int oldMinWidth = 0;
protected int oldMaxWidth = 0;
public void makeVisible(boolean viz) {
if(viz == visible) return;
if(viz) {
peaksTable.getColumnModel().getColumn(this.colno).setMinWidth(this.oldMinWidth);
peaksTable.getColumnModel().getColumn(this.colno).setMaxWidth(this.oldMaxWidth);
this.visible=true;
} else {
this.oldMinWidth = peaksTable.getColumnModel().getColumn(this.colno).getMinWidth();
this.oldMaxWidth = peaksTable.getColumnModel().getColumn(this.colno).getMaxWidth();
peaksTable.getColumnModel().getColumn(this.colno).setMinWidth(0);
peaksTable.getColumnModel().getColumn(this.colno).setMaxWidth(0);
this.visible = false;
}
peaksTable.updateUI();
}
static {
floatFormat.setMaximumFractionDigits(2);
floatFormat.setMinimumFractionDigits(2);
floatFormat.setGroupingUsed(false);
for(peaksData pd: peaksData.values()) pd.colno = pd.ordinal();
Accept.colClass = Boolean.class;
Peptide.colClass = String.class;
Precursor.colClass = MRMTransition.class;
Daughter.colClass = MRMDaughter.class;
CoStart.colClass = Number.class;
CoEnd.colClass = Number.class;
CoDelta.colClass = Number.class;
AUC.colClass = Number.class;
MaxPeak.colClass = Number.class;
MidTime.colClass = Number.class;
Quality.colClass = Number.class;
Label.colClass = String.class;
Code.colClass = Integer.class;
LHRatio.colClass = Number.class;
Comment.colClass = String.class;
Accept.colWidth = 50;
Peptide.colWidth = 75;
Precursor.colWidth = 60;
Daughter.colWidth = 50;
CoStart.colWidth = 50;
CoEnd.colWidth = 50;
CoDelta.colWidth = 50;
AUC.colWidth = 90;
MaxPeak.colWidth = 90;
MidTime.colWidth = 90;
Quality.colWidth = 50;
Label.colWidth = 50;
Code.colWidth = 35;
LHRatio.colWidth = 45;
Comment.colWidth = 150;
}
public String SaveFileFormat(Object thing) {
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setGroupingUsed(false);
if(thing == null) return "";
switch(this) {
case Accept: return ((Boolean)thing).toString();
case Peptide: return (String) thing;
case Code: return ((Integer)thing).toString();
case Precursor:
nf.setMaximumFractionDigits(3);
nf.setMinimumFractionDigits(3);
return nf.format(((MRMTransition)thing).getPrecursorMz());
case Daughter:
nf.setMaximumFractionDigits(3);
nf.setMinimumFractionDigits(3);
return nf.format(((MRMDaughter)thing).getMeanMz());
case CoStart:
nf.setMaximumFractionDigits(1);
nf.setMinimumFractionDigits(1);
return nf.format(((Number)thing).doubleValue());
case CoEnd:
nf.setMaximumFractionDigits(1);
nf.setMinimumFractionDigits(1);
return nf.format(((Number)thing).doubleValue());
case CoDelta:
nf.setMaximumFractionDigits(1);
nf.setMinimumFractionDigits(1);
return nf.format(((Number)thing).doubleValue());
case LHRatio:
case AUC:
case MaxPeak:
case MidTime:
case Quality:
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
return nf.format(((Number)thing).doubleValue());
case Label:
case Comment:
return (String) thing;
default: return "";
}
}
}
protected void scrollPeakTableToRow(int row)
{
peaksTable.getSelectionModel().setSelectionInterval(row,row);
int rowHeight = peaksTable.getHeight()/((PeaksTableModel)peaksTable.getModel()).getRowCount();
int scrollVal = (row-5)*rowHeight;
if(scrollVal < 0) scrollVal = 0;
peaksScrollPane.getVerticalScrollBar().setValue(scrollVal);
peaksTable.repaint();
}
protected void scrollPeakTableToTransition(MRMTransition trans)
{
int dataIndex = -1;
Object[][] tableData = ((PeaksTableModel)(peaksTable.getModel())).data;
for(int j = 0; j<tableData.length; j++)
{
if(trans == (MRMTransition)(tableData[j][peaksData.Precursor.colno]))
{
dataIndex = j;
break;
}
}
if(dataIndex > -1)
{
scrollPeakTableToRow(dataIndex+trans.getCurrentDaughterIndex()+1);
}
peaksTable.repaint();
}
Axis findAxisOfPanel(JPanel panel, whichAxis wa)
{
for(Component c: panel.getComponents()) {
if(c instanceof PanelWithChart) {
PanelWithChart pwc = (PanelWithChart)c;
JFreeChart jfc = pwc.getChart();
XYPlot xyp = (XYPlot)jfc.getPlot();
switch(wa)
{
case Domain: return xyp.getDomainAxis();
case Range: return xyp.getRangeAxis();
default: return null;
}
}
}
return null;
}
protected void updateDaughterCharts(boolean clear, graphZone gz)
{
XYSeriesCollection daughterDatasets = new XYSeriesCollection();
if(clear)
{
transitionOnPlot = null;
}
else
{
daughterDatasets = makeDaughterCollection();
}
//Center daughter data on graph by finding the time associated
//with the most data (a centroid or center of mass), centering
//this time on the plot, and scaling to assure the extreme
//timepoints are included
/*
double weightedAverageTime = getWeightedAverageDaughtersTime(daughterDatasets);
double extremeHalf = Math.max(weightedAverageTime-getMinRetentionTimeForPlot(transitionOnPlot),getMaxRetentionTimeForPlot(transitionsOnPlot)-weightedAverageTime);
double left = weightedAverageTime-extremeHalf;
double right = weightedAverageTime+extremeHalf;
*/
Range r = null;
if(transitionOnPlot != null) r = gz.getRange(transitionOnPlot);
if(r==null) {
r=new Range(transitionOnPlot.getMinTimeOfAllDaughters(),transitionOnPlot.getMaxTimeOfAllDaughters());
}
createChartInPanel(daughterContainerPanel, daughterDatasets,
r.getLowerBound(),r.getUpperBound(),
getDrawingSupplierForPlot(transitionOnPlot),
whichGraph.Daughter
);
}
protected void updateDaughterCharts(boolean clear)
{
updateDaughterCharts(clear,new defaultGraphZone());
}
protected void updateDaughterCharts(graphZone gz)
{
updateDaughterCharts(false,gz);
}
protected void updatePrecursorChart(boolean clear, graphZone gz)
{
XYSeriesCollection precursorDatasets = new XYSeriesCollection();
if(clear)
{
transitionOnPlot = null;
}
else
{
if(transitionOnPlot.getGraphData() == null)
//transitionOnPlot.setGraphData(makeParentSeries(transitionOnPlot));
ApplicationContext.infoMessage("Precursor data for '"+transitionOnPlot.toString()+"' wasn't initialized");
precursorDatasets.addSeries(transitionOnPlot.getGraphData());
}
//Center daughter data on graph by finding the time associated
//with the most data (a centroid or center of mass), centering
//this time on the plot, and scaling to assure the extreme
//timepoints are included
/*
double weightedAverageTime = getWeightedAverageDaughtersTime(makeDaughterCollection());
double extremeHalf = Math.max(weightedAverageTime-getMinRetentionTimeForPlot(transitionsOnPlot),getMaxRetentionTimeForPlot(transitionsOnPlot)-weightedAverageTime);
double left = weightedAverageTime-extremeHalf;
double right = weightedAverageTime+extremeHalf;
*/
Range r = null;
if(transitionOnPlot != null)r = gz.getRange(transitionOnPlot);
if(r == null) r = new Range(0,100);
createChartInPanel(precursorContainerPanel, precursorDatasets,
r.getLowerBound(),r.getUpperBound(),
null,
whichGraph.Precursor
);
}
protected void updatePrecursorChart(boolean clear) {
updatePrecursorChart(clear,new defaultGraphZone());
}
protected void updatePrecursorChart(graphZone gz) {
updatePrecursorChart(false,gz);
}
public void updateChartsAndFields(boolean clear)
{
updatePrecursorChart(clear);
updateDaughterCharts(clear);
}
public void updateChartsAndFields(graphZone gz) {
updatePrecursorChart(gz);
updateDaughterCharts(gz);
//System.gc();
}
protected double getMinRetentionTimeForPlot(MRMTransition plot)
{
if(plot == null) return 0;
double retVal = 1000000d;
for(MRMDaughter mrmd : plot.getDaughters().values()) {
//Note: scanVals are sorted so we only have to look at the first one
Double testVal = mrmd.getScanVals().values().iterator().next().getTime();
if(testVal < retVal) retVal = testVal;
}
return retVal;
}
protected double getMaxRetentionTimeForPlot(MRMTransition plot)
{
if(plot == null) return 5000d;
double retVal = 0d;
for(MRMDaughter mrmd : plot.getDaughters().values()) {
//Note: scanVals are sorted so we only have to look at the first one
ElutionDataPoint edpvals[] = mrmd.getScanVals().values().toArray(new ElutionDataPoint[0]);
Double testVal = edpvals[edpvals.length-1].getTime();
if(testVal > retVal) retVal = testVal;
}
return retVal;
}
protected XYSeries makeParentSeries(MRMTransition parent)
{
float minMz = parent.getPrecursorMz() - _precursorDiscoveryMzTolerance - _precursorChromatogramWindow;
float maxMz = parent.getPrecursorMz() + _precursorDiscoveryMzTolerance + _precursorChromatogramWindow;
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(1);
nf.setMinimumFractionDigits(1);
XYSeries result = new XYSeries(parent.getName()+"\u00B1"+nf.format( _precursorDiscoveryMzTolerance + _precursorChromatogramWindow));
//precursor scans
for (int i=parent.getMinScanOfDaughters(); i<=parent.getMaxScanOfDaughters(); i++)
{
int scanNum = _run.getIndexForScanNum(i);
if (scanNum <= 0) continue;
MSRun.MSScan ms1Scan = _run.getScan(scanNum);
boolean sim_only = _sim;
String scanType = ms1Scan.getScanType();
if(!sim_only || (sim_only && scanType.equalsIgnoreCase("SIM")))
result.add(ms1Scan.getDoubleRetentionTime(),Utils.getMaxIntensityForScan(ms1Scan, minMz, maxMz));
}
return result;
}
public boolean precursorChromatogramEmpty(MRMTransition parent){
if(parent == null) return true;
XYSeries pData;
if((pData =parent.getGraphData()) == null) return true;
for(Object xydio: pData.getItems()){
XYDataItem xydi = (XYDataItem)xydio;
if(xydi.getY().doubleValue() != 0.0) return false;
}
return true;
}
private XYSeriesCollection makeDaughterCollection() {
XYSeriesCollection retVal = new XYSeriesCollection();
for(MRMDaughter d: transitionOnPlot.getDaughters().values()){
if(d.getGraphData()== null)
d.setGraphData(d.makeDaughterSeries());
//if ((Boolean)(((PeaksTableModel)(peaksTable.getModel())).data[d.getElutionDataTableRow()][peaksData.Accept.colno]))
retVal.addSeries(d.getGraphData());
}
return retVal;
}
public class defaultGraphZone implements graphZone {
public Range getRange(MRMTransition mrmt) {
double left = 0;
double right = 0;
double elutionWidth = 0;
if(mrmt.getElutionRegionStart() != -1 && mrmt.getElutionRegionEnd() != -1) {
elutionWidth = mrmt.getElutionRegionEnd()-mrmt.getElutionRegionStart();
left = Math.max(0.0,mrmt.getElutionRegionStart()-(elutionWidth*0.1));
right = mrmt.getElutionRegionEnd() + (elutionWidth*0.1);
} else {
left = mrmt.calculateMinOfAllBestDaughterCurves();
right = mrmt.calculateMaxOfAllBestDaughterCurves();
}
if(right <= 0) {
if(mrmt.getParentData() != null && mrmt.getParentData().getItemCount()>0) {
left = mrmt.getParentData().getDataItem(0).getX().doubleValue();
right = mrmt.getParentData().getDataItem(mrmt.getParentData().getItemCount()-1).getX().doubleValue();
left = Math.max(0,left-((right-left)*0.05));
right = right + ((right-left)*0.05);
}
}
if(left>=right)return null;
return new Range(left,right);
}
}
public class zoomedGraphZone implements graphZone {
public Range getRange(MRMTransition mrmt) {
double left = getMinRetentionTimeForPlot(transitionOnPlot);
double right = getMaxRetentionTimeForPlot(transitionOnPlot);
if(left >= right)return null;
return new Range(left, right);
}
}
// zoom in on best elution curve
public class zoomToCurveGraphZone implements graphZone {
public Range getRange(MRMTransition mrmt) {
MRMDaughter mrmd = mrmt.getCurrentDaughter();
zoomedGraphZone zgd = new zoomedGraphZone();
if(mrmd == null) return zgd.getRange(mrmt);
ElutionCurve ec = mrmd.getBestElutionCurve();
if(ec == null) return zgd.getRange(mrmt);
double left = ec.getMinElutionTimeSecs();
double right = ec.getMaxElutionTimeSecs();
if(left >= right)return null;
return new Range(left, right);
}
}
protected void createChartInPanelPrecursorTasksOnly(XYPlot xyp) {
boolean shouldDisplay = false;
if(!precursorChromatogramEmpty(transitionOnPlot)) {
shouldDisplay = true;
if(!transitionOnPlot.getElutionCurves().isEmpty()) {
ElutionCurveStrategy ecs = transitionOnPlot.getElutionCurves().values().iterator().next();
List<ElutionCurve> ecl = ecs.getParentCurves();
if(ecl != null) {
for(ElutionCurve e: ecl) {
List<Line2D.Double> ll2dd = e.getSegments();
for(Line2D.Double l2dd: ll2dd) {
xyp.addAnnotation(Utils.line2Annotation(l2dd,new BasicStroke(2.0f),(ecs.isBestParentCurve(e)) ? Color.GREEN :Color.LIGHT_GRAY));
}
}
}
}
}
precursorContainerContainerPanel.setVisible(shouldDisplay);
// updateDaughterCharts(false);
if(this.getWidth() >= 100 && this.getHeight() >= 100)
this.setPreferredSize(new Dimension(this.getWidth(),this.getHeight()));
pack();
}
protected void createChartInPanelDaughterTasksOnly(XYPlot xyp) {
XYSeries coloredDataset = transitionOnPlot.getCurrentDaughter().getGraphData();
Paint daughterColor = Utils.paleColor((Color) transitionOnPlot.getCurrentDaughter().getGraphColor());
ArrayList<XYLineAnnotation> coloredDaughters = new ArrayList<XYLineAnnotation>();
//Trace calculated elution curves over data spikes
if(transitionOnPlot.getElutionCurves() != null && !transitionOnPlot.getElutionCurves().isEmpty()) {
MRMDaughter curDaughter = transitionOnPlot.getCurrentDaughter();
ElutionCurveStrategy ecs = transitionOnPlot.getElutionCurves().get(curDaughter);
//Is current daughter rejected?
Boolean accepted =
(Boolean)((PeaksTableModel)peaksTable.getModel()).data[curDaughter.getElutionDataTableRow()][peaksData.Accept.colno];
if(accepted == null || !accepted) {
xyp.setBackgroundPaint(
new Color(255,230,230)
);
}
List<ElutionCurve> ecl = ecs.getDaughterCurves();
if(ecl != null) {
for(ElutionCurve e: ecl) {
List<Line2D.Double> ll2dd = e.getSegments();
for(Line2D.Double l2dd: ll2dd) {
xyp.addAnnotation(Utils.line2Annotation(l2dd,new BasicStroke(2.0f),ecs.isBestDaughterCurve(e) ? Color.BLACK : Color.LIGHT_GRAY));
}
}
}
}
// If there is a valid "current" daughter draw the spikes in the daughter's color
// as annotations (sensu JFree)
if(coloredDataset != null) {
int nOfPoints = coloredDataset.getItemCount();
for(int i = 0; i<(nOfPoints-1); i++){
XYDataItem p1 = coloredDataset.getDataItem(i);
XYDataItem p2 = coloredDataset.getDataItem(i+1);
coloredDaughters.add(
new XYLineAnnotation(p1.getX().doubleValue(),p1.getY().doubleValue(),p2.getX().doubleValue(),p2.getY().doubleValue(),new BasicStroke(1.5f),transitionOnPlot.getCurrentDaughter().getGraphColor())
// new XYLineAnnotation(p1.getX().doubleValue(),p1.getY().doubleValue(),p2.getX().doubleValue(),p2.getY().doubleValue(),new BasicStroke(1.5f),daughterColor)
);
}
}
if(_traceAllFragments) {
for(MRMDaughter d: transitionOnPlot.getDaughters().values()) {
if(d == transitionOnPlot.getCurrentDaughter()) continue;
XYSeries curXYSeries = d.getContinDaughterData();
if(curXYSeries == null || curXYSeries.getItemCount() == 0) continue;
if(d.getBestElutionCurve() == null) continue;
int nOfPoints = curXYSeries.getItemCount();
for(int i = 0; i<(nOfPoints-1); i++){
XYDataItem p1 = curXYSeries.getDataItem(i);
XYDataItem p2 = curXYSeries.getDataItem(i+1);
coloredDaughters.add(
// new XYLineAnnotation(p1.getX().doubleValue(),p1.getY().doubleValue(),p2.getX().doubleValue(),p2.getY().doubleValue(),new BasicStroke(1f),Utils.paleColor((Color)d.getGraphColor()))
new XYLineAnnotation(p1.getX().doubleValue(),p1.getY().doubleValue(),p2.getX().doubleValue(),p2.getY().doubleValue(),new BasicStroke(1f),d.getGraphColor())
);
}
}
}
if(coloredDaughters != null){
for(XYLineAnnotation xyla: coloredDaughters) {
xyp.addAnnotation(xyla);
}
}
coloredDaughters.clear();
//Display L or H label in upper left hand corner
Range xRange = xyp.getDomainAxis().getRange();
Range yRange = xyp.getRangeAxis().getRange();
XYTextAnnotation lab =
new XYTextAnnotation(
(String)((PeaksTableModel)peaksTable.getModel()).data[transitionOnPlot.getCurrentDaughter().getElutionDataTableRow()][peaksData.Label.colno],
xRange.getUpperBound()-(0.05*xRange.getLength()),
yRange.getUpperBound()-(0.05*yRange.getLength())
);
lab.setFont(lab.getFont().deriveFont(Font.BOLD,40.0F));
xyp.addAnnotation(lab);
XYTextAnnotation midMarker =
new XYTextAnnotation(
"\u25BC",
((MRMTransition) transitionOnPlot).getCalcXatMaxYAllDaughters(),
((MRMTransition) transitionOnPlot).getCalcMaxYAllDaughters()
);
midMarker.setPaint(Color.RED);
midMarker.setFont(midMarker.getFont().deriveFont(Font.BOLD,20F));
XYTextAnnotation midMarkerOutline =
new XYTextAnnotation(
"\u25BC",
((MRMTransition) transitionOnPlot).getCalcXatMaxYAllDaughters(),
((MRMTransition) transitionOnPlot).getCalcMaxYAllDaughters()
);
midMarkerOutline.setPaint(Color.BLACK);
midMarkerOutline.setFont(midMarker.getFont().deriveFont(Font.BOLD,23F));
xyp.addAnnotation(midMarkerOutline);
xyp.addAnnotation(midMarker);
}
public XYPlot oldPrecursorChart = null;
public XYPlot oldProductChart = null;
protected void clearPreviousChartJunk(XYPlot xyp) {
if(xyp != null) {
xyp.clearAnnotations();
xyp.clearDomainAxes();
xyp.clearRangeAxes();
xyp.setDataset(null);
}
}
/**
* Draw a chart in a panel. Good for precursors and daughters
* @param parentPanel
* @param dataset
* @param domainMin
* @param domainMax
* @param supplier
* @param wg
*/
protected void createChartInPanel(JPanel parentPanel,
XYSeriesCollection dataset,
Double domainMin, Double domainMax,
DrawingSupplier supplier,
whichGraph wg
)
{
if(precursorChromatogramEmpty(transitionOnPlot) && wg == whichGraph.Precursor){
precursorContainerContainerPanel.setVisible(false);
if(this.getWidth() >= 100 && this.getHeight() >= 100)
this.setPreferredSize(new Dimension(this.getWidth(),this.getHeight()));
pack();
return;
}
switch(wg) {
case Precursor:
clearPreviousChartJunk(oldPrecursorChart);
oldPrecursorChart = null;
break;
case Daughter:
clearPreviousChartJunk(oldProductChart);
oldProductChart = null;
break;
}
JFreeChart chart =
ChartFactory.createXYLineChart(null,"seconds", null, dataset,
PlotOrientation.VERTICAL, true, false, false);
chart.setBackgroundPaint(new Color(220,220,220));
XYPlot xyp = (XYPlot)(chart.getPlot());
xyp.setBackgroundPaint(Color.WHITE);
xyp.setDomainGridlinesVisible(true);
xyp.setRangeGridlinesVisible(true);
xyp.setDomainGridlinePaint(Color.LIGHT_GRAY);
xyp.setRangeGridlinePaint(Color.LIGHT_GRAY);
if(supplier != null)
{
xyp.setDrawingSupplier(supplier);
} else {
xyp.setDrawingSupplier(Utils.plainDrawingSupplier(Color.LIGHT_GRAY));
}
xyp.setSeriesRenderingOrder(SeriesRenderingOrder.REVERSE);
CenterZoomNumberAxis axisDomain = new CenterZoomNumberAxis("seconds");
axisDomain.setAutoRangeIncludesZero(false);
axisDomain.setRange(Math.max(0.0,domainMin), domainMax);
axisDomain.addChangeListener(new domainAxisZoomCoordinator(axisDomain));
xyp.clearAnnotations();
xyp.setDomainAxis(axisDomain);
xyp.getDomainAxis().setAutoRange(false);
xyp.getRangeAxis().setAutoRange(false);
XYLineAndShapeRenderer xylsr = (XYLineAndShapeRenderer) xyp.getRenderer();
xylsr.setLegendLine(Utils.legendThing(16,6));
xylsr.setShapesFilled(true);
xylsr.setBaseShapesFilled(true);
PanelWithChart panelWithChart = new PanelWithChart(chart);
ChartPanel cp = panelWithChart.getChartPanel();
cp.removeMouseListener(cp);
cp.removeMouseMotionListener(cp);
if(peaksTable != null) {
MRMerMouseListener mml = new MRMerMouseListener(cp,(PeaksTableModel)peaksTable.getModel());
cp.addMouseListener(mml);
cp.addMouseMotionListener(mml);
}
cp.setPreferredSize(
new Dimension(parentPanel.getWidth(), parentPanel.getHeight() - 10));
cp.setDomainZoomable(true);
cp.setRangeZoomable(false);
cp.setPopupMenu(null);
parentPanel.removeAll();
parentPanel.add(panelWithChart);
switch(wg) {
case Precursor:
createChartInPanelPrecursorTasksOnly(xyp);
oldPrecursorChart = xyp;
break;
case Daughter:
createChartInPanelDaughterTasksOnly(xyp);
oldProductChart = xyp;
break;
}
parentPanel.updateUI();
listTransition.requestFocus();
}
private int indexOfMaxY(XYSeries s)
{
double _maxy = -10000000000.0;
int retVal = -1;
for(int i = 0; i<s.getItemCount(); i++) {
XYDataItem xydi = s.getDataItem(i);
if(_maxy < xydi.getY().doubleValue()) {
_maxy = xydi.getY().doubleValue();
retVal = i;
}
}
return retVal;
}
private static NumberFormat _transitionNumberFormat =
NumberFormat.getNumberInstance();
static {
_transitionNumberFormat.setMaximumFractionDigits(4);
_transitionNumberFormat.setMinimumFractionDigits(4);
}
public interface mzXML2TransitionArray {
public MRMTransition[] reParse(MSRun run);
}
public static boolean isMRM(MSRun.MSScan scan){
return (scan != null) && scan.getScanType() != null &&
(scan.getScanType().equalsIgnoreCase("MRM") ||
scan.getScanType().equalsIgnoreCase("SRM") ||
scan.getScanType().equalsIgnoreCase("MultipleReaction"))
;
}
protected class originalReParser implements mzXML2TransitionArray {
public MRMTransition[] reParse(MSRun run) {
Vector<MRMTransition> transitions = new Vector<MRMTransition>();
Map<Float, MRMDaughter> meanDaughterTransitionMap = new HashMap<Float, MRMDaughter>();
for (MSRun.MSScan ms2Scan : run.getMS2Scans())
{
if (isMRM(ms2Scan))
{
// See if a parent MRMTransition within the mz tolerance exists
// If not. Create one.
float testPrecursor = ms2Scan.getPrecursorMz();
MRMTransition curTrans = null;
for(MRMTransition testTrans: transitions) {
if(testTrans.getPrecursorMz() >= (testPrecursor-_precursorDiscoveryMzTolerance) &&
testTrans.getPrecursorMz() <= (testPrecursor+_precursorDiscoveryMzTolerance)) {
curTrans = testTrans;
break;
}
}
if(curTrans == null) {
curTrans = new MRMTransition(testPrecursor,run);
curTrans.setName(_transitionNumberFormat.format(curTrans.getPrecursorMz()));
transitions.add(curTrans);
}
// See if a daughter mean mz exists yet for that parent
// If not. Create one. Attach it to parent.
float meanDaughter = (ms2Scan.getLowMz() + ms2Scan.getHighMz()) / 2;
MRMDaughter curDaughter = null;
for(MRMDaughter testDaughter: curTrans.getDaughters().values()) {
if(meanDaughter >= (testDaughter.getMeanMz() - _daughterMzTolerance) &&
meanDaughter <= (testDaughter.getMeanMz() + _daughterMzTolerance)
) {
curDaughter = testDaughter;
break;
}
}
if(curDaughter == null)
{
curDaughter = new MRMDaughter(
meanDaughter,
ms2Scan.getLowMz(),
ms2Scan.getHighMz(),
ms2Scan.getNum(),
ms2Scan.getNum(),
curTrans
);
curDaughter.setGraphColor(MRMTransition.COLOR_SERIES[curTrans.getDaughters().size() % (MRMTransition.COLOR_SERIES.length)]);
curDaughter.setName(_transitionNumberFormat.format(curDaughter.getPrecursor().getPrecursorMz())+"/"+_transitionNumberFormat.format(curDaughter.getMeanMz()));
meanDaughterTransitionMap.put(curDaughter.getMeanMz(),curDaughter);
curTrans.getDaughters().put(curDaughter.getMeanMz(),curDaughter);
//make sure this line doesn't duplicate initial scan number
curDaughter.addScanVal(ms2Scan.getNum(),new ElutionDataPoint(ms2Scan.getDoubleRetentionTime(),Utils.getMaxIntensityForScan(ms2Scan, curDaughter.getLowMz(), curDaughter.getHighMz())));
//allDaughters.add(new ReactionClusterable(curTrans.getPrecursorMz(),curDaughter.getMeanMz()));
} else {
// Add current scan to daughter.
curDaughter.addScanVal(ms2Scan.getNum(),new ElutionDataPoint(ms2Scan.getDoubleRetentionTime(),Utils.getMaxIntensityForScan(ms2Scan, curDaughter.getLowMz(), curDaughter.getHighMz())));
//allDaughters.add(new ReactionClusterable(curTrans.getPrecursorMz(),curDaughter.getMeanMz()));
}
}
}
ArrayList<MRMDaughter> mrmTransitionLists = new ArrayList<MRMDaughter>();
for (MRMDaughter daughter : meanDaughterTransitionMap.values())
{
mrmTransitionLists.add(daughter);
}
MRMTransition[] result = transitions.toArray(new MRMTransition[0]);
Arrays.sort(result, new MRMTransition.PrecursorMzComparator());
return result;
}
}
protected class thermoReParser implements mzXML2TransitionArray {
protected Range[] parseFilterLine(String fline)
{
String rangeStrings[] = fline.split("\\[")[1].split(",");
rangeStrings[rangeStrings.length-1] = rangeStrings[rangeStrings.length-1].replace("]","");
Range retVal[] = new Range[rangeStrings.length];
for(int i = 0; i<rangeStrings.length; i++) {
String ends[] = rangeStrings[i].split("-");
retVal[i] = new Range(Double.parseDouble(ends[0]),Double.parseDouble(ends[1]));
}
return retVal;
}
public MRMTransition[] reParse(MSRun run) {
// New (Post Jan '08) thermo files have "filterLine" attributes
// on the <run> element. These define transitions. There will
// be one "peak" in the <peaks> element for each daughter.
// Considerations: each daughter must (should) be assigned a
// distinct time. So the entire ms2/MRM scan should be divided
// into n retention time segments for n daughters. This means
// we have to know the value of the NEXT scan retention time
// in order to get some estimate for the length of the ms2
// scan. It also means we'll keep around average times so that
// we can process the last scan.
//for final mean scan time
double sumRetentionTimeDeltas = 0.0d;
int countMRMScans = 0;
//places to keep precursors and products
Vector<MRMTransition> transitions = new Vector<MRMTransition>();
Map<Float, MRMDaughter> meanProductTransitionMap = new HashMap<Float, MRMDaughter>();
for (MSRun.MSScan ms2Scan : run.getMS2Scans())
{
if (isMRM(ms2Scan))
{
try{
if(ms2Scan.getFilterLine() == null) {
throw new Exception("No filter line in Thermo MRM scan '"+ms2Scan.toString()+"'");
}
float testPrecursor = ms2Scan.getPrecursorMz();
MRMTransition curTrans = null;
// Have we seen a transition with this precursor value yet?
for(MRMTransition testTrans: transitions) {
if(testTrans.getPrecursorMz() >= (testPrecursor-_precursorDiscoveryMzTolerance) &&
testTrans.getPrecursorMz() <= (testPrecursor+_precursorDiscoveryMzTolerance)) {
curTrans = testTrans;
break;
}
}
if(curTrans == null) {
curTrans = new MRMTransition(testPrecursor,run);
curTrans.setName(_transitionNumberFormat.format(curTrans.getPrecursorMz()));
transitions.add(curTrans);
}
//Determine length of scan
double scanLen = 0d;
MSRun.MSScan nextScan = _run.getScanByNum(ms2Scan.getNum()+1);
if(nextScan != null) {
scanLen = nextScan.getDoubleRetentionTime()-ms2Scan.getDoubleRetentionTime();
sumRetentionTimeDeltas += scanLen;
countMRMScans++;
} else {
scanLen = sumRetentionTimeDeltas/countMRMScans; //mean daughter scan time
}
//Create a daughter (if necessary) or just a daughter datapoint
//Assume there are as many points in the "spectrum" as there are
//daughters. Assume they come in the same order as they are described
//in the filterLine. We can change the assumptions and complicate the
//code if necessary.
Range productRanges[] = parseFilterLine(ms2Scan.getFilterLine());
Vector<MRMDaughter> productRangeDaughters = new Vector<MRMDaughter>();
for(int i = 0; i<productRanges.length; i++){
Range daughterCenter = productRanges[i];
float meanDaughter = (float)daughterCenter.getCentralValue();
MRMDaughter curDaughter = null;
for(MRMDaughter testDaughter: curTrans.getDaughters().values()) {
if(
meanDaughter >= (testDaughter.getMeanMz() - _daughterMzTolerance) &&
meanDaughter <= (testDaughter.getMeanMz() + _daughterMzTolerance)
) {
curDaughter = testDaughter;
break;
}
}
if(curDaughter == null){
curDaughter =
new MRMDaughter(
meanDaughter,
(float)daughterCenter.getLowerBound(),
(float)daughterCenter.getUpperBound(),
ms2Scan.getNum(),
ms2Scan.getNum(),
curTrans
);
curDaughter.setGraphColor(MRMTransition.COLOR_SERIES[curTrans.getDaughters().size() % (MRMTransition.COLOR_SERIES.length)]);
curDaughter.setName(_transitionNumberFormat.format(curDaughter.getPrecursor().getPrecursorMz())+"/"+_transitionNumberFormat.format(curDaughter.getMeanMz()));
meanProductTransitionMap.put(curDaughter.getMeanMz(),curDaughter);
curTrans.getDaughters().put(curDaughter.getMeanMz(),curDaughter);
}
productRangeDaughters.add(curDaughter);
}
//Now we know a daughter defined by the filterLine is associated with
//with the precursor. We have to find which spectrum datapoint goes
//with which daughter.
int dcount = -1;
for(MRMDaughter mrmd: productRangeDaughters) {
dcount++;
int spectrumPointCount = 0;
double curMZ = -1d;
double curIntensity = -1d;
for(int j = 0; j<ms2Scan.getSpectrum()[0].length; j++) {
if((ms2Scan.getSpectrum()[0][j] >= (mrmd.getMeanMz()-_daughterMzTolerance)) && (ms2Scan.getSpectrum()[0][j] <= (mrmd.getMeanMz()+_daughterMzTolerance))) {
curMZ = ms2Scan.getSpectrum()[0][j];
curIntensity = ms2Scan.getSpectrum()[1][j];
spectrumPointCount++;
}
}
if(spectrumPointCount == 1) {
mrmd.addScanVal(
ms2Scan.getNum(),
new ElutionDataPoint(
ms2Scan.getDoubleRetentionTime()+((scanLen/productRanges.length)*dcount),
curIntensity
)
);
} else {
if(spectrumPointCount > 1) {
ApplicationContext.infoMessage("More than one spectrum point can belong to same daughter in same scan");
} else {
if(spectrumPointCount == 0) {
mrmd.addScanVal(
ms2Scan.getNum(),
new ElutionDataPoint(
ms2Scan.getDoubleRetentionTime()+((scanLen/productRanges.length)*dcount),
0d
)
);
ApplicationContext.infoMessage("No datapoint found matching daughter "+mrmd+" for scan "+ms2Scan.getNum());
}
}
}
}
} catch (Exception e) {
ApplicationContext.infoMessage("Can't parse scan "+ms2Scan.getNum()+" in thermo reparser: "+e);
}
}
}
ArrayList<MRMDaughter> mrmTransitionLists = new ArrayList<MRMDaughter>();
for (MRMDaughter daughter : meanProductTransitionMap.values())
{
mrmTransitionLists.add(daughter);
}
MRMTransition[] result = transitions.toArray(new MRMTransition[0]);
Arrays.sort(result, new MRMTransition.PrecursorMzComparator());
return result;
}
}
protected class agilentReParser implements mzXML2TransitionArray {
public MRMTransition[] reParse(MSRun run) {
// New (Post Sept '09) agilent files translated by TRAPPER.
// These files are similar to thermo files in that they store
// all the MRM products in one scan. But they do not have
// thermo's FilterLine data to suggest M/Z of the products.
// So the daughter M/Zs must be deduced from the scan. Also
// as in the thermo reparser, each product lacks its own
// distinct time. So the entire ms2/MRM scan must be divided
// into n retention time segments for n daughters. This means
// we have to know the value of the NEXT scan retention time
// in order to get some estimate for the length of the ms2
// scan. It also means we'll keep around average times so that
// we can fill in something reasonable for the last scan.
//for final mean scan time
double sumRetentionTimeDeltas = 0.0d;
int countMRMScans = 0;
//places to keep precursors and products
Vector<MRMTransition> transitions = new Vector<MRMTransition>();
Map<Float, MRMDaughter> meanProductTransitionMap = new HashMap<Float, MRMDaughter>();
for (MSRun.MSScan ms2Scan : run.getMS2Scans())
{
if (isMRM(ms2Scan))
{
try{
float testPrecursor = ms2Scan.getPrecursorMz();
MRMTransition curTrans = null;
// Have we seen a transition with this precursor value yet?
for(MRMTransition testTrans: transitions) {
if(testTrans.getPrecursorMz() >= (testPrecursor-_precursorDiscoveryMzTolerance) &&
testTrans.getPrecursorMz() <= (testPrecursor+_precursorDiscoveryMzTolerance)) {
curTrans = testTrans;
break;
}
}
if(curTrans == null) {
curTrans = new MRMTransition(testPrecursor,run);
curTrans.setName(_transitionNumberFormat.format(curTrans.getPrecursorMz()));
transitions.add(curTrans);
}
//Determine time-span of scan
double scanLen = 0d;
MSRun.MSScan nextScan = _run.getScanByNum(ms2Scan.getNum()+1);
if(nextScan != null) {
scanLen = nextScan.getDoubleRetentionTime()-ms2Scan.getDoubleRetentionTime();
sumRetentionTimeDeltas += scanLen;
countMRMScans++;
} else {
scanLen = sumRetentionTimeDeltas/countMRMScans; //mean daughter scan time
}
//Create a daughter (if necessary) or just a daughter datapoint
Vector<MRMDaughter> productRangeDaughters = new Vector<MRMDaughter>();
for(int i = 0; i<ms2Scan.getPeaksCount(); i++){
float meanDaughter = ms2Scan.getSpectrum()[0][i];
MRMDaughter curDaughter = null;
for(MRMDaughter testDaughter: curTrans.getDaughters().values()) {
if(
meanDaughter >= (testDaughter.getMeanMz() - _daughterMzTolerance) &&
meanDaughter <= (testDaughter.getMeanMz() + _daughterMzTolerance)
) {
curDaughter = testDaughter;
break;
}
}
if(curDaughter == null){
curDaughter =
new MRMDaughter(
meanDaughter,
ms2Scan.getSpectrum()[0][i]-_daughterMzTolerance,
ms2Scan.getSpectrum()[0][i]+_daughterMzTolerance,
ms2Scan.getNum(),
ms2Scan.getNum(),
curTrans
);
curDaughter.setGraphColor(MRMTransition.COLOR_SERIES[curTrans.getDaughters().size() % (MRMTransition.COLOR_SERIES.length)]);
curDaughter.setName(_transitionNumberFormat.format(curDaughter.getPrecursor().getPrecursorMz())+"/"+_transitionNumberFormat.format(curDaughter.getMeanMz()));
meanProductTransitionMap.put(curDaughter.getMeanMz(),curDaughter);
curTrans.getDaughters().put(curDaughter.getMeanMz(),curDaughter);
}
productRangeDaughters.add(curDaughter);
}
//Now we know a daughter is associated with
//with the precursor. We have to find which spectrum datapoint goes
//with which daughter.
int dcount = -1;
for(MRMDaughter mrmd: productRangeDaughters) {
dcount++;
int spectrumPointCount = 0;
double curMZ = -1d;
double curIntensity = -1d;
for(int j = 0; j<ms2Scan.getSpectrum()[0].length; j++) {
if((ms2Scan.getSpectrum()[0][j] >= (mrmd.getMeanMz()-_daughterMzTolerance)) && (ms2Scan.getSpectrum()[0][j] <= (mrmd.getMeanMz()+_daughterMzTolerance))) {
curMZ = ms2Scan.getSpectrum()[0][j];
curIntensity = ms2Scan.getSpectrum()[1][j];
spectrumPointCount++;
}
}
if(spectrumPointCount == 1) {
mrmd.addScanVal(
ms2Scan.getNum(),
new ElutionDataPoint(
ms2Scan.getDoubleRetentionTime()+((scanLen/ms2Scan.getSpectrum()[0].length)*dcount),
curIntensity
)
);
} else {
if(spectrumPointCount > 1) {
ApplicationContext.infoMessage("More than one spectrum point can belong to same daughter in same scan");
} else {
if(spectrumPointCount == 0) {
mrmd.addScanVal(
ms2Scan.getNum(),
new ElutionDataPoint(
ms2Scan.getDoubleRetentionTime()+((scanLen/ms2Scan.getSpectrum()[0].length)*dcount),
0d
)
);
ApplicationContext.infoMessage("No datapoint found matching daughter "+mrmd+" for scan "+ms2Scan.getNum());
}
}
}
}
} catch (Exception e) {
ApplicationContext.infoMessage("Can't parse scan "+ms2Scan.getNum()+" in thermo reparser: "+e);
}
}
}
ArrayList<MRMDaughter> mrmTransitionLists = new ArrayList<MRMDaughter>();
for (MRMDaughter daughter : meanProductTransitionMap.values())
{
mrmTransitionLists.add(daughter);
}
MRMTransition[] result = transitions.toArray(new MRMTransition[0]);
Arrays.sort(result, new MRMTransition.PrecursorMzComparator());
return result;
}
}
/**
/**
* Detect all the transitions and load into an array
* @param run
* @return
*
* There is a lot of legacy code here to be cleaned up later
*
*/
private MRMTransition[] loadMRMTransitions(MSRun run)
{
for (MSRun.MSScan ms2Scan : run.getMS2Scans())
{
if (isMRM(ms2Scan))
{
if(ms2Scan.getFilterLine() != null && ms2Scan.getFilterLine().length() > 0) {
return(new thermoReParser()).reParse(run);
} else
if(ms2Scan.getScanType().equalsIgnoreCase("MultipleReaction")) {
return(new agilentReParser()).reParse(run);
} else
return (new originalReParser()).reParse(run);
}
break;
}
return(new originalReParser()).reParse(run);
}
}