Skip to content
Snippets Groups Projects
BamView.java 105 KiB
Newer Older
  • Learn to ignore specific revisions
  • tjc's avatar
    tjc committed
      }
      
    
    tcarver's avatar
    tcarver committed
      protected void setHighlightSAMRecord(SAMRecord highlightSAMRecord)
      {
        this.highlightSAMRecord = highlightSAMRecord;
      }
      
      protected SAMRecord getHighlightSAMRecord()
      {
        return highlightSAMRecord;
      }
      
    
    tcarver's avatar
    tcarver committed
      protected FeatureDisplay getFeatureDisplay()
      {
        return feature_display;
      }
      
    
    tjc's avatar
    tjc committed
      private String getVersion()
      {
        final ClassLoader cl = this.getClass().getClassLoader();
        try
        {
          String line;
          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 = 2000;
    
    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));
    
        /*frame.addWindowFocusListener(new WindowFocusListener()
    
    tjc's avatar
    tjc committed
        {
          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
      }
    }