Skip to content
Snippets Groups Projects
BamView.java 136 KiB
Newer Older
tjc's avatar
tjc committed
      g2.setColor(Color.red);
    else
      g2.setColor(Color.blue);
tcarver's avatar
tcarver committed
    drawRead(g2, bamViewRecord, pixPerBase, ypos, baseAtStartOfView, snps, ydiff);
tjc's avatar
tjc committed
    
    /*if (isSNPs)
      showSNPsOnReads(g2, samRecord, pixPerBase, ypos, offset);*/
tjc's avatar
tjc committed
  }
tjc's avatar
tjc committed

tjc's avatar
tjc committed
  
tjc's avatar
tjc committed
  private void drawScale(Graphics2D g2, int start, int end, float pixPerBase, int ypos)
tjc's avatar
tjc committed
  {
    g2.setColor(Color.black);
tjc's avatar
tjc committed
    g2.drawLine( 0, ypos-14,
                 (int)((end - getBaseAtStartOfView())*pixPerBase),   ypos-14);
tjc's avatar
tjc committed
    int interval = end-start;
    
    if(interval > 256000)
tjc's avatar
tjc committed
      drawTicks(g2, start, end, pixPerBase, 512000, ypos);
tjc's avatar
tjc committed
    else if(interval > 64000)
tjc's avatar
tjc committed
      drawTicks(g2, start, end, pixPerBase, 12800, ypos);
tjc's avatar
tjc committed
    else if(interval > 16000)
tjc's avatar
tjc committed
      drawTicks(g2, start, end, pixPerBase, 3200, ypos);
tjc's avatar
tjc committed
    else if(interval > 4000)
tjc's avatar
tjc committed
      drawTicks(g2, start, end, pixPerBase, 800, ypos);
tjc's avatar
tjc committed
    else if(interval > 1000)
tjc's avatar
tjc committed
      drawTicks(g2, start, end, pixPerBase, 400, ypos);
tjc's avatar
tjc committed
    else
tjc's avatar
tjc committed
      drawTicks(g2, start, end, pixPerBase, 100, ypos);
tjc's avatar
tjc committed
  }
  
tjc's avatar
tjc committed
  private void drawTicks(Graphics2D g2, int start, int end, float pixPerBase, int division, int ypos)
