1 /* VCFview 2 * 3 * created: July 2010 4 * 5 * This file is part of Artemis 6 * 7 * Copyright(C) 2010 Genome Research Limited 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License 11 * as published by the Free Software Foundation; either version 2 12 * of the License, or(at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 * 23 */ 24 25 package uk.ac.sanger.artemis.components.variant; 26 import java.awt.AlphaComposite; 27 import java.awt.BorderLayout; 28 import java.awt.Color; 29 import java.awt.Component; 30 import java.awt.Composite; 31 import java.awt.Container; 32 import java.awt.Cursor; 33 import java.awt.Dimension; 34 import java.awt.FlowLayout; 35 import java.awt.FontMetrics; 36 import java.awt.Frame; 37 import java.awt.Graphics; 38 import java.awt.Graphics2D; 39 import java.awt.GridBagConstraints; 40 import java.awt.GridBagLayout; 41 import java.awt.Insets; 42 import java.awt.Point; 43 import java.awt.Rectangle; 44 import java.awt.event.ActionEvent; 45 import java.awt.event.ActionListener; 46 import java.awt.event.AdjustmentEvent; 47 import java.awt.event.AdjustmentListener; 48 import java.awt.event.MouseAdapter; 49 import java.awt.event.MouseEvent; 50 import java.awt.event.MouseMotionListener; 51 import java.awt.image.BufferedImage; 52 import java.io.File; 53 import java.io.FileInputStream; 54 import java.io.FileOutputStream; 55 import java.io.IOException; 56 import java.io.InputStream; 57 import java.net.URL; 58 import java.util.HashMap; 59 import java.util.Hashtable; 60 import java.util.List; 61 import java.util.Map; 62 import java.util.Vector; 63 import java.util.regex.Pattern; 64 65 import javax.swing.BorderFactory; 66 import javax.swing.Box; 67 import javax.swing.ButtonGroup; 68 import javax.swing.ImageIcon; 69 import javax.swing.JButton; 70 import javax.swing.JCheckBox; 71 import javax.swing.JCheckBoxMenuItem; 72 import javax.swing.JComponent; 73 import javax.swing.JFrame; 74 import javax.swing.JLabel; 75 import javax.swing.JMenu; 76 import javax.swing.JMenuBar; 77 import javax.swing.JMenuItem; 78 import javax.swing.JOptionPane; 79 import javax.swing.JPanel; 80 import javax.swing.JPopupMenu; 81 import javax.swing.JRadioButton; 82 import javax.swing.JRadioButtonMenuItem; 83 import javax.swing.JScrollBar; 84 import javax.swing.JScrollPane; 85 import javax.swing.JSeparator; 86 import javax.swing.border.Border; 87 import javax.swing.border.EmptyBorder; 88 89 import htsjdk.samtools.util.BlockCompressedInputStream; 90 91 import org.apache.log4j.Level; 92 93 import uk.ac.sanger.artemis.Entry; 94 import uk.ac.sanger.artemis.EntryGroup; 95 import uk.ac.sanger.artemis.Feature; 96 import uk.ac.sanger.artemis.FeatureKeyPredicate; 97 import uk.ac.sanger.artemis.FeatureVector; 98 import uk.ac.sanger.artemis.Options; 99 import uk.ac.sanger.artemis.Selection; 100 import uk.ac.sanger.artemis.SelectionChangeEvent; 101 import uk.ac.sanger.artemis.SelectionChangeListener; 102 import uk.ac.sanger.artemis.SimpleEntryGroup; 103 import uk.ac.sanger.artemis.components.DisplayAdjustmentEvent; 104 import uk.ac.sanger.artemis.components.DisplayAdjustmentListener; 105 import uk.ac.sanger.artemis.components.EntryEdit; 106 import uk.ac.sanger.artemis.components.EntryFileDialog; 107 import uk.ac.sanger.artemis.components.FeatureDisplay; 108 import uk.ac.sanger.artemis.components.FileViewer; 109 import uk.ac.sanger.artemis.components.IndexReferenceEvent; 110 import uk.ac.sanger.artemis.components.MessageDialog; 111 import uk.ac.sanger.artemis.components.MultiComparator; 112 import uk.ac.sanger.artemis.components.SequenceComboBox; 113 import uk.ac.sanger.artemis.components.Utilities; 114 import uk.ac.sanger.artemis.components.alignment.FileSelectionDialog; 115 import uk.ac.sanger.artemis.components.alignment.LineAttributes; 116 import uk.ac.sanger.artemis.editor.MultiLineToolTipUI; 117 import uk.ac.sanger.artemis.io.EntryInformation; 118 import uk.ac.sanger.artemis.io.Key; 119 import uk.ac.sanger.artemis.io.Range; 120 import uk.ac.sanger.artemis.io.RangeVector; 121 import uk.ac.sanger.artemis.sequence.Bases; 122 import uk.ac.sanger.artemis.sequence.MarkerRange; 123 import uk.ac.sanger.artemis.sequence.NoSequenceException; 124 import uk.ac.sanger.artemis.util.Document; 125 import uk.ac.sanger.artemis.util.DocumentFactory; 126 import uk.ac.sanger.artemis.util.FTPSeekableStream; 127 import uk.ac.sanger.artemis.util.OutOfRangeException; 128 129 130 public class VCFview extends JPanel 131 implements DisplayAdjustmentListener, SelectionChangeListener 132 { 133 134 private static final long serialVersionUID = 1L; 135 136 private JScrollPane jspView; 137 138 private JScrollBar scrollBar; 139 private JPanel vcfPanel; 140 private AbstractVCFReader vcfReaders[]; 141 private List<String> vcfFiles; 142 private List<Integer> hideVcfList = new Vector<Integer>(); 143 144 private FeatureDisplay feature_display; 145 private Selection selection; 146 private int nbasesInView; 147 protected int seqLength; 148 private EntryGroup entryGroup; 149 private String chr; 150 private Point lastMousePoint; 151 private VCFRecord mouseVCF; 152 private int mouseOverIndex = -1; 153 private int mouseOverSampleIndex = -1; 154 155 private GraphPanel graphPanel; 156 157 //record of where a mouse drag starts 158 private int dragStart = -1; 159 private JPopupMenu popup; 160 private JMenu vcfFilesMenu = new JMenu("VCF files"); 161 private int LINE_HEIGHT = 14; 162 163 protected boolean showSynonymous = true; 164 protected boolean showNonSynonymous = true; 165 protected boolean showDeletions = true; 166 protected boolean showInsertions = true; 167 protected boolean showMultiAlleles = true; 168 protected boolean showHomozygous = true; 169 // show variants that do not overlap CDS 170 protected boolean showNonOverlappings = true; 171 protected boolean showNonVariants = false; 172 173 private Map<String, Boolean> manualHash = new HashMap<String, Boolean>(); 174 175 //private boolean markAsNewStop = false; 176 177 private boolean showLabels = false; 178 179 private JCheckBoxMenuItem markNewStops = 180 new JCheckBoxMenuItem("Mark new stops within CDS features", true); 181 182 private static int VARIANT_COLOUR_SCHEME = 0; 183 private static int SYN_COLOUR_SCHEME = 1; 184 private static int QUAL_COLOUR_SCHEME = 2; 185 186 private int colourScheme = 0; 187 private Color colMap[] = makeColours(Color.RED, 255); 188 private Color lighterGrey = new Color(220,220,220); 189 190 private VCFFilter filter; 191 Hashtable<String, Integer> offsetLengths = null; 192 private boolean concatSequences = false; 193 private boolean splitSamples = true; 194 195 protected static Pattern tabPattern = Pattern.compile("\t"); 196 197 public static String VCFFILE_SUFFIX = ".*\\.[bv]{1}cf(\\.gz)*$"; 198 private static String FILE_SUFFIX = "\\.[bv]{1}cf(\\.gz)*$"; 199 200 private List<Integer> cacheVariantLines; 201 private SequenceComboBox combo; 202 203 public static org.apache.log4j.Logger logger4j = 204 org.apache.log4j.Logger.getLogger(VCFview.class); 205 VCFview(final JFrame frame, final JPanel vcfPanel, final List<String> vcfFiles, final int nbasesInView, final int seqLength, final String chr, final String reference, final EntryEdit entry_edit, final FeatureDisplay feature_display)206 public VCFview(final JFrame frame, 207 final JPanel vcfPanel, 208 final List<String> vcfFiles, 209 final int nbasesInView, 210 final int seqLength, 211 final String chr, 212 final String reference, 213 final EntryEdit entry_edit, 214 final FeatureDisplay feature_display) 215 { 216 super(); 217 218 this.nbasesInView = nbasesInView; 219 this.seqLength = seqLength; 220 this.chr = chr; 221 222 this.feature_display = feature_display; 223 this.vcfPanel = vcfPanel; 224 this.vcfFiles = vcfFiles; 225 226 jspView = new JScrollPane(this, 227 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 228 JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 229 230 setBackground(Color.white); 231 MultiLineToolTipUI.initialize(); 232 setToolTipText(""); 233 vcfPanel.setPreferredSize(new Dimension(900, 234 (vcfFiles.size()+1)*(LINE_HEIGHT+5))); 235 236 if(feature_display != null) 237 this.entryGroup = feature_display.getEntryGroup(); 238 else if(reference != null) 239 this.entryGroup = getReference(reference); 240 if(entryGroup != null) 241 this.seqLength = entryGroup.getSequenceEntry().getBases().getLength(); 242 243 try 244 { 245 vcfReaders = new AbstractVCFReader[vcfFiles.size()]; 246 247 for(int i=0; i<vcfFiles.size(); i++) 248 { 249 readHeader(vcfFiles.get(i), i); 250 } 251 } 252 catch(java.lang.UnsupportedClassVersionError err) 253 { 254 JOptionPane.showMessageDialog(null, 255 "This requires Java 1.8 or higher.", 256 "Check Java Version", JOptionPane.WARNING_MESSAGE); 257 } 258 259 vcfPanel.setLayout(new BorderLayout()); 260 vcfPanel.add(jspView, BorderLayout.CENTER); 261 262 JPanel bottomPanel = new JPanel(new BorderLayout()); 263 graphPanel = new GraphPanel(this); 264 graphPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, Color.gray)); 265 graphPanel.setVisible(false); 266 267 bottomPanel.add(graphPanel, BorderLayout.CENTER); 268 vcfPanel.add(bottomPanel, BorderLayout.SOUTH); 269 270 if(this.nbasesInView > this.seqLength) 271 this.nbasesInView = this.seqLength/2; 272 273 scrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 1, this.nbasesInView, 1, this.seqLength); 274 scrollBar.setUnitIncrement(nbasesInView/20); 275 scrollBar.addAdjustmentListener(new AdjustmentListener() 276 { 277 public void adjustmentValueChanged(AdjustmentEvent e) 278 { 279 repaint(); 280 } 281 }); 282 283 // 284 // 285 addMouseListener(new PopupListener()); 286 287 // 288 createTopPanel(frame, entry_edit); 289 createMenus(); 290 setDisplay(); 291 292 if(feature_display == null) 293 { 294 bottomPanel.add(scrollBar, BorderLayout.SOUTH); 295 selection = new Selection(null); 296 } 297 else 298 { 299 Border empty = new EmptyBorder(0,0,0,0); 300 jspView.setBorder(empty); 301 selection = feature_display.getSelection(); 302 } 303 } 304 createMenus()305 private void createMenus() 306 { 307 // popup menu 308 popup = new JPopupMenu(); 309 310 JMenuItem addVCFMenu = new JMenuItem("Add VCF ..."); 311 addVCFMenu.addActionListener(new ActionListener() 312 { 313 public void actionPerformed(ActionEvent e) 314 { 315 FileSelectionDialog fileSelection = new FileSelectionDialog( 316 null, true, "VCFview", "VCF"); 317 List<String> vcfFileList = fileSelection.getFiles(VCFFILE_SUFFIX); 318 vcfFiles.addAll(vcfFileList); 319 320 int count = vcfFileList.size(); 321 int oldSize = vcfReaders.length; 322 323 AbstractVCFReader[] trTmp = new AbstractVCFReader[count + vcfReaders.length]; 324 System.arraycopy(vcfReaders, 0, trTmp, 0, vcfReaders.length); 325 vcfReaders = trTmp; 326 327 for (int i = 0; i < vcfFileList.size(); i++) 328 readHeader(vcfFileList.get(i), i+oldSize); 329 330 for(int i=0; i<vcfFileList.size(); i++) 331 addToViewMenu(i+oldSize); 332 333 setDisplay(); 334 repaint(); 335 jspView.revalidate(); 336 } 337 }); 338 popup.add(addVCFMenu); 339 popup.add(vcfFilesMenu); 340 341 for(int i=0; i<vcfFiles.size(); i++) 342 addToViewMenu(i); 343 344 final JMenu lineHgt = new JMenu("Row Height"); 345 popup.add(lineHgt); 346 final ButtonGroup groupLnHgt = new ButtonGroup(); 347 for(int i=8; i<37; i+=2) 348 { 349 final int ii = i; 350 final JCheckBoxMenuItem hgtMenu = new JCheckBoxMenuItem( 351 Integer.toString(i), (i == LINE_HEIGHT)); 352 groupLnHgt.add(hgtMenu); 353 hgtMenu.addActionListener(new ActionListener() 354 { 355 public void actionPerformed(ActionEvent e) 356 { 357 if(hgtMenu.isSelected()) 358 { 359 LINE_HEIGHT = ii; 360 setDisplay(); 361 revalidate(); 362 } 363 } 364 }); 365 lineHgt.add(hgtMenu); 366 } 367 368 popup.addSeparator(); 369 370 markNewStops.addActionListener(new ActionListener() 371 { 372 public void actionPerformed(ActionEvent e) 373 { 374 repaint(); 375 } 376 }); 377 popup.add(markNewStops); 378 379 380 final JCheckBoxMenuItem split = new JCheckBoxMenuItem("Separate out into samples", splitSamples); 381 split.addActionListener(new ActionListener() 382 { 383 public void actionPerformed(ActionEvent e) 384 { 385 splitSamples = split.isSelected(); 386 setDisplay(); 387 revalidate(); 388 } 389 }); 390 popup.add(split); 391 392 393 final JMenuItem byQuality = new JMenuItem("Filter ..."); 394 if(!Options.getOptions().getPropertyTruthValue("java.awt.headless")) 395 filter = new VCFFilter(VCFview.this); 396 397 byQuality.addActionListener(new ActionListener(){ 398 public void actionPerformed(ActionEvent e) 399 { 400 filter.setVisible(true); 401 } 402 }); 403 popup.add(byQuality); 404 405 final JMenu colourBy = new JMenu("Colour By"); 406 popup.add(colourBy); 407 ButtonGroup group = new ButtonGroup(); 408 final JRadioButtonMenuItem colByAlt = new JRadioButtonMenuItem("Variant"); 409 colByAlt.addActionListener(new ActionListener(){ 410 public void actionPerformed(ActionEvent e) 411 { 412 if(colByAlt.isSelected()) 413 colourScheme = 0; 414 repaint(); 415 } 416 }); 417 colourBy.add(colByAlt); 418 419 final JRadioButtonMenuItem colBySyn = new JRadioButtonMenuItem("Synonymous/Non-synonymous"); 420 colBySyn.addActionListener(new ActionListener(){ 421 public void actionPerformed(ActionEvent e) 422 { 423 if(colBySyn.isSelected()) 424 colourScheme = 1; 425 repaint(); 426 } 427 }); 428 colourBy.add(colBySyn); 429 430 final JRadioButtonMenuItem colByScore = new JRadioButtonMenuItem("Score"); 431 colByScore.addActionListener(new ActionListener(){ 432 public void actionPerformed(ActionEvent e) 433 { 434 if(colByScore.isSelected()) 435 colourScheme = 2; 436 repaint(); 437 } 438 }); 439 colourBy.add(colByScore); 440 441 group.add(colByAlt); 442 group.add(colBySyn); 443 group.add(colByScore); 444 colByAlt.setSelected(true); 445 446 popup.addSeparator(); 447 448 if (feature_display != null) 449 { 450 final JMenu create = new JMenu("Create"); 451 final JMenuItem createTab = new JMenuItem( 452 "Features from variants"); 453 popup.add(create); 454 create.add(createTab); 455 createTab.addActionListener(new ActionListener() 456 { 457 public void actionPerformed(ActionEvent e) 458 { 459 Container f = getVcfContainer(); 460 try 461 { 462 f.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 463 IOUtils.createFeatures(VCFview.this, entryGroup); 464 } 465 finally 466 { 467 f.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 468 } 469 } 470 }); 471 } 472 473 final JMenu export = new JMenu("Write"); 474 popup.add(export); 475 476 final JMenuItem exportVCF = new JMenuItem("Filtered VCF"); 477 exportVCF.addActionListener(new ActionListener(){ 478 public void actionPerformed(ActionEvent e) 479 { 480 Container f = getVcfContainer(); 481 try 482 { 483 f.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 484 IOUtils.export(manualHash, vcfFiles, VCFview.this); 485 } 486 finally 487 { 488 f.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 489 } 490 } 491 }); 492 export.add(exportVCF); 493 494 export.add(new JSeparator()); 495 496 final JMenuItem exportFastaSelected = new JMenuItem("FASTA of selected feature(s) ..."); 497 exportFastaSelected.addActionListener(new ActionListener(){ 498 public void actionPerformed(ActionEvent e) 499 { 500 Container f = getVcfContainer(); 501 try 502 { 503 f.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 504 IOUtils.exportFasta(VCFview.this, selection.getAllFeatures(), false, null); 505 } 506 finally 507 { 508 f.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 509 } 510 } 511 }); 512 export.add(exportFastaSelected); 513 514 final JMenuItem exportFasta = new JMenuItem("FASTA of selected base range ..."); 515 exportFasta.addActionListener(new ActionListener(){ 516 public void actionPerformed(ActionEvent e) 517 { 518 Container f = getVcfContainer(); 519 try 520 { 521 f.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 522 IOUtils.exportFastaByRange(VCFview.this, selection, false, null); 523 } 524 finally 525 { 526 f.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 527 } 528 } 529 }); 530 export.add(exportFasta); 531 532 final JMenuItem viewMinimalFasta = new JMenuItem("FASTA of variant sites only ..."); 533 viewMinimalFasta.addActionListener(new ActionListener(){ 534 public void actionPerformed(ActionEvent e) 535 { 536 Container f = getVcfContainer(); 537 try 538 { 539 f.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 540 IOUtils.exportVariantFasta(VCFview.this); 541 } 542 finally 543 { 544 f.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 545 } 546 } 547 }); 548 export.addSeparator(); 549 export.add(viewMinimalFasta); 550 551 552 final JMenu view = new JMenu("View"); 553 popup.add(view); 554 final JMenuItem viewFastaSelected = new JMenuItem("FASTA of selected feature(s) ..."); 555 viewFastaSelected.addActionListener(new ActionListener(){ 556 public void actionPerformed(ActionEvent e) 557 { 558 Container f = getVcfContainer(); 559 try 560 { 561 f.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 562 IOUtils.exportFasta(VCFview.this, selection.getAllFeatures(), true, null); 563 } 564 finally 565 { 566 f.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 567 } 568 } 569 }); 570 view.add(viewFastaSelected); 571 572 final JMenuItem viewFasta = new JMenuItem("FASTA of selected base range ..."); 573 viewFasta.addActionListener(new ActionListener(){ 574 public void actionPerformed(ActionEvent e) 575 { 576 Container f = getVcfContainer(); 577 try 578 { 579 f.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 580 IOUtils.exportFastaByRange(VCFview.this, selection, true, null); 581 } 582 finally 583 { 584 f.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 585 } 586 } 587 }); 588 view.add(viewFasta); 589 590 591 JMenu graph = new JMenu("Graph"); 592 popup.add(graph); 593 594 final JCheckBoxMenuItem graphSNP = new JCheckBoxMenuItem("SNP"); 595 final JCheckBoxMenuItem graphDP = new JCheckBoxMenuItem("Depth (DP)"); 596 final JCheckBoxMenuItem graphSim = new JCheckBoxMenuItem("Base Similarity (%)"); 597 graph.add(graphSNP); 598 graphSNP.addActionListener(new ActionListener(){ 599 public void actionPerformed(ActionEvent e) 600 { 601 graphPanel.setVisible(graphSNP.isSelected()); 602 graphDP.setSelected(false); 603 graphSim.setSelected(false); 604 graphPanel.setType(0); 605 setGraphSize(); 606 } 607 }); 608 609 graph.add(graphDP); 610 graphDP.addActionListener(new ActionListener(){ 611 public void actionPerformed(ActionEvent e) 612 { 613 graphPanel.setVisible(graphDP.isSelected()); 614 graphSNP.setSelected(false); 615 graphSim.setSelected(false); 616 graphPanel.setType(1); 617 setGraphSize(); 618 } 619 }); 620 621 graph.add(graphSim); 622 graphSim.addActionListener(new ActionListener(){ 623 public void actionPerformed(ActionEvent e) 624 { 625 graphPanel.setVisible(graphSim.isSelected()); 626 graphSNP.setSelected(false); 627 graphDP.setSelected(false); 628 graphPanel.setType(2); 629 setGraphSize(); 630 } 631 }); 632 633 final JMenuItem snpOverview = new JMenuItem("Overview for selected features"); 634 popup.add(snpOverview); 635 snpOverview.addActionListener(new ActionListener() 636 { 637 public void actionPerformed(ActionEvent e) 638 { 639 Container f = getVcfContainer(); 640 try 641 { 642 f.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 643 IOUtils.countVariants(VCFview.this, selection.getAllFeatures()); 644 } 645 catch (IOException e1) 646 { 647 JOptionPane.showMessageDialog(null, e1.getMessage()); 648 } 649 finally 650 { 651 f.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 652 } 653 } 654 }); 655 656 final JCheckBoxMenuItem labels = new JCheckBoxMenuItem("Show Labels", showLabels); 657 labels.addActionListener(new ActionListener(){ 658 public void actionPerformed(ActionEvent e) 659 { 660 showLabels = labels.isSelected(); 661 repaint(); 662 } 663 }); 664 popup.add(new JSeparator()); 665 popup.add(labels); 666 } 667 setGraphSize()668 private void setGraphSize() 669 { 670 repaint(); 671 if(graphPanel.isVisible()) 672 graphPanel.setPreferredSize(new Dimension(900, 70)); 673 else 674 graphPanel.setPreferredSize(new Dimension(900, 1)); 675 676 vcfPanel.setPreferredSize(new Dimension(900, 677 graphPanel.getPreferredSize().height+getPreferredSize().height)); 678 vcfPanel.revalidate(); 679 } 680 createTopPanel(final JFrame frame, final EntryEdit entry_edit)681 private void createTopPanel(final JFrame frame, final EntryEdit entry_edit) 682 { 683 final JComponent topPanel; 684 if(feature_display != null) 685 topPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0)); 686 else 687 { 688 markNewStops.setSelected(false); 689 markNewStops.setEnabled(false); 690 topPanel = new JMenuBar(); 691 if(frame != null) 692 frame.setJMenuBar((JMenuBar)topPanel); 693 694 JMenu fileMenu = new JMenu("File"); 695 topPanel.add(fileMenu); 696 697 JMenuItem printImage = new JMenuItem("Save As Image Files (png/jpeg)..."); 698 printImage.addActionListener(new ActionListener() 699 { 700 public void actionPerformed(ActionEvent e) 701 { 702 PrintVCFview part = new PrintVCFview(VCFview.this); 703 part.print(); 704 } 705 }); 706 fileMenu.add(printImage); 707 708 JMenuItem printPS = new JMenuItem("Print..."); 709 printPS.addActionListener(new ActionListener() 710 { 711 public void actionPerformed(ActionEvent e) 712 { 713 PrintVCFview part = new PrintVCFview(VCFview.this); 714 part.validate(); 715 part.doPrintActions(); 716 } 717 }); 718 fileMenu.add(printPS); 719 720 721 JMenuItem close = new JMenuItem("Close"); 722 fileMenu.add(close); 723 close.addActionListener(new ActionListener() 724 { 725 public void actionPerformed(ActionEvent e) 726 { 727 VCFview.this.setVisible(false); 728 Component comp = VCFview.this; 729 730 while( !(comp instanceof JFrame) ) 731 comp = comp.getParent(); 732 ((JFrame)comp).dispose(); 733 } 734 }); 735 736 JButton zoomIn = new JButton("-"); 737 Insets ins = new Insets(1,1,1,1); 738 zoomIn.setMargin(ins); 739 zoomIn.addActionListener(new ActionListener() 740 { 741 public void actionPerformed(ActionEvent e) 742 { 743 setZoomLevel((int) (VCFview.this.nbasesInView * 1.1)); 744 } 745 }); 746 topPanel.add(zoomIn); 747 748 JButton zoomOut = new JButton("+"); 749 zoomOut.setMargin(ins); 750 zoomOut.addActionListener(new ActionListener() 751 { 752 public void actionPerformed(ActionEvent e) 753 { 754 setZoomLevel((int) (VCFview.this.nbasesInView * .9)); 755 } 756 }); 757 topPanel.add(zoomOut); 758 } 759 760 combo = new SequenceComboBox(vcfReaders[0].getSeqNames()){ 761 private static final long serialVersionUID = 1L; 762 public void update(IndexReferenceEvent event) 763 { 764 if(combo.getSelectedItem().equals("Combine References")) 765 concatSequences = true; 766 else 767 { 768 VCFview.this.chr = (String) combo.getSelectedItem(); 769 concatSequences = false; 770 } 771 repaint(); 772 } 773 }; 774 775 if(vcfReaders[0].getSeqNames().length > 1) 776 combo.addItem("Combine References"); 777 778 if(chr == null) 779 this.chr = vcfReaders[0].getSeqNames()[0]; 780 combo.setSelectedItem(this.chr); 781 782 topPanel.add(combo); 783 if(topPanel instanceof JPanel) 784 vcfPanel.add(topPanel, BorderLayout.NORTH); 785 786 // auto hide top panel 787 final JCheckBox buttonAutoHide = new JCheckBox("Hide", true); 788 buttonAutoHide.setToolTipText("Auto-Hide"); 789 topPanel.add(buttonAutoHide); 790 final MouseMotionListener mouseMotionListener = new MouseMotionListener() 791 { 792 public void mouseDragged(MouseEvent event) 793 { 794 handleCanvasMouseDrag(event); 795 } 796 797 public void mouseMoved(MouseEvent e) 798 { 799 lastMousePoint = e.getPoint(); 800 801 int thisHgt = HEIGHT; 802 if (thisHgt < 5) 803 thisHgt = 15; 804 805 int y = (int) (e.getY() - jspView.getViewport().getViewRect().getY()); 806 if (y < thisHgt) 807 topPanel.setVisible(true); 808 else 809 { 810 if (buttonAutoHide.isSelected()) 811 topPanel.setVisible(false); 812 } 813 814 } 815 }; 816 addMouseMotionListener(mouseMotionListener); 817 818 819 if(feature_display != null) 820 { 821 JButton close = new JButton("Close"); 822 topPanel.add(close); 823 close.addActionListener(new ActionListener() 824 { 825 public void actionPerformed(ActionEvent e) 826 { 827 setVisible(false); 828 if(entry_edit != null) 829 entry_edit.setNGDivider(); 830 else 831 vcfPanel.setVisible(false); 832 } 833 }); 834 } 835 } 836 837 /** 838 * Create an icon of a box using the given colour. 839 * @param c 840 * @return 841 */ getImageIcon(Color c)842 protected ImageIcon getImageIcon(Color c) 843 { 844 BufferedImage image = (BufferedImage)this.createImage(10, 10); 845 if(image == null) 846 return null; 847 Graphics2D g2 = image.createGraphics(); 848 g2.setColor(c); 849 g2.fillRect(0, 0, 10, 10); 850 return new ImageIcon(image); 851 } 852 addToViewMenu(final int thisBamIndex)853 private void addToViewMenu(final int thisBamIndex) 854 { 855 LineAttributes ln[] = GraphPanel.getLineAttributes(vcfReaders.length); 856 final JCheckBoxMenuItem cbBam = new JCheckBoxMenuItem( 857 getLabel(thisBamIndex), 858 getImageIcon(ln[thisBamIndex].getLineColour()), 859 true); 860 861 vcfFilesMenu.add(cbBam); 862 cbBam.addActionListener(new ActionListener() 863 { 864 public void actionPerformed(ActionEvent e) 865 { 866 if(cbBam.isSelected()) 867 hideVcfList.remove(new Integer(thisBamIndex)); 868 else 869 hideVcfList.add(new Integer(thisBamIndex)); 870 repaint(); 871 } 872 }); 873 } 874 875 /** 876 * Test and download if on a http server 877 * @param fileName 878 * @return 879 */ testForURL(String fileName, boolean isBCF)880 private String testForURL(String fileName, boolean isBCF) 881 { 882 if(!fileName.startsWith("http:") && !fileName.startsWith("ftp:")) 883 return fileName; 884 885 return download(fileName+".tbi", ".tbi"); 886 } 887 download(String f, String suffix)888 protected String download(String f, String suffix) 889 { 890 try 891 { 892 final URL urlFile = new URL(f); 893 InputStream is = urlFile.openStream(); 894 895 // Create temp file. 896 String name = urlFile.getFile(); 897 int ind = name.lastIndexOf('/'); 898 if(ind > -1) 899 name = name.substring(ind+1); 900 File bcfFile = File.createTempFile(name.replaceAll("[\\/\\s]", "_"), suffix); 901 902 bcfFile.deleteOnExit(); 903 904 FileOutputStream out = new FileOutputStream(bcfFile); 905 int c; 906 while ((c = is.read()) != -1) 907 out.write(c); 908 out.flush(); 909 out.close(); 910 is.close(); 911 return bcfFile.getAbsolutePath(); 912 } 913 catch(IOException ioe) 914 { 915 JOptionPane.showMessageDialog(null, 916 "Problem downloading\n"+f, 917 "Problem", JOptionPane.WARNING_MESSAGE); 918 } 919 return null; 920 } 921 getReference(String reference)922 private static EntryGroup getReference(String reference) 923 { 924 EntryGroup entryGroup = new SimpleEntryGroup(); 925 final Document entry_document = DocumentFactory.makeDocument(reference); 926 final EntryInformation artemis_entry_information = 927 Options.getArtemisEntryInformation(); 928 929 final uk.ac.sanger.artemis.io.Entry new_embl_entry = 930 EntryFileDialog.getEntryFromFile(null, entry_document, 931 artemis_entry_information, 932 false); 933 if(new_embl_entry != null) // the read failed 934 { 935 Entry entry = null; 936 Bases bases = null; 937 try 938 { 939 if (entryGroup.getSequenceEntry() != null) 940 bases = entryGroup.getSequenceEntry().getBases(); 941 if (bases == null) 942 { 943 entry = new Entry(new_embl_entry); 944 bases = entry.getBases(); 945 } 946 else 947 entry = new Entry(bases, new_embl_entry); 948 entryGroup.add(entry); 949 } 950 catch (OutOfRangeException e) 951 { 952 new MessageDialog(null, "read failed: one of the features in " 953 + reference + " has an out of range " + "location: " 954 + e.getMessage()); 955 } 956 catch (NoSequenceException e) 957 { 958 // TODO Auto-generated catch block 959 e.printStackTrace(); 960 } 961 } 962 return entryGroup; 963 } 964 965 /** 966 * Read the vcf header 967 * @param fileName 968 * @return 969 */ readHeader(String fileName, int index)970 private void readHeader(String fileName, int index) 971 { 972 StringBuffer buff = new StringBuffer(); 973 //buff.append(fileName+"\n"); 974 try 975 { 976 if(IOUtils.isBCF(fileName)) 977 { 978 vcfReaders[index] = new BCFReader(fileName); 979 String hdr = ((BCFReader)vcfReaders[index]).headerToString(); 980 if(hdr.indexOf("VCFv4") > -1) 981 vcfReaders[index].setVcf_v4(true); 982 983 vcfReaders[index].setHeader(hdr); 984 return; 985 } 986 987 String indexfileName = testForURL(fileName, false); 988 BlockCompressedInputStream is; 989 if(fileName.startsWith("http")|| fileName.startsWith("ftp")) 990 { 991 URL url = new URL(fileName); 992 if(fileName.startsWith("ftp")) 993 vcfReaders[index] = new TabixReader(indexfileName.substring(0, indexfileName.length()-4), new FTPSeekableStream(url)); 994 else 995 vcfReaders[index] = new TabixReader(indexfileName.substring(0, indexfileName.length()-4), url); 996 is = new BlockCompressedInputStream(url); 997 } 998 else 999 { 1000 vcfReaders[index] = new TabixReader(fileName); 1001 is = new BlockCompressedInputStream(new FileInputStream(fileName)); 1002 } 1003 1004 String line; 1005 while( (line = TabixReader.readLine(is) ) != null ) 1006 { 1007 if(!line.startsWith("#")) 1008 break; 1009 1010 if(line.indexOf("VCFv4") > -1) 1011 vcfReaders[index].setVcf_v4(true); 1012 buff.append(line+"\n"); 1013 } 1014 is.close(); 1015 } 1016 catch (IOException e) 1017 { 1018 e.printStackTrace(); 1019 } 1020 1021 vcfReaders[index].setHeader(buff.toString()); 1022 return; 1023 } 1024 1025 /** 1026 * Set the number of bases being displayed 1027 * @param nbasesInView 1028 */ setZoomLevel(final int nbasesInView)1029 private void setZoomLevel(final int nbasesInView) 1030 { 1031 int startValue = scrollBar.getValue(); 1032 this.nbasesInView = nbasesInView; 1033 float pixPerBase = getPixPerBaseByWidth(); 1034 this.nbasesInView = (int)(getWidth()/pixPerBase); 1035 1036 if(scrollBar != null) 1037 { 1038 scrollBar.setValues(startValue, nbasesInView, 1, seqLength); 1039 scrollBar.setUnitIncrement(nbasesInView/20); 1040 scrollBar.setBlockIncrement(nbasesInView); 1041 } 1042 } 1043 getToolTipText()1044 public String getToolTipText() 1045 { 1046 if(vcfReaders == null) 1047 return null; 1048 1049 mouseVCF = null; 1050 findVariantAtPoint(lastMousePoint); 1051 if(mouseVCF == null) 1052 return null; 1053 1054 String msg = 1055 "Seq: "+mouseVCF.getChrom()+"\n"; 1056 msg += "Pos: "+mouseVCF.getPos()+"\n"; 1057 msg += "ID: "+mouseVCF.getID()+"\n"; 1058 msg += "Variant: "+mouseVCF.getRef()+" -> "+mouseVCF.getAlt().toString()+"\n"; 1059 msg += "Qual: "+mouseVCF.getQuality()+"\n"; 1060 String dp; 1061 1062 if(splitSamples && mouseOverSampleIndex >= 0) 1063 { 1064 msg += "Genotype "; 1065 msg += mouseVCF.getFormat(); 1066 msg += "\n"; 1067 msg += mouseVCF.getFormatValueForSample(mouseOverSampleIndex); 1068 } 1069 else if((dp = mouseVCF.getInfoValue("DP")) != null) 1070 { 1071 msg += "DP:"+dp; 1072 } 1073 return msg; 1074 } 1075 1076 1077 /** 1078 * For VCF files with multiple references sequences, calculate 1079 * the offset from the start of the concatenated sequence for 1080 * a given reference. 1081 * @param refName 1082 * @return 1083 */ getSequenceOffset(String refName)1084 protected int getSequenceOffset(String refName) 1085 { 1086 if(!concatSequences) 1087 return 0; 1088 1089 if(offsetLengths == null) 1090 { 1091 String[] contigs = vcfReaders[0].getSeqNames(); 1092 FeatureVector features = entryGroup.getAllFeatures(); 1093 offsetLengths = new Hashtable<String, Integer>(contigs.length); 1094 for(int i=0; i<contigs.length; i++) 1095 { 1096 FeatureContigPredicate predicate = new FeatureContigPredicate(contigs[i]); 1097 for(int j=0; j<features.size(); j++) 1098 { 1099 if(predicate.testPredicate(features.elementAt(j))) 1100 { 1101 offsetLengths.put(contigs[i], features.elementAt(j).getFirstBase()-1); 1102 break; 1103 } 1104 } 1105 } 1106 1107 if(offsetLengths.size() != contigs.length) 1108 { 1109 System.err.println("Number of contigs found : "+offsetLengths.size() + 1110 "\nNumber of contigs in VCF: "+contigs.length); 1111 JOptionPane.showMessageDialog(this, 1112 "There is a problem matching the reference sequences\n"+ 1113 "to the names in the VCF file. This may mean the labels\n"+ 1114 "on the reference features do not match those in the in\n"+ 1115 "the VCF file.", 1116 "Problem Found", JOptionPane.WARNING_MESSAGE); 1117 concatSequences = false; 1118 return 0; 1119 } 1120 } 1121 return offsetLengths.get(refName); 1122 } 1123 repaint()1124 public void repaint() 1125 { 1126 super.repaint(); 1127 if(graphPanel != null && graphPanel.isVisible()) 1128 graphPanel.repaint(); 1129 } 1130 paintComponent(Graphics g)1131 protected void paintComponent(Graphics g) 1132 { 1133 super.paintComponent(g); 1134 1135 Graphics2D g2d = (Graphics2D)g; 1136 mouseVCF = null; 1137 1138 float pixPerBase = getPixPerBaseByWidth(); 1139 int start = getBaseAtStartOfView(); 1140 int end = start+nbasesInView; 1141 1142 drawSelectionRange((Graphics2D)g, pixPerBase, start, end); 1143 1144 int sumSamples = 0; 1145 FeatureVector features = getCDSFeaturesInRange(start, end); 1146 1147 for (int i = 0; i < vcfReaders.length; i++) 1148 { 1149 if(hideVcfList.contains(i)) 1150 continue; 1151 1152 if(concatSequences) 1153 { 1154 String[] contigs = vcfReaders[0].getSeqNames(); 1155 for(int j=0; j<contigs.length; j++) 1156 { 1157 int offset = getSequenceOffset(contigs[j]); 1158 int nextOffset; 1159 if(j<contigs.length-1) 1160 nextOffset = getSequenceOffset(contigs[j+1]); 1161 else 1162 nextOffset = seqLength; 1163 1164 if( (offset >= start && offset < end) || 1165 (offset < start && start < nextOffset) ) 1166 { 1167 int thisStart = start - offset; 1168 if(thisStart < 1) 1169 thisStart = 1; 1170 int thisEnd = end - offset; 1171 1172 drawRegion(g2d, contigs[j], thisStart, thisEnd, i, sumSamples, start, pixPerBase, features); 1173 1174 } 1175 } 1176 1177 } 1178 else 1179 { 1180 int thisStart = start; 1181 if(thisStart < 1) 1182 thisStart = 1; 1183 drawRegion(g2d, chr, thisStart, end, i, sumSamples, start, pixPerBase, features); 1184 } 1185 sumSamples += vcfReaders[i].getNumberOfSamples(); 1186 } 1187 1188 if(feature_display == null) 1189 drawScale(g2d, start, end, pixPerBase, getHeight()); 1190 1191 // show labels for each VCF 1192 if(showLabels) 1193 showLabels(g2d); 1194 } 1195 showLabels(Graphics2D g2d)1196 private void showLabels(Graphics2D g2d) 1197 { 1198 int max = 0; 1199 final FontMetrics fm = getFontMetrics(getFont()); 1200 1201 for (int i = 0; i < vcfReaders.length; i++) 1202 { 1203 if(hideVcfList.contains(i)) 1204 continue; 1205 1206 if(splitSamples) 1207 { 1208 for(int sampleIdx = 0; sampleIdx < vcfReaders[i].getNumberOfSamples(); sampleIdx++) 1209 { 1210 if(vcfReaders[i].sampleNames == null) 1211 { 1212 int width = fm.stringWidth(getLabel(i)); 1213 if (max < width) 1214 max = width; 1215 break; 1216 } 1217 1218 String labStr = vcfReaders[i].sampleNames[sampleIdx]; 1219 int width = fm.stringWidth(labStr); 1220 if (max < width) 1221 max = width; 1222 } 1223 } 1224 else 1225 { 1226 String labStr = getLabel(i); 1227 int width = fm.stringWidth(labStr); 1228 if (max < width) 1229 max = width; 1230 } 1231 } 1232 1233 Rectangle square = new Rectangle(0, 0, max, getHeight()); 1234 Composite originalComposite = g2d.getComposite(); 1235 g2d.setPaint(Color.lightGray); 1236 g2d.setComposite(makeComposite(0.75f)); 1237 g2d.fill(square); 1238 g2d.setComposite(originalComposite); 1239 1240 g2d.setColor(Color.black); 1241 g2d.drawLine(max+1, 0, max+1, getHeight()); 1242 1243 int sumSample = 0; 1244 for (int i = 0; i < vcfReaders.length; i++) 1245 { 1246 if(hideVcfList.contains(i)) 1247 continue; 1248 1249 if(splitSamples) 1250 { 1251 for(int sampleIdx=0; sampleIdx < vcfReaders[i].getNumberOfSamples(); sampleIdx++) 1252 { 1253 if(vcfReaders[i].sampleNames == null) 1254 g2d.drawString(getLabel(i), 1, getYPostion(sumSample+sampleIdx)); 1255 else 1256 g2d.drawString(vcfReaders[i].sampleNames[sampleIdx], 1, getYPostion(sumSample+sampleIdx)); 1257 } 1258 sumSample += vcfReaders[i].getNumberOfSamples(); 1259 } 1260 else 1261 g2d.drawString(getLabel(i), 1, getYPostion(i)); 1262 } 1263 } 1264 getLabel(int index)1265 private String getLabel(int index) 1266 { 1267 return vcfReaders[index].getName().replaceAll(FILE_SUFFIX, ""); 1268 } 1269 makeComposite(float alpha)1270 private AlphaComposite makeComposite(float alpha) 1271 { 1272 return(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha)); 1273 } 1274 1275 drawRegion(final Graphics2D g, final String chr, final int sbeg, final int send, final int vcfFileIndex, final int sumSamples, final int start, final float pixPerBase, final FeatureVector features)1276 private void drawRegion(final Graphics2D g, 1277 final String chr, 1278 final int sbeg, 1279 final int send, 1280 final int vcfFileIndex, 1281 final int sumSamples, 1282 final int start, 1283 final float pixPerBase, 1284 final FeatureVector features) 1285 { 1286 cacheVariantLines = new Vector<Integer>(5); 1287 try 1288 { 1289 VCFRecord record; 1290 1291 // viewport position and height 1292 int viewIndex = getHeight()/(LINE_HEIGHT+5) - jspView.getViewport().getViewPosition().y/(LINE_HEIGHT+5); 1293 int viewHgt = jspView.getViewport().getExtentSize().height/(LINE_HEIGHT+5); 1294 1295 while((record = vcfReaders[vcfFileIndex].getNextRecord(chr, sbeg, send)) != null) 1296 { 1297 int basePosition = record.getPos() + getSequenceOffset(record.getChrom()); 1298 if(!splitSamples) 1299 { 1300 drawVariantCall(g, record, start, vcfFileIndex, -1, -1, pixPerBase, features, 1301 vcfReaders[vcfFileIndex], basePosition); 1302 continue; 1303 } 1304 1305 for(int sampleIndex = 0; sampleIndex < vcfReaders[vcfFileIndex].getNumberOfSamples(); sampleIndex++) 1306 { 1307 if(sampleIndex+sumSamples <= viewIndex+2 && sampleIndex+sumSamples >= viewIndex-viewHgt-2) 1308 { 1309 drawVariantCall(g, record, start, vcfFileIndex, sampleIndex, sumSamples, pixPerBase, features, 1310 vcfReaders[vcfFileIndex], basePosition); 1311 } 1312 } 1313 } 1314 } 1315 catch (IOException e) 1316 { 1317 logger4j.warn(chr+":"+sbeg+"-"+send+"\n"+e.getMessage()); 1318 e.printStackTrace(); 1319 } 1320 } 1321 getCDSFeaturesInRange(int start, int end)1322 protected FeatureVector getCDSFeaturesInRange(int start, int end) 1323 { 1324 if(entryGroup == null) 1325 return null; 1326 try 1327 { 1328 Range range = new Range(start, end); 1329 FeatureVector features = entryGroup.getFeaturesInRange(range); 1330 1331 FeatureKeyPredicate predicate = new FeatureKeyPredicate(Key.CDS); 1332 final FeatureVector cdsFeatures = new FeatureVector(); 1333 1334 for(int i=0; i<features.size(); i++) 1335 { 1336 final Feature this_feature = features.elementAt(i); 1337 if(predicate.testPredicate(this_feature)) 1338 cdsFeatures.add(this_feature); 1339 } 1340 return cdsFeatures; 1341 } 1342 catch (OutOfRangeException e1) 1343 { 1344 e1.printStackTrace(); 1345 } 1346 return null; 1347 } 1348 1349 /** 1350 * Highlight a selected range 1351 * @param g2 1352 * @param pixPerBase 1353 * @param start 1354 * @param end 1355 */ drawSelectionRange(Graphics2D g2, float pixPerBase, int start, int end)1356 private void drawSelectionRange(Graphics2D g2, float pixPerBase, int start, int end) 1357 { 1358 if(getSelection() != null) 1359 { 1360 Range selectedRange = getSelection().getSelectionRange(); 1361 1362 if(selectedRange != null) 1363 { 1364 int rangeStart = selectedRange.getStart(); 1365 int rangeEnd = selectedRange.getEnd(); 1366 1367 if(end < rangeStart || start > rangeEnd) 1368 return; 1369 1370 int x = (int) (pixPerBase*(rangeStart-getBaseAtStartOfView())); 1371 int width = (int) (pixPerBase*(rangeEnd-rangeStart+1)); 1372 1373 g2.setColor(Color.pink); 1374 g2.fillRect(x, 0, width, getHeight()); 1375 } 1376 } 1377 } 1378 getSelection()1379 private Selection getSelection() 1380 { 1381 return selection; 1382 } 1383 getBaseAtStartOfView()1384 protected int getBaseAtStartOfView() 1385 { 1386 if(feature_display != null) 1387 return feature_display.getForwardBaseAtLeftEdge(); 1388 else 1389 return scrollBar.getValue(); 1390 } 1391 showVariant(final VCFRecord record, final FeatureVector features, final int basePosition, final AbstractVCFReader vcfReader, final int nsample, final int vcfIndex)1392 protected boolean showVariant(final VCFRecord record, final FeatureVector features, final int basePosition, 1393 final AbstractVCFReader vcfReader, final int nsample, final int vcfIndex) 1394 { 1395 return VCFFilter.passFilter(manualHash, record, vcfReader, features, basePosition, nsample, vcfIndex); 1396 } 1397 setAsStop(VCFRecord record, FeatureVector features, int basePosition, AbstractVCFReader vcfReader)1398 private void setAsStop(VCFRecord record, FeatureVector features, int basePosition, AbstractVCFReader vcfReader) 1399 { 1400 if(!record.isMarkAsNewStop() && 1401 markNewStops.isSelected() && 1402 !record.getAlt().isDeletion(vcfReader.isVcf_v4()) && 1403 !record.getAlt().isInsertion(vcfReader.isVcf_v4()) && 1404 record.getAlt().length() == 1 && 1405 record.getRef().length() == 1) 1406 { 1407 short isSyn = record.getSynFlag(features, basePosition); 1408 if(isSyn == 2) 1409 record.setMarkAsNewStop(true); 1410 } 1411 } 1412 isOverlappingFeature(FeatureVector features, int basePosition)1413 protected static boolean isOverlappingFeature(FeatureVector features, int basePosition) 1414 { 1415 for(int i = 0; i<features.size(); i++) 1416 { 1417 Feature feature = features.elementAt(i); 1418 if(feature.getRawFirstBase() < basePosition && feature.getRawLastBase() > basePosition) 1419 { 1420 RangeVector ranges = feature.getLocation().getRanges(); 1421 for(int j=0; j< ranges.size(); j++) 1422 { 1423 Range range = (Range) ranges.get(j); 1424 if(range.getStart() < basePosition && range.getEnd() > basePosition) 1425 return true; 1426 } 1427 } 1428 } 1429 return false; 1430 } 1431 isOverlappingFeature(List<CDSFeature> cdsFeatures, int basePosition)1432 protected static boolean isOverlappingFeature(List<CDSFeature> cdsFeatures, int basePosition) { 1433 for (CDSFeature cdsFeature : cdsFeatures) { 1434 if (cdsFeature.firstBase < basePosition && cdsFeature.lastBase > basePosition) 1435 { 1436 for(int i = 0 ; i < cdsFeature.ranges.size() ; ++i) 1437 { 1438 Range range = (Range)cdsFeature.ranges.elementAt(i); 1439 if (range.getStart() < basePosition && range.getEnd() > basePosition) 1440 return true; 1441 } 1442 } 1443 } 1444 return false; 1445 } 1446 1447 /** 1448 * Draw the VCF record 1449 * @param g 1450 * @param record 1451 * @param start 1452 * @param vcfIndex 1453 * @param sampleIndex 1454 * @param sumSamples 1455 * @param pixPerBase 1456 * @param features 1457 * @param vcfReader 1458 * @param basePosition 1459 */ drawVariantCall(final Graphics2D g, final VCFRecord record, final int start, final int vcfIndex, final int sampleIndex, final int sumSamples, final float pixPerBase, final FeatureVector features, final AbstractVCFReader vcfReader, final int basePosition)1460 private void drawVariantCall(final Graphics2D g, 1461 final VCFRecord record, 1462 final int start, 1463 final int vcfIndex, 1464 final int sampleIndex, 1465 final int sumSamples, 1466 final float pixPerBase, 1467 final FeatureVector features, 1468 final AbstractVCFReader vcfReader, 1469 final int basePosition) 1470 { 1471 boolean show = showVariant(record, features, basePosition, vcfReader, sampleIndex, vcfIndex); 1472 if( !show ) 1473 return; 1474 1475 setAsStop(record, features, basePosition, vcfReader); 1476 final int pos[]; 1477 if(sampleIndex < 0) 1478 pos = getScreenPosition(basePosition, pixPerBase, start, vcfIndex); 1479 else 1480 pos = getScreenPosition(basePosition, pixPerBase, start, sampleIndex+sumSamples); 1481 1482 if (colourScheme == QUAL_COLOUR_SCHEME) 1483 g.setColor(getQualityColour(record)); 1484 else if (record.getAlt().isDeletion(vcfReader.isVcf_v4())) 1485 g.setColor(Color.gray); 1486 else if (record.getAlt().isInsertion(vcfReader.isVcf_v4())) 1487 g.setColor(Color.magenta); 1488 else if (record.getAlt().isMultiAllele(sampleIndex)) 1489 { 1490 g.setColor(Color.orange); 1491 g.fillArc(pos[0] - 3, pos[1] - LINE_HEIGHT - 3, 6, 6, 0, 360); 1492 } 1493 else if (record.getAlt().length() == 1 && record.getRef().length() == 1) 1494 { 1495 g.setColor(getColourForSNP(record, features, basePosition)); 1496 if (record.getAlt().isNonVariant()) 1497 { 1498 // use the cache to avoid drawing over a variant with a non-variant 1499 if (!cacheVariantLines.contains(pos[0])) 1500 g.drawLine(pos[0], pos[1], pos[0], pos[1] - LINE_HEIGHT + 6); 1501 return; 1502 } 1503 } 1504 else 1505 g.setColor(Color.pink); 1506 1507 if (record.isMarkAsNewStop()) 1508 g.fillArc(pos[0] - 3, pos[1] - (LINE_HEIGHT / 2) - 3, 6, 6, 0, 360); 1509 1510 if (cacheVariantLines.size() == 5) 1511 cacheVariantLines.clear(); 1512 cacheVariantLines.add(pos[0]); 1513 1514 g.drawLine(pos[0], pos[1], pos[0], pos[1] - LINE_HEIGHT); 1515 } 1516 1517 /** 1518 * Determine the colour depending on the colour scheme in use. 1519 * @param record 1520 * @param features 1521 * @param basePosition 1522 * @return 1523 */ getColourForSNP(VCFRecord record, FeatureVector features, int basePosition)1524 private Color getColourForSNP(VCFRecord record, FeatureVector features, int basePosition) 1525 { 1526 if(colourScheme == VARIANT_COLOUR_SCHEME) 1527 return getVariantColour(record.getAlt().toString()); 1528 else if(colourScheme == SYN_COLOUR_SCHEME) // synonymous / non-synonymous 1529 { 1530 if(!record.getAlt().isNonVariant()) 1531 { 1532 short synFlag = record.getSynFlag(features, basePosition); 1533 if(synFlag == 1) 1534 return Color.red; 1535 else if(synFlag == 0 || synFlag == 2) 1536 return Color.blue; 1537 } 1538 return getVariantColour(record.getAlt().toString()); 1539 } 1540 else // score 1541 return getQualityColour(record); 1542 } 1543 getQualityColour(VCFRecord record)1544 private Color getQualityColour(VCFRecord record) 1545 { 1546 if(colMap == null) 1547 colMap = makeColours(Color.RED, 255); 1548 int idx = (int) record.getQuality()-1; 1549 if(idx > colMap.length-1) 1550 idx = colMap.length-1; 1551 else if(idx < 0) 1552 idx = 0; 1553 return colMap[idx]; 1554 } 1555 getVariantColour(String variant)1556 private Color getVariantColour(String variant) 1557 { 1558 if(variant.equals("C")) 1559 return Color.red; 1560 else if(variant.equals("A")) 1561 return Color.green; 1562 else if(variant.equals("G")) 1563 return Color.blue; 1564 else if(variant.equals("T")) 1565 return Color.black; 1566 else 1567 return lighterGrey; // non-variant 1568 } 1569 1570 /** 1571 * Generate the colours for heat map plots. 1572 * @param col 1573 * @param NUMBER_OF_SHADES 1574 * @return 1575 */ makeColours(Color col, int NUMBER_OF_SHADES)1576 private Color[] makeColours(Color col, int NUMBER_OF_SHADES) 1577 { 1578 Color definedColour[] = new Color[NUMBER_OF_SHADES]; 1579 for(int i = 0; i < NUMBER_OF_SHADES; ++i) 1580 { 1581 int R = col.getRed(); 1582 int G = col.getGreen(); 1583 int B = col.getBlue(); 1584 1585 float scale = ((float)(NUMBER_OF_SHADES-i) * (float)(255 / NUMBER_OF_SHADES )) ; 1586 1587 if((R+scale) <= 255) 1588 R += scale; 1589 else 1590 R = 254; 1591 if((G+scale) <= 255) 1592 G += scale; 1593 else 1594 G = 254; 1595 if((B+scale) <= 255) 1596 B += scale; 1597 else 1598 B = 254; 1599 1600 definedColour[i] = new Color(R,G,B); 1601 } 1602 return definedColour; 1603 } 1604 getScreenPosition(int base, float pixPerBase, int start, int vcfFileIndex)1605 private int[] getScreenPosition(int base, float pixPerBase, int start, int vcfFileIndex) 1606 { 1607 int pos[] = new int[2]; 1608 pos[0] = Math.round((base - start)*pixPerBase); 1609 pos[1] = getYPostion(vcfFileIndex); 1610 return pos; 1611 } 1612 getYPostion(int vcfFileIndex)1613 private int getYPostion(int vcfFileIndex) 1614 { 1615 int pos = 0; 1616 if(hideVcfList.size() == 0 || splitSamples) 1617 pos = vcfFileIndex; 1618 else 1619 { 1620 for(int i=0; i<vcfFileIndex; i++) 1621 if(!hideVcfList.contains(i)) 1622 pos++; 1623 } 1624 1625 return getHeight() - 15 - (pos*(LINE_HEIGHT+5)); 1626 } 1627 findVariantAtPoint(Point mousePoint)1628 private void findVariantAtPoint(Point mousePoint) 1629 { 1630 float pixPerBase = getPixPerBaseByWidth(); 1631 int startBase = getBaseAtStartOfView(); 1632 int start = startBase + (int)(mousePoint.getX()/pixPerBase) - 20; 1633 int end = start+20; 1634 FeatureVector features = getCDSFeaturesInRange(start, end); 1635 int sumSamples = 0; 1636 1637 for (int i = 0; i < vcfReaders.length; i++) 1638 { 1639 1640 if(concatSequences) 1641 { 1642 String[] contigs = vcfReaders[0].getSeqNames(); 1643 for(int k=0; k<contigs.length; k++) 1644 { 1645 int offset = getSequenceOffset(contigs[k]); 1646 int nextOffset; 1647 if(k<contigs.length-1) 1648 nextOffset = getSequenceOffset(contigs[k+1]); 1649 else 1650 nextOffset = seqLength; 1651 1652 if( (offset >= start && offset < end) || 1653 (offset < start && start < nextOffset) ) 1654 { 1655 int thisStart = start - offset; 1656 if(thisStart < 1) 1657 thisStart = 1; 1658 int thisEnd = end - offset; 1659 searchRegion(contigs[k], thisStart, thisEnd, i, sumSamples, mousePoint, features, startBase, pixPerBase); 1660 } 1661 } 1662 } 1663 else 1664 { 1665 int thisStart = start; 1666 if(thisStart < 1) 1667 thisStart = 1; 1668 searchRegion(chr, thisStart, end, i, sumSamples, mousePoint, features, startBase, pixPerBase); 1669 } 1670 1671 1672 sumSamples += vcfReaders[i].getNumberOfSamples(); 1673 } 1674 } 1675 searchRegion(final String chr, final int sbeg, final int send, final int fileIndex, final int sumSamples, final Point mousePoint, FeatureVector features, int start, float pixPerBase)1676 private void searchRegion(final String chr, 1677 final int sbeg, final int send, 1678 final int fileIndex, 1679 final int sumSamples, 1680 final Point mousePoint, FeatureVector features, 1681 int start, float pixPerBase) 1682 { 1683 try 1684 { 1685 VCFRecord bcfRecord; 1686 while((bcfRecord = vcfReaders[fileIndex].getNextRecord(chr, sbeg, send)) != null) 1687 { 1688 1689 if(splitSamples) 1690 { 1691 for(int sampleIndex=0; sampleIndex<vcfReaders[fileIndex].getNumberOfSamples(); sampleIndex++) 1692 { 1693 int ypos = getYPostion(sampleIndex+sumSamples); 1694 if(mousePoint.getY() > ypos && 1695 mousePoint.getY() < ypos-LINE_HEIGHT) 1696 continue; 1697 1698 isMouseOver(mousePoint, bcfRecord, features, fileIndex, sampleIndex, sumSamples, start, pixPerBase, vcfReaders[fileIndex]); 1699 } 1700 } 1701 else 1702 { 1703 int ypos = getYPostion(fileIndex); 1704 if(mousePoint.getY() > ypos && 1705 mousePoint.getY() < ypos-LINE_HEIGHT) 1706 continue; 1707 1708 isMouseOver(mousePoint, bcfRecord, features, fileIndex, -1, sumSamples, start, pixPerBase, vcfReaders[fileIndex]); 1709 } 1710 1711 1712 } 1713 } 1714 catch (IOException e) 1715 { 1716 logger4j.warn(chr+":"+sbeg+"-"+send+"\n"+e.getMessage()); 1717 e.printStackTrace(); 1718 } 1719 } 1720 isMouseOver(final Point mousePoint, final VCFRecord record, final FeatureVector features, final int vcfFileIndex, final int sampleIndex, final int sumSamples, final int start, final float pixPerBase, final AbstractVCFReader vcfReader)1721 private void isMouseOver(final Point mousePoint, 1722 final VCFRecord record, 1723 final FeatureVector features, 1724 final int vcfFileIndex, 1725 final int sampleIndex, 1726 final int sumSamples, 1727 final int start, final float pixPerBase, 1728 final AbstractVCFReader vcfReader) 1729 { 1730 int basePosition = record.getPos() + getSequenceOffset(record.getChrom()); 1731 if( !showVariant(record, features, basePosition, vcfReader, sampleIndex, vcfFileIndex) ) 1732 return; 1733 1734 int pos[]; 1735 if(!splitSamples) 1736 pos = getScreenPosition(basePosition, pixPerBase, start, vcfFileIndex); 1737 else 1738 pos = getScreenPosition(basePosition, pixPerBase, start, sampleIndex+sumSamples); 1739 1740 if(mousePoint != null && 1741 mousePoint.getY() < pos[1] && 1742 mousePoint.getY() > pos[1]-LINE_HEIGHT && 1743 mousePoint.getX() > pos[0]-3 && 1744 mousePoint.getX() < pos[0]+3) 1745 { 1746 mouseVCF = record; 1747 mouseOverIndex = vcfFileIndex; 1748 mouseOverSampleIndex = sampleIndex; 1749 } 1750 } 1751 drawScale(Graphics2D g2, int start, int end, float pixPerBase, int ypos)1752 private void drawScale(Graphics2D g2, int start, int end, float pixPerBase, int ypos) 1753 { 1754 g2.setColor(Color.black); 1755 g2.drawLine( 0, ypos-14, 1756 (int)((end - start)*pixPerBase), ypos-14); 1757 int interval = end-start; 1758 1759 if(interval > 20000000) 1760 drawTicks(g2, start, end, pixPerBase, 10000000, ypos); 1761 else if(interval > 4000000) 1762 drawTicks(g2, start, end, pixPerBase, 2000000, ypos); 1763 else if(interval > 800000) 1764 drawTicks(g2, start, end, pixPerBase, 400000, ypos); 1765 else if(interval > 160000) 1766 drawTicks(g2, start, end, pixPerBase, 80000, ypos); 1767 else if(interval > 50000) 1768 drawTicks(g2, start, end, pixPerBase, 25000, ypos); 1769 else if(interval > 16000) 1770 drawTicks(g2, start, end, pixPerBase, 8000, ypos); 1771 else if(interval > 4000) 1772 drawTicks(g2, start, end, pixPerBase, 2000, ypos); 1773 else if(interval > 1000) 1774 drawTicks(g2, start, end, pixPerBase, 500, ypos); 1775 else 1776 drawTicks(g2, start, end, pixPerBase, 100, ypos); 1777 } 1778 1779 /** 1780 * Handle a mouse drag event on the drawing canvas. 1781 **/ handleCanvasMouseDrag(final MouseEvent event)1782 private void handleCanvasMouseDrag(final MouseEvent event) 1783 { 1784 if(event.getButton() == MouseEvent.BUTTON3) 1785 return; 1786 1787 if(event.getClickCount() > 1) 1788 { 1789 getSelection().clear(); 1790 repaint(); 1791 return; 1792 } 1793 1794 highlightRange(event, 1795 MouseEvent.BUTTON1_DOWN_MASK & MouseEvent.BUTTON2_DOWN_MASK); 1796 } 1797 1798 /** 1799 * 1800 * @param event 1801 * @param onmask 1802 */ highlightRange(MouseEvent event, int onmask)1803 private void highlightRange(MouseEvent event, int onmask) 1804 { 1805 if(entryGroup == null) 1806 return; 1807 float pixPerBase = getPixPerBaseByWidth(); 1808 int start = (int) ( ( (event.getPoint().getX())/pixPerBase) + getBaseAtStartOfView() ); 1809 1810 if(start < 1) 1811 start = 1; 1812 if(start > seqLength) 1813 start = seqLength; 1814 1815 if (dragStart < 0 && (event.getModifiersEx() & onmask) == onmask) 1816 dragStart = start; 1817 else if((event.getModifiersEx() & onmask) != onmask) 1818 dragStart = -1; 1819 1820 MarkerRange drag_range; 1821 try 1822 { 1823 if(dragStart < 0) 1824 drag_range = new MarkerRange (entryGroup.getSequenceEntry().getBases().getForwardStrand(), start, start); 1825 else 1826 drag_range = new MarkerRange (entryGroup.getSequenceEntry().getBases().getForwardStrand(), dragStart, start); 1827 getSelection().setMarkerRange(drag_range); 1828 repaint(); 1829 } 1830 catch (OutOfRangeException e) 1831 { 1832 e.printStackTrace(); 1833 } 1834 } 1835 drawTicks(Graphics2D g2, int start, int end, float pixPerBase, int division, int ypos)1836 private void drawTicks(Graphics2D g2, int start, int end, 1837 float pixPerBase, int division, int ypos) 1838 { 1839 int markStart = (Math.round(start/division)*division); 1840 1841 if(markStart < 1) 1842 markStart = 1; 1843 1844 int sm = markStart-(division/2); 1845 float x; 1846 if(sm > start) 1847 { 1848 x = (sm-start)*pixPerBase; 1849 g2.drawLine((int)x, ypos-14,(int)x, ypos-12); 1850 } 1851 1852 for(int m=markStart; m<end; m+=division) 1853 { 1854 x = (m-start)*pixPerBase; 1855 g2.drawString(Integer.toString(m), x, ypos-1); 1856 g2.drawLine((int)x, ypos-14,(int)x, ypos-11); 1857 1858 sm = m+(division/2); 1859 1860 if(sm < end) 1861 { 1862 x = (sm-start)*pixPerBase; 1863 g2.drawLine((int)x, ypos-14,(int)x, ypos-12); 1864 } 1865 1866 if(m == 1) 1867 m = 0; 1868 } 1869 } 1870 getPixPerBaseByWidth()1871 protected float getPixPerBaseByWidth() 1872 { 1873 return (float)vcfPanel.getWidth() / (float)nbasesInView; 1874 } 1875 getBasesInView()1876 protected int getBasesInView() 1877 { 1878 return nbasesInView; 1879 } 1880 1881 getEntryGroup()1882 protected EntryGroup getEntryGroup() 1883 { 1884 return entryGroup; 1885 } 1886 getChr()1887 protected String getChr() 1888 { 1889 return chr; 1890 } 1891 isConcatenate()1892 protected boolean isConcatenate() 1893 { 1894 return concatSequences; 1895 } 1896 1897 /** 1898 * @return the combo 1899 */ getCombo()1900 public SequenceComboBox getCombo() 1901 { 1902 return combo; 1903 } 1904 1905 /** 1906 * @return the vcfReaders 1907 */ getVcfReaders()1908 protected AbstractVCFReader[] getVcfReaders() 1909 { 1910 return vcfReaders; 1911 } 1912 1913 getVcfContainer()1914 private Container getVcfContainer() 1915 { 1916 try 1917 { 1918 Frame fs[] = JFrame.getFrames(); 1919 for(Frame f: fs) 1920 { 1921 if( f instanceof JFrame && 1922 ((JFrame)f) instanceof EntryEdit || 1923 ((JFrame)f) instanceof MultiComparator) 1924 return ((JFrame)f).getContentPane(); 1925 } 1926 } 1927 catch(Exception e){} 1928 return VCFview.this; 1929 } 1930 1931 /** 1932 * Popup menu listener 1933 */ 1934 class PopupListener extends MouseAdapter 1935 { 1936 JMenuItem showDetails; 1937 JMenuItem annotate; 1938 mouseClicked(MouseEvent e)1939 public void mouseClicked(MouseEvent e) 1940 { 1941 if(e.isPopupTrigger() || 1942 e.getButton() == MouseEvent.BUTTON3) 1943 return; 1944 1945 if(e.getClickCount() > 1) 1946 { 1947 getSelection().clear(); 1948 repaint(); 1949 } 1950 } 1951 mousePressed(MouseEvent e)1952 public void mousePressed(MouseEvent e) 1953 { 1954 maybeShowPopup(e); 1955 } 1956 mouseReleased(MouseEvent e)1957 public void mouseReleased(MouseEvent e) 1958 { 1959 dragStart = -1; 1960 maybeShowPopup(e); 1961 } 1962 maybeShowPopup(MouseEvent e)1963 private void maybeShowPopup(MouseEvent e) 1964 { 1965 if(e.isPopupTrigger()) 1966 { 1967 if(showDetails != null) 1968 { 1969 popup.remove(showDetails); 1970 popup.remove(annotate); 1971 } 1972 1973 mouseVCF = null; 1974 findVariantAtPoint(e.getPoint()); 1975 final VCFRecord thisMouseVCF = mouseVCF; 1976 final int thisMouseOverIndex = mouseOverIndex; 1977 if( thisMouseVCF != null ) 1978 { 1979 showDetails = new JMenuItem("Show details of : "+ 1980 thisMouseVCF.getChrom()+":"+thisMouseVCF.getPos()+" "+thisMouseVCF.getID()); 1981 showDetails.addActionListener(new ActionListener() 1982 { 1983 public void actionPerformed(ActionEvent e) 1984 { 1985 FileViewer viewDetail = new FileViewer( 1986 thisMouseVCF.getChrom()+":"+thisMouseVCF.getPos()+" "+thisMouseVCF.getID(), true, false, true); 1987 1988 viewDetail.appendString(vcfReaders[mouseOverIndex].getHeader()+"\n", Level.INFO); 1989 1990 viewDetail.appendString("Seq : "+thisMouseVCF.getChrom()+"\n", Level.DEBUG); 1991 viewDetail.appendString("Pos : "+thisMouseVCF.getPos()+"\n", Level.DEBUG); 1992 viewDetail.appendString("ID : "+thisMouseVCF.getID()+"\n", Level.DEBUG); 1993 viewDetail.appendString("Ref : "+thisMouseVCF.getRef()+"\n", Level.DEBUG); 1994 viewDetail.appendString("Alt : "+thisMouseVCF.getAlt().toString()+"\n", Level.DEBUG); 1995 viewDetail.appendString("Qual : "+thisMouseVCF.getQuality()+"\n", Level.DEBUG); 1996 viewDetail.appendString("Filter: "+thisMouseVCF.getFilter()+"\n", Level.DEBUG); 1997 viewDetail.appendString("Info : "+thisMouseVCF.getInfo()+"\n", Level.DEBUG); 1998 1999 if(thisMouseVCF.getFormat() != null) 2000 { 2001 viewDetail.appendString("\nGenotype information:\n", Level.INFO); 2002 viewDetail.appendString("Format: "+thisMouseVCF.getFormat()+"\n", Level.DEBUG); 2003 viewDetail.appendString(thisMouseVCF.getSampleDataString()+"\n", Level.DEBUG); 2004 } 2005 2006 viewDetail.getTextPane().setCaretPosition(0); 2007 } 2008 }); 2009 popup.add(showDetails); 2010 2011 annotate = new JMenuItem("Manual PASS / FAIL"); 2012 annotate.addActionListener(new ActionListener() 2013 { 2014 public void actionPerformed(ActionEvent e) 2015 { 2016 new ManualAnnotation(thisMouseVCF, thisMouseOverIndex); 2017 } 2018 }); 2019 popup.add(annotate); 2020 } 2021 popup.show(e.getComponent(), 2022 e.getX(), e.getY()); 2023 } 2024 } 2025 } 2026 setDisplay()2027 private void setDisplay() 2028 { 2029 Dimension d = new Dimension(); 2030 2031 if(splitSamples) 2032 { 2033 int count = 0; 2034 for(int i=0; i<vcfReaders.length; i++) 2035 count += vcfReaders[i].getNumberOfSamples(); 2036 d.setSize(nbasesInView*getPixPerBaseByWidth(), (count+1)*(LINE_HEIGHT+5)); 2037 } 2038 else 2039 d.setSize(nbasesInView*getPixPerBaseByWidth(), (vcfReaders.length+1)*(LINE_HEIGHT+5)); 2040 setPreferredSize(d); 2041 } 2042 displayAdjustmentValueChanged(DisplayAdjustmentEvent event)2043 public void displayAdjustmentValueChanged(DisplayAdjustmentEvent event) 2044 { 2045 nbasesInView = feature_display.getMaxVisibleBases(); 2046 setDisplay(); 2047 repaint(); 2048 } 2049 selectionChanged(SelectionChangeEvent event)2050 public void selectionChanged(SelectionChangeEvent event) 2051 { 2052 repaint(); 2053 } 2054 2055 /** 2056 * Manual annotation of a variant record. 2057 */ 2058 class ManualAnnotation extends JFrame 2059 { 2060 private static final long serialVersionUID = 1L; 2061 ManualAnnotation(final VCFRecord thisMouseVCF, final int thisMouseOverIndex)2062 ManualAnnotation(final VCFRecord thisMouseVCF, final int thisMouseOverIndex) 2063 { 2064 super("Manual PASS / FAIL"); 2065 final JPanel pane = (JPanel) getContentPane(); 2066 pane.setLayout(new BorderLayout()); 2067 final JPanel panel = new JPanel(new GridBagLayout()); 2068 final JScrollPane jsp = new JScrollPane(panel); 2069 jsp.setPreferredSize(new Dimension(350, 180)); 2070 pane.add(jsp, BorderLayout.NORTH); 2071 2072 final GridBagConstraints c = new GridBagConstraints(); 2073 c.gridx = 0; 2074 c.gridy = 0; 2075 c.gridwidth = 3; 2076 c.anchor = GridBagConstraints.NORTHWEST; 2077 panel.add(new JLabel("Seq : "+thisMouseVCF.getChrom()), c); 2078 c.gridy++; 2079 panel.add(new JLabel("Pos : "+thisMouseVCF.getPos()), c); 2080 c.gridy++; 2081 panel.add(new JLabel("ID : "+thisMouseVCF.getPos()), c); 2082 c.gridy++; 2083 panel.add(new JLabel("Ref : "+thisMouseVCF.getRef()), c); 2084 c.gridy++; 2085 panel.add(new JLabel("Alt : "+thisMouseVCF.getAlt().toString()), c); 2086 c.gridy++; 2087 panel.add(new JLabel("Qual : "+thisMouseVCF.getQuality()), c); 2088 c.gridy++; 2089 panel.add(new JLabel("Filter: "+thisMouseVCF.getFilter()), c); 2090 c.gridy++; 2091 panel.add(new JLabel("Info : "+thisMouseVCF.getInfo()), c); 2092 2093 final JRadioButton passB = new JRadioButton("PASS"); 2094 final JRadioButton failB = new JRadioButton("FAIL"); 2095 final JRadioButton noManualB = new JRadioButton("NO MANUAL FILTER", true); 2096 2097 final ButtonGroup group = new ButtonGroup(); 2098 group.add(passB); 2099 group.add(failB); 2100 group.add(noManualB); 2101 2102 int res = VCFFilter.checkManualHash(manualHash, thisMouseVCF, thisMouseOverIndex, false); 2103 switch(res) 2104 { 2105 case 1: passB.setSelected(true); 2106 break; 2107 case 2: failB.setSelected(true); 2108 break; 2109 default: noManualB.setSelected(true); 2110 break; 2111 } 2112 2113 c.gridy++; 2114 panel.add(Box.createVerticalStrut(10), c); 2115 2116 c.gridwidth = 1; 2117 c.gridy++; 2118 panel.add(passB, c); 2119 c.gridx++; 2120 panel.add(failB, c); 2121 c.gridx++; 2122 panel.add(noManualB, c); 2123 2124 final JButton apply = new JButton("Apply"); 2125 apply.addActionListener(new ActionListener() 2126 { 2127 public void actionPerformed(ActionEvent arg0) 2128 { 2129 setVisible(false); 2130 if(passB.isSelected()) 2131 manualHash.put(thisMouseVCF.getPos()+":"+thisMouseVCF.getChrom()+":"+thisMouseOverIndex, true); 2132 else if(failB.isSelected()) 2133 manualHash.put(thisMouseVCF.getPos()+":"+thisMouseVCF.getChrom()+":"+thisMouseOverIndex, false); 2134 else 2135 manualHash.remove(thisMouseVCF.getPos()+":"+thisMouseVCF.getChrom()+":"+thisMouseOverIndex); 2136 VCFview.this.repaint(); 2137 ManualAnnotation.this.dispose(); 2138 } 2139 }); 2140 pane.add(apply, BorderLayout.SOUTH); 2141 pack(); 2142 Utilities.centreFrame(this); 2143 setVisible(true); 2144 } 2145 } 2146 main(String args[])2147 public static void main(String args[]) 2148 { 2149 List<String> vcfFileList = new Vector<String>(); 2150 String reference = null; 2151 if(args.length == 0) 2152 { 2153 System.setProperty("default_directory", System.getProperty("user.dir")); 2154 FileSelectionDialog fileSelection = new FileSelectionDialog( 2155 null, true, "VCFview", "VCF"); 2156 vcfFileList = fileSelection.getFiles(VCFFILE_SUFFIX); 2157 reference = fileSelection.getReferenceFile(); 2158 if(reference.equals("")) 2159 reference = null; 2160 2161 if(vcfFileList == null || vcfFileList.size() < 1) 2162 System.exit(0); 2163 } 2164 else if(!args[0].startsWith("-")) 2165 { 2166 for(int i=0; i< args.length; i++) 2167 vcfFileList.add(args[i]); 2168 } 2169 2170 int nbasesInView = 5000000; 2171 2172 for(int i=0;i<args.length; i++) 2173 { 2174 if(args[i].equals("-f")) 2175 { 2176 while(i < args.length-1 && !args[++i].startsWith("-")) 2177 { 2178 String filename = args[i]; 2179 if(FileSelectionDialog.isListOfFiles(filename)) 2180 vcfFileList.addAll(FileSelectionDialog.getListOfFiles(filename)); 2181 else 2182 vcfFileList.add(filename); 2183 } 2184 --i; 2185 } 2186 else if(args[i].equals("-r")) 2187 reference = args[++i]; 2188 else if(args[i].equals("-v")) 2189 nbasesInView = Integer.parseInt(args[++i]); 2190 else if(args[i].startsWith("-h")) 2191 { 2192 System.out.println("-h\t show help"); 2193 2194 System.out.println("-f\t VCF file to display"); 2195 System.out.println("-r\t reference file (optional)"); 2196 System.out.println("-v\t number of bases to display in the view (optional)"); 2197 //System.out.println("-t\t chr:start-end - this writes out the given region"); 2198 2199 System.exit(0); 2200 } 2201 } 2202 2203 JFrame f = new JFrame(); 2204 new VCFview(f, (JPanel) f.getContentPane(), vcfFileList, 2205 nbasesInView, 100000000, null, reference, null, null); 2206 2207 f.pack(); 2208 f.setVisible(true); 2209 } 2210 }