/* OrthoParalogTable.java * This file is part of Artemis * * Copyright (C) 2007 Genome Research Limited * * 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 2 * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package uk.ac.sanger.artemis.components.genebuilder.ortholog; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Vector; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.ListSelectionModel; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; import javax.swing.table.TableModel; import org.gmod.schema.sequence.FeatureLoc; import uk.ac.sanger.artemis.Feature; import uk.ac.sanger.artemis.FeaturePredicate; import uk.ac.sanger.artemis.chado.ArtemisUtils; import uk.ac.sanger.artemis.chado.ClusterLazyQualifierValue; import uk.ac.sanger.artemis.io.ChadoCanonicalGene; import uk.ac.sanger.artemis.io.DocumentEntry; import uk.ac.sanger.artemis.io.GFFStreamFeature; import uk.ac.sanger.artemis.io.InvalidRelationException; import uk.ac.sanger.artemis.io.PartialSequence; import uk.ac.sanger.artemis.io.Qualifier; import uk.ac.sanger.artemis.io.QualifierLazyLoading; import uk.ac.sanger.artemis.io.QualifierVector; import uk.ac.sanger.artemis.sequence.AminoAcidSequence; import uk.ac.sanger.artemis.util.DatabaseDocument; import uk.ac.sanger.artemis.util.StringVector; public class OrthoParalogTable extends AbstractMatchTable { private static int NUMBER_COLUMNS = 10; private Vector rowData = new Vector(); private Vector tableData = new Vector(NUMBER_COLUMNS); private JTable table; private JButton infoLevelButton = new JButton("Details"); private JPopupMenu popupMenu = new JPopupMenu(); private boolean showCluster; // // column headings protected final static String CLUSTER_NAME_COL = "Cluster"; protected final static String MATCH_NAME_COL = "Match"; protected final static String ROW_TYPE_HIDE_COL = "Term"; protected final static String ROW_TYPE_COL = "Type"; protected final static String PROGRAM_COL = "Program"; protected final static String ORGANISM_COL = "Organism"; protected final static String PRODUCT_COL = "Product"; protected final static String GENE_COL = "Gene"; protected final static String LINK_COL = "Link"; protected final static String VIEW_BUTTON_COL = "View"; protected final static String REMOVE_BUTTON_COL = ""; /** * Contruct a component for an ortholog or paralog line * @param doc * @param orthologQualifier * @param paralogQualifier * @param feature * @param showCluster */ protected OrthoParalogTable(final DatabaseDocument doc, final Qualifier orthologQualifier, final Qualifier paralogQualifier, final Feature feature, final boolean showCluster) { this.origQualifiers = new QualifierVector(); this.showCluster = showCluster; if(orthologQualifier != null) this.origQualifiers.add(orthologQualifier); if(paralogQualifier != null) this.origQualifiers.add(paralogQualifier); createPopupMenu(doc, feature); infoLevelButton.setOpaque(false); tableData.setSize(NUMBER_COLUMNS); tableData.setElementAt(CLUSTER_NAME_COL,0); tableData.setElementAt(MATCH_NAME_COL,1); tableData.setElementAt(ROW_TYPE_HIDE_COL,2); if(showCluster) tableData.setElementAt(PROGRAM_COL,3); else tableData.setElementAt(ROW_TYPE_COL,3); tableData.setElementAt(ORGANISM_COL,4); tableData.setElementAt(GENE_COL,5); tableData.setElementAt(LINK_COL,6); tableData.setElementAt(PRODUCT_COL,7); tableData.setElementAt(VIEW_BUTTON_COL,8); tableData.setElementAt(REMOVE_BUTTON_COL,9); // add row data int columnIndex; for(int i=0; i 1) { clusterName = ArtemisUtils.getString(rowStr, "cluster_name="); if(!clusterName.equals("")) clusterName = clusterName.substring(13); } String matchName = ""; if(rowStr.size() > 1) { matchName = ArtemisUtils.getString(rowStr, "match_name="); if(!matchName.equals("")) matchName = matchName.substring(11); } String program = ""; if(rowStr.size() > 1) { program = ArtemisUtils.getString(rowStr, "program="); if(!program.equals("")) program = program.substring(8); } String product = ""; if(rowStr.size() > 1) { product = ArtemisUtils.getString(rowStr, "product="); if(!product.equals("")) product = product.substring(8); } int columnIndex; for(int k = 0; k < orthoparalogs.length; k++) { Vector thisRowData = new Vector(NUMBER_COLUMNS); String geneNameAndLinkAndType[] = orthoparalogs[k].split("link="); String linkAndType[] = geneNameAndLinkAndType[1].split("type="); String gene[] = geneNameAndLinkAndType[0].trim().split(":"); thisRowData.setSize(NUMBER_COLUMNS); columnIndex = tableData.indexOf(ORGANISM_COL); thisRowData.setElementAt(gene[0], columnIndex); columnIndex = tableData.indexOf(GENE_COL); thisRowData.setElementAt(geneNameAndLinkAndType[0].trim(), columnIndex); columnIndex = tableData.indexOf(LINK_COL); thisRowData.setElementAt(linkAndType[0].trim(), columnIndex); columnIndex = tableData.indexOf(CLUSTER_NAME_COL); thisRowData.setElementAt(clusterName, columnIndex); columnIndex = tableData.indexOf(MATCH_NAME_COL); thisRowData.setElementAt(matchName, columnIndex); columnIndex = tableData.indexOf(ROW_TYPE_HIDE_COL); thisRowData.setElementAt(qualifierName, columnIndex); columnIndex = tableData.indexOf(PRODUCT_COL); thisRowData.setElementAt(product, columnIndex); columnIndex = tableData.indexOf(ROW_TYPE_COL); if(columnIndex > -1) { final String symbol; if(linkAndType[1].trim().equals(MatchPanel.ORTHOLOG)) symbol = "O"; else symbol = "P"; thisRowData.setElementAt(symbol, columnIndex); } columnIndex = tableData.indexOf(PROGRAM_COL); if(columnIndex > -1) thisRowData.setElementAt(program, columnIndex); rowData.add(thisRowData); } } /** * Find if this contains any clusters * @return */ protected static boolean hasCluster(final Qualifier orthoQualifier, final Qualifier paraQualifier, final GFFStreamFeature feature) { if(hasClusterOrOrthoParalog(true, orthoQualifier, feature)) return true; return hasClusterOrOrthoParalog(true, paraQualifier, feature); } /** * Find if this contains any ortholog or paralog * @return */ protected static boolean hasOrthoParlaog(final Qualifier orthoQualifier, final Qualifier paraQualifier, final GFFStreamFeature feature) { if(hasClusterOrOrthoParalog(false, orthoQualifier, feature)) { forceBulkLoad(paraQualifier, feature); return true; } return hasClusterOrOrthoParalog(false, paraQualifier, feature); } private static boolean hasClusterOrOrthoParalog(final boolean lookForCluster, final Qualifier qualifier, final GFFStreamFeature feature) { if(qualifier == null) return false; forceBulkLoad(qualifier, feature); StringVector values = qualifier.getValues(); for(int j = 0; j < values.size(); j++) { StringVector rowStr = StringVector.getStrings((String) values.get(j), ";"); if( (!ArtemisUtils.getString(rowStr, "cluster_name=").equals("") && lookForCluster) || (ArtemisUtils.getString(rowStr, "cluster_name=").equals("") && !lookForCluster) ) return true; } return false; } /** * For long lists of ortho/paralogs this speeds-up their loading * @param qualifier * @param feature */ private static void forceBulkLoad(final Qualifier qualifier, final GFFStreamFeature feature) { if(qualifier instanceof QualifierLazyLoading && !((QualifierLazyLoading)qualifier).isAllLazyValuesLoaded()) { List values = ((QualifierLazyLoading)qualifier).getLazyValues(); final DatabaseDocument document = (DatabaseDocument)((DocumentEntry)feature.getEntry()).getDocument(); ClusterLazyQualifierValue.setClusterFromValueList(values, document); } } /** * Find the parent feature * @param feature * @return */ private Feature getParentFeature(final Feature feature) { final QualifierVector qualifiers = feature.getQualifiers(); String featureId = null; for(int i=0; i 1) { int select = JOptionPane.showConfirmDialog(null, "Open all selected sequences in seperate Artemis windows?", "Open Artemis x"+selectedRows.length, JOptionPane.OK_CANCEL_OPTION); if(select == JOptionPane.CANCEL_OPTION) return; } for(int i=0; i -1) value2 = value2.substring(index+1); String clusterElements2[] = value2.split(", "); final List searchList = Arrays.asList(clusterElements2); if(searchList.contains(findMe)) found = true; } if(!found) return false; } return true; } for(int i=0; i -1) value2 = value2.substring(index+1); if(!clusterName1.equals("") && !ArtemisUtils.getString(orth2, "cluster_name").equals("")) System.out.println(value1+" ==> "+value2); // ortholog/paralog/cluster if(value1.indexOf(value2) < 0 && value2.indexOf(value1) < 0 ) continue; // cluster name final String clusterName2 = ArtemisUtils.getString(orth2, "cluster_name"); if(!clusterName1.equals(clusterName2)) continue; // rank /* final String rank2 = ArtemisUtils.getString(orth2, "rank"); if(!rank1.equals(rank2)) continue; */ // description /* if( orth1.size() > 1 && orth2.size() > 1 && !((String)orth1.get(1)).equals((String)orth2.get(1)) ) continue; */ return true; } return false; } /** * Renderer for the Ortholog cells */ private class OrthologRenderer extends DefaultTableCellRenderer { /** */ private static final long serialVersionUID = 1L; private int minHeight = -1; private final JLabel gene = new JLabel(); private final JLabel link = new JLabel(); private final JLabel type = new JLabel(); private final JLabel program = new JLabel(); private final JLabel symbol = new JLabel(); private final JLabel organism = new JLabel(); private final JLabel product = new JLabel(); private final JTextArea descriptionTextArea = new JTextArea(); private final JLabel clusterName = new JLabel(); private final JLabel matchName = new JLabel(); private final JLabel buttRemove = new JLabel("X"); private final JLabel buttView = new JLabel("VIEW"); private Color fgColor = new Color(139,35,35); private Color fgLinkColor = Color.BLUE; public OrthologRenderer() { gene.setForeground(Color.BLUE); gene.setOpaque(true); clusterName.setOpaque(true); organism.setOpaque(true); link.setOpaque(true); product.setOpaque(true); descriptionTextArea.setLineWrap(true); descriptionTextArea.setWrapStyleWord(true); buttRemove.setOpaque(true); buttRemove.setText("X"); Font font = getFont().deriveFont(Font.BOLD); buttRemove.setFont(font); buttRemove.setToolTipText("REMOVE"); buttRemove.setHorizontalAlignment(SwingConstants.CENTER); buttView.setOpaque(true); buttView.setFont(font); buttView.setHorizontalAlignment(SwingConstants.CENTER); symbol.setOpaque(true); symbol.setFont(font); symbol.setHorizontalAlignment(SwingConstants.CENTER); } public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, final int row, final int column) { Component c = null; String text = null; if(value != null) text = (String)value; Dimension dim; TableColumn tableCol; if(column == getColumnIndex(GENE_COL)) { String geneStr[] = text.split(":"); if(geneStr.length > 1) gene.setText(geneStr[1]); if(isSelected) { gene.setForeground(fgLinkColor); gene.setBackground(table.getSelectionBackground()); } else { gene.setForeground(fgLinkColor); gene.setBackground(UIManager.getColor("Button.background")); } c = gene; } else if(column == getColumnIndex(ORGANISM_COL)) { organism.setText(text); c = organism; } else if(column == getColumnIndex(PRODUCT_COL)) { product.setText(text); c = product; } else if(column == getColumnIndex(LINK_COL)) { link.setText(text); c = link; } else if(column == getColumnIndex(CLUSTER_NAME_COL)) { clusterName.setText(text); tableCol = table.getColumnModel().getColumn(column); clusterName.setSize(tableCol.getWidth(), table .getRowHeight(row)); dim = clusterName.getPreferredSize(); minHeight = Math.max(minHeight, dim.height); c = clusterName; } else if(column == getColumnIndex(MATCH_NAME_COL)) { matchName.setText(text); c = matchName; } else if(column == getColumnIndex(ROW_TYPE_HIDE_COL)) { type.setText(text); c = type; } else if(column == getColumnIndex(PROGRAM_COL)) { program.setText(text); c = program; } else if(column == getColumnIndex(ROW_TYPE_COL)) { symbol.setText(text); if(text.equals("O")) symbol.setForeground(fgColor); else symbol.setForeground(Color.GREEN); tableCol = table.getColumnModel().getColumn(column); symbol.setSize(tableCol.getWidth(), table .getRowHeight(row)); dim = symbol.getPreferredSize(); minHeight = Math.max(minHeight, dim.height); c = symbol; } else if(column == getColumnIndex(VIEW_BUTTON_COL)) { if(isSelected) { buttView.setForeground(fgColor); buttView.setBackground(table.getSelectionBackground()); } else { buttView.setForeground(fgColor); buttView.setBackground(UIManager.getColor("Button.background")); } c = buttView; } else if(column == getColumnIndex(REMOVE_BUTTON_COL)) { if(isSelected) { buttRemove.setForeground(fgColor); buttRemove.setBackground(table.getSelectionBackground()); } else { buttRemove.setForeground(fgColor); buttRemove.setBackground(UIManager.getColor("Button.background")); } c = buttRemove; } else { throw new RuntimeException("invalid column! " + column + " " + text); } // adjust row height for columns with multiple lines if(column < 3) { if(table.getRowHeight(row) < minHeight) table.setRowHeight(row, minHeight); minHeight = -1; } // highlight on selection if(isSelected) c.setBackground(table.getSelectionBackground()); else c.setBackground(Color.white); return c; } } public class OrthoParalogValueComparator implements Comparator { public int compare(Object o1, Object o2) { final String value1 = (String)o1; final String value2 = (String)o2; StringVector values1 = StringVector.getStrings((String)value1, ";"); String rank1 = ArtemisUtils.getString(values1, "rank"); if(!rank1.equals("")) { if(rank1.startsWith("rank=") || rank1.startsWith("rank ")) rank1 = rank1.substring(5); } else rank1 = "0"; StringVector values2 = StringVector.getStrings((String)value2, ";"); String rank2 = ArtemisUtils.getString(values2, "rank"); if(!rank2.equals("")) { if(rank2.startsWith("rank=") || rank2.startsWith("rank ")) rank2 = rank2.substring(5); } else rank2 = "0"; return (new Integer(rank1)).compareTo(new Integer(rank2)); } } public class FeatureNamePredicate implements FeaturePredicate { private String uniqueName; public FeatureNamePredicate(final String uniqueName) { this.uniqueName = uniqueName; } public boolean testPredicate(Feature feature) { try { String featureId = (String)feature.getQualifierByName("ID").getValues().get(0); if(featureId.equals(uniqueName)) return true; } catch(InvalidRelationException e){} return false; } } }