tjc's avatar
tjc committed
  {
tjc's avatar
tjc committed
    int markStart = (Math.round(start/division)*division);
    
    if(markStart < 1)
      markStart = 1;
    
tjc's avatar
tjc committed
    int sm = markStart-(division/2);
tjc's avatar
tjc committed
    float x;
tjc's avatar
tjc committed
    if(sm > start)
tjc's avatar
tjc committed
    {
      x = (sm-getBaseAtStartOfView())*pixPerBase;
tjc's avatar
tjc committed
      g2.drawLine((int)x, ypos-14,(int)x, ypos-12);
tjc's avatar
tjc committed
    }
tjc's avatar
tjc committed
    
    for(int m=markStart; m<end; m+=division)
    {
tjc's avatar
tjc committed
      x = (m-getBaseAtStartOfView())*pixPerBase;
tjc's avatar
tjc committed
      g2.drawString(Integer.toString(m), x, ypos-1);
      g2.drawLine((int)x, ypos-14,(int)x, ypos-11);
tjc's avatar
tjc committed
      
      sm = m+(division/2);
      
      if(sm < end)
tjc's avatar
tjc committed
      {
        x = (sm-getBaseAtStartOfView())*pixPerBase;
tjc's avatar
tjc committed
        g2.drawLine((int)x, ypos-14,(int)x, ypos-12);
tjc's avatar
tjc committed
      }
tjc's avatar
tjc committed
      
      if(m == 1)
        m = 0;
  /**
   * Draw a y-scale for inferred size (isize) of reads.
   * @param g2
   * @param xScaleHeight
   */
tjc's avatar
tjc committed
  private void drawYScale(Graphics2D g2, int xScaleHeight)
  {
    g2.setColor(Color.black);
    int maxY = getPreferredSize().height-xScaleHeight;
    if(logScale)
    {
      int start = 10;
      int count = 0;
      int ypos = getYPos(xScaleHeight, start);
      
      while(ypos > 0 && count < 15 && start > 1)
      {
        g2.drawLine(0, ypos, 2, ypos);
        g2.drawString(Integer.toString(start), 3, ypos);
        start = start*5;
        ypos = getYPos(xScaleHeight, start);
        count++;
      }
      return;
    }
    
    for(int i=100; i<maxY; i+=100)
    {
      int ypos = getHeight()-i-xScaleHeight;
tjc's avatar
tjc committed
      g2.drawLine(0, ypos, 2, ypos);
      g2.drawString(Integer.toString(i), 3, ypos);
  /**
   * Draw a given read.
   * @param g2
   * @param thisRead
   * @param pixPerBase
   * @param ypos
   * @param baseAtStartOfView
tcarver's avatar
tcarver committed
  private void drawRead(Graphics2D g2, 
      final BamViewRecord bamViewRecord,
tcarver's avatar
tcarver committed
      final float pixPerBase,
      final int ypos,
tcarver's avatar
tcarver committed
      final List<Integer> snps,
      final int ydiff)
tjc's avatar
tjc committed
  {
    SAMRecord thisRead = bamViewRecord.sam;
tjc's avatar
tjc committed
    int offset = getSequenceOffset(thisRead.getReferenceName());

    int thisStart = thisRead.getAlignmentStart()+offset-baseAtStartOfView;
    int thisEnd   = thisRead.getAlignmentEnd()+offset-baseAtStartOfView;
        
    	if(highlightSAMRecord != null && 
    		highlightSAMRecord.sam.getReadName().equals(thisRead.getReadName()))
	{
    		Stroke originalStroke = g2.getStroke();
		Stroke stroke =
		  new BasicStroke (readLnHgt*1.6f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
		g2.setStroke(stroke);
		Color c = g2.getColor();

		if (isThisBamRecordHighlighted(bamViewRecord) )
		{
			// Selected read alignment
			g2.setColor(Color.black);
		}
		else 
		{
			// For a read with the same name as selected one.
			g2.setColor(NON_SELECTED_READ_HIGHLIGHT_COLOUR);
		}
		
		g2.drawLine((int)( thisStart * pixPerBase), ypos,
		            (int)( thisEnd * pixPerBase), ypos);
		g2.setColor(c);
		g2.setStroke(originalStroke);
	}
    
    if(thisRead.getCigar().getCigarElements().size() == 1)
      g2.drawLine((int)( thisStart * pixPerBase), ypos,
                  (int)( thisEnd * pixPerBase), ypos);
    else
    {
      List<AlignmentBlock> blocks = thisRead.getAlignmentBlocks();
      Color c = g2.getColor();
      int lastEnd = 0;
      for(int i=0; i<blocks.size(); i++)
      {
        AlignmentBlock block = blocks.get(i);
        int blockStart = block.getReferenceStart()+offset-baseAtStartOfView;
        int blockEnd = blockStart + block.getLength() - 1;
        g2.drawLine((int)( blockStart * pixPerBase), ypos,
                    (int)( blockEnd * pixPerBase), ypos);
        if(i > 0 && blockStart != lastEnd)
        {
          g2.setColor(Color.gray);
          g2.drawLine((int)( blockStart * pixPerBase), ypos,
                      (int)( lastEnd * pixPerBase), ypos);
          g2.setColor(c);
        }
        lastEnd = blockEnd;
      }
    }
    
    if(isOrientation)
tcarver's avatar
tcarver committed
      drawArrow(g2, thisRead, thisStart, thisEnd, pixPerBase, ypos, ydiff);
    // test if the mouse is over this read
    if(lastMousePoint != null)
    {
	    	if(lastMousePoint.getY() > ypos-(Math.abs(ydiff)/2) && lastMousePoint.getY() < ypos+(Math.abs(ydiff)/2))
	    	{
		      if(lastMousePoint.getX() > thisStart * pixPerBase &&
		         lastMousePoint.getX() < thisEnd * pixPerBase)
		      {
		    	  	mouseOverSAMRecord = bamViewRecord;
		      }
	    }
    if (isSNPs && snps != null && snps.size() > 0)
      showSNPsOnReads(snps, g2, pixPerBase, ypos);
tjc's avatar
tjc committed
  }
  
  /**
   * Draw arrow on the read to indicate orientation.
   * @param g2
   * @param thisRead
   * @param thisStart
   * @param thisEnd
   * @param pixPerBase
   * @param ypos
   */
tcarver's avatar
tcarver committed
  private void drawArrow(final Graphics2D g2,
      final SAMRecord thisRead, 
      final int thisStart, 
      final int thisEnd, 
      final float pixPerBase, 
      int ypos,
      int ydiff)
tcarver's avatar
tcarver committed
    if(ydiff < 0)
      ydiff = -ydiff;
    
    if(thisRead.getReadNegativeStrandFlag())
    {
tcarver's avatar
tcarver committed
      ypos-=readLnHgt/2;
      int apos = ypos + ydiff - 1;
      g2.drawLine((int)( (thisStart+5) * pixPerBase), apos,
                  (int)( thisStart * pixPerBase), ypos);
    }
    else
    {
tcarver's avatar
tcarver committed
      ypos+=readLnHgt/2;
      int apos = ypos - ydiff + 1;
      g2.drawLine((int)( (thisEnd-5) * pixPerBase), apos,
                  (int)( thisEnd * pixPerBase), ypos);
    }  
  }
  
  /**
   * Highlight a selected range
   * @param g2
   * @param pixPerBase
   * @param start
   * @param end
   */
  private void drawSelectionRange(Graphics2D g2, float pixPerBase, int start, int end, Color c)
  {
    if(getSelection() != null)
    {
      Range selectedRange = getSelection().getSelectionRange();

      if(selectedRange != null)
      {
        int rangeStart = selectedRange.getStart();
        int rangeEnd   = selectedRange.getEnd();
        
        if(end < rangeStart || start > rangeEnd)
          return;
        
tjc's avatar
tjc committed
        int x = (int) (pixPerBase*(rangeStart-getBaseAtStartOfView()));
        int width = (int) (pixPerBase*(rangeEnd-rangeStart+1));
        
        g2.fillRect(x, 0, width, getHeight());
      }
    }
  }
  
  /**
   * Draw a translucent line
   * @param g2
   * @param start
   * @param end
   * @param ypos
   */
  private void drawTranslucentLine(Graphics2D g2, int start, int end, int ypos)
  {
    Composite origComposite = g2.getComposite();
    g2.setComposite(translucent);
    g2.drawLine(start, ypos, end, ypos);
    g2.setComposite(origComposite);
  }
  
  /**
   * Draw a translucent line
   * @param g2
   * @param start
   * @param end
   * @param ypos
   */
  private void drawTranslucentJointedLine(Graphics2D g2, int start, int end, int ypos)
  {
    Composite origComposite = g2.getComposite();
    g2.setComposite(translucent);
    
    int mid = (int) ((end-start)/2.f)+start;
    //g2.drawLine(start, ypos, end, ypos);
    g2.drawLine(start, ypos, mid, ypos-5);
    g2.drawLine(mid, ypos-5, end, ypos);
    g2.setComposite(origComposite);
  }
  
tjc's avatar
tjc committed
  /**
   * Display the SNPs for the given read.
tjc's avatar
tjc committed
   * @param g2
   * @param pixPerBase
   * @param ypos
   */
tcarver's avatar
tcarver committed
  private void showSNPsOnReads(final List<Integer> snps,
tcarver's avatar
tcarver committed
                               float pixPerBase, final int ypos)
tjc's avatar
tjc committed
  {
tcarver's avatar
tcarver committed
    final Stroke originalStroke = g2.getStroke();
    final BasicStroke stroke = new BasicStroke(
        1.3f,
        BasicStroke.CAP_BUTT, 
        BasicStroke.JOIN_MITER);
    g2.setStroke(stroke);
    
    g2.setColor(Color.red);
    for(int pos: snps)
      g2.drawLine((int) (pos * pixPerBase), ypos + 2,
                  (int) (pos * pixPerBase), ypos - 2);
tcarver's avatar
tcarver committed
    g2.setStroke(originalStroke);
tcarver's avatar
tcarver committed
  private List<Integer> getSNPs(final SAMRecord samRecord)
  {
    if(!isSNPs)  // return null if not displaying SNPs
      return null;
    int rbeg = samRecord.getAlignmentStart();
    int rend = samRecord.getAlignmentEnd();
    int offset = getSequenceOffset(samRecord.getReferenceName());
    ArrayList<Integer> snps = null;
    
    // use alignment blocks of the contiguous alignment of
    // subsets of read bases to a reference sequence
tjc's avatar
tjc committed
    try
tjc's avatar
tjc committed
    {
      final char[] refSeq = bases.getSubSequenceC(
          new Range(rbeg+offset, rend+offset), Bases.FORWARD);
      final byte[] readSeq = samRecord.getReadBases();
      if (readSeq == null || readSeq.length == 0) 
      {
    	  	// Can occur for secondary alignments
    	  	return null;
      }
      
      offset = offset - getBaseAtStartOfView();
      final List<AlignmentBlock> blocks = samRecord.getAlignmentBlocks();
tcarver's avatar
tcarver committed
      for(AlignmentBlock block: blocks)
tjc's avatar
tjc committed
      {
        int readStart = block.getReadStart();
        int refStart  = block.getReferenceStart();
        int len = block.getLength();
        for(int j=0; j<len; j++)
tjc's avatar
tjc committed
        {
          int readPos = readStart-1+j;
          int refPos  = refStart+j;
tcarver's avatar
tcarver committed
          if (Character.toUpperCase(refSeq[refPos-rbeg]) != Character.toUpperCase( (char)readSeq[readPos]) )
            if(snps == null)
              snps = new ArrayList<Integer>();
            snps.add(refPos+offset);
tjc's avatar
tjc committed
        }
      }
tjc's avatar
tjc committed
    }
    catch (OutOfRangeException e)
    {
      System.err.println(samRecord.getReadName()+" "+e.getMessage());
tjc's avatar
tjc committed
    }
tjc's avatar
tjc committed
  }
  
  /**
   * Add the alignment view to the supplied <code>JPanel</code> in
   * a <code>JScrollPane</code>.
   * @param mainPanel  panel to add the alignment to
tjc's avatar
tjc committed
   * @param frame
   * @param autohide automatically hide the top panel containing the buttons
tjc's avatar
tjc committed
   * @param feature_display
tjc's avatar
tjc committed
  private void addBamToPanel(final JFrame frame)
tjc's avatar
tjc committed
  {
tjc's avatar
tjc committed
    final JComponent topPanel = bamTopPanel(frame);
tjc's avatar
tjc committed
    mainPanel.setPreferredSize(new Dimension(900, 400));
tjc's avatar
tjc committed
    
    setDisplay(1, nbasesInView, null);
    mainPanel.setLayout(new BorderLayout());
tjc's avatar
tjc committed
    if(topPanel instanceof JPanel)
      mainPanel.add(topPanel, BorderLayout.NORTH);
    mainPanel.add(jspView, BorderLayout.CENTER);
tjc's avatar
tjc committed
    JPanel bottomPanel = new JPanel(new BorderLayout());
    coveragePanel = new CoveragePanel(this);
    bottomPanel.add(coveragePanel, BorderLayout.CENTER);

tjc's avatar
tjc committed
    //
    snpPanel = new SnpPanel(this, bases);
    bottomPanel.add(snpPanel, BorderLayout.NORTH);
    
tjc's avatar
tjc committed
    if(feature_display == null)
    {
      scrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 1, nbasesInView, 1,
          getMaxBasesInPanel(getSequenceLength()));
      scrollBar.setUnitIncrement(nbasesInView/20);
tjc's avatar
tjc committed
      scrollBar.addAdjustmentListener(new AdjustmentListener()
      {
        public void adjustmentValueChanged(AdjustmentEvent e)
        {
          repaint();

          if(isSNPplot)
            snpPanel.repaint();
          if(isCoverage)
            coveragePanel.repaint();
tjc's avatar
tjc committed
        }
      });
      bottomPanel.add(scrollBar, BorderLayout.SOUTH);
    }
      if(!isConcatSequences())
      {
        int seqLen = seqLengths.get((String) combo.getSelectedItem());
        int artemisSeqLen = feature_display.getSequenceLength();
        if(seqLen != artemisSeqLen)
        {
          int newIndex = -1;
          for(int i=0; i<seqNames.size(); i++)
          {
            if(seqLengths.get(seqNames.get(i)) == artemisSeqLen)
            {
              // this looks like the correct sequence
              combo.setSelectedIndex(i);
              newIndex = i;
            }
          }

          if(!Options.isBlackBeltMode())
          {
            String label[] = {
                "The length of the sequence loaded does not match the length of",
                "the default reference sequence in the BAM ("+seqNames.get(0)+").",
                (newIndex == -1 ? "" : "The length does match the reference "+
tcarver's avatar
tcarver committed
                    seqNames.get(newIndex)+" so this has been set as the default.") 
            };
            new NonModalDialog(frame, label);
          }
tjc's avatar
tjc committed

    mainPanel.add(bottomPanel, BorderLayout.SOUTH);
    coveragePanel.setPreferredSize(new Dimension(900, 100));
    coveragePanel.setVisible(false);
tjc's avatar
tjc committed
    snpPanel.setPreferredSize(new Dimension(900, 100));
    snpPanel.setVisible(false);

tjc's avatar
tjc committed
    mainPanel.revalidate();
tjc's avatar
tjc committed
    jspView.getVerticalScrollBar().setValue(
        jspView.getVerticalScrollBar().getMaximum());
  private void addToViewMenu(final short thisBamIndex)
    final File f = new File(bamList.get(thisBamIndex));
    final JCheckBoxMenuItem cbBam = new JCheckBoxMenuItem(
                                     f.getName(), 
                                     getImageIcon(getColourByCoverageColour(thisBamIndex)), 
                                     true);
    bamFilesMenu.add(cbBam);
tcarver's avatar
tcarver committed
    cbBam.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {
        if(cbBam.isSelected())
tcarver's avatar
tcarver committed
          hideBamList.remove(new Short(thisBamIndex));
tcarver's avatar
tcarver committed
          hideBamList.add(new Short(thisBamIndex));
  /**
   * Refresh the colour of the icons used to identify the
   * BAM files.
   */
  protected void refreshColourOfBamMenu()
  {
    final Component cs[] = bamFilesMenu.getMenuComponents();
    for(Component c : cs)
    {
      if(c instanceof JCheckBoxMenuItem)
      {
        final JCheckBoxMenuItem cbBam = (JCheckBoxMenuItem) c;
tcarver's avatar
tcarver committed
        final Color col = getColorByJCheckBoxMenuItem(cbBam);
        if(col != null)
          cbBam.setIcon(getImageIcon(col));
tcarver's avatar
tcarver committed
  protected Color getColorByJCheckBoxMenuItem(JCheckBoxMenuItem cbBam)
  {
    final String bam = cbBam.getText();
    for(short i=0; i<bamList.size(); i++)
tcarver's avatar
tcarver committed
    {
      final File f = new File(bamList.get(i));
      if(f.getName().equals(bam))
        return getColourByCoverageColour(i);
    }
    return null;
  }
  
  /**
   * Create an icon of a box using the given colour.
   * @param c
   * @return
   */
tcarver's avatar
tcarver committed
  ImageIcon getImageIcon(Color c)
  {
    BufferedImage image = (BufferedImage)this.createImage(10, 10);
    Graphics2D g2 = image.createGraphics();
    g2.setColor(c);
    g2.fillRect(0, 0, 10, 10);
    return new ImageIcon(image);
  }

  private void createMenus(JComponent menu)
    final JMenuItem addBam = new JMenuItem("Add BAM ...");
    menu.add(addBam);
    addBam.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        FileSelectionDialog bamFileSelection = new FileSelectionDialog(
            null, false, "BamView", "BAM");
tcarver's avatar
tcarver committed
        List<String> bamFiles = bamFileSelection.getFiles(BAM_SUFFIX);
        short count = (short) bamList.size();
tcarver's avatar
tcarver committed
        bamList.addAll(bamFileSelection.getFiles(BAM_SUFFIX));
        for(short i=0; i<bamFiles.size(); i++)
          addToViewMenu((short) (i+count));
tjc's avatar
tjc committed
        laststart = -1; 
        repaint();
      } 
    });
    
    bamFilesMenu.setFont(addBam.getFont());
tcarver's avatar
tcarver committed

tcarver's avatar
tcarver committed
    final JMenuItem groupBams = new JMenuItem("Group BAMs ...");
    groupBams.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent arg0)
      {
        groupsFrame.updateAndDisplay();
      }
    });
    bamFilesMenu.add(groupBams);
    bamFilesMenu.addSeparator();
    menu.add(bamFilesMenu);
    final JMenu analyse = new JMenu("Analyse");
    menu.add(analyse);
tjc's avatar
tjc committed
    final JMenuItem readCount = new JMenuItem("Read count of selected features ...");
    analyse.add(readCount);
    if(feature_display == null)
      readCount.setEnabled(false);
    readCount.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        FeatureVector features = feature_display.getSelection().getAllFeatures();
        JCheckBox overlap = new JCheckBox("Include all overlapping reads", true);
        overlap.setToolTipText("Include reads that partially overlap the feature");
        JCheckBox spliced = new JCheckBox("Introns included", true);
        Box yBox = Box.createVerticalBox();
        yBox.add(overlap);
        yBox.add(spliced);
tcarver's avatar
tcarver committed
        
        final ReadCountDialog opts = new ReadCountDialog(new JFrame(),
            "Read Count Options", feature_display, yBox);
        if(opts.getStatus() == -1)
          return;
        //JOptionPane.showMessageDialog(null, yBox, "Read Count Option", JOptionPane.INFORMATION_MESSAGE);
        new MappedReads(BamView.this, features,
            !overlap.isSelected(), spliced.isSelected(), colourByStrandTag.isSelected());
tjc's avatar
tjc committed
      } 
    });
    
    final JMenuItem rpkm = new JMenuItem("RPKM value of selected features ...");
    analyse.add(rpkm);
    if(feature_display == null)
      rpkm.setEnabled(false);
