1 /* OrthoParalogTable.java 2 * This file is part of Artemis 3 * 4 * Copyright (C) 2007 Genome Research Limited 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 * 20 */ 21 22 package uk.ac.sanger.artemis.components.genebuilder.ortholog; 23 24 import java.awt.Color; 25 import java.awt.Component; 26 import java.awt.Cursor; 27 import java.awt.Dimension; 28 import java.awt.Font; 29 import java.awt.event.ActionEvent; 30 import java.awt.event.ActionListener; 31 import java.awt.event.MouseAdapter; 32 import java.awt.event.MouseEvent; 33 import java.awt.event.MouseMotionAdapter; 34 import java.util.Arrays; 35 import java.util.Collections; 36 import java.util.Comparator; 37 import java.util.List; 38 import java.util.Vector; 39 40 import javax.swing.JButton; 41 import javax.swing.JCheckBox; 42 import javax.swing.JLabel; 43 import javax.swing.JMenuItem; 44 import javax.swing.JOptionPane; 45 import javax.swing.JPopupMenu; 46 import javax.swing.JTable; 47 import javax.swing.JTextArea; 48 import javax.swing.JTextField; 49 import javax.swing.ListSelectionModel; 50 import javax.swing.SwingConstants; 51 import javax.swing.UIManager; 52 import javax.swing.table.DefaultTableCellRenderer; 53 import javax.swing.table.DefaultTableModel; 54 import javax.swing.table.TableColumn; 55 import javax.swing.table.TableModel; 56 57 import org.gmod.schema.sequence.FeatureLoc; 58 59 import uk.ac.sanger.artemis.Feature; 60 import uk.ac.sanger.artemis.FeaturePredicate; 61 import uk.ac.sanger.artemis.chado.ArtemisUtils; 62 import uk.ac.sanger.artemis.chado.ClusterLazyQualifierValue; 63 import uk.ac.sanger.artemis.io.ChadoCanonicalGene; 64 import uk.ac.sanger.artemis.io.DocumentEntry; 65 import uk.ac.sanger.artemis.io.GFFStreamFeature; 66 import uk.ac.sanger.artemis.io.InvalidRelationException; 67 import uk.ac.sanger.artemis.io.PartialSequence; 68 import uk.ac.sanger.artemis.io.Qualifier; 69 import uk.ac.sanger.artemis.io.QualifierLazyLoading; 70 import uk.ac.sanger.artemis.io.QualifierVector; 71 import uk.ac.sanger.artemis.sequence.AminoAcidSequence; 72 import uk.ac.sanger.artemis.util.DatabaseDocument; 73 import uk.ac.sanger.artemis.util.StringVector; 74 75 public class OrthoParalogTable extends AbstractMatchTable 76 { 77 private static int NUMBER_COLUMNS = 10; 78 private Vector rowData = new Vector(); 79 private Vector tableData = new Vector(NUMBER_COLUMNS); 80 private JTable table; 81 private JButton infoLevelButton = new JButton("Details"); 82 private JPopupMenu popupMenu = new JPopupMenu(); 83 private boolean showCluster; 84 85 // 86 // column headings 87 protected final static String CLUSTER_NAME_COL = "Cluster"; 88 protected final static String MATCH_NAME_COL = "Match"; 89 protected final static String ROW_TYPE_HIDE_COL = "Term"; 90 protected final static String ROW_TYPE_COL = "Type"; 91 protected final static String PROGRAM_COL = "Program"; 92 protected final static String ORGANISM_COL = "Organism"; 93 protected final static String PRODUCT_COL = "Product"; 94 protected final static String GENE_COL = "Gene"; 95 protected final static String LINK_COL = "Link"; 96 protected final static String VIEW_BUTTON_COL = "View"; 97 protected final static String REMOVE_BUTTON_COL = ""; 98 99 100 /** 101 * Contruct a component for an ortholog or paralog line 102 * @param doc 103 * @param orthologQualifier 104 * @param paralogQualifier 105 * @param feature 106 * @param showCluster 107 */ OrthoParalogTable(final DatabaseDocument doc, final Qualifier orthologQualifier, final Qualifier paralogQualifier, final Feature feature, final boolean showCluster)108 protected OrthoParalogTable(final DatabaseDocument doc, 109 final Qualifier orthologQualifier, 110 final Qualifier paralogQualifier, 111 final Feature feature, 112 final boolean showCluster) 113 { 114 this.origQualifiers = new QualifierVector(); 115 this.showCluster = showCluster; 116 117 if(orthologQualifier != null) 118 this.origQualifiers.add(orthologQualifier); 119 if(paralogQualifier != null) 120 this.origQualifiers.add(paralogQualifier); 121 122 createPopupMenu(doc, feature); 123 124 infoLevelButton.setOpaque(false); 125 tableData.setSize(NUMBER_COLUMNS); 126 127 tableData.setElementAt(CLUSTER_NAME_COL,0); 128 tableData.setElementAt(MATCH_NAME_COL,1); 129 tableData.setElementAt(ROW_TYPE_HIDE_COL,2); 130 if(showCluster) 131 tableData.setElementAt(PROGRAM_COL,3); 132 else 133 tableData.setElementAt(ROW_TYPE_COL,3); 134 tableData.setElementAt(ORGANISM_COL,4); 135 tableData.setElementAt(GENE_COL,5); 136 tableData.setElementAt(LINK_COL,6); 137 tableData.setElementAt(PRODUCT_COL,7); 138 tableData.setElementAt(VIEW_BUTTON_COL,8); 139 tableData.setElementAt(REMOVE_BUTTON_COL,9); 140 141 // add row data 142 int columnIndex; 143 144 for(int i=0; i<origQualifiers.size(); i++) 145 { 146 final Vector qualifierValuesToDelete = new Vector(); 147 148 final Qualifier origQualifier = (Qualifier) origQualifiers.elementAt(i); 149 150 // ensure the gene name is loaded as well 151 if(origQualifier instanceof QualifierLazyLoading) 152 { 153 List lazyValues = ((QualifierLazyLoading)origQualifier).getLazyValues(); 154 for(int j=0; j<lazyValues.size(); j++) 155 { 156 ClusterLazyQualifierValue lazyValue = (ClusterLazyQualifierValue)lazyValues.get(j); 157 158 if(!lazyValue.isLazyLoaded()) 159 lazyValue.setLoadGeneName(true); 160 } 161 } 162 163 final StringVector values = origQualifier.getValues(); 164 165 // sort by their rank value 166 Collections.sort(values, new OrthoParalogValueComparator()); 167 168 for(int j = 0; j < values.size(); j++) 169 { 170 StringVector rowStr = StringVector.getStrings((String) values.get(j), 171 ";"); 172 173 if(rowStr.size() < 1) 174 { 175 qualifierValuesToDelete.add(values.get(j)); 176 continue; 177 } 178 if( (ArtemisUtils.getString(rowStr, "cluster_name=").equals("") && !showCluster) || 179 (!ArtemisUtils.getString(rowStr, "cluster_name=").equals("") && showCluster) ) 180 processRowData(rowStr, rowData, origQualifier.getName()); 181 } 182 183 values.removeAll(qualifierValuesToDelete); 184 } 185 186 table = new JTable(rowData, tableData); 187 setTable(table); 188 189 // set hand cursor 190 table.addMouseMotionListener( new MouseMotionAdapter() 191 { 192 private Cursor handCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); 193 public void mouseMoved(MouseEvent e) 194 { 195 int col = table.columnAtPoint(e.getPoint()); 196 final String colName = table.getColumnName(col); 197 198 if(colName.equals(GENE_COL) || colName.equals(REMOVE_BUTTON_COL)) 199 table.setCursor(handCursor); 200 else 201 table.setCursor(Cursor.getDefaultCursor()); 202 } 203 }); 204 205 table.addMouseListener(new MouseAdapter() 206 { 207 public void mousePressed(MouseEvent e) 208 { 209 showPopup(e); 210 } 211 212 public void mouseReleased(MouseEvent e) 213 { 214 showPopup(e); 215 } 216 217 private void showPopup(MouseEvent e) 218 { 219 if(e.isPopupTrigger()) 220 popupMenu.show(e.getComponent(), e.getX(), e.getY()); 221 } 222 }); 223 224 final TableColumn[] hideColumns = new TableColumn[4]; 225 226 hideColumns[0] = table.getColumn(ROW_TYPE_HIDE_COL); 227 hideColumns[1] = table.getColumn(MATCH_NAME_COL); 228 if(showCluster) 229 hideColumns[2] = table.getColumn(REMOVE_BUTTON_COL); 230 else 231 hideColumns[2] = table.getColumn(CLUSTER_NAME_COL); 232 hideColumns[3] = table.getColumn(PRODUCT_COL); 233 234 for(int i=0; i<hideColumns.length; i++) 235 { 236 if(i == 3 && !showCluster) 237 continue; 238 hideColumns[i].setMinWidth(0); 239 hideColumns[i].setMaxWidth(0); 240 } 241 242 table.setColumnSelectionAllowed(false); 243 table.setRowSelectionAllowed(true); 244 table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 245 table.setDragEnabled(true); 246 table.setTransferHandler(new TableTransferHandler()); 247 248 TableModel tableModel = table.getModel(); 249 // remove button column 250 TableColumn col; 251 if(!showCluster) 252 { 253 col = table.getColumn(REMOVE_BUTTON_COL); 254 col.setMinWidth(35); 255 col.setMaxWidth(40); 256 col.setPreferredWidth(40); 257 } 258 259 final OrthologRenderer renderer = new OrthologRenderer(); 260 261 for(columnIndex = 0; columnIndex <tableModel.getColumnCount(); 262 columnIndex++) 263 { 264 col = table.getColumnModel().getColumn(columnIndex); 265 col.setCellRenderer(renderer); 266 col.setCellEditor(new CellEditing(new JTextField())); 267 } 268 269 packColumn(table, getColumnIndex(GENE_COL), 4); 270 packColumn(table, getColumnIndex(LINK_COL), 4); 271 packColumn(table, getColumnIndex(ORGANISM_COL), 4); 272 packColumn(table, getColumnIndex(VIEW_BUTTON_COL), 4); 273 274 if(showCluster) 275 { 276 packColumn(table, getColumnIndex(CLUSTER_NAME_COL), 4); 277 packColumn(table, getColumnIndex(PROGRAM_COL), 4); 278 } 279 else 280 { 281 packColumn(table, getColumnIndex(ROW_TYPE_COL), 4); 282 packColumn(table, getColumnIndex(PRODUCT_COL), 4); 283 } 284 285 // remove JButton column 286 col = table.getColumn(REMOVE_BUTTON_COL); 287 col.setCellEditor(new ButtonEditor(new JCheckBox(), 288 (DefaultTableModel)table.getModel(), "X", doc)); 289 290 // remove JButton column 291 col = table.getColumn(VIEW_BUTTON_COL); 292 col.setCellEditor(new ButtonEditor(new JCheckBox(), 293 (DefaultTableModel)table.getModel(), "VIEW", doc)); 294 295 // orthologue link 296 col = table.getColumn(GENE_COL); 297 col.setCellEditor(new LinkEditor(new JCheckBox(), 298 (DefaultTableModel)table.getModel(), doc)); 299 } 300 301 /** 302 * Parse the qualifier string into row data 303 * @param rowStr 304 * @param rowData 305 * @param qualifierName 306 */ processRowData(final StringVector rowStr, final Vector rowData, final String qualifierName)307 private void processRowData(final StringVector rowStr, 308 final Vector rowData, 309 final String qualifierName) 310 { 311 final String orthoparalogs[] = ((String) rowStr.get(0)).split(","); 312 313 String clusterName = ""; 314 if(rowStr.size() > 1) 315 { 316 clusterName = ArtemisUtils.getString(rowStr, "cluster_name="); 317 if(!clusterName.equals("")) 318 clusterName = clusterName.substring(13); 319 } 320 321 String matchName = ""; 322 if(rowStr.size() > 1) 323 { 324 matchName = ArtemisUtils.getString(rowStr, "match_name="); 325 if(!matchName.equals("")) 326 matchName = matchName.substring(11); 327 } 328 329 String program = ""; 330 if(rowStr.size() > 1) 331 { 332 program = ArtemisUtils.getString(rowStr, "program="); 333 if(!program.equals("")) 334 program = program.substring(8); 335 } 336 337 String product = ""; 338 if(rowStr.size() > 1) 339 { 340 product = ArtemisUtils.getString(rowStr, "product="); 341 if(!product.equals("")) 342 product = product.substring(8); 343 } 344 345 int columnIndex; 346 for(int k = 0; k < orthoparalogs.length; k++) 347 { 348 Vector thisRowData = new Vector(NUMBER_COLUMNS); 349 350 String geneNameAndLinkAndType[] = orthoparalogs[k].split("link="); 351 String linkAndType[] = geneNameAndLinkAndType[1].split("type="); 352 String gene[] = geneNameAndLinkAndType[0].trim().split(":"); 353 354 thisRowData.setSize(NUMBER_COLUMNS); 355 356 columnIndex = tableData.indexOf(ORGANISM_COL); 357 thisRowData.setElementAt(gene[0], columnIndex); 358 359 columnIndex = tableData.indexOf(GENE_COL); 360 thisRowData.setElementAt(geneNameAndLinkAndType[0].trim(), columnIndex); 361 362 columnIndex = tableData.indexOf(LINK_COL); 363 thisRowData.setElementAt(linkAndType[0].trim(), columnIndex); 364 365 columnIndex = tableData.indexOf(CLUSTER_NAME_COL); 366 thisRowData.setElementAt(clusterName, columnIndex); 367 368 columnIndex = tableData.indexOf(MATCH_NAME_COL); 369 thisRowData.setElementAt(matchName, columnIndex); 370 371 columnIndex = tableData.indexOf(ROW_TYPE_HIDE_COL); 372 thisRowData.setElementAt(qualifierName, columnIndex); 373 374 columnIndex = tableData.indexOf(PRODUCT_COL); 375 thisRowData.setElementAt(product, columnIndex); 376 377 columnIndex = tableData.indexOf(ROW_TYPE_COL); 378 379 if(columnIndex > -1) 380 { 381 final String symbol; 382 if(linkAndType[1].trim().equals(MatchPanel.ORTHOLOG)) 383 symbol = "O"; 384 else 385 symbol = "P"; 386 thisRowData.setElementAt(symbol, columnIndex); 387 } 388 389 columnIndex = tableData.indexOf(PROGRAM_COL); 390 if(columnIndex > -1) 391 thisRowData.setElementAt(program, columnIndex); 392 393 rowData.add(thisRowData); 394 } 395 } 396 397 /** 398 * Find if this contains any clusters 399 * @return 400 */ hasCluster(final Qualifier orthoQualifier, final Qualifier paraQualifier, final GFFStreamFeature feature)401 protected static boolean hasCluster(final Qualifier orthoQualifier, 402 final Qualifier paraQualifier, 403 final GFFStreamFeature feature) 404 { 405 if(hasClusterOrOrthoParalog(true, orthoQualifier, feature)) 406 return true; 407 return hasClusterOrOrthoParalog(true, paraQualifier, feature); 408 } 409 410 /** 411 * Find if this contains any ortholog or paralog 412 * @return 413 */ hasOrthoParlaog(final Qualifier orthoQualifier, final Qualifier paraQualifier, final GFFStreamFeature feature)414 protected static boolean hasOrthoParlaog(final Qualifier orthoQualifier, 415 final Qualifier paraQualifier, 416 final GFFStreamFeature feature) 417 { 418 if(hasClusterOrOrthoParalog(false, orthoQualifier, feature)) 419 { 420 forceBulkLoad(paraQualifier, feature); 421 return true; 422 } 423 return hasClusterOrOrthoParalog(false, paraQualifier, feature); 424 } 425 hasClusterOrOrthoParalog(final boolean lookForCluster, final Qualifier qualifier, final GFFStreamFeature feature)426 private static boolean hasClusterOrOrthoParalog(final boolean lookForCluster, 427 final Qualifier qualifier, 428 final GFFStreamFeature feature) 429 { 430 if(qualifier == null) 431 return false; 432 433 forceBulkLoad(qualifier, feature); 434 435 StringVector values = qualifier.getValues(); 436 437 for(int j = 0; j < values.size(); j++) 438 { 439 StringVector rowStr = StringVector.getStrings((String) values.get(j), 440 ";"); 441 442 if( (!ArtemisUtils.getString(rowStr, "cluster_name=").equals("") && lookForCluster) || 443 (ArtemisUtils.getString(rowStr, "cluster_name=").equals("") && !lookForCluster) ) 444 return true; 445 } 446 447 return false; 448 } 449 450 /** 451 * For long lists of ortho/paralogs this speeds-up their loading 452 * @param qualifier 453 * @param feature 454 */ forceBulkLoad(final Qualifier qualifier, final GFFStreamFeature feature)455 private static void forceBulkLoad(final Qualifier qualifier, 456 final GFFStreamFeature feature) 457 { 458 if(qualifier instanceof QualifierLazyLoading && 459 !((QualifierLazyLoading)qualifier).isAllLazyValuesLoaded()) 460 { 461 List values = ((QualifierLazyLoading)qualifier).getLazyValues(); 462 final DatabaseDocument document = 463 (DatabaseDocument)((DocumentEntry)feature.getEntry()).getDocument(); 464 ClusterLazyQualifierValue.setClusterFromValueList(values, document); 465 } 466 } 467 468 /** 469 * Find the parent feature 470 * @param feature 471 * @return 472 */ getParentFeature(final Feature feature)473 private Feature getParentFeature(final Feature feature) 474 { 475 final QualifierVector qualifiers = feature.getQualifiers(); 476 477 478 String featureId = null; 479 for(int i=0; i<qualifiers.size(); i++) 480 { 481 Qualifier qualifier = (Qualifier)qualifiers.elementAt(i); 482 if(qualifier.getName().equalsIgnoreCase("Derives_from") || 483 qualifier.getName().equalsIgnoreCase("Parent")) 484 { 485 featureId = (String) qualifier.getValues().get(0); 486 break; 487 } 488 } 489 FeatureNamePredicate predicate = new FeatureNamePredicate(featureId); 490 final uk.ac.sanger.artemis.FeatureVector features = feature.getEntry().getAllFeatures(); 491 for(int i=0; i<features.size(); i++) 492 { 493 Feature thisFeature = features.elementAt(i); 494 if(predicate.testPredicate(thisFeature)) 495 return thisFeature; 496 } 497 return null; 498 } 499 500 501 /** 502 * Create the popup menu for the table 503 * 504 */ createPopupMenu(final DatabaseDocument doc, final Feature feature)505 private void createPopupMenu(final DatabaseDocument doc, 506 final Feature feature) 507 { 508 JMenuItem showSequenceMenu = new JMenuItem("Show selected sequences"); 509 popupMenu.add(showSequenceMenu); 510 showSequenceMenu.addActionListener(new ActionListener() 511 { 512 public void actionPerformed(ActionEvent e) 513 { 514 Cursor orginalCursor = table.getCursor(); 515 table.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 516 showAlignmentEditor(feature, doc, false); 517 table.setCursor(orginalCursor); 518 } 519 }); 520 521 522 JMenuItem showAASequenceMenu = new JMenuItem("Show selected amino acid sequences"); 523 popupMenu.add(showAASequenceMenu); 524 showAASequenceMenu.addActionListener(new ActionListener() 525 { 526 public void actionPerformed(ActionEvent e) 527 { 528 Cursor orginalCursor = table.getCursor(); 529 table.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 530 showAlignmentEditor(feature, doc, true); 531 table.setCursor(orginalCursor); 532 } 533 }); 534 535 JMenuItem openMenu = new JMenuItem("Open selected in Artemis"); 536 popupMenu.add(openMenu); 537 openMenu.addActionListener(new ActionListener() 538 { 539 public void actionPerformed(ActionEvent e) 540 { 541 Cursor orginalCursor = table.getCursor(); 542 table.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 543 int selectedRows[] = getTable().getSelectedRows(); 544 545 if(selectedRows.length > 1) 546 { 547 int select = JOptionPane.showConfirmDialog(null, 548 "Open all selected sequences in seperate Artemis windows?", 549 "Open Artemis x"+selectedRows.length, JOptionPane.OK_CANCEL_OPTION); 550 if(select == JOptionPane.CANCEL_OPTION) 551 return; 552 } 553 for(int i=0; i<selectedRows.length; i++) 554 openArtemis(doc,selectedRows[i]); 555 table.setCursor(orginalCursor); 556 } 557 }); 558 } 559 560 /** 561 * Display this feature and selected features in the table in 562 * Jemboss alignment editor. 563 * @param feature 564 * @param doc 565 * @param showPeptideSequence 566 */ showAlignmentEditor(final Feature feature, final DatabaseDocument doc, final boolean showPeptideSequence)567 private void showAlignmentEditor(final Feature feature, 568 final DatabaseDocument doc, 569 final boolean showPeptideSequence) 570 { 571 final int[] rows = table.getSelectedRows(); 572 final int orthoColumn = getColumnIndex(GENE_COL); 573 final Vector seqs = new Vector(); 574 575 // find the gene feature 576 Feature gene = feature; 577 if(!feature.getKey().equals("gene")) 578 { 579 gene = getParentFeature(feature); 580 if(!gene.getKey().equals("gene")) 581 gene = getParentFeature(gene); 582 } 583 584 // find the exons for the gene 585 if(gene != null) 586 { 587 ChadoCanonicalGene chadoGene = ((GFFStreamFeature)gene.getEmblFeature()).getChadoGene(); 588 StringBuffer buffer = new StringBuffer(); 589 try 590 { 591 String transcriptName = 592 chadoGene.getTranscriptFromName((String) feature.getQualifierByName("ID").getValues().get(0)); 593 594 List exons = chadoGene.getSplicedFeaturesOfTranscript(transcriptName); 595 596 for (int i = 0 ; i < exons.size () ; ++i) 597 { 598 final uk.ac.sanger.artemis.io.Feature this_feature = 599 (uk.ac.sanger.artemis.io.Feature)exons.get(i); 600 buffer.append (((Feature)this_feature.getUserData()).getBases ()); 601 } 602 603 final String seqStr; 604 if(showPeptideSequence) 605 seqStr = AminoAcidSequence.getTranslation (buffer.toString(), true).toString(); 606 else 607 seqStr = buffer.toString(); 608 609 final String sysName = gene.getSystematicName(); 610 seqs.add(new org.emboss.jemboss.editor.Sequence(sysName, seqStr)); 611 } 612 catch(InvalidRelationException e) 613 { 614 e.printStackTrace(); 615 } 616 } 617 618 for(int i=0; i<rows.length; i++) 619 { 620 String ortho = (String)table.getValueAt(rows[i], orthoColumn); 621 final String reference[] = ortho.split(":"); 622 DatabaseDocument newdoc = new DatabaseDocument(doc, 623 reference[0], reference[1], true, stream_progress_listener); 624 625 try 626 { 627 // gene sequence 628 PartialSequence sequence = newdoc.getChadoSequence(reference[1]); 629 630 // cds featureloc's 631 List featureLocs = 632 newdoc.getCdsFeatureLocsByPeptideName( 633 (String)table.getValueAt(rows[i], getColumnIndex(LINK_COL))); 634 635 // 636 int phase = 0; 637 final StringBuffer sequenceBuffer = new StringBuffer(); 638 if(featureLocs != null) 639 { 640 for(int j = 0; j < featureLocs.size(); j++) 641 { 642 FeatureLoc featureLoc = (FeatureLoc) featureLocs.get(j); 643 if(featureLoc.getPhase() != null) 644 phase = featureLoc.getPhase().intValue(); 645 char[] subSeq = sequence.getCharSubSequence( 646 (featureLoc.getFmin().intValue() + 1), 647 featureLoc.getFmax().intValue()); 648 sequenceBuffer.append(subSeq); 649 } 650 } 651 else 652 { 653 char[] subSeq = sequence.getSequence(); 654 sequenceBuffer.append(subSeq); 655 if(sequence.getPhase() != null) 656 phase = sequence.getPhase().intValue(); 657 } 658 659 final String seqStr; 660 if(showPeptideSequence) 661 seqStr = AminoAcidSequence.getTranslation( 662 sequenceBuffer.toString().substring(phase), true).toString(); 663 else 664 seqStr = new String(sequenceBuffer.toString()); 665 666 seqs.add(new org.emboss.jemboss.editor.Sequence(ortho, seqStr)); 667 } 668 catch(NullPointerException npe) 669 { 670 JOptionPane.showMessageDialog(null, 671 "Cannot get the sequence for "+ortho, 672 "Warning", JOptionPane.WARNING_MESSAGE); 673 npe.printStackTrace(); 674 } 675 } 676 677 org.emboss.jemboss.editor.AlignJFrame ajFrame = 678 new org.emboss.jemboss.editor.AlignJFrame(seqs); 679 ajFrame.setVisible(true); 680 } 681 682 /** 683 * Called by AbstractMatchTable.updateQualifier() 684 */ updateQualifierString(final int row)685 protected String updateQualifierString(final int row) 686 { 687 final String type; 688 if( ((String)getTable().getValueAt(row, getColumnIndex(ROW_TYPE_COL))).equals("O") ) 689 type = MatchPanel.ORTHOLOG; 690 else 691 type = MatchPanel.PARALOG; 692 693 StringBuffer orthologStr = new StringBuffer( 694 (String)getTable().getValueAt(row, getColumnIndex(GENE_COL))+ 695 " link="+ 696 (String)getTable().getValueAt(row, getColumnIndex(LINK_COL))+ 697 " type="+type); // ortholog link 698 orthologStr.append(";"); 699 700 String clusterName = (String)getTable().getValueAt(row, getColumnIndex(CLUSTER_NAME_COL)); 701 if(clusterName != null && !clusterName.equals("")) 702 orthologStr.append("cluster_name="+clusterName+ ";" ); // cluster name 703 704 String product = (String)getTable().getValueAt(row, getColumnIndex(PRODUCT_COL)); 705 if(product != null && !product.equals("")) 706 orthologStr.append("product="+product+ ";" ); 707 708 709 String matchName = (String)getTable().getValueAt(row, getColumnIndex(MATCH_NAME_COL)); 710 if(matchName != null && !matchName.equals("")) 711 orthologStr.append("match_name="+matchName+ ";" ); // match name 712 713 orthologStr.append("rank="+row); 714 715 return orthologStr.toString(); 716 } 717 718 /** 719 * Override AbstractMatchTables.getOtherValues(). 720 * Removes all values apart from those that are not displayed in 721 * the table, i.e. depending on whether a cluster table is displayed 722 * or the ortholog/paralog table. 723 * @param origQualifier 724 * @return 725 */ getOtherValues(final Qualifier origQualifier)726 protected StringVector getOtherValues(final Qualifier origQualifier) 727 { 728 StringVector values = origQualifier.getValues(); 729 Vector removeValues = new Vector(); 730 for(int j=0; j<values.size(); j++) 731 { 732 String value = (String) values.elementAt(j); 733 if( (value.indexOf("cluster_name=") > -1 && showCluster) || 734 (value.indexOf("cluster_name=") < 0 && !showCluster) ) 735 removeValues.add(value); 736 } 737 values.removeAll(removeValues); 738 739 return values; 740 } 741 742 /** 743 * Returns true if the qualifier name matches the row type, e.g. 744 * orthologous_to / paralogous_to 745 * @param qualifierName 746 * @param row 747 * @return 748 */ isRowOfType(String qualifierName, int row)749 protected boolean isRowOfType(String qualifierName, int row) 750 { 751 String rowType = (String)getTable().getValueAt(row, getColumnIndex(ROW_TYPE_HIDE_COL)); 752 753 if(rowType.equals(qualifierName)) 754 return true; 755 return false; 756 } 757 758 /** 759 * Check whether ortholog/paralog qualifier string exists in a StringVector for that qualifier. 760 * If the StringVector contains the hit, description return true. 761 * @param qualStr 762 * @param qualStringVector 763 * @return 764 */ containsStringInStringVector(final String qualStr, final StringVector qualStringVector)765 public static boolean containsStringInStringVector(final String qualStr, 766 final StringVector qualStringVector) 767 { 768 final StringVector orth1 = StringVector.getStrings(qualStr, ";"); 769 final String clusterName1 = ArtemisUtils.getString(orth1, "cluster"); 770 //final String rank1 = ArtemisUtils.getString(orth1, "rank"); 771 String value1 = (String)orth1.get(0); 772 int index; 773 774 if(!clusterName1.equals("")) // if a part of a cluster 775 { 776 final String clusterElements1[] = value1.split(", "); 777 final List findAll = Arrays.asList(clusterElements1); 778 779 for(int i=0; i<findAll.size(); i++) 780 { 781 final String findMe = (String)findAll.get(i); 782 boolean found = false; 783 for(int j=0; j<qualStringVector.size(); j++) 784 { 785 String thisStr = (String)qualStringVector.get(j); 786 StringVector orth2 = StringVector.getStrings(thisStr, ";"); 787 final String clusterName2 = ArtemisUtils.getString(orth2, "cluster_name"); 788 if(!clusterName1.equals(clusterName2)) 789 continue; 790 791 String value2 = (String)orth2.get(0); 792 if((index = value2.indexOf('=')) > -1) 793 value2 = value2.substring(index+1); 794 String clusterElements2[] = value2.split(", "); 795 796 final List searchList = Arrays.asList(clusterElements2); 797 798 if(searchList.contains(findMe)) 799 found = true; 800 } 801 if(!found) 802 return false; 803 } 804 return true; 805 } 806 807 for(int i=0; i<qualStringVector.size(); i++) 808 { 809 String thisStr = (String)qualStringVector.get(i); 810 811 StringVector orth2 = StringVector.getStrings(thisStr, ";"); 812 813 if(orth1.size() != orth2.size()) 814 continue; 815 816 String value2 = (String)orth2.get(0); 817 if((index = value2.indexOf('=')) > -1) 818 value2 = value2.substring(index+1); 819 820 if(!clusterName1.equals("") && !ArtemisUtils.getString(orth2, "cluster_name").equals("")) 821 System.out.println(value1+" ==> "+value2); 822 // ortholog/paralog/cluster 823 if(value1.indexOf(value2) < 0 && 824 value2.indexOf(value1) < 0 ) 825 continue; 826 827 // cluster name 828 final String clusterName2 = ArtemisUtils.getString(orth2, "cluster_name"); 829 if(!clusterName1.equals(clusterName2)) 830 continue; 831 832 // rank 833 /* 834 final String rank2 = ArtemisUtils.getString(orth2, "rank"); 835 if(!rank1.equals(rank2)) 836 continue; 837 */ 838 839 // description 840 /* 841 if( orth1.size() > 1 && orth2.size() > 1 && 842 !((String)orth1.get(1)).equals((String)orth2.get(1)) ) 843 continue; 844 */ 845 846 return true; 847 } 848 return false; 849 } 850 851 /** 852 * Renderer for the Ortholog cells 853 */ 854 private class OrthologRenderer extends DefaultTableCellRenderer 855 { 856 /** */ 857 private static final long serialVersionUID = 1L; 858 private int minHeight = -1; 859 860 private final JLabel gene = new JLabel(); 861 private final JLabel link = new JLabel(); 862 private final JLabel type = new JLabel(); 863 private final JLabel program = new JLabel(); 864 private final JLabel symbol = new JLabel(); 865 private final JLabel organism = new JLabel(); 866 private final JLabel product = new JLabel(); 867 private final JTextArea descriptionTextArea = new JTextArea(); 868 private final JLabel clusterName = new JLabel(); 869 private final JLabel matchName = new JLabel(); 870 private final JLabel buttRemove = new JLabel("X"); 871 private final JLabel buttView = new JLabel("VIEW"); 872 private Color fgColor = new Color(139,35,35); 873 private Color fgLinkColor = Color.BLUE; 874 OrthologRenderer()875 public OrthologRenderer() 876 { 877 gene.setForeground(Color.BLUE); 878 gene.setOpaque(true); 879 880 clusterName.setOpaque(true); 881 organism.setOpaque(true); 882 link.setOpaque(true); 883 product.setOpaque(true); 884 885 descriptionTextArea.setLineWrap(true); 886 descriptionTextArea.setWrapStyleWord(true); 887 888 buttRemove.setOpaque(true); 889 buttRemove.setText("X"); 890 891 Font font = getFont().deriveFont(Font.BOLD); 892 buttRemove.setFont(font); 893 buttRemove.setToolTipText("REMOVE"); 894 buttRemove.setHorizontalAlignment(SwingConstants.CENTER); 895 896 buttView.setOpaque(true); 897 buttView.setFont(font); 898 buttView.setHorizontalAlignment(SwingConstants.CENTER); 899 900 symbol.setOpaque(true); 901 symbol.setFont(font); 902 symbol.setHorizontalAlignment(SwingConstants.CENTER); 903 } 904 905 getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, final int row, final int column)906 public Component getTableCellRendererComponent( 907 JTable table, 908 Object value, 909 boolean isSelected, 910 boolean hasFocus, 911 final int row, 912 final int column) 913 { 914 Component c = null; 915 String text = null; 916 if(value != null) 917 text = (String)value; 918 Dimension dim; 919 920 TableColumn tableCol; 921 if(column == getColumnIndex(GENE_COL)) 922 { 923 String geneStr[] = text.split(":"); 924 if(geneStr.length > 1) 925 gene.setText(geneStr[1]); 926 927 if(isSelected) 928 { 929 gene.setForeground(fgLinkColor); 930 gene.setBackground(table.getSelectionBackground()); 931 } 932 else 933 { 934 gene.setForeground(fgLinkColor); 935 gene.setBackground(UIManager.getColor("Button.background")); 936 } 937 938 c = gene; 939 } 940 else if(column == getColumnIndex(ORGANISM_COL)) 941 { 942 organism.setText(text); 943 c = organism; 944 } 945 else if(column == getColumnIndex(PRODUCT_COL)) 946 { 947 product.setText(text); 948 c = product; 949 } 950 else if(column == getColumnIndex(LINK_COL)) 951 { 952 link.setText(text); 953 c = link; 954 } 955 else if(column == getColumnIndex(CLUSTER_NAME_COL)) 956 { 957 clusterName.setText(text); 958 959 tableCol = table.getColumnModel().getColumn(column); 960 clusterName.setSize(tableCol.getWidth(), table 961 .getRowHeight(row)); 962 963 dim = clusterName.getPreferredSize(); 964 minHeight = Math.max(minHeight, dim.height); 965 c = clusterName; 966 } 967 else if(column == getColumnIndex(MATCH_NAME_COL)) 968 { 969 matchName.setText(text); 970 c = matchName; 971 } 972 else if(column == getColumnIndex(ROW_TYPE_HIDE_COL)) 973 { 974 type.setText(text); 975 c = type; 976 } 977 else if(column == getColumnIndex(PROGRAM_COL)) 978 { 979 program.setText(text); 980 c = program; 981 } 982 else if(column == getColumnIndex(ROW_TYPE_COL)) 983 { 984 symbol.setText(text); 985 986 if(text.equals("O")) 987 symbol.setForeground(fgColor); 988 else 989 symbol.setForeground(Color.GREEN); 990 tableCol = table.getColumnModel().getColumn(column); 991 symbol.setSize(tableCol.getWidth(), table 992 .getRowHeight(row)); 993 994 dim = symbol.getPreferredSize(); 995 minHeight = Math.max(minHeight, dim.height); 996 c = symbol; 997 } 998 else if(column == getColumnIndex(VIEW_BUTTON_COL)) 999 { 1000 if(isSelected) 1001 { 1002 buttView.setForeground(fgColor); 1003 buttView.setBackground(table.getSelectionBackground()); 1004 } 1005 else 1006 { 1007 buttView.setForeground(fgColor); 1008 buttView.setBackground(UIManager.getColor("Button.background")); 1009 } 1010 c = buttView; 1011 } 1012 else if(column == getColumnIndex(REMOVE_BUTTON_COL)) 1013 { 1014 if(isSelected) 1015 { 1016 buttRemove.setForeground(fgColor); 1017 buttRemove.setBackground(table.getSelectionBackground()); 1018 } 1019 else 1020 { 1021 buttRemove.setForeground(fgColor); 1022 buttRemove.setBackground(UIManager.getColor("Button.background")); 1023 } 1024 c = buttRemove; 1025 } 1026 else 1027 { 1028 throw new RuntimeException("invalid column! " + column + 1029 " " + text); 1030 } 1031 1032 // adjust row height for columns with multiple lines 1033 if(column < 3) 1034 { 1035 if(table.getRowHeight(row) < minHeight) 1036 table.setRowHeight(row, minHeight); 1037 1038 minHeight = -1; 1039 } 1040 1041 // highlight on selection 1042 if(isSelected) 1043 c.setBackground(table.getSelectionBackground()); 1044 else 1045 c.setBackground(Color.white); 1046 1047 return c; 1048 } 1049 } 1050 1051 public class OrthoParalogValueComparator implements Comparator 1052 { compare(Object o1, Object o2)1053 public int compare(Object o1, Object o2) 1054 { 1055 final String value1 = (String)o1; 1056 final String value2 = (String)o2; 1057 1058 StringVector values1 = StringVector.getStrings((String)value1, ";"); 1059 String rank1 = ArtemisUtils.getString(values1, "rank"); 1060 if(!rank1.equals("")) 1061 { 1062 if(rank1.startsWith("rank=") || rank1.startsWith("rank ")) 1063 rank1 = rank1.substring(5); 1064 } 1065 else 1066 rank1 = "0"; 1067 1068 StringVector values2 = StringVector.getStrings((String)value2, ";"); 1069 String rank2 = ArtemisUtils.getString(values2, "rank"); 1070 if(!rank2.equals("")) 1071 { 1072 if(rank2.startsWith("rank=") || rank2.startsWith("rank ")) 1073 rank2 = rank2.substring(5); 1074 } 1075 else 1076 rank2 = "0"; 1077 1078 1079 return (new Integer(rank1)).compareTo(new Integer(rank2)); 1080 } 1081 } 1082 1083 public class FeatureNamePredicate implements FeaturePredicate 1084 { 1085 private String uniqueName; 1086 FeatureNamePredicate(final String uniqueName)1087 public FeatureNamePredicate(final String uniqueName) 1088 { 1089 this.uniqueName = uniqueName; 1090 } 1091 testPredicate(Feature feature)1092 public boolean testPredicate(Feature feature) 1093 { 1094 try 1095 { 1096 String featureId = (String)feature.getQualifierByName("ID").getValues().get(0); 1097 if(featureId.equals(uniqueName)) 1098 return true; 1099 } 1100 catch(InvalidRelationException e){} 1101 1102 return false; 1103 } 1104 1105 } 1106 }