Skip to content
Snippets Groups Projects
BamView.java 104 KiB
Newer Older
tjc's avatar
tjc committed
      InputStream in = cl.getResourceAsStream("etc/versions");
      BufferedReader reader = new BufferedReader(new InputStreamReader(in));
      while((line = reader.readLine()) != null)
      {
        if(line.startsWith("BamView"))
          return line.substring( "BamView".length() ).trim();
      }
      reader.close();
      in.close();
    }
    catch (Exception ex)
    {
    }
    return null;
  }
  
tjc's avatar
tjc committed
  /**
   * Artemis event notification
   */
  public void displayAdjustmentValueChanged(final DisplayAdjustmentEvent event)
    if(event.getType() == DisplayAdjustmentEvent.REV_COMP_EVENT &&
       event.isRevCompDisplay())
      JOptionPane.showMessageDialog(this, 
          "Flipping the display is not supported by BamView.", "Warning", 
          JOptionPane.WARNING_MESSAGE);

    if(!asynchronous)
    {
      // if not asynchronous
      displayAdjustmentWork(event);
      return;
    }
    
    SwingWorker worker = new SwingWorker()
tjc's avatar
tjc committed
    {
      public Object construct()
      {
        try
        {
          Thread.sleep(500);
        }
        catch (InterruptedException e)
        {
          e.printStackTrace();
        }
        
        if(event.getStart() != ((FeatureDisplay)event.getSource()).getForwardBaseAtLeftEdge())
        {
          waitingFrame.showWaiting("waiting...", mainPanel);
        displayAdjustmentWork(event);
        waitingFrame.setVisible(false);
        return null;
      }
    };
    worker.start();
  /**
   * Carry out the display agjustment event action.
   * @param event
   */
  private void displayAdjustmentWork(final DisplayAdjustmentEvent event)
  {
    if(event.getType() == DisplayAdjustmentEvent.SCALE_ADJUST_EVENT)
    {
      laststart = -1;
tjc's avatar
tjc committed

      BamView.this.startBase = event.getStart();
      BamView.this.endBase   = event.getEnd();

      int width = feature_display.getMaxVisibleBases();
      setZoomLevel(width);
      repaint();
    }
    else
    {
      setDisplay(event.getStart(), 
        event.getStart()+feature_display.getMaxVisibleBases(), event);
      repaint();
    }
  }
  
tjc's avatar
tjc committed
  public void selectionChanged(SelectionChangeEvent event)
  {
    repaint();
tjc's avatar
tjc committed
  private class Ruler extends JPanel
tjc's avatar
tjc committed
  {
tjc's avatar
tjc committed
    private static final long serialVersionUID = 1L;
tjc's avatar
tjc committed
    int start;
    int end;
tjc's avatar
tjc committed

tjc's avatar
tjc committed
    public Ruler()
    {
      super();
      setPreferredSize(new Dimension(mainPanel.getWidth(), 15));
tjc's avatar
tjc committed
      setBackground(Color.white);
      setFont(getFont().deriveFont(11.f));
    }
tjc's avatar
tjc committed

tjc's avatar
tjc committed
    public void paintComponent(Graphics g)
    {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D)g;
      drawBaseScale(g2, start, end, 12);
    }
tjc's avatar
tjc committed

    private void drawBaseScale(Graphics2D g2, int start, int end, int ypos)
    {
      int startMark = (((int)(start/10))*10)+1;

      if(end > getSequenceLength())
        end = getSequenceLength();
      
tjc's avatar
tjc committed
      for(int i=startMark; i<end; i+=10)
      {
tjc's avatar
tjc committed
        int xpos = (i-start)*ALIGNMENT_PIX_PER_BASE;
tjc's avatar
tjc committed
        g2.drawString(Integer.toString(i), xpos, ypos);
        
        xpos+=(ALIGNMENT_PIX_PER_BASE/2);
        g2.drawLine(xpos, ypos+1, xpos, ypos+5);
      }
    }
tjc's avatar
tjc committed
  }
  
  /**
  * Popup menu listener
  */
  class PopupListener extends MouseAdapter
  {
    public void mouseClicked(MouseEvent e)
    {
      if(e.isPopupTrigger() ||
         e.getButton() == MouseEvent.BUTTON3)
        return;
      
      
      if(e.getClickCount() > 1)
        getSelection().clear(); 
      else if(e.getButton() == MouseEvent.BUTTON1)
        highlightSAMRecord = mouseOverSAMRecord;
      else
        highlightRange(e, MouseEvent.BUTTON2_DOWN_MASK);
    }
    
    public void mousePressed(MouseEvent e)
    {
      maybeShowPopup(e);
    }

    public void mouseReleased(MouseEvent e)
    {
      maybeShowPopup(e);
    }

    private void maybeShowPopup(MouseEvent e)
    {
      if(e.isPopupTrigger())
tjc's avatar
tjc committed
      {
        if(popup == null)
        {
          popup = new JPopupMenu();
          createMenus(popup);
tjc's avatar
tjc committed
        }
        
        if(gotoMateMenuItem != null)
          popup.remove(gotoMateMenuItem);

        if(showDetails != null)
          popup.remove(showDetails);
        
        if( mouseOverSAMRecord != null && 
            mouseOverSAMRecord.getReadPairedFlag() &&
           !mouseOverSAMRecord.getMateUnmappedFlag() )
        {
          final SAMRecord thisSAMRecord = mouseOverSAMRecord;
          gotoMateMenuItem = new JMenuItem("Go to mate of : "+
              thisSAMRecord.getReadName());
          gotoMateMenuItem.addActionListener(new ActionListener()
          {
			public void actionPerformed(ActionEvent e) 
			{
			  String name = thisSAMRecord.getMateReferenceName();
			  if(name.equals("="))
			    name = thisSAMRecord.getReferenceName();
			  int offset = getSequenceOffset(name);
			  if(feature_display != null)
			    feature_display.makeBaseVisible(
			        thisSAMRecord.getMateAlignmentStart()+offset);
			  else
			    scrollBar.setValue(
			        thisSAMRecord.getMateAlignmentStart()+offset-
			        (nbasesInView/2));
			  
			  highlightSAMRecord = thisSAMRecord; 
			}  
          });
          popup.add(gotoMateMenuItem);
        }  
          
        if( mouseOverSAMRecord != null)
        {
          final SAMRecord thisSAMRecord = mouseOverSAMRecord;
          showDetails = new JMenuItem("Show details of : "+
              thisSAMRecord.getReadName());
          showDetails.addActionListener(new ActionListener()
          {
            public void actionPerformed(ActionEvent e) 
            {
tcarver's avatar
tcarver committed
              openFileViewer(thisSAMRecord, getMate(thisSAMRecord));
            }
        popup.show(e.getComponent(),
                e.getX(), e.getY());
tjc's avatar
tjc committed
      }
tcarver's avatar
tcarver committed
  protected static void openFileViewer(SAMRecord readRecord, SAMRecord mateRecord)
  {
    FileViewer viewDetail = new FileViewer(readRecord.getReadName(), true, false, false);
    appendToDetailView(readRecord, mateRecord, viewDetail);
  }
  
  private static void appendToDetailView(SAMRecord thisSAMRecord, SAMRecord thisSAMRecordMate, FileViewer viewDetail)
  {
    viewDetail.appendString("Read Name             "+thisSAMRecord.getReadName()+"\n", Level.INFO);
    viewDetail.appendString("Coordinates           "+thisSAMRecord.getAlignmentStart()+".."+
                                                     thisSAMRecord.getAlignmentEnd()+"\n", Level.DEBUG);
    viewDetail.appendString("Length                "+thisSAMRecord.getReadLength()+"\n", Level.DEBUG);
    viewDetail.appendString("Reference Name        "+thisSAMRecord.getReferenceName()+"\n", Level.DEBUG);
    viewDetail.appendString("Inferred Size         "+thisSAMRecord.getInferredInsertSize()+"\n", Level.DEBUG);
tjc's avatar
tjc committed
    viewDetail.appendString("Mapping Quality       "+thisSAMRecord.getMappingQuality()+"\n", Level.DEBUG);
    viewDetail.appendString("Cigar String          "+thisSAMRecord.getCigarString()+"\n", Level.DEBUG);
    viewDetail.appendString("Strand                "+
        (thisSAMRecord.getReadNegativeStrandFlag() ? "-\n\n" : "+\n\n"), Level.DEBUG);
    
    if(!thisSAMRecord.getMateUnmappedFlag())
    {     
      if(thisSAMRecordMate != null)
      {
        viewDetail.appendString("Mate Coordinates      "+thisSAMRecordMate.getAlignmentStart()+".."+
            thisSAMRecordMate.getAlignmentEnd()+"\n", Level.DEBUG);
        viewDetail.appendString("Mate Length           "+thisSAMRecordMate.getReadLength()+"\n", Level.DEBUG);
        viewDetail.appendString("Mate Reference Name   "+thisSAMRecordMate.getReferenceName()+"\n", Level.DEBUG);
        viewDetail.appendString("Mate Inferred Size    "+thisSAMRecordMate.getInferredInsertSize()+"\n", Level.DEBUG);
        viewDetail.appendString("Mate Mapping Quality  "+thisSAMRecordMate.getMappingQuality()+"\n", Level.DEBUG);
        viewDetail.appendString("Mate Cigar String     "+thisSAMRecordMate.getCigarString()+"\n", Level.DEBUG);
      }
      else
      {
        viewDetail.appendString("Mate Start Coordinate "+thisSAMRecord.getMateAlignmentStart()+"\n", Level.DEBUG);
        viewDetail.appendString("Mate Reference Name   "+thisSAMRecord.getMateReferenceName()+"\n", Level.DEBUG);
      }
      viewDetail.appendString("Mate Strand           "+
          (thisSAMRecord.getMateNegativeStrandFlag() ? "-" : "+"), Level.DEBUG);
      viewDetail.appendString("Mate Unmapped ", Level.DEBUG);
    }
    
    viewDetail.appendString("\n\nFlags:", Level.INFO);
    viewDetail.appendString("\nDuplicate Read    "+
        (thisSAMRecord.getDuplicateReadFlag() ? "yes" : "no"), Level.DEBUG);
tjc's avatar
tjc committed
    
    viewDetail.appendString("\nRead Paired       "+
        (thisSAMRecord.getReadPairedFlag() ? "yes" : "no"), Level.DEBUG);
    if(thisSAMRecord.getReadPairedFlag())
    {
      viewDetail.appendString("\nFirst of Pair     "+
        (thisSAMRecord.getFirstOfPairFlag() ? "yes" : "no"), Level.DEBUG);
tjc's avatar
tjc committed
      viewDetail.appendString("\nMate Unmapped     "+
        (thisSAMRecord.getMateUnmappedFlag() ? "yes" : "no"), Level.DEBUG);  
tjc's avatar
tjc committed
      viewDetail.appendString("\nProper Pair       "+
        (thisSAMRecord.getProperPairFlag() ? "yes" : "no"), Level.DEBUG);
    viewDetail.appendString("\nRead Fails Vendor\nQuality Check     "+
        (thisSAMRecord.getReadFailsVendorQualityCheckFlag() ? "yes" : "no"), Level.DEBUG);
    viewDetail.appendString("\nRead Unmapped     "+
        (thisSAMRecord.getReadUnmappedFlag() ? "yes" : "no"), Level.DEBUG);
tjc's avatar
tjc committed
    
    if(thisSAMRecord.getReadPairedFlag())
      viewDetail.appendString("\nSecond Of Pair    "+
        (thisSAMRecord.getSecondOfPairFlag() ? "yes" : "no"), Level.DEBUG);
    
    viewDetail.appendString("\n\nRead Bases:\n", Level.INFO);
    
    // wrap the read bases
    String seq = new String(thisSAMRecord.getReadBases());
    int MAX_SEQ_LINE_LENGTH = 100;
    for(int i=0; i<=seq.length(); i+=MAX_SEQ_LINE_LENGTH)
    {
      int iend = i+MAX_SEQ_LINE_LENGTH;
      if(iend > seq.length())
    	iend = seq.length();
      viewDetail.appendString(seq.substring(i, iend)+"\n", Level.DEBUG);
    }
  /**
   * Query for the mate of a read
   * @param mate
   * @return
   */
tcarver's avatar
tcarver committed
  protected SAMRecord getMate(SAMRecord thisSAMRecord)
  {
    SAMRecord mate = null;
    try
    {
      int fileIndex = 0;
      if(bamList.size()>1)
        fileIndex = (Integer) thisSAMRecord.getAttribute("FL");
      String bam = bamList.get(fileIndex);  
      final SAMFileReader inputSam = getSAMFileReader(bam);
      mate = inputSam.queryMate(thisSAMRecord);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
    return mate;
  }
  
tjc's avatar
tjc committed
  protected SAMRecordPredicate getSamRecordFlagPredicate()
  {
    return samRecordFlagPredicate;
  }

  protected void setSamRecordFlagPredicate(
tjc's avatar
tjc committed
      SAMRecordPredicate samRecordFlagPredicate)
  {
    laststart = -1;
    lastend = -1;
    this.samRecordFlagPredicate = samRecordFlagPredicate;
  }
tjc's avatar
tjc committed
  protected SAMRecordMapQPredicate getSamRecordMapQPredicate()
  {
    return samRecordMapQPredicate;
  }

  protected void setSamRecordMapQPredicate(
      SAMRecordMapQPredicate samRecordMapQPredicate)
  {
    laststart = -1;
    lastend = -1;
    this.samRecordMapQPredicate = samRecordMapQPredicate;
  }
  
  class PairedRead
  {
    SAMRecord sam1;
    SAMRecord sam2;
tjc's avatar
tjc committed
  public static void main(String[] args)
  {
tjc's avatar
tjc committed
    BamFrame frame = new BamFrame();
tjc's avatar
tjc committed
    if(args.length == 0 && BamFrame.isMac())
    {
      try
      {
        Thread.sleep(1000);
      }
      catch (InterruptedException e1) {}
tjc's avatar
tjc committed
      if(frame.getBamFile() != null)
tjc's avatar
tjc committed
        args = new String[]{ frame.getBamFile() };
    }
tjc's avatar
tjc committed
      
    List<String> bam = new Vector<String>();
tjc's avatar
tjc committed
    String reference = null;
    if(args.length == 0 || args[0].equals("NEW-BAMVIEW"))
tjc's avatar
tjc committed
      System.setProperty("default_directory", System.getProperty("user.dir"));
      FileSelectionDialog fileSelection = new FileSelectionDialog(
          null, true, "BamView", "BAM");
      bam = fileSelection.getFiles(".*\\.bam$");
      reference = fileSelection.getReferenceFile();
      if(reference == null || reference.equals(""))
        reference = null;
tjc's avatar
tjc committed
      
      if(bam == null || bam.size() < 1)
        if(args.length > 0 && args[0].equals("NEW-BAMVIEW"))
          return;
        System.err.println("No files found.");
tjc's avatar
tjc committed
        System.exit(0);
    else if(!args[0].startsWith("-"))
    {
      for(int i=0; i< args.length; i++)
        bam.add(args[i]);
    }
    int nbasesInView = 1000;
tjc's avatar
tjc committed
    String chr = null;
    String vw  = null;
    boolean orientation = false;
    boolean covPlot     = false;
    boolean snpPlot     = false;
    int base = 0;
    
tjc's avatar
tjc committed
    for(int i=0;i<args.length; i++)
    {
      if(args[i].equals("-a"))
      {
        while(i < args.length-1 && !args[++i].startsWith("-"))
        {
          String filename = args[i];
          if(FileSelectionDialog.isListOfFiles(filename))
            bam.addAll(FileSelectionDialog.getListOfFiles(filename));
          else
            bam.add(filename);
        }
tjc's avatar
tjc committed
      else if(args[i].equals("-r"))
        reference = args[++i];
tjc's avatar
tjc committed
      else if(args[i].equals("-n"))
tjc's avatar
tjc committed
        nbasesInView = Integer.parseInt(args[++i]);
      else if(args[i].equals("-s"))
        System.setProperty("samtoolDir", args[++i]);
tjc's avatar
tjc committed
      else if(args[i].equals("-c"))
        chr = args[++i].trim();
      else if(args[i].equals("-b"))
        base = Integer.parseInt(args[++i].trim());
      else if(args[i].equals("-v"))
        vw = args[++i].trim();
      else if(args[i].equals("-o"))
        orientation = true;
      else if(args[i].equals("-pc"))
        covPlot = true;
      else if(args[i].equals("-ps"))
        snpPlot = true;
tjc's avatar
tjc committed
      else if(args[i].startsWith("-h"))
      { 
        System.out.println("-h\t show help");
        
        System.out.println("-a\t BAM/SAM file to display");
        System.out.println("-r\t reference file (optional)");
tjc's avatar
tjc committed
        System.out.println("-n\t number of bases to display in the view (optional)");
        System.out.println("-c\t chromosome name (optional)");
        System.out.println("-v\t view (optional - IS (inferred size), S (stack, default), PS (paired stack), ST (strand), C (coverage))");
        System.out.println("-b\t base position (optional)");
        System.out.println("-o\t show orientation (optional)");
        System.out.println("-pc\t plot coverage (optional)");
        System.out.println("-ps\t plot SNP (optional and only with -r)");
tjc's avatar
tjc committed
        System.exit(0);
      }
    }

tjc's avatar
tjc committed
    final BamView view = new BamView(bam, reference, nbasesInView, null, null,
        (JPanel)frame.getContentPane(), frame);
tjc's avatar
tjc committed
    frame.setTitle("BamView v"+view.getVersion());
tjc's avatar
tjc committed
    
tjc's avatar
tjc committed
    if(chr != null)
      view.combo.setSelectedItem(chr);
    if(vw != null)
    {
      if(vw.equalsIgnoreCase("IS"))
        view.cbIsizeStackView.setSelected(true);
      if(vw.equalsIgnoreCase("PS"))
        view.cbPairedStackView.setSelected(true);
      if(vw.equalsIgnoreCase("ST"))
        view.cbStrandStackView.setSelected(true);
      if(vw.equalsIgnoreCase("C"))
        view.cbCoverageView.setSelected(true);
    }
    if(base > 0)
      view.scrollBar.setValue(base);
    if(orientation)
      view.isOrientation = true;
    if(covPlot)
    {
      view.isCoverage = true;
      view.coveragePanel.setVisible(true);
    }
    if(snpPlot)
    {
      view.isSNPplot = true;
      view.snpPanel.setVisible(true);
    }

    // translucent
    //frame.getRootPane().putClientProperty("Window.alpha", new Float(0.9f));
tjc's avatar
tjc committed
    frame.addWindowFocusListener(new WindowFocusListener()
    {
      public void windowGainedFocus(WindowEvent e)
      {
        view.requestFocus();
      }
      public void windowLostFocus(WindowEvent e){}
    });
tjc's avatar
tjc committed
    frame.pack();
tjc's avatar
tjc committed
    view.jspView.getVerticalScrollBar().setValue(
        view.jspView.getVerticalScrollBar().getMaximum());
    frame.setVisible(true);
tjc's avatar
tjc committed
  }
}