tjc's avatar
tjc committed
    rpkm.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
tcarver's avatar
tcarver committed
        final FeatureVector features = feature_display.getSelection().getAllFeatures();
tjc's avatar
tjc committed
        JCheckBox overlap = new JCheckBox("Include all overlapping reads", true);
        overlap.setToolTipText("Include reads that partially overlap the feature");
        JCheckBox spliced = new JCheckBox("Introns included", true);
        JCheckBox allRefSeqs = new JCheckBox("Use reads mapped to all reference sequences", false);
        
tjc's avatar
tjc committed
        Box yBox = Box.createVerticalBox();
        yBox.add(overlap);
        yBox.add(spliced);
        
        if(seqLengths.size() > 1)
          yBox.add(allRefSeqs);
tcarver's avatar
tcarver committed
     
        final ReadCountDialog opts = new ReadCountDialog(new JFrame(),
            "RPKM Options", feature_display, yBox);
        if(opts.getStatus() == -1)
          return;

tjc's avatar
tjc committed
        int seqlen = 0;
        if(feature_display != null)
          seqlen = feature_display.getSequenceLength();
        else if(bases != null)
          seqlen = bases.getLength();
        new MappedReads(BamView.this, features, seqlen,
            !overlap.isSelected(), spliced.isSelected(), allRefSeqs.isSelected(),
            colourByStrandTag.isSelected());
