1 /*************************************************************** 2 * 3 * This program is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU General Public License 5 * as published by the Free Software Foundation; either version 2 6 * of the License, or (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program; if not, write to the Free Software 15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * 17 * @author: Copyright (C) Tim Carver 18 * 19 ***************************************************************/ 20 21 package org.emboss.jemboss.editor; 22 23 import java.awt.*; 24 import java.awt.print.PageFormat; 25 import java.awt.print.Printable; 26 import java.awt.print.PrinterException; 27 import java.io.File; 28 import java.util.*; 29 30 import javax.swing.*; 31 32 import org.emboss.jemboss.gui.form.MultiLineToolTipUI; 33 34 /** 35 * 36 * This class can be used to get a grapical representation 37 * of a collection of sequences. 38 * 39 */ 40 public class GraphicSequenceCollection extends JPanel 41 implements Printable, Scrollable 42 { 43 44 /** Vector of sequences removed from panel */ 45 private Vector removedSeqs = new Vector(); 46 /** Vector containing Sequence objects */ 47 protected Vector seqs; 48 /** Vector containing graphical sequences */ 49 protected Vector graphicSequence; 50 /** Vector containing graphical names of sequences */ 51 protected Vector graphicName; 52 /** Colour scheme to use */ 53 protected Hashtable colorScheme; 54 /** Consensus plot */ 55 private PlotConsensus pc = null; 56 private int hgt; 57 private int len; 58 /** longest sequence length */ 59 protected int MAXSEQLENGTH = 0; 60 /** number of residues on each line for print */ 61 private int numResiduePerLine = 0; 62 /** panel for sequence numbers */ 63 protected SequenceJPanel numberDraw; 64 /** sequence scrollpane */ 65 protected JScrollPane jspSequence; 66 /** sequence name panel */ 67 private JPanel seqNamePanel; 68 /** container for sequences */ 69 protected Box seqBox; 70 /** container for sequence names */ 71 protected Box seqNameBox; 72 /** container for consensus plot */ 73 private Box plotconsSeqBox = null; 74 /** draw the sequence */ 75 protected boolean drawSequence; 76 /** draw black square around residues */ 77 protected boolean drawBlackBox; 78 /** colour residues */ 79 protected boolean drawColorBox; 80 /** draw sequence position number */ 81 protected boolean drawNumber; 82 /** draw as per prettplot */ 83 //private boolean prettPlot = false; 84 /** gap between sequences and consensus plot */ 85 private int plotConStrut = 20; 86 /** pretty plot values */ 87 private PrettyPlotJFrame prettyPlot; 88 /** scoring matrix */ 89 private Matrix mat; 90 91 /** 92 * 93 * @param seqs vector of sequences 94 * @param colorScheme sequence colour scheme 95 * @param jspSequence sequence scrollpane 96 * @param drawSequence true to draw the sequence 97 * @param drawBlackBox true to draw black square around residues 98 * @param drawColorBox true to colour residues 99 * @param drawNumber true to draw sequence position number 100 * @param statusField status field in the editor 101 * 102 */ GraphicSequenceCollection(Vector seqs, Hashtable colorScheme, JScrollPane jspSequence, boolean drawSequence, boolean drawBlackBox, boolean drawColorBox, boolean drawNumber, JTextField statusField)103 public GraphicSequenceCollection(Vector seqs, Hashtable colorScheme, 104 JScrollPane jspSequence, 105 boolean drawSequence, boolean drawBlackBox, 106 boolean drawColorBox, boolean drawNumber, 107 JTextField statusField) 108 { 109 super(new BorderLayout()); 110 this.seqs = seqs; 111 this.colorScheme = colorScheme; 112 this.jspSequence = jspSequence; 113 this.drawSequence = drawSequence; 114 this.drawBlackBox = drawBlackBox; 115 this.drawColorBox = drawColorBox; 116 this.drawNumber = drawNumber; 117 118 jspSequence.getViewport().setBackground(Color.white); 119 setBackground(Color.white); 120 MultiLineToolTipUI.initialize(); 121 graphicSequence = new Vector(); 122 graphicName = new Vector(); 123 124 // find maximum seq length 125 setMaxSeqLength(); 126 127 Box centerBox = new Box(BoxLayout.Y_AXIS); 128 seqBox = new Box(BoxLayout.Y_AXIS); 129 centerBox.add(seqBox); 130 131 Box westBox = new Box(BoxLayout.Y_AXIS); 132 seqNameBox = new Box(BoxLayout.Y_AXIS); 133 westBox.add(seqNameBox); 134 seqNamePanel = new JPanel(new BorderLayout()); 135 seqNamePanel.add(westBox,BorderLayout.CENTER); 136 seqNamePanel.setBackground(Color.white); 137 jspSequence.setRowHeaderView(seqNamePanel); 138 139 // draw residue/base numbering 140 if(drawNumber) 141 drawNumber(); 142 143 // draw names and sequences 144 Enumeration enumer = seqs.elements(); 145 while(enumer.hasMoreElements()) 146 addSequence((Sequence)enumer.nextElement(),false,0,0); 147 148 westBox.add(Box.createVerticalGlue()); 149 centerBox.add(Box.createVerticalGlue()); 150 plotconsSeqBox = new Box(BoxLayout.Y_AXIS); 151 centerBox.add(plotconsSeqBox); 152 add(centerBox,BorderLayout.CENTER); 153 154 int xfill = getNameWidth(); 155 seqNamePanel.setPreferredSize(new Dimension(xfill,2000)); 156 } 157 158 159 /** 160 * 161 * @param seqs vector of sequences 162 * @param jspSequence sequence scrollpane 163 * @param drawSequence true to draw the sequence 164 * @param drawBlackBox true to draw black square around residues 165 * @param drawColorBox true to colour residues 166 * @param drawNumber true to draw sequence position number 167 * @param statusField status field in the editor 168 * 169 */ GraphicSequenceCollection(Vector seqs, JScrollPane jspSequence, boolean drawSequence, boolean drawBlackBox, boolean drawColorBox, boolean drawNumber, JTextField statusField)170 public GraphicSequenceCollection(Vector seqs, JScrollPane jspSequence, 171 boolean drawSequence, boolean drawBlackBox, 172 boolean drawColorBox, boolean drawNumber, 173 JTextField statusField) 174 { 175 this(seqs,null,jspSequence,drawSequence, 176 drawBlackBox,drawColorBox,drawNumber,statusField); 177 } 178 179 /** 180 * 181 * Get the vector of Sequences 182 * @return vector of Sequences 183 * 184 */ getSequenceCollection()185 protected Vector getSequenceCollection() 186 { 187 return seqs; 188 } 189 190 191 /** 192 * 193 * Get the consensus sequence 194 * @return consensus sequence 195 * 196 */ getConsensusSequence()197 protected Sequence getConsensusSequence() 198 { 199 Enumeration enumer = seqs.elements(); 200 while(enumer.hasMoreElements()) 201 { 202 Sequence s = (Sequence)enumer.nextElement(); 203 String name = s.getName(); 204 if(name.equals(Consensus.DEFAULT_SEQUENCE_NAME)) 205 return s; 206 } 207 return null; 208 } 209 210 211 /** 212 * 213 * Get the number of sequences 214 * @return vector of Sequences 215 * 216 */ getNumberSequences()217 protected int getNumberSequences() 218 { 219 return seqs.size(); 220 } 221 222 223 /** 224 * 225 * Get the position of the sequence JViewPort 226 * @return position of the sequence JViewPort 227 * 228 */ getViewPosition()229 protected Point getViewPosition() 230 { 231 return jspSequence.getViewport().getViewPosition(); 232 } 233 234 /** 235 * 236 * Get the Rectangle being displayed by the sequence JViewPort 237 * @return rectangle being displayed by the sequence JViewPort 238 * 239 */ getViewRect()240 protected Rectangle getViewRect() 241 { 242 Rectangle r = jspSequence.getViewport().getViewRect(); 243 244 // adjustment for the sequence names on the west 245 // r.x = r.x - westBox.getWidth(); 246 // if(r.x < 0) 247 // r.x = 0; 248 return r; 249 } 250 251 /** 252 * 253 * Calculate and display the consensus plot 254 * @param File matrix - scoring matrix 255 * @param int wsize window size to average scores over 256 * 257 */ showConsensusPlot(File matrix, int wsize)258 protected void showConsensusPlot(File matrix, int wsize) 259 { 260 deleteConsensusPlot(); 261 SequenceJPanel sj = (SequenceJPanel)graphicSequence.get(0); 262 int interval = sj.getSequenceResidueWidth(); 263 264 pc = new PlotConsensus(matrix,seqs,wsize,interval,this); 265 pc.setBackground(Color.white); 266 267 Box XBox = new Box(BoxLayout.X_AXIS); 268 XBox.add(pc); 269 XBox.add(Box.createHorizontalGlue()); 270 plotconsSeqBox.add(Box.createVerticalStrut(plotConStrut)); 271 plotconsSeqBox.add(XBox); 272 plotconsSeqBox.add(Box.createVerticalGlue()); 273 Dimension dpane = getPanelSize(); 274 setMinimumSize(dpane); 275 setPreferredSize(dpane); 276 setJScrollPaneViewportView(); 277 } 278 279 /** 280 * 281 * Calculate and display the consensus plot 282 * @param File matrix - scoring matrix 283 * @param int wsize window size to average scores over 284 * 285 */ showConsensusPlot(Matrix mat, int wsize)286 protected void showConsensusPlot(Matrix mat, int wsize) 287 { 288 deleteConsensusPlot(); 289 SequenceJPanel sj = (SequenceJPanel)graphicSequence.get(0); 290 int interval = sj.getSequenceResidueWidth(); 291 292 Vector seqs_ = new Vector(seqs); 293 Sequence seq = (Sequence)seqs.lastElement(); 294 if (seq.getName().equals(Consensus.DEFAULT_SEQUENCE_NAME)) 295 seqs_.removeElementAt(seqs.size()-1); 296 pc = new PlotConsensus(mat,seqs_,wsize,interval,this); 297 pc.setBackground(Color.white); 298 299 Box XBox = new Box(BoxLayout.X_AXIS); 300 XBox.add(pc); 301 XBox.add(Box.createHorizontalGlue()); 302 plotconsSeqBox.add(Box.createVerticalStrut(20)); 303 plotconsSeqBox.add(XBox); 304 plotconsSeqBox.add(Box.createVerticalGlue()); 305 Dimension dpane = getPanelSize(); 306 setMinimumSize(dpane); 307 setPreferredSize(dpane); 308 setJScrollPaneViewportView(); 309 } 310 311 /** 312 * 313 * Remove the consensus plot from the sequence editor 314 * 315 */ deleteConsensusPlot()316 protected void deleteConsensusPlot() 317 { 318 plotconsSeqBox.removeAll(); 319 } 320 321 /** 322 * 323 * Set the longest sequence length 324 * @param max longest sequence length 325 * 326 */ setMaxSequenceLength(int max)327 protected void setMaxSequenceLength(int max) 328 { 329 if(max > MAXSEQLENGTH) 330 MAXSEQLENGTH = max; 331 } 332 333 /** 334 * 335 * Calculate the longest sequence length 336 * 337 */ setMaxSeqLength()338 protected void setMaxSeqLength() 339 { 340 MAXSEQLENGTH = 0; 341 Enumeration enumer = seqs.elements(); 342 while(enumer.hasMoreElements()) 343 { 344 Sequence seq = (Sequence)(enumer.nextElement()); 345 if(seq.getSequence().length()>MAXSEQLENGTH) 346 MAXSEQLENGTH = seq.getSequence().length(); 347 } 348 } 349 350 /** 351 * 352 * Get the longest sequence length 353 * @return longest sequence length 354 * 355 */ getMaxSeqLength()356 public int getMaxSeqLength() 357 { 358 return MAXSEQLENGTH; 359 } 360 361 /** 362 * 363 * Lock/group the sequences 364 * @param true to lock sequences 365 * 366 */ setSequenceLock(boolean llock)367 protected void setSequenceLock(boolean llock) 368 { 369 Enumeration enumer = graphicName.elements(); 370 if(!llock) 371 { 372 while(enumer.hasMoreElements()) 373 ((SequenceNameJButton)enumer.nextElement()).setSelected(false); 374 enumer = graphicSequence.elements(); 375 while(enumer.hasMoreElements()) 376 ((SequenceJPanel)enumer.nextElement()).detachAll(); 377 378 return; 379 } 380 381 int i = 0; 382 Vector selected = new Vector(); 383 while(enumer.hasMoreElements()) 384 { 385 SequenceNameJButton sbutt = (SequenceNameJButton)enumer.nextElement(); 386 if(sbutt.isSelected()) 387 selected.add((SequenceJPanel)graphicSequence.get(i)); 388 i++; 389 } 390 391 // group sequences 392 for(i=0;i<selected.size();i++) 393 { 394 SequenceJPanel si = (SequenceJPanel)selected.get(i); 395 for(int j=0;j<selected.size();j++) 396 if(i!=j) 397 ((SequenceJPanel)selected.get(j)).attach(si); 398 } 399 } 400 401 /** 402 * 403 * Set the size of the sequence number panel 404 * 405 */ setNumberSize()406 protected void setNumberSize() 407 { 408 Dimension actual = numberDraw.getMaximumSize(); 409 int slen = numberDraw.getResidueWidth()*(int)(MAXSEQLENGTH*1.5); 410 numberDraw.setMaximumSize(new Dimension(slen,(int)actual.getHeight())); 411 } 412 413 setMatrix(Matrix mat)414 protected void setMatrix(Matrix mat) 415 { 416 this.mat = mat; 417 } 418 419 /** 420 * 421 * Determine the colour of a residue at a given position. If 422 * the residues at that position in all the sequences are identical 423 * then return red otherwise return black. 424 * @param s residue at position pos 425 * @param pos residue position 426 * @param seqName sequence name 427 * @return red if all identical otherwise return black 428 * 429 */ getColor(String s, int pos, String seqName)430 protected Color getColor(String s, int pos, String seqName) 431 { 432 if(s.equals("-") || s.equals(".")) 433 return Color.black; 434 435 int identical = 1; 436 int nseqs = 0; 437 Enumeration enumer = seqs.elements(); 438 while(enumer.hasMoreElements()) 439 { 440 nseqs++; 441 Sequence seq = (Sequence)(enumer.nextElement()); 442 if(!seqName.equals(seq.getName())) 443 { 444 SequenceJPanel seqPanel = (SequenceJPanel)graphicSequence.get(nseqs); 445 if(pos < seq.getLength() && seqPanel.isPrettyPlot()) 446 if(seq.getResidue(pos).equalsIgnoreCase(s)) 447 identical++; 448 } 449 } 450 451 if(identical >= prettyPlot.getMinimumIdentity(nseqs)) 452 return prettyPlot.getIDColour(); 453 454 else if(mat != null) 455 { 456 double threshold = prettyPlot.getMatchThreshold(); 457 int m1 = mat.getMatrixIndex(s); 458 int matrix[][] = mat.getMatrix(); 459 float matching = 0.f; 460 nseqs = 0; 461 462 enumer = seqs.elements(); 463 while(enumer.hasMoreElements()) 464 { 465 nseqs++; 466 Sequence seq = (Sequence)(enumer.nextElement()); 467 SequenceJPanel seqPanel = (SequenceJPanel)graphicSequence.get(nseqs); 468 // if(!seqName.equals(seq.getName())) 469 // { 470 if(pos < seq.getLength() && seqPanel.isPrettyPlot()) 471 { 472 int m2 = mat.getMatrixIndex(seq.getResidue(pos)); 473 if(m1 >= 0 && m2 >= 0 && matrix[m1][m2]>0) 474 matching += seq.getWeight(); 475 } 476 // } 477 } 478 if(matching >= threshold) 479 return prettyPlot.getMatchColour(); 480 } 481 return Color.black; 482 } 483 484 485 /** 486 * 487 * Determine the colour of a residue background 488 * 489 */ getPrettyBackground(Color textColour)490 protected Color getPrettyBackground(Color textColour) 491 { 492 if(textColour.equals(prettyPlot.getIDColour())) 493 return prettyPlot.getIDBackgroundColour(); 494 else if(textColour.equals(prettyPlot.getMatchColour())) 495 return prettyPlot.getMatchBackgroundColour(); 496 else 497 return null; 498 } 499 500 501 /** 502 * 503 * Determine if the identities are to be boxed 504 * @return true if to draw boxes 505 * 506 */ isPrettyBox()507 protected boolean isPrettyBox() 508 { 509 return prettyPlot.isPrettyBox(); 510 } 511 512 513 /** 514 * 515 * 516 * 517 */ testUpAndDown(int pos, Sequence seq)518 protected int testUpAndDown(int pos, Sequence seq) 519 { 520 int seqIndex = seqs.indexOf(seq); 521 522 int testUp = -1; 523 if(seqIndex == 0) 524 testUp = 1; 525 else 526 { 527 Sequence seqUp = (Sequence)seqs.get(seqIndex-1); 528 String res = seqUp.getSequence().substring(pos,pos+1); 529 Color col = getColor(res,pos,seqUp.getName()); 530 if(col.equals(Color.black)) 531 testUp = 1; 532 } 533 534 int testDown = -1; 535 if(seqIndex+1 == seqs.size()) 536 testDown= 1; 537 else 538 { 539 Sequence seqDown = (Sequence)seqs.get(seqIndex+1); 540 SequenceJPanel seqPanelDown = (SequenceJPanel)graphicSequence.get(seqIndex+2); 541 String res = seqDown.getSequence().substring(pos,pos+1); 542 Color col = getColor(res,pos,seqDown.getName()); 543 if(col.equals(Color.black) || !seqPanelDown.isPrettyPlot()) 544 testDown = 1; 545 } 546 547 if(testUp > -1 && testDown > -1) 548 return 3; 549 else if(testDown > -1) 550 return 2; 551 else if(testUp > -1) 552 return 1; 553 return -1; 554 } 555 556 557 /** 558 * 559 * Remove a sequence from the editor display 560 * @param name name of sequence to remove 561 * 562 */ removeSequence(String name)563 private Sequence removeSequence(String name) 564 { 565 boolean removed = false; 566 int index = 0; 567 Enumeration enumer = seqs.elements(); 568 Sequence seq = null; 569 570 while(enumer.hasMoreElements()) 571 { 572 seq = (Sequence)enumer.nextElement(); 573 if(seq.getName().equals(name)) 574 { 575 removedSeqs.add(seq); 576 removed = true; 577 seqs.remove(seq); 578 break; 579 } 580 index++; 581 } 582 583 if(!removed) 584 return null; 585 if(drawNumber) 586 index++; 587 588 seqBox.remove(index); 589 seqNameBox.remove(index); 590 graphicName.removeElementAt(index); 591 graphicSequence.removeElementAt(index); 592 return seq; 593 } 594 595 /** 596 * 597 * Delete a sequence from the sequence collection display 598 * and resize the sequence panel display 599 * @param name name of sequence to remove 600 * 601 */ deleteSequence(String name)602 protected void deleteSequence(String name) 603 { 604 removeSequence(name); 605 setMaxSeqLength(); 606 numberDraw.setSequenceLength(MAXSEQLENGTH); 607 Dimension dpane = getPanelSize(); 608 setMinimumSize(dpane); 609 setPreferredSize(dpane); 610 numberDraw.setMaximumSize(numberDraw.getPreferredSize()); 611 numberDraw.setMinimumSize(numberDraw.getPreferredSize()); 612 setJScrollPaneViewportView(); 613 } 614 615 /** 616 * 617 * Move a sequence to a new position 618 * @param name name of sequence to remove 619 * @param i new position in the sequence editor 620 * 621 */ moveSequence(String name, int i)622 protected void moveSequence(String name, int i) 623 { 624 Sequence seq = removeSequence(name); 625 addSequence(seq,true,0,0,i); 626 } 627 628 /** 629 * 630 * Sorts the sequences and displays them by their id's 631 * 632 */ idSort()633 protected void idSort() 634 { 635 int nseqs = 0; 636 637 // get no. of sequences excl. consensus 638 Enumeration enumer = seqs.elements(); 639 while(enumer.hasMoreElements()) 640 { 641 String name = ((Sequence)enumer.nextElement()).getName(); 642 if(!name.equals(Consensus.DEFAULT_SEQUENCE_NAME)) 643 nseqs++; 644 } 645 646 String seqName[] = new String[nseqs]; 647 int i = 0; 648 enumer = seqs.elements(); 649 while(enumer.hasMoreElements()) 650 { 651 String name = ((Sequence)enumer.nextElement()).getName(); 652 if(!name.equals(Consensus.DEFAULT_SEQUENCE_NAME)) 653 { 654 seqName[i] = new String(name); 655 i++; 656 } 657 } 658 659 Arrays.sort(seqName); 660 for(i=0;i<nseqs;i++) 661 moveSequence(seqName[i],i); 662 } 663 664 /** 665 * 666 * Add a sequence at a particular index to the sequence 667 * collection display and to the collection of sequences 668 * (seqs) with a specified y-padding. 669 * @param seq sequence to add to the editor display 670 * @param addToSequences true to add seq to the vector of sequences 671 * @param ypad sequence panel height padding 672 * @param fontSize font size 673 * @param index sequence index 674 * 675 */ addSequence(Sequence seq, boolean addToSequences, int ypad, int fontSize, int index)676 protected void addSequence(Sequence seq, boolean addToSequences, 677 int ypad, int fontSize, int index) 678 { 679 if(addToSequences) 680 seqs.add(index,seq); 681 if(drawNumber) 682 index++; 683 684 SequenceJPanel gs = new SequenceJPanel(seq,this, 685 drawSequence,drawBlackBox,drawColorBox, 686 colorScheme,ypad); 687 graphicSequence.add(index,gs); 688 689 Box XBox = new Box(BoxLayout.X_AXIS); 690 XBox.add(gs); 691 XBox.add(Box.createHorizontalGlue()); 692 seqBox.add(XBox,index); 693 gs.setToolTipText(""); //enable tooltip display 694 695 SequenceNameJButton snj = new SequenceNameJButton(seq,ypad); 696 graphicName.add(index,snj); 697 XBox = new Box(BoxLayout.X_AXIS); 698 XBox.add(Box.createHorizontalGlue()); 699 XBox.add(snj); 700 seqNameBox.add(XBox,index); 701 702 if(seq.getLength()>MAXSEQLENGTH) 703 MAXSEQLENGTH = seq.getLength(); 704 705 Dimension actual = gs.getMaximumSize(); 706 int slen = gs.getResidueWidth()*(int)(MAXSEQLENGTH*1.2); 707 gs.setMaximumSize(new Dimension(slen,(int)actual.getHeight())); 708 } 709 710 711 712 /** 713 * 714 * Add a sequence to the sequence collection display and 715 * to the collection of sequences (seqs) with a specified 716 * y-padding. 717 * @param seq sequence to add to the editor display 718 * @param addToSequences true to add seq to the vector of sequences 719 * @param ypad sequence panel height padding 720 * @param fontSize font size 721 * 722 */ addSequence(Sequence seq, boolean addToSequences, int ypad, int fontSize)723 protected void addSequence(Sequence seq, boolean addToSequences, 724 int ypad, int fontSize) 725 { 726 if(addToSequences) 727 seqs.add(seq); 728 SequenceJPanel gs = new SequenceJPanel(seq,this, 729 drawSequence,drawBlackBox,drawColorBox, 730 colorScheme,fontSize,ypad); 731 graphicSequence.add(gs); 732 733 Box XBox = new Box(BoxLayout.X_AXIS); 734 XBox.add(gs); 735 XBox.add(Box.createHorizontalGlue()); 736 seqBox.add(XBox); 737 gs.setToolTipText(""); //enable tooltip display 738 739 SequenceNameJButton snj = new SequenceNameJButton(seq,ypad); 740 graphicName.add(snj); 741 XBox = new Box(BoxLayout.X_AXIS); 742 XBox.add(Box.createHorizontalGlue()); 743 XBox.add(snj); 744 seqNameBox.add(XBox); 745 746 if(seq.getLength()>MAXSEQLENGTH) 747 MAXSEQLENGTH = seq.getLength(); 748 749 Dimension actual = gs.getMaximumSize(); 750 int slen = gs.getResidueWidth()*(int)(MAXSEQLENGTH*1.2); 751 gs.setMaximumSize(new Dimension(slen,(int)actual.getHeight())); 752 } 753 754 755 /** 756 * 757 * Get the sequence view size 758 * @return sequence view dimension 759 * 760 */ getViewSize()761 public Dimension getViewSize() 762 { 763 hgt = 1; 764 len = 0; 765 Enumeration enumer = graphicSequence.elements(); 766 while(enumer.hasMoreElements()) 767 { 768 SequenceJPanel gs = (SequenceJPanel)enumer.nextElement(); 769 hgt = hgt+gs.getSequenceHeight(); 770 if(len<gs.getSequenceWidth()) 771 len = gs.getSequenceWidth(); 772 } 773 774 if(pc !=null) 775 { 776 Dimension dplot = pc.getPreferredSize(); 777 hgt = hgt + (int)dplot.getHeight() + plotConStrut; 778 } 779 return new Dimension(len,hgt); 780 } 781 782 getName(int i)783 public String getName(int i) 784 { 785 return ((Sequence)seqs.get(i)).getName(); 786 } 787 788 /** 789 * 790 * Get the sequence name view size 791 * @return sequence name dimension 792 * 793 */ getNameViewSize()794 public Dimension getNameViewSize() 795 { 796 int hgtName = getNameHeight(); 797 int lenName = getNameWidth(); 798 return new Dimension(lenName,hgtName); 799 } 800 801 /** 802 * 803 * Get the sequence view size 804 * @return sequence view dimension 805 * 806 */ getPanelSize()807 public Dimension getPanelSize() 808 { 809 getViewSize(); 810 return new Dimension(len,hgt); 811 } 812 813 /** 814 * 815 * Get the sequence name panel height 816 * @return sequence name panel height 817 * 818 */ getNameHeight()819 public int getNameHeight() 820 { 821 int hgtName = 0; 822 Enumeration enumer = graphicName.elements(); 823 while(enumer.hasMoreElements()) 824 hgtName = hgtName+ 825 ((SequenceNameJButton)enumer.nextElement()).getPanelHeight(); 826 return hgtName; 827 } 828 829 /** 830 * 831 * Get the sequence name panel width 832 * @return sequence name panel width 833 * 834 */ getNameWidth()835 public int getNameWidth() 836 { 837 int lenName = 0; 838 Enumeration enumer = graphicName.elements(); 839 while(enumer.hasMoreElements()) 840 { 841 SequenceNameJButton gs = (SequenceNameJButton)enumer.nextElement(); 842 if(lenName<gs.getPanelWidth()) 843 lenName = gs.getPanelWidth(); 844 } 845 return lenName; 846 } 847 848 /** 849 * 850 * Set the sequence name panel width 851 * @param x sequence name panel width 852 * 853 */ setNamePanelWidth(int x)854 public void setNamePanelWidth(int x) 855 { 856 seqNamePanel.setPreferredSize(new Dimension(x,1000)); 857 } 858 859 /** 860 * 861 * Get the sequence panel height 862 * @return sequence panel height 863 * 864 */ getPanelHeight()865 public int getPanelHeight() 866 { 867 getViewSize(); 868 return hgt; 869 } 870 871 /** 872 * 873 * Get the sequence panel width 874 * @return sequence panel width 875 * 876 */ getPanelWidth()877 public int getPanelWidth() 878 { 879 // getNameViewSize(); 880 getViewSize(); 881 return len; 882 } 883 884 /** 885 * 886 * Get the vector containing the SequenceJPanel objects 887 * @return vector containing the SequenceJPanel objects 888 * 889 */ getGraphicSequence()890 public Vector getGraphicSequence() 891 { 892 return graphicSequence; 893 } 894 895 /** 896 * 897 * Draw the boxes around the residues of each sequence 898 * @param true to draw boxes, false not to display 899 * boxes 900 * 901 */ setDrawBoxes(boolean drawBlackBox)902 public void setDrawBoxes(boolean drawBlackBox) 903 { 904 this.drawBlackBox = drawBlackBox; 905 Enumeration enumer = graphicSequence.elements(); 906 while(enumer.hasMoreElements()) 907 ((SequenceJPanel)(enumer.nextElement())).setDrawBoxes(drawBlackBox); 908 setJScrollPaneViewportView(); 909 } 910 911 /** 912 * 913 * Draw the residue colours in each sequence 914 * @param true to display colour, false not to display 915 * colour 916 * 917 */ setDrawColor(boolean drawColorBox)918 public void setDrawColor(boolean drawColorBox) 919 { 920 this.drawColorBox = drawColorBox; 921 Enumeration enumer = graphicSequence.elements(); 922 while(enumer.hasMoreElements()) 923 ((SequenceJPanel)(enumer.nextElement())).setDrawColor(drawColorBox); 924 setJScrollPaneViewportView(); 925 } 926 927 /** 928 * 929 * Set the font size of the sequences in the editor 930 * @param font size to use 931 * 932 */ setFontSizeForCollection(int fs)933 public void setFontSizeForCollection(int fs) 934 { 935 Enumeration enumer = graphicSequence.elements(); 936 937 while(enumer.hasMoreElements()) 938 { 939 SequenceJPanel gs = (SequenceJPanel)enumer.nextElement(); 940 gs.setFontSize(fs); 941 Dimension actual = gs.getMaximumSize(); 942 int slen = gs.getResidueWidth()*(int)(MAXSEQLENGTH*1.2); 943 gs.setMaximumSize(new Dimension(slen,(int)actual.getHeight())); 944 } 945 946 Enumeration enumName = graphicName.elements(); 947 while(enumName.hasMoreElements()) 948 { 949 SequenceNameJButton snjp = (SequenceNameJButton)enumName.nextElement(); 950 snjp.setFontSize(fs); 951 snjp.setMaximumSize(snjp.getPreferredSize()); 952 } 953 954 // rescale consensus plot 955 if(pc != null) 956 { 957 SequenceJPanel sj = (SequenceJPanel)graphicSequence.get(0); 958 int interval = sj.getSequenceResidueWidth(); 959 pc.setInterval(interval); 960 pc.setPlotSize(); 961 } 962 963 // 964 Dimension dpane = getPanelSize(); 965 setMinimumSize(dpane); 966 setPreferredSize(dpane); 967 968 setNamePanelWidth(getNameWidth()); 969 setJScrollPaneViewportView(); 970 } 971 972 /** 973 * 974 * Get the font size used to display the sequences in the 975 * editor 976 * return font size 977 * 978 */ getFontSize()979 public int getFontSize() 980 { 981 return ((SequenceJPanel)graphicSequence.get(0)).getFontSize(); 982 } 983 984 /** 985 * 986 * Search sequences for a pattern and highlight matches. Set the 987 * viewport to that position. 988 * 989 * @param String pat pattern to match 990 * @param int oldResPosition if this is a repeat of a search 991 * this is the position the old search finished at 992 * @param boolean wrapAround true if the search should wrap 993 * around the sequences 994 * @return int the matching position found (or -1 if none found) 995 * 996 */ findPattern(String pat, int oldResPosition, boolean wrapAround)997 public int findPattern(String pat, int oldResPosition, 998 boolean wrapAround) 999 { 1000 int resWidth = ((SequenceJPanel)graphicSequence.get(0)). 1001 getSequenceResidueWidth(); 1002 Rectangle r = getViewRect(); 1003 int ypos = r.y; 1004 int xpos = r.x/resWidth; 1005 int viewWidth = r.width/resWidth; 1006 pat = pat.toLowerCase(); 1007 1008 // highlight matching segments of seqs 1009 Enumeration enumer = graphicSequence.elements(); 1010 while(enumer.hasMoreElements()) 1011 { 1012 SequenceJPanel sjp = (SequenceJPanel)enumer.nextElement(); 1013 sjp.showPattern(pat); 1014 } 1015 1016 // move view to the next occurence of that pattern 1017 if(oldResPosition > -1) // possibly this as well: (&& xpos < oldResPosition) 1018 xpos = oldResPosition; 1019 1020 int newResPos = searchSequences(xpos,pat); 1021 1022 if(newResPos > -1) 1023 { 1024 int mid = findMiddle(newResPos,viewWidth,pat); 1025 jspSequence.getViewport().setViewPosition( 1026 new Point(mid*resWidth,ypos)); 1027 // System.out.println("xpos "+xpos+" newResPos "+newResPos+ 1028 // " viewWidth "+viewWidth+" mid "+mid+ 1029 // " oldResPosition "+oldResPosition); 1030 } 1031 else if(wrapAround) // search from start of seqs 1032 { 1033 // JOptionPane.show 1034 newResPos = searchSequences(0,pat); 1035 // System.out.println("SEARCH FROM START OF SEQUENCE"); 1036 if(newResPos > -1) 1037 { 1038 int mid = findMiddle(newResPos,viewWidth,pat); 1039 jspSequence.getViewport().setViewPosition( 1040 new Point(mid*resWidth,ypos)); 1041 } 1042 } 1043 else if(!wrapAround) 1044 newResPos = oldResPosition; 1045 1046 return newResPos+1; 1047 } 1048 1049 /** 1050 * 1051 * Search the sequences for the position in that matches 1052 * the given pattern to search for. 1053 * 1054 * @param int startSearch position at which the search is started 1055 * @param String pat is the pattern to search 1056 * @return int position in a sequence that next matches the pattern 1057 * (or -1 if none found) 1058 * 1059 */ searchSequences(int startSearch, String pat)1060 private int searchSequences(int startSearch, String pat) 1061 { 1062 int newResPos = 0; 1063 int nfound = 0; 1064 1065 Enumeration enumer = seqs.elements(); 1066 while(enumer.hasMoreElements()) 1067 { 1068 Sequence seq = (Sequence)enumer.nextElement(); 1069 int index = seq.getSequence().toLowerCase().indexOf(pat,startSearch); 1070 if(index > -1) 1071 { 1072 if(nfound == 0 || index < newResPos) 1073 newResPos = index; 1074 nfound++; 1075 } 1076 } 1077 if(nfound == 0) 1078 return -1; 1079 return newResPos; 1080 } 1081 1082 /** 1083 * 1084 * Locate the center of a vieport view that contains the 1085 * defined position to display 1086 * 1087 * @param int newResPos position in the sequence to display 1088 * @param int viewWidth width of the viewport 1089 * @param String pat matching pattern 1090 * @return int position to set the viewport to so that the 1091 * pattern is displayed in the middle of it 1092 * 1093 */ findMiddle(int newResPos, int viewWidth, String pat)1094 private int findMiddle(int newResPos, int viewWidth, String pat) 1095 { 1096 int mid; 1097 int viewWidth2 = viewWidth/2; 1098 if(newResPos <= viewWidth2) 1099 mid = 0; 1100 else 1101 mid = newResPos-viewWidth2+(pat.length()/2); 1102 return mid; 1103 } 1104 1105 /** 1106 * 1107 * Set the colour scheme to use 1108 * @param colourTable colour scheme as a hashtable 1109 * 1110 */ setColorScheme(Hashtable colourTable)1111 public void setColorScheme(Hashtable colourTable) 1112 { 1113 this.colorScheme = colourTable; 1114 this.drawColorBox = true; 1115 1116 Enumeration enumer = graphicSequence.elements(); 1117 while(enumer.hasMoreElements()) 1118 { 1119 SequenceJPanel sjp = (SequenceJPanel)enumer.nextElement(); 1120 sjp.setColorScheme(colourTable); 1121 sjp.setDrawColor(drawColorBox); 1122 } 1123 } 1124 1125 /** 1126 * 1127 * Display the sequences as per emboss prettyplot colours 1128 * @param bpretty true if displaying as prettyplot 1129 * 1130 */ setPrettyPlot(boolean bpretty, PrettyPlotJFrame prettyPlot)1131 public void setPrettyPlot(boolean bpretty, PrettyPlotJFrame prettyPlot) 1132 { 1133 this.prettyPlot = prettyPlot; 1134 Enumeration enumer = graphicSequence.elements(); 1135 while(enumer.hasMoreElements()) 1136 ((SequenceJPanel)(enumer.nextElement())).setPrettyPlot(bpretty); 1137 } 1138 1139 /** 1140 * 1141 * Force display in the viewport 1142 * 1143 */ setJScrollPaneViewportView()1144 public void setJScrollPaneViewportView() 1145 { 1146 jspSequence.setViewportView(this); 1147 } 1148 1149 /** 1150 * 1151 * Get the number of pages to print the alignment in 1152 * a given format 1153 * @param format format for printing 1154 * @return number of pages 1155 * 1156 */ getNumberPages(PageFormat format)1157 public int getNumberPages(PageFormat format) 1158 { 1159 return getNumberPages(format,getResiduesPerLine(format)); 1160 } 1161 1162 /** 1163 * 1164 * Get the number of pages to print the alignment in 1165 * a given format and with a given number of residues per line 1166 * @param format format for printing 1167 * @param numResPerLine number of residues per line 1168 * @return number of pages 1169 * 1170 */ getNumberPages(PageFormat format, int numResPerLine)1171 public int getNumberPages(PageFormat format, int numResPerLine) 1172 { 1173 double pageHeight = format.getImageableHeight(); 1174 int residueWidth = ((SequenceJPanel)graphicSequence.get(0)).getSequenceHeight(); 1175 int nblockPerPage = (int)(pageHeight/((graphicSequence.size()+2)*residueWidth)); 1176 int npage = MAXSEQLENGTH/(nblockPerPage*numResPerLine)+1; 1177 return npage; 1178 } 1179 1180 /** 1181 * 1182 * Get the imageable size. This is for fitting the image 1183 * to one page. 1184 * @return image size 1185 * 1186 */ getImageableSize(int numResPerLine)1187 public Dimension getImageableSize(int numResPerLine) 1188 { 1189 SequenceJPanel seq = (SequenceJPanel)graphicSequence.get(0); 1190 int residueHeight = seq.getSequenceHeight(); 1191 int alignHeight = (graphicSequence.size()+1)*residueHeight; 1192 int nalign = Math.round(((float)MAXSEQLENGTH/ 1193 (float)numResPerLine)+.5f)*alignHeight; 1194 // System.out.println("nalign "+ 1195 // Math.round(((float)MAXSEQLENGTH/(float)numResPerLine)+.5f)+ 1196 // " alignHeight "+alignHeight+" nalign "+nalign+" 1197 // residueHeight "+residueHeight+ 1198 // " graphicSequence.size()+1 "+(graphicSequence.size()+1)); 1199 int width = (seq.getResidueWidth()*(numResPerLine+2))+getNameWidth(); 1200 return new Dimension(width,nalign); 1201 } 1202 1203 /** 1204 * 1205 * Get the number residues per line 1206 * @param format format for printing 1207 * @return number residues per line 1208 * 1209 */ getResiduesPerLine(PageFormat format)1210 public int getResiduesPerLine(PageFormat format) 1211 { 1212 double pwidth = format.getImageableWidth()-(double)getNameWidth(); 1213 // int resWidth = ((SequenceJPanel)graphicSequence.get(0)).getSequenceHeight(); 1214 int resWidth = ((SequenceJPanel)graphicSequence.get(0)).getSequenceResidueWidth(); 1215 return (int)(pwidth/(double)resWidth); 1216 } 1217 1218 /** 1219 * 1220 * Get the number residues per page 1221 * @param format format for printing 1222 * @param numResPerLine number residues per line 1223 * @return number residues per page 1224 * 1225 */ getResiduesPerPage(PageFormat format, int numResPerLine)1226 public int getResiduesPerPage(PageFormat format, int numResPerLine) 1227 { 1228 double pageHeight = format.getImageableHeight(); 1229 int residueWidth = ((SequenceJPanel)graphicSequence.get(0)).getSequenceHeight(); 1230 int nblockPerPage = (int)(pageHeight/(residueWidth*(graphicSequence.size()+2))); 1231 return nblockPerPage*numResPerLine; 1232 } 1233 1234 /** 1235 * 1236 * Used to print the sequence alignment 1237 * @param g graphics 1238 * @param format page format 1239 * @param pageIndex page number to print 1240 * @throws PrinterException 1241 * 1242 */ print(Graphics g, PageFormat format, int pageIndex)1243 public int print(Graphics g, PageFormat format, int pageIndex) 1244 throws PrinterException 1245 { 1246 Graphics2D g2d = (Graphics2D) g.create(); 1247 drawSequences(g2d,format,pageIndex,numResiduePerLine); 1248 return Printable.PAGE_EXISTS; 1249 } 1250 1251 /** 1252 * 1253 * Set the number of residues per line to user setting 1254 * @param numResiduePerLine number of residues per line 1255 * 1256 */ setNumberOfResiduesPerLine(int numResiduePerLine)1257 protected void setNumberOfResiduesPerLine(int numResiduePerLine) 1258 { 1259 this.numResiduePerLine = numResiduePerLine; 1260 } 1261 1262 /** 1263 * 1264 * Draws the sequences for printing 1265 * @param g2d graphics 1266 * @param format page format 1267 * @param pageIndex page number to print 1268 * 1269 */ drawSequences(Graphics2D g2d, PageFormat format, int pageIndex)1270 public void drawSequences(Graphics2D g2d, PageFormat format, 1271 int pageIndex) 1272 { 1273 int numResPerLine = getResiduesPerLine(format); 1274 drawSequences(g2d,format,pageIndex,numResPerLine); 1275 } 1276 1277 /** 1278 * 1279 * Draws the sequences for printing 1280 * @param g2d graphics 1281 * @param format page format 1282 * @param pageIndex page number to print 1283 * @param numResPerLine number of residues per line 1284 */ drawSequences(Graphics2D g2d, PageFormat format, int pageIndex, int numResPerLine)1285 public void drawSequences(Graphics2D g2d, PageFormat format, 1286 int pageIndex, int numResPerLine) 1287 { 1288 // move origin from the corner of the Paper to the corner of imageable area 1289 g2d.translate(format.getImageableX(), format.getImageableY()); 1290 1291 int resPerPage = getResiduesPerPage(format,numResPerLine); 1292 int istart = resPerPage*pageIndex; 1293 int istop = istart+resPerPage; 1294 1295 if(istop > MAXSEQLENGTH) 1296 istop = MAXSEQLENGTH; 1297 1298 // System.out.println("pageIndex "+pageIndex+" numResPerLine "+numResPerLine); 1299 for(int i=istart;i<istop;i+=numResPerLine) 1300 { 1301 Enumeration enumer = graphicSequence.elements(); 1302 SequenceJPanel gs = null; 1303 int iend; 1304 1305 while(enumer.hasMoreElements()) 1306 { 1307 iend = i+numResPerLine; 1308 if(iend > istop) 1309 iend = istop; 1310 1311 gs = (SequenceJPanel)(enumer.nextElement()); 1312 gs.getSequencePrintGraphic(g2d,getNameWidth(),i,iend); 1313 // i+numResPerLine); 1314 gs.getNamePrintGraphic(g2d); 1315 g2d.translate(0,gs.getSequenceHeight()); 1316 } 1317 g2d.translate(0,gs.getSequenceHeight()); 1318 } 1319 } 1320 1321 //scrollable interface methods 1322 1323 /** 1324 * 1325 * Override for scrollable interface 1326 * 1327 */ getPreferredScrollableViewportSize()1328 public Dimension getPreferredScrollableViewportSize() 1329 { 1330 return getPreferredSize(); 1331 } 1332 1333 /** 1334 * 1335 * Override for scrollable interface 1336 * 1337 */ getScrollableTracksViewportHeight()1338 public boolean getScrollableTracksViewportHeight() 1339 { 1340 return false; 1341 } 1342 1343 /** 1344 * 1345 * Override for scrollable interface 1346 * 1347 */ getScrollableTracksViewportWidth()1348 public boolean getScrollableTracksViewportWidth() 1349 { 1350 return false; 1351 } 1352 1353 /** 1354 * 1355 * Override for scrollable interface 1356 * 1357 */ getScrollableBlockIncrement(Rectangle r, int orientation, int direction)1358 public int getScrollableBlockIncrement(Rectangle r, 1359 int orientation, int direction) 1360 { 1361 return 60; 1362 } 1363 1364 /** 1365 * 1366 * Override for scrollable interface 1367 * 1368 */ getScrollableUnitIncrement(Rectangle r, int orientation, int direction)1369 public int getScrollableUnitIncrement(Rectangle r, 1370 int orientation, int direction) 1371 { 1372 return 60; 1373 } 1374 1375 main(String args[])1376 public static void main(String args[]) 1377 { 1378 Vector seqs = new Vector(); 1379 seqs.add(new Sequence("Seq1","ACCaaaaaaaaaaaaaaaaaaaaTAGAtTAT"+ 1380 "ACCaaaaaaaaaaaaaaaaaaaaTAGAtTAT"+ 1381 "ACCaaaaaaaaaaaaaaaaaaaaTAGAtTAT")); 1382 seqs.add(new Sequence("Seq2","ACCaaaaaaaaaaaaaaaaaaaaTAGAtTAT"+ 1383 "ACCaaaaaaaaaaaaaaaaaaaaTAGAtTAT"+ 1384 "ACCaaaaaaaaaaaaaaaaaaaaTAGAtTAT")); 1385 1386 JScrollPane jspSequence = new JScrollPane(); 1387 GraphicSequenceCollection gsc = new GraphicSequenceCollection( 1388 seqs,null,jspSequence, 1389 true,true,true,false,null); 1390 jspSequence.setViewportView(gsc); 1391 JFrame f = new JFrame("Sequence Panel"); 1392 JPanel pane = (JPanel)f.getContentPane(); 1393 1394 pane.add(jspSequence); 1395 f.pack(); 1396 f.setVisible(true); 1397 1398 } 1399 drawNumber()1400 protected void drawNumber() 1401 { 1402 numberDraw = new SequenceJPanel(10,MAXSEQLENGTH); 1403 graphicSequence.add(numberDraw); 1404 Box XBox = new Box(BoxLayout.X_AXIS); 1405 XBox.add(numberDraw); 1406 XBox.add(Box.createHorizontalGlue()); 1407 seqBox.add(XBox); 1408 1409 setNumberSize(); 1410 SequenceNameJButton snjBlank = 1411 new SequenceNameJButton(new Sequence("seq-id:",""),0); 1412 snjBlank.setEnabled(false); 1413 graphicName.add(snjBlank); 1414 XBox = new Box(BoxLayout.X_AXIS); 1415 XBox.add(Box.createHorizontalGlue()); 1416 XBox.add(snjBlank); 1417 seqNameBox.add(XBox); 1418 } 1419 addAnnotationSequence(Sequence s)1420 protected void addAnnotationSequence(Sequence s) 1421 { 1422 addSequence(s,true,0,getFontSize()); 1423 } 1424 1425 } 1426 1427