package com.compomics.util.gui.isotopic_calculator; import com.compomics.util.AlternateRowColoursJTable; import com.compomics.util.enumeration.MolecularElement; import com.compomics.util.general.IsotopicDistribution; import com.compomics.util.general.IsotopicDistributionSpectrum; import com.compomics.util.general.MassCalc; import com.compomics.util.general.UnknownElementMassException; import com.compomics.util.gui.spectrum.SpectrumPanel; import com.compomics.util.protein.AASequenceImpl; import com.compomics.util.protein.MolecularFormula; import com.jgoodies.looks.FontPolicies; import com.jgoodies.looks.FontPolicy; import com.jgoodies.looks.FontSet; import com.jgoodies.looks.FontSets; import com.jgoodies.looks.plastic.PlasticLookAndFeel; import com.jgoodies.looks.plastic.PlasticXPLookAndFeel; import com.jgoodies.looks.plastic.theme.Silver; import org.apache.log4j.Logger; import javax.imageio.ImageIO; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableModel; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Hashtable; /** * This class is a GUI that visualizes the isotopic calculator. * <p> * Created by IntelliJ IDEA. * User: Niklaas * Date: 16-Aug-2010 * Time: 13:24:41 */ public class IsotopeDistributionGui extends JFrame { // Class specific log4j logger for MolecularFormula instances. Logger logger = Logger.getLogger(MolecularFormula.class); //gui objects private JTextArea txtSequence; private JLabel lblComp; private JLabel lblMass; private JButton calculateButton; private AlternateRowColoursJTable table1; private JPanel jpanContent; private JPanel headerTable; private JPanel spectrumPanel; private JSpinner spinCharge; private JLabel lblPeptide; /** * The amino acid sequence */ private AASequenceImpl iSequence = null; /** * HashMap with the molecular formula for all the aminoacids */ private HashMap<String, MolecularFormula> iElements; /** * The charge */ private double iCharge; /** * The constructor * * @param lStandAlone Boolean that indicates if this is a standalone JFrame */ public IsotopeDistributionGui(boolean lStandAlone) { super("Isotopic distribution calculator"); $$$setupUI$$$(); if (lStandAlone) { //set the frame parameters this.setContentPane(jpanContent); this.setSize(800, 800); this.setLocationRelativeTo(null); this.setVisible(true); this.setIconImage(new ImageIcon(getClass().getResource("/icons/compomics-utilities.png")).getImage()); //add a closing window listener addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { System.exit(0); } }); // Look n feel. try { FontSet fontSet = FontSets.createDefaultFontSet( new Font("Tahoma", Font.PLAIN, 11), // control font new Font("Tahoma", Font.PLAIN, 11), // menu font new Font("Tahoma", Font.BOLD, 11) // title font ); FontPolicy fixedPolicy = FontPolicies.createFixedPolicy(fontSet); PlasticLookAndFeel.setFontPolicy(fixedPolicy); PlasticLookAndFeel.setPlasticTheme(new Silver()); UIManager.setLookAndFeel(new PlasticXPLookAndFeel()); } catch (UnsupportedLookAndFeelException e) { logger.error(e.getMessage(), e); } } //get the elements iElements = new HashMap<String, MolecularFormula>(); //get the elements that can be used try { BufferedReader br = new BufferedReader(new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("elements.txt"))); String line; String[] lHeaderElements = null; while ((line = br.readLine()) != null) { if (line.startsWith("#")) { //do nothing } else if (line.startsWith("Header")) { String lTemp = line.substring(line.indexOf("=") + 1); lHeaderElements = lTemp.split(","); } else { String lAa = line.substring(0, line.indexOf("=")); String[] lContribution = line.substring(line.indexOf("=") + 1).split(","); MolecularFormula lAaFormula = new MolecularFormula(); for (int i = 0; i < lHeaderElements.length; i++) { for (MolecularElement lMolecularElement : MolecularElement.values()) { if (lMolecularElement.toString().equalsIgnoreCase(lHeaderElements[i])) { lAaFormula.addElement(lMolecularElement, Integer.valueOf(lContribution[i])); } } } iElements.put(lAa, lAaFormula); } } br.close(); } catch (Exception e) { logger.error(e); } calculateButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { calculate(); } }); spinCharge.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { calculate(); } }); } /** * This method will do the calculations */ public void calculate() { //Get the sequence String lSeq = txtSequence.getText(); //exclude unwanted characters lSeq = lSeq.trim().toUpperCase(); lSeq = lSeq.replace("\n", ""); lSeq = lSeq.replace("\t", ""); lSeq = lSeq.replace(" ", ""); //check the aminoacids for (int i = 0; i < lSeq.length(); i++) { String lLetter = String.valueOf(lSeq.charAt(i)); if (!isElement(lLetter)) { //return JOptionPane.showMessageDialog(this, lLetter + " at position " + (i + 1) + " is not a valid element", "Not valid element", JOptionPane.ERROR_MESSAGE); return; } } if (lSeq.length() == 0) { //return JOptionPane.showMessageDialog(this, "Sequence cannot be of length zero!", "Not valid sequence", JOptionPane.ERROR_MESSAGE); return; } //create the sequence iSequence = new AASequenceImpl(lSeq); //get the charge iCharge = (Double) spinCharge.getValue(); //set the labels lblComp.setText(iSequence.getMolecularFormula().toString()); double lMz = iSequence.getMz((int) iCharge); lblMass.setText(String.valueOf(Math.floor(lMz * 10000.0) / 10000.0) + " Da"); lblPeptide.setText("NH2-" + lSeq + "-COOH (" + iCharge + "+)"); //calculate the distribution IsotopicDistribution lIso = iSequence.getIsotopicDistribution(); HashMap lPeaks = new HashMap(); //add the data to the table for (int i = 0; i < 10; i++) { table1.setValueAt(i, i, 0); table1.setValueAt(Math.floor(lIso.getPercTot()[i] * 10000.0) / 100.0, i, 1); table1.setValueAt(Math.floor(lIso.getPercMax()[i] * 10000.0) / 100.0, i, 2); try { lPeaks.put(lMz + (i * (new MassCalc().calculateMass("H") / iCharge)), lIso.getPercMax()[i]); } catch (UnknownElementMassException ume) { logger.error(ume.getMessage(), ume); } } //do gui updates an add the spectrum panel table1.updateUI(); IsotopicDistributionSpectrum lSpecFile = new IsotopicDistributionSpectrum(); lSpecFile.setCharge(Integer.valueOf(String.valueOf(iCharge).substring(0, String.valueOf(iCharge).indexOf(".")))); lSpecFile.setPrecursorMZ(lMz); lSpecFile.setPeaks(lPeaks); spectrumPanel.removeAll(); SpectrumPanel lSpecPanel = new SpectrumPanel(lSpecFile, false); lSpecPanel.rescale(lMz - (0.5 / iCharge), lMz + (0.5 / iCharge) + (10.0 / iCharge)); spectrumPanel.add(lSpecPanel); spectrumPanel.updateUI(); } /** * This methods gives a JPanel holding everything from this frame * * @return JPanel */ public JPanel getContentPane() { return jpanContent; } /** * Method that checks if a given string is an element we can calculate an isotopic distribution for * * @param lElement String with the element to check * @return boolean that indicates if we can use this element */ public boolean isElement(String lElement) { Object lValue = iElements.get(lElement); if (lValue == null) { return false; } return true; } /** * Main method * * @param Args The arguments */ public static void main(String[] Args) { new IsotopeDistributionGui(true); } /** * Create gui components */ private void createUIComponents() { String[] columnNames = {"Isotope Number", "% Total", "% Maximum"}; TableModel lModel = new SparseTableModel(10, columnNames); for (int i = 0; i < 10; i++) { lModel.setValueAt(i, i, 0); lModel.setValueAt(0.0, i, 1); lModel.setValueAt(0.0, i, 2); } table1 = new AlternateRowColoursJTable(lModel); headerTable = new JPanel(); headerTable.setLayout(new BoxLayout(headerTable, BoxLayout.Y_AXIS)); headerTable.add(table1.getTableHeader()); spectrumPanel = new JPanel(); spectrumPanel.setLayout(new BoxLayout(spectrumPanel, BoxLayout.X_AXIS)); spectrumPanel.add(Box.createVerticalStrut(1)); spectrumPanel.add(new ImagePanel("icons/compomics.png")); //spectrumPanel.add(Box.createVerticalStrut(1)); spectrumPanel.add(Box.createVerticalGlue()); spinCharge = new JSpinner(); spinCharge.setModel(new SpinnerNumberModel(1.0, 1.0, 20.0, 1.0)); } /** * Method generated by IntelliJ IDEA GUI Designer * >>> IMPORTANT!! <<< * DO NOT edit this method OR call it in your code! * * @noinspection ALL */ private void $$$setupUI$$$() { createUIComponents(); jpanContent = new JPanel(); jpanContent.setLayout(new GridBagLayout()); final JLabel label1 = new JLabel(); label1.setHorizontalAlignment(11); label1.setText("Composition:"); GridBagConstraints gbc; gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 4; gbc.anchor = GridBagConstraints.EAST; gbc.ipadx = 30; gbc.insets = new Insets(10, 10, 10, 10); jpanContent.add(label1, gbc); final JLabel label2 = new JLabel(); label2.setHorizontalAlignment(11); label2.setText("M/Z"); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 5; gbc.anchor = GridBagConstraints.EAST; gbc.insets = new Insets(10, 10, 10, 10); jpanContent.add(label2, gbc); lblComp = new JLabel(); lblComp.setFont(new Font(lblComp.getFont().getName(), lblComp.getFont().getStyle(), 16)); lblComp.setText("/"); gbc = new GridBagConstraints(); gbc.gridx = 4; gbc.gridy = 4; gbc.gridwidth = 2; gbc.anchor = GridBagConstraints.WEST; gbc.insets = new Insets(10, 10, 10, 10); jpanContent.add(lblComp, gbc); lblMass = new JLabel(); lblMass.setFont(new Font(lblMass.getFont().getName(), lblMass.getFont().getStyle(), 16)); lblMass.setText("/"); gbc = new GridBagConstraints(); gbc.gridx = 4; gbc.gridy = 5; gbc.gridwidth = 2; gbc.anchor = GridBagConstraints.WEST; gbc.insets = new Insets(10, 10, 10, 10); jpanContent.add(lblMass, gbc); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 7; gbc.gridwidth = 6; gbc.fill = GridBagConstraints.BOTH; gbc.insets = new Insets(0, 10, 10, 10); jpanContent.add(table1, gbc); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 6; gbc.gridwidth = 6; gbc.weightx = 1.0; gbc.fill = GridBagConstraints.BOTH; gbc.insets = new Insets(10, 10, 0, 10); jpanContent.add(headerTable, gbc); final JPanel panel1 = new JPanel(); panel1.setLayout(new GridBagLayout()); panel1.setMaximumSize(new Dimension(50, 50)); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 6; gbc.weighty = 0.5; gbc.fill = GridBagConstraints.BOTH; gbc.insets = new Insets(10, 10, 10, 10); jpanContent.add(panel1, gbc); final JScrollPane scrollPane1 = new JScrollPane(); scrollPane1.setHorizontalScrollBarPolicy(30); scrollPane1.setMaximumSize(new Dimension(50, 50)); scrollPane1.setVerticalScrollBarPolicy(20); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.weightx = 0.1; gbc.weighty = 0.5; gbc.fill = GridBagConstraints.BOTH; gbc.insets = new Insets(10, 10, 10, 10); panel1.add(scrollPane1, gbc); txtSequence = new JTextArea(); txtSequence.setMaximumSize(new Dimension(50, 50)); scrollPane1.setViewportView(txtSequence); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 8; gbc.gridwidth = 6; gbc.gridheight = 6; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.fill = GridBagConstraints.BOTH; gbc.insets = new Insets(10, 10, 10, 10); jpanContent.add(spectrumPanel, gbc); gbc = new GridBagConstraints(); gbc.gridx = 5; gbc.gridy = 1; gbc.anchor = GridBagConstraints.WEST; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.insets = new Insets(10, 10, 10, 10); jpanContent.add(spinCharge, gbc); final JLabel label3 = new JLabel(); label3.setHorizontalAlignment(11); label3.setText("Charge:"); gbc = new GridBagConstraints(); gbc.gridx = 4; gbc.gridy = 1; gbc.anchor = GridBagConstraints.EAST; gbc.ipadx = 30; gbc.insets = new Insets(10, 10, 10, 10); jpanContent.add(label3, gbc); calculateButton = new JButton(); calculateButton.setText("Calculate"); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 1; gbc.gridwidth = 4; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.insets = new Insets(10, 10, 10, 10); jpanContent.add(calculateButton, gbc); final JSeparator separator1 = new JSeparator(); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 2; gbc.gridwidth = 6; gbc.fill = GridBagConstraints.BOTH; jpanContent.add(separator1, gbc); lblPeptide = new JLabel(); lblPeptide.setFont(new Font(lblPeptide.getFont().getName(), Font.ITALIC, 18)); lblPeptide.setHorizontalAlignment(0); lblPeptide.setHorizontalTextPosition(0); lblPeptide.setText(" "); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 3; gbc.gridwidth = 6; jpanContent.add(lblPeptide, gbc); } /** * Returns the root components. * * @return the root component */ public JComponent $$$getRootComponent$$$() { return jpanContent; } /** * This is an imagepane class * It paint a given image in its panel */ class ImagePanel extends JPanel { /** * The image */ private BufferedImage image; /** * Constructor * * @param lFilename String with the filename that has to be in the classpath */ public ImagePanel(String lFilename) { try { image = ImageIO.read(getClass().getResource("/" + lFilename)); } catch (IOException ex) { logger.error(ex); } } @Override /** * Paint method */ public void paintComponent(Graphics g) { g.drawImage(image, 0, 0, null); } } /** * This is a table model extension */ class SparseTableModel extends AbstractTableModel { /** * The lookup hashtable */ private Hashtable lookup; /** * number of rows */ private final int rows; /** * number of columns */ private final int columns; /** * The colum headers */ private final String headers[]; /** * Constructor * * @param rows number of rows * @param columnHeaders the column headers */ public SparseTableModel(int rows, String columnHeaders[]) { if ((rows < 0) || (columnHeaders == null)) { throw new IllegalArgumentException("Invalid row count/columnHeaders"); } this.rows = rows; this.columns = columnHeaders.length; headers = columnHeaders; lookup = new Hashtable(); } /** * Getter for the number of columns * * @return int with the number of columns */ public int getColumnCount() { return columns; } /** * Getter for the number of rows * * @return int with the number of rows */ public int getRowCount() { return rows; } /** * Getter for the column title * * @param column int with the column number * @return String with the column title */ public String getColumnName(int column) { return headers[column]; } /** * Getter for the element on the given position * * @param row int with the row number * @param column int with the column number * @return Object with the element at that position */ public Object getValueAt(int row, int column) { return lookup.get(new Point(row, column)); } /** * Setter for the element on the given position * * @param value The object that has to be set * @param row int with the row number * @param column int with the column number */ public void setValueAt(Object value, int row, int column) { if ((rows < 0) || (columns < 0)) { throw new IllegalArgumentException("Invalid row/column setting"); } if ((row < rows) && (column < columns)) { lookup.put(new Point(row, column), value); } } } }