tcarver's avatar
tcarver committed
    final JMenuItem createFeatures = new JMenuItem("Create features from coverage peaks ...");
    analyse.add(createFeatures);
    if(feature_display == null)
      createFeatures.setEnabled(false);
tcarver's avatar
tcarver committed
    createFeatures.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if(feature_display == null)
          return;
        new CreateFeatures(groupsFrame);
    for(short i=0; i<bamList.size(); i++)
      addToViewMenu(i);
    
    menu.add(new JSeparator());
    
    JMenu viewMenu = new JMenu("Views");
tjc's avatar
tjc committed
    cbStackView.setFont(viewMenu.getFont());
    cbIsizeStackView.setFont(viewMenu.getFont());
    cbPairedStackView.setFont(viewMenu.getFont());
    cbStrandStackView.setFont(viewMenu.getFont());
    cbCoverageView.setFont(viewMenu.getFont());
    cbCoverageStrandView.setFont(viewMenu.getFont());
tcarver's avatar
tcarver committed
    cbCoverageHeatMap.setFont(viewMenu.getFont());
tjc's avatar
tjc committed
    
    baseQualityColour.setFont(viewMenu.getFont());
tcarver's avatar
tcarver committed
    colourByReadGrp.setFont(viewMenu.getFont());
tjc's avatar
tjc committed
    colourByCoverageColour.setFont(viewMenu.getFont());
    colourByStrandTag.setFont(viewMenu.getFont());
