Java tutorial
/** * Musite * Copyright (C) 2010 Digital Biology Laboratory, University Of Missouri * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package musite.ui; import java.awt.Color; import java.awt.Font; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Hashtable; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTable; import javax.swing.JTextPane; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import javax.swing.text.StyleConstants; import javax.swing.text.StyledDocument; import javax.swing.text.SimpleAttributeSet; import org.apache.commons.lang.StringUtils; import musite.MusiteInit; import musite.Proteins; import musite.Protein; import musite.prediction.SpecificityEstimator; import musite.prediction.PredictionModel; import musite.prediction.PredictionResult; import musite.prediction.PredictionResultImpl; import musite.io.fasta.DefaultProteinsFastaWriter; import musite.io.fasta.ResidueAnnotator; import musite.io.xml.PredictionResultXMLWriter; import musite.ui.task.AbstractTask; import musite.ui.task.WriteTask; import musite.ui.task.TaskUtil; import musite.ui.util.CMap; import musite.ui.util.CTable; import musite.ui.util.GradientSliderUI; import musite.util.FileExtensionsFilter; import musite.util.FilePathParser; import musite.util.IOUtil; import musite.util.StringUtil; /** * * @author Jianjiong Gao */ public class MusiteResultPanel extends javax.swing.JPanel { public MusiteResultPanel(String panelName, PredictionResult result) { this(panelName, result, false); } /** Creates new form MusiteResultPanel */ public MusiteResultPanel(String panelName, PredictionResult result, boolean saved) { this.panelName = panelName; this.result = result; this.saved = saved; initComponents(); specificity = 0.95; setResult(); runResetProteinList(); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; resDispPanel = new javax.swing.JPanel(); javax.swing.JPanel modelPanel = new javax.swing.JPanel(); modelComboBox = new javax.swing.JComboBox(); javax.swing.JPanel accPanel = new javax.swing.JPanel(); proteinListComboBox = new javax.swing.JComboBox(); javax.swing.JPanel optionPanel = new javax.swing.JPanel(); phosphoCheckBox = new javax.swing.JCheckBox(); alphabetCheckBox = new javax.swing.JCheckBox(); displayTabbedPane = new javax.swing.JTabbedPane(); sequenceScrollPane = new javax.swing.JScrollPane(); sitesScrollPane = new javax.swing.JScrollPane(); javax.swing.JPanel adjustPanel = new javax.swing.JPanel(); javax.swing.JPanel threholdPanel = new javax.swing.JPanel(); javax.swing.JPanel sliderBasePanel = new javax.swing.JPanel(); sliderTitleComboBox = new javax.swing.JComboBox(); javax.swing.JPanel specificityPanel = new javax.swing.JPanel(); javax.swing.JLabel specificityLabel = new javax.swing.JLabel(); specificityTextField = new javax.swing.JTextField(); javax.swing.JLabel percLabel = new javax.swing.JLabel(); javax.swing.JLabel scoreCutoffLabel = new javax.swing.JLabel(); scoreCutoffTextField = new javax.swing.JTextField(); specificitySlider = new javax.swing.JSlider(); javax.swing.JPanel exportPanel = new javax.swing.JPanel(); exportComboBox = new javax.swing.JComboBox(); javax.swing.JPanel closePanel = new javax.swing.JPanel(); javax.swing.JButton saveButton = new javax.swing.JButton(); setLayout(new java.awt.GridBagLayout()); resDispPanel.setLayout(new java.awt.GridBagLayout()); modelPanel.setVisible(result.getModels().size() > 1); modelPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Select model")); modelPanel.setLayout(new javax.swing.BoxLayout(modelPanel, javax.swing.BoxLayout.LINE_AXIS)); PredictionModel[] models = result.getModels().toArray(new PredictionModel[0]); java.util.Arrays.sort(models, new java.util.Comparator<PredictionModel>() { public int compare(PredictionModel model1, PredictionModel model2) { String name1 = model1.getName(); String name2 = model2.getName(); if (name1 == null) return name2 == null ? 0 : -1; if (name2 == null) return 1; return name1.compareTo(name2); } }); modelComboBox.setModel(new javax.swing.DefaultComboBoxModel(models)); modelComboBox.setSelectedIndex(0); modelComboBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { modelComboBoxActionPerformed(evt); } }); modelPanel.add(modelComboBox); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3); resDispPanel.add(modelPanel, gridBagConstraints); accPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Select protein(s)")); accPanel.setLayout(new java.awt.GridBagLayout()); Vector pros = new Vector(result.proteins()); //pros.add("Display all listed proteins"); proteinListComboBox.setModel(new javax.swing.DefaultComboBoxModel(pros)); proteinListComboBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { proteinListComboBoxActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3); accPanel.add(proteinListComboBox, gridBagConstraints); optionPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 3, 3)); phosphoCheckBox.setText("List predicted phosphoproteins only"); phosphoCheckBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { phosphoCheckBoxActionPerformed(evt); } }); optionPanel.add(phosphoCheckBox); alphabetCheckBox.setText("List alphabetically (according to accessions)"); alphabetCheckBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { alphabetCheckBoxActionPerformed(evt); } }); optionPanel.add(alphabetCheckBox); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; accPanel.add(optionPanel, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 1.0; resDispPanel.add(accPanel, gridBagConstraints); displayTextPane = new ViewResultTextPane(); sequenceScrollPane.setViewportView(displayTextPane); displayTabbedPane.addTab("Sequence(s)", sequenceScrollPane); displayTable = new ViewResultTable(); sitesScrollPane.setViewportView(displayTable); displayTabbedPane.addTab("Predicted Sites", sitesScrollPane); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; resDispPanel.add(displayTabbedPane, gridBagConstraints); adjustPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Stringency setting")); adjustPanel.setLayout(new java.awt.GridBagLayout()); threholdPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 5, 0)); sliderBasePanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Sliding according to")); sliderBasePanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 5, 0)); sliderTitleComboBox.setMinimumSize(new java.awt.Dimension(150, 18)); sliderTitleComboBox.setPreferredSize(new java.awt.Dimension(150, 22)); sliderTitleComboBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { sliderTitleComboBoxActionPerformed(evt); } }); sliderBasePanel.add(sliderTitleComboBox); threholdPanel.add(sliderBasePanel); specificityPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Cutoff")); specificityPanel.setLayout(new java.awt.GridBagLayout()); specificityLabel.setText("Specificity:"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridy = 0; gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 0); specificityPanel.add(specificityLabel, gridBagConstraints); specificityTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT); specificityTextField.setMinimumSize(new java.awt.Dimension(60, 19)); specificityTextField.setPreferredSize(new java.awt.Dimension(60, 19)); specificityTextField.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { specificityTextFieldActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridy = 0; gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 1); specificityPanel.add(specificityTextField, gridBagConstraints); percLabel.setText("%"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridy = 0; gridBagConstraints.insets = new java.awt.Insets(0, 1, 0, 20); specificityPanel.add(percLabel, gridBagConstraints); scoreCutoffLabel.setText("Score:"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridy = 0; specificityPanel.add(scoreCutoffLabel, gridBagConstraints); scoreCutoffTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT); scoreCutoffTextField.setMinimumSize(new java.awt.Dimension(60, 19)); scoreCutoffTextField.setPreferredSize(new java.awt.Dimension(60, 19)); scoreCutoffTextField.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { scoreCutoffTextFieldActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridy = 0; gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 20); specificityPanel.add(scoreCutoffTextField, gridBagConstraints); threholdPanel.add(specificityPanel); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; adjustPanel.add(threholdPanel, gridBagConstraints); specificitySlider.setPaintLabels(true); specificitySlider.addChangeListener(new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { specificitySliderStateChanged(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 1.0; adjustPanel.add(specificitySlider, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 3; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2); resDispPanel.add(adjustPanel, gridBagConstraints); exportPanel.setLayout(new javax.swing.BoxLayout(exportPanel, javax.swing.BoxLayout.LINE_AXIS)); exportComboBox.setModel(new javax.swing.DefaultComboBoxModel( new String[] { "Export this result as...", "Tab-delimited text file" })); exportComboBox.setMinimumSize(new java.awt.Dimension(200, 18)); exportComboBox.setPreferredSize(new java.awt.Dimension(200, 22)); exportComboBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { exportComboBoxActionPerformed(evt); } }); exportPanel.add(exportComboBox); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 4; gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); resDispPanel.add(exportPanel, gridBagConstraints); closePanel.setLayout(new javax.swing.BoxLayout(closePanel, javax.swing.BoxLayout.LINE_AXIS)); saveButton.setText("Save As..."); saveButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { saveButtonActionPerformed(evt); } }); closePanel.add(saveButton); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 4; gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); resDispPanel.add(closePanel, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; add(resDispPanel, gridBagConstraints); }// </editor-fold>//GEN-END:initComponents private void specificityTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_specificityTextFieldActionPerformed double value; try { value = Double.valueOf(specificityTextField.getText()); } catch (Exception e) { JOptionPane.showMessageDialog(this, "Please specify a number between 0 and 100."); return; } if (value < 0 || value > 100) { JOptionPane.showMessageDialog(this, "Please specify a number between 0 and 100."); return; } if (value / 100 == specificity) return; specificity = value / 100; threshold = selectedModel().getSpecEstimator().threshold(specificity); scoreCutoffTextField.setText(String.format("%.2f", threshold)); lockScore = true; lockSpec = true; specificitySlider.setValue((int) Math.round(maxTick * (threshold - minScore) / (maxScore - minScore))); lockScore = false; lockSpec = false; }//GEN-LAST:event_specificityTextFieldActionPerformed private void specificitySliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_specificitySliderStateChanged if (ignoreSlideChangeEvent) return; javax.swing.JSlider source = (javax.swing.JSlider) evt.getSource(); if (!lockScore) { int value = (int) source.getValue(); threshold = (maxScore - minScore) * value / maxTick + minScore; scoreCutoffTextField.setText(String.format("%.2f", threshold)); } if (!lockSpec) { if (selectedModel().getSpecEstimator() != null) { setSpecificity(threshold); specificityTextField.setText(String.format("%.2f", specificity * 100)); } } if (!source.getValueIsAdjusting()) { // does not work result.setThreshold(selectedModel(), threshold); if (phosphoCheckBox.isSelected()) { runResetProteinList(); } else { resetDisplay(); } } }//GEN-LAST:event_specificitySliderStateChanged private void proteinListComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_proteinListComboBoxActionPerformed resetDisplay(); }//GEN-LAST:event_proteinListComboBoxActionPerformed private void exportComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportComboBoxActionPerformed String name = panelName.replaceAll("[\\\\/:\\*\\?\"<>\\|]+", "-"); String defaultFile = MusiteInit.defaultPath + File.separator + name; if (sliderTitleComboBox.getSelectedItem().equals(SPECIFICITY)) { defaultFile += String.format("-Sp_%.2f", specificity); } else { defaultFile += String.format("-Score_%.3f", threshold); } defaultFile += ".result"; switch (exportComboBox.getSelectedIndex()) { case 1: // tab-delimited text file { JFileChooser fc = new JFileChooser(MusiteInit.defaultPath); fc.setSelectedFile(new File(defaultFile)); ArrayList<String> exts = new ArrayList<String>(1); String fasta = "txt"; exts.add(fasta); FileExtensionsFilter fastaFilter = new FileExtensionsFilter(exts, "Tab-delimited file (.txt)"); fc.addChoosableFileFilter(fastaFilter); //fc.setAcceptAllFileFilterUsed(true); fc.setDialogTitle("Save the the result to..."); int returnVal = fc.showSaveDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); MusiteInit.defaultPath = file.getParent(); String filePath = MusiteInit.defaultPath + File.separator + file.getName(); String ext = FilePathParser.getExt(filePath); if (ext == null || !ext.equalsIgnoreCase("txt")) { filePath += ".txt"; } if (IOUtil.fileExist(filePath)) { int ret = JOptionPane.showConfirmDialog(this, "Are you sure to replace the existing file?", "Relace the existing file?", JOptionPane.YES_NO_OPTION); if (ret == JOptionPane.NO_OPTION) break; } Vector<Vector> data = formatData(proteinList, false, true); int n = data.size(); ArrayList<String> dataOut = new ArrayList(n + 1); dataOut.add(StringUtils.join(header.iterator(), '\t')); for (Vector vec : data) { dataOut.add(StringUtils.join(vec.iterator(), '\t')); } try { IOUtil.writeCollectionAscii(dataOut, filePath); } catch (IOException e) { e.printStackTrace(); JOptionPane.showMessageDialog(this, "Error: failed to write the file."); break; } JOptionPane.showMessageDialog(this, "Successfully exported."); } break; } // case 2: // fasta // { // JFileChooser fc = new JFileChooser(MusiteInit.defaultPath); // fc.setSelectedFile(new File(defaultFile)); // // ArrayList<String> exts = new ArrayList<String>(1); // String fasta = "fasta"; // exts.add(fasta); // FileExtensionsFilter fastaFilter = new FileExtensionsFilter(exts,"Fasta file (.fasta)"); // fc.addChoosableFileFilter(fastaFilter); // // //fc.setAcceptAllFileFilterUsed(true); // fc.setDialogTitle("Save the the result to..."); // int returnVal = fc.showSaveDialog(this); // if (returnVal == JFileChooser.APPROVE_OPTION) { // File file = fc.getSelectedFile(); // MusiteInit.defaultPath = file.getParent(); // // String filePath = MusiteInit.defaultPath + File.separator + file.getName(); // // String ext = FilePathParser.getExt(filePath); // if (ext==null||!ext.equalsIgnoreCase("fasta")) { // filePath += ".fasta"; // } // // if (IOUtil.fileExist(filePath)) { // int ret = JOptionPane.showConfirmDialog(this, "Are you sure to replace the existing file?", "Relace the existing file?", JOptionPane.YES_NO_OPTION); // if (ret==JOptionPane.NO_OPTION) // break; // } // // ProteinsWriter writer = new ModifiedProteinsFastaWriter(); // WriteTask writeTask = new WriteTask(resultDisplay, writer, filePath); // TaskUtil.execute(writeTask); // if (!writeTask.success()) { // JOptionPane.showMessageDialog(this, "Failed to export."); // break; // } // // JOptionPane.showMessageDialog(this, "Successfully exported."); // } // // break; // } // case 3: // xml // { // JFileChooser fc = new JFileChooser(MusiteInit.defaultPath); // fc.setSelectedFile(new File(defaultFile)); // // ArrayList<String> exts = new ArrayList<String>(1); // String xml = "xml"; // exts.add(xml); // FileExtensionsFilter xmlFilter = new FileExtensionsFilter(exts,"XML file (.xml)"); // fc.addChoosableFileFilter(xmlFilter); // // //fc.setAcceptAllFileFilterUsed(true); // fc.setDialogTitle("Save the the result to..."); // int returnVal = fc.showSaveDialog(this); // if (returnVal == JFileChooser.APPROVE_OPTION) { // File file = fc.getSelectedFile(); // MusiteInit.defaultPath = file.getParent(); // // String filePath = MusiteInit.defaultPath + File.separator + file.getName(); // // String ext = FilePathParser.getExt(filePath); // if (ext==null||!ext.equalsIgnoreCase("xml")) { // filePath += ".xml"; // } // // if (IOUtil.fileExist(filePath)) { // int ret = JOptionPane.showConfirmDialog(this, "Are you sure to replace the existing file?", "Relace the existing file?", JOptionPane.YES_NO_OPTION); // if (ret==JOptionPane.NO_OPTION) // break; // } // // ProteinsXMLWriter writer = ProteinsXMLWriter.createWriter(); // WriteTask xmlWriteTask = new WriteTask(resultDisplay, writer, filePath); // TaskUtil.execute(xmlWriteTask); // if (!xmlWriteTask.success()) { // JOptionPane.showMessageDialog(this, "Failed to export."); // break; // } // // JOptionPane.showMessageDialog(this, "Successfully exported."); // } // // break; // } } exportComboBox.setSelectedIndex(0); }//GEN-LAST:event_exportComboBoxActionPerformed private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed saveResult(true); }//GEN-LAST:event_saveButtonActionPerformed private void phosphoCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_phosphoCheckBoxActionPerformed runResetProteinList(); }//GEN-LAST:event_phosphoCheckBoxActionPerformed private void alphabetCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_alphabetCheckBoxActionPerformed runResetProteinList(); }//GEN-LAST:event_alphabetCheckBoxActionPerformed private void sliderTitleComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sliderTitleComboBoxActionPerformed setSliderLabels(); }//GEN-LAST:event_sliderTitleComboBoxActionPerformed private void scoreCutoffTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_scoreCutoffTextFieldActionPerformed double value; try { value = Double.valueOf(scoreCutoffTextField.getText()); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(this, "Please input a number."); return; } lockScore = true; this.threshold = value; specificitySlider.setValue((int) Math.round(maxTick * (threshold - minScore) / (maxScore - minScore))); // if (phosphoCheckBox.isSelected()) { // resetProteinList(); // } else { // resetDisplay(); // } lockScore = false; }//GEN-LAST:event_scoreCutoffTextFieldActionPerformed private void modelComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_modelComboBoxActionPerformed setResult(); runResetProteinList(); }//GEN-LAST:event_modelComboBoxActionPerformed private PredictionModel selectedModel() { return (PredictionModel) modelComboBox.getSelectedItem(); } private void setResult() { PredictionModel model = selectedModel(); maxScore = result.getMaxPredictionScore(model); minScore = result.getMinPredictionScore(model); SpecificityEstimator est = model.getSpecEstimator(); if (est != null) { double spec1 = est.threshold(1.0); double spec0 = est.threshold(0.0); if (maxScore < spec1) { maxScore = spec1; } if (minScore > spec0) { minScore = spec0; } threshold = result.getThreshold(model); if (Double.isInfinite(threshold)) { //specificity = 0.95; threshold = est.threshold(0.95); } else { specificity = est.specificity(threshold); } } else { this.threshold = (maxScore + minScore) / 2; } result.setThreshold(model, threshold); double eps = (maxScore - minScore) / maxTick; // one more tic each side maxScore += eps; minScore -= eps; // set ui ignoreSlideChangeEvent = true; setSliderTitleModel(); String textSpec; if (est == null) { textSpec = "N/A"; specificityTextField.setEditable(false); } else { textSpec = String.format("%.2f", specificity * 100); } specificityTextField.setText(textSpec); scoreCutoffTextField.setText(String.format("%.2f", threshold)); setSliderLabels(); setMapScoreColor(); specificitySlider.setValue((int) Math.round(maxTick * (threshold - minScore) / (maxScore - minScore))); ignoreSlideChangeEvent = false; } // public void setGroundTruth(Proteins groundTruth) { // boolean succ; // try { // succ = ResultUtil.resetResultInterpreter(result, groundTruth); // } catch (Exception e) { // e.printStackTrace(); // succ = false; // } // if (!succ) { // JOptionPane.showMessageDialog(this, "Failed to integrate the ground truth data."); // return; // } // // specificityTextField.setEditable(true); // // //setThreshold(threshold); // setSpecificity(threshold); // specificityTextField.setText(String.format("%.2f", specificity*100)); // // sliderTitleComboBox.setModel(new javax.swing.DefaultComboBoxModel( // new String[] {SPECIFICITY, SCORE})); // // setSliderLabels(); // setMapScoreColor(); // // this.groundTruth = groundTruth; // resetDisplay(); // // JOptionPane.showMessageDialog(this, "Done."); // } private static final int maxTick = 10000; private static final String SPECIFICITY = "Specificity"; private static final String SCORE = "Score"; private void setSliderTitleModel() { PredictionModel model = selectedModel(); SpecificityEstimator est = model.getSpecEstimator(); String[] ops; if (est == null) { ops = new String[] { SCORE }; } else { ops = new String[] { SPECIFICITY, SCORE }; } sliderTitleComboBox.setModel(new javax.swing.DefaultComboBoxModel(ops)); } private void setSliderLabels() { specificitySlider.setMaximum(maxTick); specificitySlider.setMinorTickSpacing(maxTick / 20); Hashtable labelTable = new Hashtable(); if (sliderTitleComboBox.getSelectedItem().equals(SPECIFICITY)) { SpecificityEstimator est = selectedModel().getSpecEstimator(); double scoreAtSpec0 = est.threshold(0.0); double scoreAtSpec50 = est.threshold(0.5); double scoreAtSpec80 = est.threshold(0.8); double scoreAtSpec90 = est.threshold(0.9); double scoreAtSpec95 = est.threshold(0.95); double scoreAtSpec100 = est.threshold(1.0); //Create the label table labelTable.put((int) (maxTick * (scoreAtSpec0 - minScore) / (maxScore - minScore)), new JLabel("0")); labelTable.put((int) (maxTick * (scoreAtSpec50 - minScore) / (maxScore - minScore)), new JLabel("50")); labelTable.put((int) (maxTick * (scoreAtSpec80 - minScore) / (maxScore - minScore)), new JLabel("80")); labelTable.put((int) (maxTick * (scoreAtSpec90 - minScore) / (maxScore - minScore)), new JLabel("90")); labelTable.put((int) (maxTick * (scoreAtSpec95 - minScore) / (maxScore - minScore)), new JLabel("95")); labelTable.put((int) (maxTick * (scoreAtSpec100 - minScore) / (maxScore - minScore)), new JLabel("100%")); } else { double step = Math.round(2 * (Math.floor(maxScore) - Math.ceil(minScore)) / 10) / 4; if (step == 0) step = 0.5; double score = Math.ceil(2 * minScore) / 2; while (score <= maxScore) { labelTable.put((int) (maxTick * (score - minScore) / (maxScore - minScore)), new JLabel(String.format("%.1f", score))); score += step; } } specificitySlider.setLabelTable(labelTable); } private void setMapScoreColor() { SpecificityEstimator est = selectedModel().getSpecEstimator(); mapScoreColor = new TreeMap(); if (est != null) { double scoreAtSpec0 = est.threshold(0.0); double scoreAtSpec50 = est.threshold(0.5); double scoreAtSpec80 = est.threshold(0.8); double scoreAtSpec90 = est.threshold(0.9); double scoreAtSpec95 = est.threshold(0.95); double scoreAtSpec100 = est.threshold(1.0); mapScoreColor.put(scoreAtSpec0, new Color(255, 255, 0)); mapScoreColor.put(scoreAtSpec50, new Color(0, 255, 0)); mapScoreColor.put(scoreAtSpec80, new Color(0, 255, 200)); mapScoreColor.put(scoreAtSpec90, new Color(50, 100, 200)); mapScoreColor.put(scoreAtSpec95, new Color(150, 50, 200)); mapScoreColor.put(scoreAtSpec100, new Color(250, 0, 0)); if (scoreAtSpec0 > minScore) { mapScoreColor.put(minScore, new Color(255, 255, 0)); } if (scoreAtSpec100 < maxScore) { mapScoreColor.put(maxScore, new Color(250, 0, 0)); } } else { mapScoreColor.put(minScore, Color.BLUE); mapScoreColor.put(maxScore, Color.RED); } specificitySlider.setUI(new GradientSliderUI(specificitySlider, mapScoreColor, minScore, maxScore)); } private void runResetProteinList() { AbstractTask task = new AbstractTask("Preparing protein list") { public void run() { try { taskMonitor.setPercentCompleted(-1); taskMonitor.setStatus("Preparing..."); resetProteinList(); taskMonitor.setPercentCompleted(100); taskMonitor.setStatus("Done."); this.success = true; } catch (Exception e) { taskMonitor.setPercentCompleted(100); taskMonitor.setStatus("Failed.\n" + e.getMessage()); e.printStackTrace(); return; } } }; TaskUtil.execute(task); if (!task.success()) { JOptionPane.showMessageDialog(this, "Failed to preparing the data"); return; } } private void resetProteinList() { boolean phospho = phosphoCheckBox.isSelected(); boolean alphabetical = alphabetCheckBox.isSelected(); if (!phospho && !alphabetical) { proteinList = result.proteins(); } else { PredictionModel model = selectedModel(); List<Protein> list = new ArrayList(result.proteins()); if (phospho) { double th = result.getThreshold(model); int n = list.size(); for (int i = n - 1; i >= 0; i--) { Protein protein = list.get(i); String acc = protein.getAccession(); Map<Integer, Double> preds = result.getPredictedSites(model, acc); if (preds == null) { list.remove(i); continue; } boolean rmv = true; for (double pred : preds.values()) { if (pred >= th) { rmv = false; break; } } if (rmv) list.remove(i); } } if (alphabetical) { Collections.sort(list, new java.util.Comparator<Protein>() { public int compare(Protein pro1, Protein pro2) { return pro1.getAccession().compareTo(pro2.getAccession().toString()); } }); } proteinList = list; } Vector vec = new Vector(proteinList); //vec.add("Display all listed proteins"); lockDisplay = true; Object obj = proteinListComboBox.getSelectedItem(); proteinListComboBox.setModel(new javax.swing.DefaultComboBoxModel(vec)); if (obj != null) proteinListComboBox.setSelectedItem(obj); // else // proteinListComboBox.setSelectedIndex(0); lockDisplay = false; resetDisplay(); // this will be called after accComboBox.selectedItem } public boolean saveResult(boolean showConfirm) { JFileChooser fc = new JFileChooser(MusiteInit.defaultPath); // TODO: windows reserverd String fileName = panelName.replaceAll("[" + StringUtil.toOct("|\\?*<\":>+[]/") + "]+", "_"); fc.setSelectedFile(new File(MusiteInit.defaultPath + File.separator + fileName + ".pred.xml.gz")); ArrayList<String> exts = new ArrayList<String>(2); exts.add("xml"); exts.add("xml.gz"); fc.addChoosableFileFilter(new FileExtensionsFilter(exts, "Prediction XML file (.xml, .xml.gz)")); exts = new ArrayList<String>(2); exts.add("pred.xml"); exts.add("pred.xml.gz"); fc.addChoosableFileFilter(new FileExtensionsFilter(exts, "Prediction result file (pred.xml, pred.xml.gz)")); //fc.setAcceptAllFileFilterUsed(true); fc.setDialogTitle("Save the the result to..."); int returnVal = fc.showSaveDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); MusiteInit.defaultPath = file.getParent(); String filePath = MusiteInit.defaultPath + File.separator + file.getName(); // if (!filePath.toLowerCase().endsWith(".xml")&&!filePath.toLowerCase().endsWith(".xml.gz")) { // filePath += ".pred.xml.gz"; // } if (IOUtil.fileExist(filePath)) { int ret = JOptionPane.showConfirmDialog(this, "Are you sure to replace the existing file?", "Relace the existing file?", JOptionPane.YES_NO_OPTION); if (ret == JOptionPane.NO_OPTION) return false; } PredictionResultXMLWriter writer = PredictionResultXMLWriter.createWriter(); WriteTask task = new WriteTask(result, writer, filePath); TaskUtil.execute(task); if (task.success()) { if (showConfirm) JOptionPane.showMessageDialog(this, "Result saved!"); saved = true; return true; } else { JOptionPane.showMessageDialog(this, "Failed to save the result."); return false; } } else { return false; } } public void dispose() { // TODO: is this enough for garbage collection result = null; proteinList = null; } public String getPanelName() { return panelName; } public void setPanelName(String panelName) { this.panelName = panelName; } // private void setThreshold(double threshold) { // this.threshold = threshold; // result.setThreshold(threshold); // ResultInterpreter ri = result.getResultInterpreter(); // if (ri!=null) { // specificity = 1-ri.getFPR(threshold); // } // // resetNumberOfSites(); // } private void setSpecificity(double threshold) { SpecificityEstimator est = selectedModel().getSpecEstimator(); if (est != null) { specificity = est.specificity(threshold); } } private void resetDisplay() { if (lockDisplay) return; final PredictionResult proteins = new PredictionResultImpl(); ; // int idx = proteinListComboBox.getSelectedIndex(); // int n = accComboBox.getItemCount(); // if (idx==n-1) { // proteins = resultDisplay; // } else { Object obj = proteinListComboBox.getSelectedItem(); if (obj != null && obj instanceof Protein) { Protein protein = (Protein) obj; PredictionModel model = selectedModel(); proteins.addModel(model); proteins.addProtein(protein); proteins.setThreshold(model, result.getThreshold(model)); } //* displayTable.setResult(proteins); displayTextPane.setResult(proteins); /*/ AbstractTask task = new AbstractTask("Preparing data for displaying") { public void run() { try { taskMonitor.setPercentCompleted(-1); taskMonitor.setStatus("Preparing..."); displayTable.setResult(proteins); displayTextPane.setResult(proteins); taskMonitor.setPercentCompleted(100); taskMonitor.setStatus("Done."); this.success = true; } catch (Exception e) { taskMonitor.setPercentCompleted(100); taskMonitor.setStatus("Failed.\n"+e.getMessage()); e.printStackTrace(); return; } } }; TaskUtil.execute(task); if (!task.success()) { JOptionPane.showMessageDialog(this, "Failed to preparing the data"); return; } //*/ } private static Vector header; private static final String headerPosition = "Position"; private static final String headerAA = "Amino Acid"; private static final String headerSeq = "Surr. Sequence"; private static final String headerScore = "Score"; private static final String headerSpecificity = "Specificity"; static { header = new Vector(); header.add(headerPosition); header.add(headerAA); header.add(headerSeq); header.add(headerScore); header.add(headerSpecificity); } private Vector formatData(Collection<Protein> proteinsList, boolean displayScoreInSequence, boolean displayHeader) { if (proteinsList == null) { return null; } PredictionModel model = selectedModel(); Vector data = new Vector(); for (Protein protein : proteinsList) { String acc = protein.getAccession(); Map<Integer, Double> preds = result.getPredictedSites(model, acc); if (preds == null || preds.isEmpty()) continue; if (displayHeader) { Vector vec = new Vector(1); vec.add('>' + protein.toString()); data.add(vec); } String proteinSeq = protein.getSequence(); int len = proteinSeq.length(); for (Map.Entry<Integer, Double> entry : preds.entrySet()) { int site = entry.getKey(); char aa = proteinSeq.charAt(site); double score = preds.get(site); String seq; if (site < offset) { seq = StringUtils.repeat("*", offset - site) + proteinSeq.substring(0, site); } else { seq = proteinSeq.substring(site - offset, site); } if (displayScoreInSequence) seq += "[" + score + aa + "]"; else seq += aa + "#"; int end = site + offset + 1; if (end > len) { seq += proteinSeq.substring(site + 1, len) + StringUtils.repeat("*", end - len); } else { seq += proteinSeq.substring(site + 1, end); } Vector vec = new Vector(header.size()); vec.add(site + 1); vec.add(aa); vec.add(seq); vec.add(String.format("%.2f", score)); SpecificityEstimator est = selectedModel().getSpecEstimator(); String strSpec; if (est != null) { double spec = est.specificity(score); strSpec = String.format("%.2f%%", 100 * spec); } else { strSpec = ""; } vec.add(strSpec); // vec.add(String.format("%.2f%%", 100*sens)); data.add(vec); } } return data; } public boolean isSaved() { return saved; } private String panelName; private PredictionResult result; private Collection<Protein> proteinList; private Proteins groundTruth = null; private double specificity; private double threshold; private double maxScore; private double minScore; private boolean saved; private final int offset = 12; private ViewResultTextPane displayTextPane; private ViewResultTable displayTable; private TreeMap<Double, Color> mapScoreColor; private boolean lockSpec = false, lockScore = false, lockDisplay = false, ignoreSlideChangeEvent = false; // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JCheckBox alphabetCheckBox; private javax.swing.JTabbedPane displayTabbedPane; private javax.swing.JComboBox exportComboBox; private javax.swing.JComboBox modelComboBox; private javax.swing.JCheckBox phosphoCheckBox; private javax.swing.JComboBox proteinListComboBox; private javax.swing.JPanel resDispPanel; private javax.swing.JTextField scoreCutoffTextField; private javax.swing.JScrollPane sequenceScrollPane; private javax.swing.JScrollPane sitesScrollPane; private javax.swing.JComboBox sliderTitleComboBox; private javax.swing.JSlider specificitySlider; private javax.swing.JTextField specificityTextField; // End of variables declaration//GEN-END:variables private Color getColorOfSite(double score) { double leftScore = 0; double rightScore = 0; for (double tick : mapScoreColor.keySet()) { if (Math.abs(tick - score) < (maxScore - minScore) / maxTick / 2) return mapScoreColor.get(tick); if (tick < score) { leftScore = tick; } else { rightScore = tick; break; } } Color leftColor = mapScoreColor.get(leftScore); Color rightColor = mapScoreColor.get(rightScore); float[] leftRGB = leftColor.getRGBColorComponents(null); float[] rightRGB = rightColor.getRGBColorComponents(null); float perc = (float) ((score - leftScore) / (rightScore - leftScore)); float red = (rightRGB[0] - leftRGB[0]) * perc + leftRGB[0]; float green = (rightRGB[1] - leftRGB[1]) * perc + leftRGB[1]; float blue = (rightRGB[2] - leftRGB[2]) * perc + leftRGB[2]; return new Color(red, green, blue); } private Color invertColor(Color color) { float[] rgb = color.getRGBColorComponents(null); return new Color(1 - rgb[0], 1 - rgb[1], 1 - rgb[2]); } class ViewResultTable extends CTable { public ViewResultTable() { setEnabled(false); this.setRowHeight(20); setHeaderRowMerged(); } private void setHeaderRowMerged() { final int columns = header.size(); CMap map = new CMap() { public int span(int row, int column) { if (isHeaderRow(row)) return columns; return 1; } public int visibleCell(int row, int column) { if (isHeaderRow(row)) return 0; return column; } }; setCMap(map); } protected void setCellRenderer() { final TableCellRenderer headAlignRender = new TableCellRenderer() { private DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer(); public java.awt.Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { java.awt.Component comp = table.getTableHeader().getDefaultRenderer() .getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (comp instanceof JLabel) { ((JLabel) comp).setHorizontalAlignment(JLabel.CENTER); return comp; } else { JLabel label = (JLabel) cellRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); label.setHorizontalAlignment(JLabel.CENTER); label.setBackground(comp.getBackground()); label.setForeground(comp.getForeground()); label.setFont(comp.getFont()); return label; } } }; final TableCellRenderer midAlignRender = new TableCellRenderer() { private DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer(); public java.awt.Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JLabel label; java.awt.Component comp = table.getDefaultRenderer(String.class) .getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (comp instanceof JLabel) { label = ((JLabel) comp); } else { label = (JLabel) cellRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); label.setHorizontalAlignment(JLabel.CENTER); label.setForeground(comp.getForeground()); label.setFont(comp.getFont()); //label.setFont(new Font("Serif", table.getFont().getStyle(), 14)); } if (isHeaderRow(row)) { label.setHorizontalAlignment(JLabel.LEFT); label.setBackground(Color.LIGHT_GRAY); } else { label.setHorizontalAlignment(JLabel.CENTER); label.setBackground(Color.WHITE); } return label; } }; final TableCellRenderer seqAlignRender = new TableCellRenderer() { public java.awt.Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (isHeaderRow(row)) { return midAlignRender.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); } JTextPane textPane = new JTextPane(); textPane.setForeground(table.getForeground()); textPane.setBackground(table.getBackground()); textPane.setFont(new Font("Monospaced", table.getFont().getStyle(), 14)); if (value == null) { return textPane; } String str = value.toString(); Pattern p = Pattern.compile("\\[(.+)(.)\\]"); Matcher m = p.matcher(str); if (m.find()) { int site = m.start(); double score = Double.parseDouble(m.group(1)); textPane.setText(m.replaceFirst("$2")); StyledDocument doc = textPane.getStyledDocument(); SimpleAttributeSet attrSet = new SimpleAttributeSet(); Color color = getColorOfSite(score); StyleConstants.setBackground(attrSet, color); StyleConstants.setForeground(attrSet, invertColor(color)); doc.setCharacterAttributes(site, 1, attrSet, true); attrSet = new SimpleAttributeSet(); StyleConstants.setAlignment(attrSet, StyleConstants.ALIGN_CENTER); doc.setParagraphAttributes(0, 0, attrSet, true); } return textPane; } }; TableColumnModel colModel = getColumnModel(); // header column int colSeq = colModel.getColumnIndex(headerSeq); TableColumn column = colModel.getColumn(colSeq); column.setCellRenderer(seqAlignRender); //column.setHeaderRenderer(headAlignRender); int nCol = colModel.getColumnCount(); for (int i = 0; i < nCol; i++) { if (i != colSeq) { column = colModel.getColumn(i); column.setCellRenderer(midAlignRender); column.setHeaderRenderer(headAlignRender); } } } private void setPreferredColumnWidths(double[] percentages) { java.awt.Dimension tableDim = this.getPreferredSize(); double total = 0; for (int i = 0; i < getColumnModel().getColumnCount(); i++) total += percentages[i]; for (int i = 0; i < getColumnModel().getColumnCount(); i++) { TableColumn column = getColumnModel().getColumn(i); column.setPreferredWidth((int) (tableDim.width * (percentages[i] / total))); } } private boolean isHeaderRow(int row) { if (row < 0 || row >= getRowCount()) return false; Object value = getModel().getValueAt(row, 0); if (value == null) return false; return value.toString().startsWith(">"); } public void setResult(final PredictionResult result) { if (result == null) { setModel(new DefaultTableModel()); return; } Vector data = formatData(result.proteins(), true, proteinListComboBox.getSelectedIndex() >= proteinListComboBox.getItemCount() - 1); setModel(new DefaultTableModel(data, header)); setCellRenderer(); setPreferredColumnWidths(new double[] { 1.0, 1.0, 4.0, 1.0, 1.0 }); } } class ViewResultTextPane extends JTextPane { private final int scorePrecision = 5; private boolean suppressRepaint = false; public ViewResultTextPane() { this.setEditable(false); setFont(new Font("Monospaced", getFont().getStyle(), 14)); //this.setForeground(Color.DARK_GRAY); } public void repaint(long tm, int x, int y, int width, int height) { if (!suppressRepaint) super.repaint(tm, x, y, width, height); } // public void paint(java.awt.Graphics g) { // if (!suppressRepaint) // super.paint(g); // } public void setResult(final PredictionResult result) { // formart sequence DefaultProteinsFastaWriter proteinsWriter = new DefaultProteinsFastaWriter(); proteinsWriter.setDisplayNumber(true); proteinsWriter.setAAPerWord(10); proteinsWriter.setResidueAnnotator(new ResidueAnnotator() { public String annotate(Protein protein, int index) { PredictionModel model = selectedModel(); String acc = protein.getAccession(); Map<Integer, Double> preds = result.getPredictedSites(model, acc); String score = String.format("%." + scorePrecision + "f", preds.get(index)); String res = "[" + score + protein.getSequence().charAt(index) + "]"; if (groundTruth == null) { return res; } Set<Integer> trueSites = new TreeSet(); Protein pro = groundTruth.getProtein(protein.getAccession()); if (pro != null) { trueSites = musite.PTMAnnotationUtil.getSites(pro, model.getSupportedPTM(), model.getSupportedAminoAcid()); } if (trueSites.isEmpty()) { return res; } if (!preds.containsKey(index)) { return res = ""; } if (trueSites.contains(index)) { res += "#"; } return res; } public Set<Integer> indicesOfResidues(Protein protein) { PredictionModel model = selectedModel(); Map<Integer, Double> preds = result.getPredictedSites(model, protein.getAccession()); if (preds == null) return new HashSet(); Set<Integer> sites = preds.keySet(); if (groundTruth != null) { Protein pro = groundTruth.getProtein(protein.getAccession()); if (pro != null) { sites.addAll(musite.PTMAnnotationUtil.getSites(pro, model.getSupportedPTM(), model.getSupportedAminoAcid())); } } return sites; } }); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { proteinsWriter.write(baos, result); } catch (java.io.IOException e) { e.printStackTrace(); } String str = baos.toString(); str = str.replaceAll("\r\n", "\n"); // convert to unix style // replace sites and return location HashMap<Integer, Double> mapLocScore = new HashMap(); HashSet<Integer> trueSites = new HashSet(); int nRemoved = 0; Pattern p = Pattern.compile("\\[(-?[0-9]*\\.[0-9]{" + scorePrecision + "})?(p?).\\]"); Matcher m = p.matcher(str); while (m.find()) { int start = m.start(); int site = start - nRemoved; String s = m.group(1); if (s != null && s.length() > 0) { nRemoved += s.length();//[] Double score = Double.valueOf(s); mapLocScore.put(site, score); } s = m.group(2); if (s != null && s.length() == 1) { nRemoved++; //p trueSites.add(site); } nRemoved += 2;//[] } str = str.replaceAll("\\[(-?[0-9]*\\.[0-9]{" + scorePrecision + "})?p?(.)\\]", "$2"); // header List<int[]> headerLocs = new ArrayList(); p = Pattern.compile(">[^\n]+"); m = p.matcher(str); while (m.find()) { int[] locs = new int[2]; locs[0] = m.start(); locs[1] = m.end(); headerLocs.add(locs); } // line number List<int[]> numberLocs = new ArrayList(); p = Pattern.compile("\n([0-9]+ *)"); m = p.matcher(str); while (m.find()) { int[] locs = new int[2]; locs[0] = m.start(1); locs[1] = m.end(1); numberLocs.add(locs); } suppressRepaint = true; // set text setText(str); // set style StyledDocument doc = getStyledDocument(); { // render header SimpleAttributeSet attrSet = new SimpleAttributeSet(); StyleConstants.setBackground(attrSet, Color.LIGHT_GRAY); for (int[] header : headerLocs) { doc.setCharacterAttributes(header[0], header[1] - header[0], attrSet, false); } } { // render number SimpleAttributeSet attrSet = new SimpleAttributeSet(); StyleConstants.setForeground(attrSet, Color.GRAY); for (int[] num : numberLocs) { doc.setCharacterAttributes(num[0], num[1] - num[0], attrSet, false); } } { // render predictions by highlighting for (Map.Entry<Integer, Double> entry : mapLocScore.entrySet()) { int site = entry.getKey(); double score = entry.getValue(); Color color = getColorOfSite(score); SimpleAttributeSet attrSet = new SimpleAttributeSet(); StyleConstants.setBackground(attrSet, color); StyleConstants.setForeground(attrSet, invertColor(color)); //StyleConstants.setUnderline(attrSet, true); doc.setCharacterAttributes(site, 1, attrSet, false); } // render true sites by underlining for (int site : trueSites) { SimpleAttributeSet attrSet = new SimpleAttributeSet(); StyleConstants.setUnderline(attrSet, true); doc.setCharacterAttributes(site, 1, attrSet, false); } } suppressRepaint = false; repaint(); } } }