package eu.isas.peptideshaker.gui;
import com.compomics.util.experiment.biology.*;
import com.compomics.util.experiment.biology.ions.PeptideFragmentIon;
import com.compomics.util.experiment.identification.matches.ModificationMatch;
import com.compomics.util.experiment.identification.matches.SpectrumMatch;
import com.compomics.util.experiment.identification.ptm.PtmtableContent;
import com.compomics.util.experiment.massspectrometry.MSnSpectrum;
import com.compomics.util.experiment.massspectrometry.SpectrumFactory;
import com.compomics.util.gui.spectrum.SpectrumPanel;
import com.compomics.util.preferences.AnnotationPreferences;
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Vector;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import no.uib.jsparklines.data.JSparklinesDataSeries;
import no.uib.jsparklines.data.JSparklinesDataset;
import no.uib.jsparklines.extra.CellHighlighterRenderer;
import no.uib.jsparklines.renderers.JSparklinesBarChartTableCellRenderer;
import no.uib.jsparklines.renderers.JSparklinesTableCellRenderer;
import org.jfree.chart.plot.PlotOrientation;
/**
* Table containing information about the peak annotation of a modified peptide.
* Heavily based on the Fragment ion table.
*
* @author Marc Vaudel
* @author Harald Barsnes
*/
public class PtmTable extends JTable {
/**
* Instance of the main GUI class
*/
private PeptideShakerGUI peptideShakerGUI;
/**
* The table tooltips.
*/
private ArrayList<String> tooltips = new ArrayList<String>();
/**
* The peptide to display.
*/
private Peptide peptide;
/**
* The PTM to analyze.
*/
private PTM ptm;
/**
* Number of PTMs.
*/
private int nPTM;
/**
* The spectrum keys.
*/
private ArrayList<String> spectrumKeys;
/**
* If true, area charts are used, false results in bar charts.
*/
private boolean areaChart = false;
/**
* The max value for the area charts.
*/
private double maxAreaChartValue = 0;
/**
* A list of the modification site indexes.
*/
private ArrayList<Integer> modificationSites;
/**
* Constructor.
*
* @param peptideShakerGUI PeptideShakerGUI parent
* @param peptide the peptide
* @param ptm the ptm
* @param spectrumKeys the spectrum keys
* @param areaChart if true an area chart version will be used, false
* displays bar charts
*/
public PtmTable(PeptideShakerGUI peptideShakerGUI, Peptide peptide, PTM ptm, ArrayList<String> spectrumKeys, boolean areaChart) {
this.peptideShakerGUI = peptideShakerGUI;
this.peptide = peptide;
this.ptm = ptm;
this.nPTM = 0;
this.spectrumKeys = spectrumKeys;
this.areaChart = areaChart;
modificationSites = new ArrayList<Integer>();
for (ModificationMatch modMatch : peptide.getModificationMatches()) {
if (modMatch.getTheoreticPtm().equals(ptm.getName())) {
modificationSites.add(modMatch.getModificationSite());
nPTM++;
}
}
setUpTable();
// add the peptide sequence and indexes to the table
addPeptideSequence();
// add the values to the table
if (areaChart) {
insertAreaCharts();
} else {
insertBarCharts();
}
}
protected JTableHeader createDefaultTableHeader() {
return new JTableHeader(columnModel) {
public String getToolTipText(MouseEvent e) {
java.awt.Point p = e.getPoint();
int index = columnModel.getColumnIndexAtX(p.x);
int realIndex = columnModel.getColumn(index).getModelIndex();
return (String) tooltips.get(realIndex);
}
};
}
/**
* Set up the table.
*/
private void setUpTable() {
// disallow column reordering
getTableHeader().setReorderingAllowed(false);
// control the cell selection
setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
// centrally align the column headers
TableCellRenderer renderer = getTableHeader().getDefaultRenderer();
JLabel label = (JLabel) renderer;
label.setHorizontalAlignment(JLabel.CENTER);
// set up the column headers, types and tooltips
Vector columnHeaders = new Vector();
ArrayList<Class> tempColumnTypes = new ArrayList<Class>();
tooltips = new ArrayList<String>();
// the index column
columnHeaders.add(" ");
tempColumnTypes.add(java.lang.Integer.class);
tooltips.add("a, b and c ion index");
AnnotationPreferences annotationPreferences = peptideShakerGUI.getAnnotationPreferences();
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.A_ION)) {
columnHeaders.add("a");
if (areaChart) {
tempColumnTypes.add(JSparklinesDataset.class);
} else {
tempColumnTypes.add(Double.class);
}
tooltips.add("a-ion");
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.B_ION)) {
columnHeaders.add("b");
if (areaChart) {
tempColumnTypes.add(JSparklinesDataset.class);
} else {
tempColumnTypes.add(Double.class);
}
tooltips.add("b-ion");
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.C_ION)) {
columnHeaders.add("c");
if (areaChart) {
tempColumnTypes.add(JSparklinesDataset.class);
} else {
tempColumnTypes.add(Double.class);
}
tooltips.add("c-ion");
}
columnHeaders.add("AA");
tempColumnTypes.add(java.lang.String.class);
tooltips.add("amino acid sequence");
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.X_ION)) {
columnHeaders.add("x");
if (areaChart) {
tempColumnTypes.add(JSparklinesDataset.class);
} else {
tempColumnTypes.add(Double.class);
}
tooltips.add("x-ion");
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.Y_ION)) {
columnHeaders.add("y");
if (areaChart) {
tempColumnTypes.add(JSparklinesDataset.class);
} else {
tempColumnTypes.add(Double.class);
}
tooltips.add("y-ion");
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.Z_ION)) {
columnHeaders.add("z");
if (areaChart) {
tempColumnTypes.add(JSparklinesDataset.class);
} else {
tempColumnTypes.add(Double.class);
}
tooltips.add("z-ion");
}
// the second index column
columnHeaders.add(" ");
tempColumnTypes.add(java.lang.Integer.class);
tooltips.add("x, y and z ion index");
final ArrayList<Class> columnTypes = tempColumnTypes;
// set the table model
setModel(new javax.swing.table.DefaultTableModel(
new Vector(),
columnHeaders) {
public Class getColumnClass(int columnIndex) {
return columnTypes.get(columnIndex);
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
});
// set the max column widths
int tempWidth = 30; // @TODO: maybe this should not be hardcoded?
getColumn(" ").setMaxWidth(tempWidth);
getColumn(" ").setMinWidth(tempWidth);
getColumn(" ").setMaxWidth(tempWidth);
getColumn(" ").setMinWidth(tempWidth);
getColumn("AA").setMaxWidth(tempWidth);
getColumn("AA").setMinWidth(tempWidth);
// centrally align the columns in the fragment ions table
getColumn(" ").setCellRenderer(new CellHighlighterRenderer(Color.LIGHT_GRAY, Color.YELLOW, SwingConstants.CENTER, "*"));
getColumn(" ").setCellRenderer(new CellHighlighterRenderer(Color.LIGHT_GRAY, Color.YELLOW, SwingConstants.CENTER, "*"));
getColumn("AA").setCellRenderer(new CellHighlighterRenderer(Color.LIGHT_GRAY, Color.YELLOW, SwingConstants.CENTER, "*"));
}
/**
* Add the peptide and sequence indexes to the table.
*/
private void addPeptideSequence() {
String peptideSequence = peptide.getSequence();
// add the peptide sequence and indexes to the table
for (int i = 0; i < peptideSequence.length(); i++) {
((DefaultTableModel) getModel()).addRow(new Object[]{(i + 1)});
}
// insert the sequence
for (int i = 0; i < peptideSequence.length(); i++) {
if (modificationSites.contains(i + 1)) {
setValueAt(peptideSequence.charAt(i) + "*", i, getColumn("AA").getModelIndex());
} else {
setValueAt(peptideSequence.charAt(i), i, getColumn("AA").getModelIndex());
}
setValueAt(peptideSequence.length() - i, i, getColumn(" ").getModelIndex());
}
}
/**
* Insert area charts into the table.
*/
private void insertAreaCharts() {
AnnotationPreferences annotationPreferences = peptideShakerGUI.getAnnotationPreferences();
PtmtableContent tempContent, tableContent = new PtmtableContent();
SpectrumFactory spectrumFactory = SpectrumFactory.getInstance();
for (String spectrumKey : spectrumKeys) {
try {
MSnSpectrum spectrum = (MSnSpectrum) spectrumFactory.getSpectrum(spectrumKey);
SpectrumMatch spectrumMatch = peptideShakerGUI.getIdentification().getSpectrumMatch(spectrumKey);
tempContent = PtmtableContent.getPTMTableContent(peptide, ptm, nPTM, spectrum, annotationPreferences.getIonTypes(),
annotationPreferences.getNeutralLosses(), annotationPreferences.getValidatedCharges(),
spectrumMatch.getBestPeptideAssumption().getIdentificationCharge().value,
annotationPreferences.getFragmentIonAccuracy(), spectrum.getIntensityLimit(annotationPreferences.getAnnotationIntensityLimit()));
tempContent.normalize();
tableContent.addAll(tempContent);
} catch (Exception e) {
peptideShakerGUI.catchException(e);
}
}
maxAreaChartValue = 0;
for (int aa = 0; aa < peptide.getSequence().length(); aa++) {
int column = 1;
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.A_ION)) {
addAreaChart(tableContent, PeptideFragmentIon.A_ION, aa + 1, column);
column++;
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.B_ION)) {
addAreaChart(tableContent, PeptideFragmentIon.B_ION, aa + 1, column);
column++;
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.C_ION)) {
addAreaChart(tableContent, PeptideFragmentIon.C_ION, aa + 1, column);
column++;
}
column++;
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.X_ION)) {
addAreaChart(tableContent, PeptideFragmentIon.X_ION, peptide.getSequence().length() - aa, column);
column++;
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.Y_ION)) {
addAreaChart(tableContent, PeptideFragmentIon.Y_ION, peptide.getSequence().length() - aa, column);
column++;
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.Z_ION)) {
addAreaChart(tableContent, PeptideFragmentIon.Z_ION, peptide.getSequence().length() - aa, column);
column++;
}
}
// set the column renderers
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.A_ION)) {
try {
getColumn("a").setCellRenderer(new JSparklinesTableCellRenderer(JSparklinesTableCellRenderer.PlotType.lineChart, PlotOrientation.VERTICAL, maxAreaChartValue));
} catch (IllegalArgumentException e) {
// do nothing
}
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.B_ION)) {
try {
getColumn("b").setCellRenderer(new JSparklinesTableCellRenderer(JSparklinesTableCellRenderer.PlotType.lineChart, PlotOrientation.VERTICAL, maxAreaChartValue));
} catch (IllegalArgumentException e) {
// do nothing
}
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.C_ION)) {
try {
getColumn("c").setCellRenderer(new JSparklinesTableCellRenderer(JSparklinesTableCellRenderer.PlotType.lineChart, PlotOrientation.VERTICAL, maxAreaChartValue));
} catch (IllegalArgumentException e) {
// do nothing
}
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.X_ION)) {
try {
getColumn("x").setCellRenderer(new JSparklinesTableCellRenderer(JSparklinesTableCellRenderer.PlotType.lineChart, PlotOrientation.VERTICAL, maxAreaChartValue));
} catch (IllegalArgumentException e) {
// do nothing
}
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.Y_ION)) {
try {
getColumn("y").setCellRenderer(new JSparklinesTableCellRenderer(JSparklinesTableCellRenderer.PlotType.lineChart, PlotOrientation.VERTICAL, maxAreaChartValue));
} catch (IllegalArgumentException e) {
// do nothing
}
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.Z_ION)) {
try {
getColumn("z").setCellRenderer(new JSparklinesTableCellRenderer(JSparklinesTableCellRenderer.PlotType.lineChart, PlotOrientation.VERTICAL, maxAreaChartValue));
} catch (IllegalArgumentException e) {
// do nothing
}
}
}
/**
* Set up and add area charts.
*
* @param tableContent
* @param fragmentIonType
* @param aa
* @param column
*/
private void addAreaChart(PtmtableContent tableContent, int fragmentIonType, int aa, int column) {
ArrayList<JSparklinesDataSeries> sparkLineDataSeriesAll = new ArrayList<JSparklinesDataSeries>();
ArrayList<Double> data;
int[] histogram;
String modification = "";
PTMFactory ptmFactory = PTMFactory.getInstance();
String ptmName = ptm.getName(), shortName = ptmFactory.getShortName(ptmName);
for (int modCpt = 0; modCpt <= nPTM; modCpt++) {
if (modCpt > 0) {
if (modCpt == 1) {
modification = " <" + shortName + ">";
} else {
modification = " <" + modCpt + shortName + ">";
}
}
// add the data points to display to an arraylist
data = new ArrayList<Double>();
histogram = tableContent.getHistogram(modCpt, fragmentIonType, aa, 50);
data.add(0.0);
for (int frequency : histogram) {
if (frequency > 0) {
data.add(new Double(frequency));
if (frequency > maxAreaChartValue) {
maxAreaChartValue = frequency;
}
}
}
data.add(0.0);
// find area color
double colorCoef;
if (nPTM == 0) {
colorCoef = 1;
} else {
colorCoef = 1.0 - ((1.0 * modCpt) / nPTM);
}
Ion genericIon = Ion.getGenericIon(Ion.IonType.PEPTIDE_FRAGMENT_ION, fragmentIonType, new ArrayList<NeutralLoss>());
Color areaColor = SpectrumPanel.determineFragmentIonColor(genericIon, false);
areaColor = new Color((int) (colorCoef * areaColor.getRed()), (int) (colorCoef * areaColor.getGreen()), (int) (colorCoef * areaColor.getBlue()));
String tooltip = "<html>" + PeptideFragmentIon.getSubTypeAsString(fragmentIonType) + "<sub>" + aa + "</sub>" + modification + "</html>";
// create a JSparklineDataSeries
JSparklinesDataSeries sparklineDataseries = new JSparklinesDataSeries(data, areaColor, tooltip);
// add the data series to JSparklineDataset
sparkLineDataSeriesAll.add(sparklineDataseries);
}
JSparklinesDataset dataset = new JSparklinesDataset(sparkLineDataSeriesAll);
// add the data to the table
setValueAt(dataset, aa - 1, column);
}
/**
* Insert bar charts into the table.
*/
private void insertBarCharts() {
AnnotationPreferences annotationPreferences = peptideShakerGUI.getAnnotationPreferences();
PtmtableContent tempContent, tableContent = new PtmtableContent();
MSnSpectrum spectrum;
SpectrumMatch spectrumMatch;
SpectrumFactory spectrumFactory = SpectrumFactory.getInstance();
PTMFactory ptmFactory = PTMFactory.getInstance();
String ptmName = ptm.getName(), shortName = ptmFactory.getShortName(ptmName);
for (String spectrumKey : spectrumKeys) {
try {
spectrum = (MSnSpectrum) spectrumFactory.getSpectrum(spectrumKey);
spectrumMatch = peptideShakerGUI.getIdentification().getSpectrumMatch(spectrumKey);
tempContent = PtmtableContent.getPTMTableContent(peptide, ptm, nPTM, spectrum, annotationPreferences.getIonTypes(),
annotationPreferences.getNeutralLosses(), annotationPreferences.getValidatedCharges(),
spectrumMatch.getBestPeptideAssumption().getIdentificationCharge().value,
annotationPreferences.getFragmentIonAccuracy(), spectrum.getIntensityLimit(annotationPreferences.getAnnotationIntensityLimit()));
tempContent.normalize();
tableContent.addAll(tempContent);
} catch (Exception e) {
peptideShakerGUI.catchException(e);
}
}
for (int aa = 0; aa < peptide.getSequence().length(); aa++) {
int column = 1;
for (int modCpt = 0; modCpt <= nPTM; modCpt++) {
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.A_ION)) {
setValueAt(tableContent.getQuantile(modCpt, PeptideFragmentIon.A_ION, aa + 1, 0.75), aa, column);
column++;
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.B_ION)) {
setValueAt(tableContent.getQuantile(modCpt, PeptideFragmentIon.B_ION, aa + 1, 0.75), aa, column);
column++;
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.C_ION)) {
setValueAt(tableContent.getQuantile(modCpt, PeptideFragmentIon.C_ION, aa + 1, 0.75), aa, column);
column++;
}
}
column++;
for (int modCpt = 0; modCpt <= nPTM; modCpt++) {
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.X_ION)) {
setValueAt(tableContent.getQuantile(modCpt, PeptideFragmentIon.X_ION, aa + 1, 0.75), aa, column);
column++;
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.Y_ION)) {
setValueAt(tableContent.getQuantile(modCpt, PeptideFragmentIon.Y_ION, aa + 1, 0.75), aa, column);
column++;
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.Z_ION)) {
setValueAt(tableContent.getQuantile(modCpt, PeptideFragmentIon.Z_ION, aa + 1, 0.75), aa, column);
column++;
}
}
}
// set the column renderers
for (int modCpt = 0; modCpt <= nPTM; modCpt++) {
String modification = "";
if (modCpt > 0) {
if (modCpt == 1) {
modification = " <" + shortName + ">";
} else {
modification = " <" + modCpt + shortName + ">";
}
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.A_ION)) {
try {
getColumn("a" + modification).setCellRenderer(new JSparklinesBarChartTableCellRenderer(PlotOrientation.HORIZONTAL, tableContent.getMaxIntensity(),
SpectrumPanel.determineFragmentIonColor(new PeptideFragmentIon(PeptideFragmentIon.A_ION), false)));
((JSparklinesBarChartTableCellRenderer) getColumn("a" + modification).getCellRenderer()).setMinimumChartValue(0);
} catch (IllegalArgumentException e) {
// do nothing
}
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.B_ION)) {
try {
getColumn("b" + modification).setCellRenderer(new JSparklinesBarChartTableCellRenderer(PlotOrientation.HORIZONTAL, tableContent.getMaxIntensity(),
SpectrumPanel.determineFragmentIonColor(new PeptideFragmentIon(PeptideFragmentIon.B_ION), false)));
((JSparklinesBarChartTableCellRenderer) getColumn("b" + modification).getCellRenderer()).setMinimumChartValue(0);
} catch (IllegalArgumentException e) {
// do nothing
}
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.C_ION)) {
try {
getColumn("c" + modification).setCellRenderer(new JSparklinesBarChartTableCellRenderer(PlotOrientation.HORIZONTAL, tableContent.getMaxIntensity(),
SpectrumPanel.determineFragmentIonColor(new PeptideFragmentIon(PeptideFragmentIon.C_ION), false)));
((JSparklinesBarChartTableCellRenderer) getColumn("c" + modification).getCellRenderer()).setMinimumChartValue(0);
} catch (IllegalArgumentException e) {
// do nothing
}
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.X_ION)) {
try {
getColumn("x" + modification).setCellRenderer(new JSparklinesBarChartTableCellRenderer(PlotOrientation.HORIZONTAL, tableContent.getMaxIntensity(),
SpectrumPanel.determineFragmentIonColor(new PeptideFragmentIon(PeptideFragmentIon.X_ION), false)));
((JSparklinesBarChartTableCellRenderer) getColumn("x" + modification).getCellRenderer()).setMinimumChartValue(0);
} catch (IllegalArgumentException e) {
// do nothing
}
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.Y_ION)) {
try {
getColumn("y" + modification).setCellRenderer(new JSparklinesBarChartTableCellRenderer(PlotOrientation.HORIZONTAL, tableContent.getMaxIntensity(),
SpectrumPanel.determineFragmentIonColor(new PeptideFragmentIon(PeptideFragmentIon.Y_ION), false)));
((JSparklinesBarChartTableCellRenderer) getColumn("y" + modification).getCellRenderer()).setMinimumChartValue(0);
} catch (IllegalArgumentException e) {
// do nothing
}
}
if (annotationPreferences.getFragmentIonTypes().contains(PeptideFragmentIon.Z_ION)) {
try {
getColumn("z" + modification).setCellRenderer(new JSparklinesBarChartTableCellRenderer(PlotOrientation.HORIZONTAL, tableContent.getMaxIntensity(),
SpectrumPanel.determineFragmentIonColor(new PeptideFragmentIon(PeptideFragmentIon.Z_ION), false)));
((JSparklinesBarChartTableCellRenderer) getColumn("z" + modification).getCellRenderer()).setMinimumChartValue(0);
} catch (IllegalArgumentException e) {
// do nothing
}
}
}
}
}