tjc's avatar
tjc committed
    markInsertions.setFont(viewMenu.getFont());
    
    cbIsizeStackView.addActionListener(new ActionListener()
tjc's avatar
tjc committed
    {
      public void actionPerformed(ActionEvent e)
      {
        laststart = -1;
        logMenuItem.setEnabled(isIsizeStackView());
tcarver's avatar
tcarver committed
        getJspView().setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
tjc's avatar
tjc committed
        repaint();
      }
    });
    viewMenu.add(cbIsizeStackView);
    cbStackView.addActionListener(new ActionListener()
tjc's avatar
tjc committed
    {
      public void actionPerformed(ActionEvent e)
      {
        laststart = -1;
tcarver's avatar
tcarver committed
        if(cbStackView.isSelected())
          logMenuItem.setEnabled(false);
        getJspView().setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
tcarver's avatar
tcarver committed
        setViewportBtm();
tjc's avatar
tjc committed
        repaint();
      }
    });
    viewMenu.add(cbStackView);
    cbPairedStackView.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        laststart = -1;
tcarver's avatar
tcarver committed
        if(cbPairedStackView.isSelected())
          logMenuItem.setEnabled(false);
        getJspView().setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
    viewMenu.add(cbPairedStackView);
    cbStrandStackView.addActionListener(new ActionListener()
tjc's avatar
tjc committed
    {
      public void actionPerformed(ActionEvent e)
      {
        laststart = -1;
        if(isStrandStackView())
tjc's avatar
tjc committed
          setViewportMidPoint();
tcarver's avatar
tcarver committed
        if(cbStrandStackView.isSelected())
          logMenuItem.setEnabled(false);
        getJspView().setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
tjc's avatar
tjc committed
        repaint();
      }
    });
    viewMenu.add(cbStrandStackView);
    
    cbCoverageView.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        laststart = -1;
        if(cbCoverageView.isSelected())
        {
          logMenuItem.setEnabled(false);
tcarver's avatar
tcarver committed
          coverageView.setPlotHeatMap(false);
          coverageView.setPlotByStrand(false);
          setViewportBtm();
tcarver's avatar
tcarver committed
          getJspView().setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
        repaint();
      }
    });
    viewMenu.add(cbCoverageView);
    
    cbCoverageStrandView.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        laststart = -1;
        if(cbCoverageStrandView.isSelected())
        {
tcarver's avatar
tcarver committed
          logMenuItem.setEnabled(true);
          coverageView.setPlotHeatMap(false);
          coverageView.setPlotByStrand(true);
          setViewportBtm();
tcarver's avatar
tcarver committed
          getJspView().setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
tcarver's avatar
tcarver committed

        repaint();
      }
    });
    viewMenu.add(cbCoverageStrandView);
    
tcarver's avatar
tcarver committed
    
    cbCoverageHeatMap.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        laststart = -1;
        if(cbCoverageHeatMap.isSelected())
        {
          logMenuItem.setEnabled(true);
          coverageView.setPlotHeatMap(true);
          setViewportBtm();
          getJspView().setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
        }

        repaint();
      }
    });
    viewMenu.add(cbCoverageHeatMap);
    
    menu.add(viewMenu);
    final JCheckBoxMenuItem checkBoxSNPs = new JCheckBoxMenuItem("SNP marks", isSNPs);
tcarver's avatar
tcarver committed
    final JMenu colourMenu = new JMenu("Colour By");
    
    final JCheckBoxMenuItem colourDefault = new JCheckBoxMenuItem ("Default", true);
    final ButtonGroup grp = new ButtonGroup();
    grp.add(colourByReadGrp);
    grp.add(colourByCoverageColour);
    grp.add(colourByStrandTag);
    grp.add(colourDefault);
    
    colourMenu.add(colourDefault);
    colourDefault.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        repaintBamView();
      }
    });
    
    colourMenu.add(colourByReadGrp);
    colourByReadGrp.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        repaintBamView();
      }
    });
    
    colourMenu.add(colourByCoverageColour);
    colourByCoverageColour.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
tcarver's avatar
tcarver committed
        repaintBamView();
    colourMenu.add(colourByStrandTag);
    colourByStrandTag.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
tcarver's avatar
tcarver committed
        repaintBamView();
    baseQualityColour.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if(baseQualityColour.isSelected())
        {
          checkBoxSNPs.setSelected(false);
          isSNPs = false;
        }
        repaint();
      }
    });
tcarver's avatar
tcarver committed
    colourMenu.addSeparator();
    colourMenu.add(baseQualityColour);
    menu.add(colourMenu);
    
    JMenu showMenu = new JMenu("Show");
    JCheckBoxMenuItem checkBoxOrientation = new JCheckBoxMenuItem("Orientation");
    checkBoxOrientation.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        isOrientation = !isOrientation;
        repaint();
      }
    });
    showMenu.add(checkBoxOrientation);
    
    JCheckBoxMenuItem checkBoxSingle = new JCheckBoxMenuItem("Single Reads");
    checkBoxSingle.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        repaint();
        isSingle = !isSingle;
      }
    });
    showMenu.add(checkBoxSingle);
    checkBoxSNPs.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (isSNPs && bases == null)
        {
          JOptionPane.showMessageDialog(null,
              "No reference sequence supplied to identify SNPs.", "SNPs",
              JOptionPane.INFORMATION_MESSAGE);
        }
        isSNPs = !isSNPs;
        
        if(isSNPs)
          baseQualityColour.setSelected(false);
        repaint();
      }
    });
    showMenu.add(checkBoxSNPs);
    
    markInsertions.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        repaint();
      }
    });
    showMenu.add(markInsertions);
tjc's avatar
tjc committed
    menu.add(showMenu);
tjc's avatar
tjc committed
    //
    JMenu graphMenu = new JMenu("Graph");
    JCheckBoxMenuItem checkBoxCoverage = new JCheckBoxMenuItem("Coverage", isCoverage);
    checkBoxCoverage.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        isCoverage = !isCoverage;
        coveragePanel.setVisible(isCoverage);
tjc's avatar
tjc committed
        
        if( isCoverage && 
            !cbCoverageView.isSelected() && 
tcarver's avatar
tcarver committed
            !cbCoverageStrandView.isSelected() &&
            !cbCoverageHeatMap.isSelected())
tjc's avatar
tjc committed
          laststart = -1;
        repaint();
      }
    });
tjc's avatar
tjc committed
    graphMenu.add(checkBoxCoverage);
    
    JCheckBoxMenuItem checkBoxSNP = new JCheckBoxMenuItem("SNP", isSNPplot);
tjc's avatar
tjc committed
    checkBoxSNP.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        isSNPplot = !isSNPplot;
        snpPanel.setVisible(isSNPplot);
        laststart = -1;
tjc's avatar
tjc committed
        repaint();
      }
    });
    graphMenu.add(checkBoxSNP);
    menu.add(graphMenu);
    
    if(feature_display != null)
      final JCheckBoxMenuItem checkBoxSync =
        new JCheckBoxMenuItem("Asynchronous", asynchronous);
      checkBoxSync.addActionListener(new ActionListener()
        public void actionPerformed(ActionEvent e)
        {
          asynchronous = checkBoxSync.isSelected();
        }
      });
      menu.add(checkBoxSync);
    menu.add(new JSeparator());
    JMenu maxHeightMenu = new JMenu("BamView Height");
    menu.add(maxHeightMenu);
    final String hgts[] =
       {"500", "800", "1000", "1500", "2500", "5000", "50000"};
    
    ButtonGroup bgroup = new ButtonGroup();
    for(int i=0; i<hgts.length; i++)
    {
      final String hgt = hgts[i];
      final JCheckBoxMenuItem maxHeightMenuItem = new JCheckBoxMenuItem(hgt);
      bgroup.add(maxHeightMenuItem);
      maxHeightMenuItem.setSelected(hgts[i].equals(Integer.toString(maxHeight)));
      maxHeightMenu.add(maxHeightMenuItem);
      maxHeightMenuItem.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent e)
        {
          if(maxHeightMenuItem.isSelected())
            maxHeight = Integer.parseInt(hgt);
          int start = getBaseAtStartOfView();
          setDisplay(start, nbasesInView+start, null);
        }
      });
    }
    menu.add(new JSeparator());
tjc's avatar
tjc committed
    logMenuItem.setFont(menu.getFont());
    menu.add(logMenuItem);
    logMenuItem.setEnabled(isIsizeStackView());
    
    logMenuItem.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        logScale = logMenuItem.isSelected();
        repaint();
      }
    });