Skip to content
Snippets Groups Projects
JamView.java 57.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • tjc's avatar
    tjc committed
        else if(interval > 16000)
          drawTicks(g2, start, end, pixPerBase, 3200);
        else if(interval > 4000)
          drawTicks(g2, start, end, pixPerBase, 800);
        else if(interval > 1000)
    
          drawTicks(g2, start, end, pixPerBase, 400);
    
    tjc's avatar
    tjc committed
        else
    
          drawTicks(g2, start, end, pixPerBase, 100);
    
    tjc's avatar
    tjc committed
      }
      
      private void drawTicks(Graphics2D g2, int start, int end, float pixPerBase, int division)
      {
    
    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);
        
        if(sm > start)
          g2.drawLine((int)(sm*pixPerBase), getHeight()-14,(int)(sm*pixPerBase), getHeight()-12);
        
        for(int m=markStart; m<end; m+=division)
        {
          g2.drawString(Integer.toString(m), m*pixPerBase, getHeight()-1);
          g2.drawLine((int)(m*pixPerBase), getHeight()-14,(int)(m*pixPerBase), getHeight()-11);
          
          sm = m+(division/2);
          
          if(sm < end)
            g2.drawLine((int)(sm*pixPerBase), getHeight()-14,(int)(sm*pixPerBase), getHeight()-12);
    
    tjc's avatar
    tjc committed
          
          if(m == 1)
            m = 0;
    
      /**
       * Draw a y-scale for inferred size (isize) of reads.
       * @param g2
       * @param start
       * @param pixPerBase
       * @param xScaleHeight
       */
      private void drawYScale(Graphics2D g2, int start, float pixPerBase, int xScaleHeight)
    
      {
        g2.setColor(Color.black);
    
        int maxY = getPreferredSize().height-xScaleHeight;
    
        int xpos = (int) (pixPerBase*start);
        
        for(int i=100; i<maxY; i+=100)
        {
    
          int ypos = getHeight()-i-xScaleHeight;
          g2.drawLine(xpos, ypos, xpos+2, ypos);
          g2.drawString(Integer.toString(i), xpos+3, ypos);
    
      /**
       * Draw a given read.
       * @param g2
       * @param thisRead
       * @param pixPerBase
       * @param stroke
       * @param ypos
       */
    
    tjc's avatar
    tjc committed
      private void drawRead(Graphics2D g2, SAMRecord thisRead,
    
    tjc's avatar
    tjc committed
    		                float pixPerBase, Stroke stroke, int ypos)
    
    tjc's avatar
    tjc committed
      {
    
    tjc's avatar
    tjc committed
        int thisStart = thisRead.getAlignmentStart()-1;
    
        int thisEnd   = thisRead.getAlignmentEnd()-1;
    
    tjc's avatar
    tjc committed
        g2.setStroke(stroke);
    
        g2.drawLine((int)(thisStart * pixPerBase), ypos,
                    (int)(thisEnd * pixPerBase), ypos);
    
    tjc's avatar
    tjc committed
    
    
        // test if the mouse is over this read
    
        if(lastMousePoint != null)
        {
          if(lastMousePoint.getY()+2 > ypos && lastMousePoint.getY()-2 < ypos)
          if(lastMousePoint.getX() > thisStart * pixPerBase &&
             lastMousePoint.getX() < thisEnd * pixPerBase)
          {
            mouseOverSAMRecord = thisRead;
          }
        }
        
    
    tjc's avatar
    tjc committed
        if (isSNPs)
    
    tjc's avatar
    tjc committed
          showSNPsOnReads(g2, thisRead, 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)
      {
        if(getSelection() != null)
        {
          Range selectedRange = getSelection().getSelectionRange();
    
          if(selectedRange != null)
          {
            int rangeStart = selectedRange.getStart();
            int rangeEnd   = selectedRange.getEnd();
            
            if(end < rangeStart || start > rangeEnd)
              return;
            
            int x = (int) (pixPerBase*(rangeStart-1));
            int width = (int) (pixPerBase*(rangeEnd-rangeStart+1));
            
            g2.setColor(Color.pink);
            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.
       * @param g2
       * @param thisRead
       * @param pixPerBase
       * @param ypos
       */
      private void showSNPsOnReads(Graphics2D g2, SAMRecord thisRead,
                                   float pixPerBase, int ypos)
      {
        int thisStart = thisRead.getAlignmentStart();
        int thisEnd   = thisRead.getAlignmentEnd();
    
        
        // use alignment blocks of the contiguous alignment of
        // subsets of read bases to a reference sequence
        List<AlignmentBlock> blocks = thisRead.getAlignmentBlocks();
    
    tjc's avatar
    tjc committed
        try
    
    tjc's avatar
    tjc committed
        {
    
    tjc's avatar
    tjc committed
          char[] refSeq = bases.getSubSequenceC(
              new Range(thisStart, thisEnd), Bases.FORWARD);
          byte[] readSeq = thisRead.getReadBases();
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
          Color col = g2.getColor();
          g2.setColor(Color.red);
    
    
          for(int i=0; i<blocks.size(); i++)
    
    tjc's avatar
    tjc committed
          {
    
            AlignmentBlock block = blocks.get(i);
            for(int j=0; j<block.getLength(); j++)
    
    tjc's avatar
    tjc committed
            {
    
              int readPos = block.getReadStart()-1+j;
              int refPos  = block.getReferenceStart()+j;
    
              if (Character.toUpperCase(refSeq[refPos-thisStart]) != readSeq[readPos])
              {
    
                g2.drawLine((int) ((refPos) * pixPerBase), ypos + 2,
                            (int) ((refPos) * pixPerBase), ypos - 2);
    
    tjc's avatar
    tjc committed
            }
    
    tjc's avatar
    tjc committed
          }
    
    tjc's avatar
    tjc committed
          g2.setColor(col);
        }
        catch (OutOfRangeException e)
        {
          e.printStackTrace();
    
    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
    
       * @param autohide automatically hide the top panel containing the buttons
    
       */
      public void addJamToPanel(final JPanel mainPanel,
    
    tjc's avatar
    tjc committed
                                final JFrame frame,
    
                                final boolean autohide,
                                final FeatureDisplay feature_display)
    
    tjc's avatar
    tjc committed
      {
    
        this.mainPanel = mainPanel;
    
    tjc's avatar
    tjc committed
        final JComponent topPanel;
    
        if(feature_display != null)
        {
          this.feature_display = feature_display;
          this.selection = feature_display.getSelection();
    
    tjc's avatar
    tjc committed
          topPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
        }
        else
        { 
          topPanel = new JMenuBar();
          frame.setJMenuBar((JMenuBar)topPanel);
    
        // auto hide top panel
    
        final JCheckBox buttonAutoHide = new JCheckBox("Hide", autohide);
        buttonAutoHide.setToolTipText("Auto-Hide");
    
        final MouseMotionListener mouseMotionListener = new MouseMotionListener()
    
    tjc's avatar
    tjc committed
        {
    
          public void mouseDragged(MouseEvent event)
    
    tjc's avatar
    tjc committed
          {
    
            handleCanvasMouseDragOrClick(event);
          }
          
          public void mouseMoved(MouseEvent e)
          {
    
            lastMousePoint = e.getPoint();
            
    
            int thisHgt = HEIGHT;
            if (thisHgt < 5)
              thisHgt = 15;
    
            int y = (int) (e.getY() - jspView.getViewport().getViewRect().getY());
            if (y < thisHgt)
    
    tjc's avatar
    tjc committed
              topPanel.setVisible(true);
    
    tjc's avatar
    tjc committed
              if (buttonAutoHide.isSelected())
                topPanel.setVisible(false);
    
            }
            mainPanel.repaint();
            mainPanel.revalidate();
          }
        };
        addMouseMotionListener(mouseMotionListener);
    
        combo = new JComboBox(seqNames);
        combo.setEditable(false);
        combo.addItemListener(new ItemListener()
        {
          public void itemStateChanged(ItemEvent e)
          {
            laststart = -1;
            lastend = -1;
            setZoomLevel(JamView.this.nbasesInView);
          }
        });
    
    tjc's avatar
    tjc committed
        topPanel.add(combo);
    
        if(feature_display == null)
    
    tjc's avatar
    tjc committed
        {
    
    tjc's avatar
    tjc committed
          final JTextField baseText = new JTextField(8);
    
          JButton goTo = new JButton("GoTo:");
    
    tjc's avatar
    tjc committed
          goTo.setToolTipText("Go to base position");
    
          goTo.addActionListener(new ActionListener()
    
    tjc's avatar
    tjc committed
          {
    
            public void actionPerformed(ActionEvent e)
    
    tjc's avatar
    tjc committed
            {
    
              try
              {
                int basePosition = Integer.parseInt(baseText.getText());
                goToBasePosition(basePosition);
              }
              catch (NumberFormatException nfe)
              {
                JOptionPane.showMessageDialog(JamView.this,
                    "Expecting a base number!", "Number Format",
                    JOptionPane.WARNING_MESSAGE);
              }
    
    tjc's avatar
    tjc committed
            }
    
    tjc's avatar
    tjc committed
          topPanel.add(goTo);
          topPanel.add(baseText);
    
          JButton zoomIn = new JButton("-");
          Insets ins = new Insets(1,1,1,1);
    
          zoomIn.setMargin(ins);
    
          zoomIn.addActionListener(new ActionListener()
    
    tjc's avatar
    tjc committed
          {
    
            public void actionPerformed(ActionEvent e)
            {
              int startBase = getBaseAtStartOfView();
              setZoomLevel((int) (JamView.this.nbasesInView * 1.1));
              goToBasePosition(startBase);
            }
          });
    
    tjc's avatar
    tjc committed
          topPanel.add(zoomIn);
    
          JButton zoomOut = new JButton("+");
          zoomOut.setMargin(ins);
    
          zoomOut.addActionListener(new ActionListener()
    
    tjc's avatar
    tjc committed
          {
    
            public void actionPerformed(ActionEvent e)
            {
              if (showBaseAlignment)
                return;
              int startBase = getBaseAtStartOfView();
              setZoomLevel((int) (JamView.this.nbasesInView * .9));
              goToBasePosition(startBase);
            }
          });
    
    tjc's avatar
    tjc committed
          topPanel.add(zoomOut);
    
    tjc's avatar
    tjc committed
        topPanel.add(buttonAutoHide);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        mainPanel.setPreferredSize(new Dimension(900, 400));
    
    tjc's avatar
    tjc committed
        
        jspView = new JScrollPane(this, 
            JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
    
    tjc's avatar
    tjc committed
            JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
    
        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);
    
        
        coveragePanel = new CoveragePanel();
        mainPanel.add(coveragePanel, BorderLayout.SOUTH);
        coveragePanel.setPreferredSize(new Dimension(900, 100));
        coveragePanel.setVisible(false);
        
    
    tjc's avatar
    tjc committed
        jspView.getVerticalScrollBar().setValue(
            jspView.getVerticalScrollBar().getMaximum());
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        if(feature_display == null)
    
    tjc's avatar
    tjc committed
        {
    
          addKeyListener(new KeyAdapter()
    
    tjc's avatar
    tjc committed
          {
    
            public void keyPressed(final KeyEvent event)
    
    tjc's avatar
    tjc committed
            {
    
              switch (event.getKeyCode())
              {
    
    tjc's avatar
    tjc committed
              case KeyEvent.VK_UP:
    
    tjc's avatar
    tjc committed
                int startBase = getBaseAtStartOfView();
    
                setZoomLevel((int) (JamView.this.nbasesInView * 1.1));
    
    tjc's avatar
    tjc committed
                goToBasePosition(startBase);
    
    tjc's avatar
    tjc committed
                break;
              case KeyEvent.VK_DOWN:
    
                if (showBaseAlignment)
                  break;
    
    tjc's avatar
    tjc committed
                startBase = getBaseAtStartOfView();
    
                setZoomLevel((int) (JamView.this.nbasesInView * .9));
    
    tjc's avatar
    tjc committed
                goToBasePosition(startBase);
    
    tjc's avatar
    tjc committed
                break;
              default:
                break;
    
    tjc's avatar
    tjc committed
            }
    
        addMouseListener(new PopupListener());
    
    tjc's avatar
    tjc committed
        setFocusable(true);
        requestFocusInWindow();
    
        addFocusListener(new FocusListener()
    
    tjc's avatar
    tjc committed
        {
    
          public void focusGained(FocusEvent fe){}
          public void focusLost(FocusEvent fe){}
    
    tjc's avatar
    tjc committed
        });
    
    tjc's avatar
    tjc committed
      private void createViewMenu(JComponent view)
    
    tjc's avatar
    tjc committed
        JCheckBoxMenuItem checkBoxSingle = new JCheckBoxMenuItem("Single Reads");
        checkBoxSingle.addActionListener(new ActionListener()
    
    tjc's avatar
    tjc committed
          public void actionPerformed(ActionEvent e)
          {
            repaint();
            isSingle = !isSingle;
          }
        });
        view.add(checkBoxSingle);
    
        JCheckBoxMenuItem checkBoxSNPs = new JCheckBoxMenuItem("SNPs");
        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;
            repaint();
          }
        });
        view.add(checkBoxSNPs);
    
        final JCheckBoxMenuItem checkBoxStackView = new JCheckBoxMenuItem("Stack View");
        final JCheckBoxMenuItem checkBoxPairedStackView = new JCheckBoxMenuItem("Paired Stack View");
        
    
    tjc's avatar
    tjc committed
        checkBoxStackView.addActionListener(new ActionListener()
        {
          public void actionPerformed(ActionEvent e)
          {
            laststart = -1;
            lastend = -1;
            isStackView = !isStackView;
    
            
            if(isStackView)
            {
              isPairedStackView = !isStackView;
              checkBoxPairedStackView.setSelected(!isStackView);
            }
    
    tjc's avatar
    tjc committed
            repaint();
          }
        });
        view.add(checkBoxStackView);
    
    
        checkBoxPairedStackView.addActionListener(new ActionListener()
        {
          public void actionPerformed(ActionEvent e)
          {
            laststart = -1;
            lastend = -1;
            isPairedStackView = !isPairedStackView;
            
            if(isPairedStackView)
            {
              isStackView = !isPairedStackView;
              checkBoxStackView.setSelected(!isPairedStackView);
            }
            repaint();
          }
        });
        view.add(checkBoxPairedStackView);
        
    
        
        JCheckBoxMenuItem checkBoxCoverage = new JCheckBoxMenuItem("Coverage");
        checkBoxCoverage.addActionListener(new ActionListener()
        {
          public void actionPerformed(ActionEvent e)
          {
            isCoverage = !isCoverage;
            coveragePanel.setVisible(isCoverage);
            repaint();
          }
        });
        view.add(checkBoxCoverage);
    
        view.add(new JSeparator());
        
        JMenu maxHeightMenu = new JMenu("Plot Height");
        view.add(maxHeightMenu);
        
        final String hgts[] = 
           {"500", "800", "1000", "1500", "2500", "5000"};
        
        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);
            }
          });
        }
    
      }
      
      public void setVisible(boolean visible)
      {
        super.setVisible(visible);
        mainPanel.setVisible(visible);
    
    tjc's avatar
    tjc committed
      }
      
    
    tjc's avatar
    tjc committed
      private int getBaseAtStartOfView()
      {
        String refName = (String) combo.getSelectedItem();
        int seqLength = seqLengths.get(refName);
        double x = jspView.getViewport().getViewRect().getX();
    
        return (int) (getMaxBasesInPanel(seqLength) * ( x / getWidth())) + 1;
    
    tjc's avatar
    tjc committed
      }
      
      /**
       * Set the panel size based on the number of bases visible
       * and repaint.
       * @param nbasesInView
       */
    
    tjc's avatar
    tjc committed
      private void setZoomLevel(final int nbasesInView)
      {
        this.nbasesInView = nbasesInView;
    
    tjc's avatar
    tjc committed
    
    
        //System.out.println("setZoomLevel "+nbasesInView+"  "+getBaseAtStartOfView());
    
    tjc's avatar
    tjc committed
        String refName = (String) combo.getSelectedItem();
        int seqLength = seqLengths.get(refName);
    
    tjc's avatar
    tjc committed
        float pixPerBase = getPixPerBaseByBasesInView(); 
    
        if(pixPerBase*3 > ALIGNMENT_PIX_PER_BASE)
    
    tjc's avatar
    tjc committed
        {
          pixPerBase = ALIGNMENT_PIX_PER_BASE;
          jspView.getVerticalScrollBar().setValue(0);
          jspView.setColumnHeaderView(ruler);
          showBaseAlignment = true;
        }
        else if(jspView != null)
        {
          jspView.setColumnHeaderView(null);
    
    tjc's avatar
    tjc committed
          jspView.getVerticalScrollBar().setValue(
              jspView.getVerticalScrollBar().getMaximum());
    
    tjc's avatar
    tjc committed
          showBaseAlignment = false;
        }
        
        Dimension d = new Dimension();
    
        d.setSize((getMaxBasesInPanel(seqLength)*pixPerBase), maxHeight);
    
    tjc's avatar
    tjc committed
        setPreferredSize(d);
    
    tjc's avatar
    tjc committed
        revalidate();
    
    tjc's avatar
    tjc committed
      }
      
      /**
       * Set the ViewPort so it starts at the given base position.
       * @param base
       */
    
    tjc's avatar
    tjc committed
      private void goToBasePosition(int base)
    
    tjc's avatar
    tjc committed
      {
        Point p = jspView.getViewport().getViewPosition();
    
    tjc's avatar
    tjc committed
        String refName = (String) combo.getSelectedItem();
        int seqLength = seqLengths.get(refName);
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        float width = (float) getPreferredSize().getWidth();
    
    tjc's avatar
    tjc committed
        
    
        p.x = Math.round(width*((float)(base-1)/(getMaxBasesInPanel(seqLength))));
        //System.out.println("goToBasePosition "+base);
    
    tjc's avatar
    tjc committed
        jspView.getViewport().setViewPosition(p);
      }
    
    tjc's avatar
    tjc committed
      /**
    
       * Set the start and end base positions to display.
       * @param start
       * @param end
       * @param event
    
    tjc's avatar
    tjc committed
       */
    
      public void setDisplay(int start,
                             int end,
                             DisplayAdjustmentEvent event)
    
    tjc's avatar
    tjc committed
      {
    
        this.startBase = start;
        this.endBase   = end;
    
    tjc's avatar
    tjc committed
        this.nbasesInView = end-start+1;
    
        lastMousePoint = null;
    
    tjc's avatar
    tjc committed
        String refName = (String) combo.getSelectedItem();
        int seqLength = seqLengths.get(refName);
    
    tjc's avatar
    tjc committed
        float pixPerBase;
        if(jspView.getViewport().getViewRect().width > 0)
    
          pixPerBase = this.getPixPerBaseByWidth(); // getPixPerBaseByBasesInView();
    
    tjc's avatar
    tjc committed
        else
        {
          if(feature_display == null)
            pixPerBase = 1000.f/(float)(end-start+1);
          else
            pixPerBase = feature_display.getWidth()/(float)(end-start+1);
        }
    
        if(pixPerBase*3 > ALIGNMENT_PIX_PER_BASE)
    
    tjc's avatar
    tjc committed
        {
    
    tjc's avatar
    tjc committed
          pixPerBase = ALIGNMENT_PIX_PER_BASE;
    
    tjc's avatar
    tjc committed
          jspView.getVerticalScrollBar().setValue(0);
    
    tjc's avatar
    tjc committed
          jspView.setColumnHeaderView(ruler);
    
          showBaseAlignment = true;
    
    tjc's avatar
    tjc committed
        }
    
    tjc's avatar
    tjc committed
        else if(jspView != null)
    
    tjc's avatar
    tjc committed
        {
    
    tjc's avatar
    tjc committed
          jspView.setColumnHeaderView(null);
    
          showBaseAlignment = false;
    
    tjc's avatar
    tjc committed
        }
    
    tjc's avatar
    tjc committed
        Dimension d = new Dimension();
    
        d.setSize((getMaxBasesInPanel(seqLength)*pixPerBase), maxHeight);
    
        
        //System.out.println("setDisplay() "+d.getWidth());
    
    tjc's avatar
    tjc committed
        setPreferredSize(d);
    
        goToBasePosition(startBase);
        
    
    tjc's avatar
    tjc committed
        if(event == null)
        {
          this.startBase = -1;
          this.endBase   = -1;
        }
    
    tjc's avatar
    tjc committed
      /**
       * Return an Artemis entry from a file 
       * @param entryFileName
       * @param entryGroup
       * @return
       * @throws NoSequenceException
       */
      private Entry getEntry(final String entryFileName, final EntryGroup entryGroup) 
                       throws NoSequenceException
      {
        final Document entry_document = DocumentFactory.makeDocument(entryFileName);
        final EntryInformation artemis_entry_information =
          Options.getArtemisEntryInformation();
        
    
        //System.out.println(entryFileName);
    
    tjc's avatar
    tjc committed
        final uk.ac.sanger.artemis.io.Entry new_embl_entry =
          EntryFileDialog.getEntryFromFile(null, entry_document,
                                           artemis_entry_information,
                                           false);
    
        if(new_embl_entry == null)  // the read failed
          return null;
    
        Entry entry = null;
        try
        {
          if(entryGroup.getSequenceEntry() != null)
            bases = entryGroup.getSequenceEntry().getBases();
    
    tjc's avatar
    tjc committed
          
    
    tjc's avatar
    tjc committed
          if(bases == null)
    
    tjc's avatar
    tjc committed
          {
    
    tjc's avatar
    tjc committed
            entry = new Entry(new_embl_entry);
    
    tjc's avatar
    tjc committed
            bases = entry.getBases();
          }
    
    tjc's avatar
    tjc committed
          else
            entry = new Entry(bases,new_embl_entry);
          
          entryGroup.add(entry);
        } 
        catch(OutOfRangeException e) 
        {
          new MessageDialog(null, "read failed: one of the features in " +
              entryFileName + " has an out of range " +
                            "location: " + e.getMessage());
        }
        return entry;
      }
    
      
      private boolean isShowScale()
      {
        return showScale;
      }
    
      public void setShowScale(boolean showScale)
      {
        this.showScale = showScale;
      }
      
      public JScrollPane getJspView()
      {
        return jspView;
      }
      
      public void setBases(Bases bases)
      {
        this.bases = bases;
      }
      
      /**
       * Remove JScrollPane border
       */
      public void removeBorder()
      {
        Border empty = new EmptyBorder(0,0,0,0);
        jspView.setBorder(empty);
      }
      
      /**
       *  Handle a mouse drag event on the drawing canvas.
       **/
    
      private void handleCanvasMouseDragOrClick(final MouseEvent event)
    
        if(event.isShiftDown()) 
    
    tjc's avatar
    tjc committed
    
    
        if(event.getClickCount() > 1)
        {
          getSelection().clear();
          repaint();
          return;  
        }
        
        int onmask = MouseEvent.BUTTON1_DOWN_MASK;
        
    
        String refName = (String) combo.getSelectedItem();
        int seqLength = seqLengths.get(refName);
    
        float pixPerBase = ((float)getWidth())/(float)(seqLength);    
        int start = (int) Math.round(event.getPoint().getX()/pixPerBase);
    
        
        if (dragStart < 0 && (event.getModifiersEx() & onmask) == onmask)
          dragStart = start;
        else if((event.getModifiersEx() & onmask) != onmask)
          dragStart = -1;
    
    
        if(start < 1)
          start = 1;
        if(start > seqLength)
          start = seqLength;
    
        MarkerRange drag_range;
        try
    
          if(dragStart < 0)
            drag_range = new MarkerRange (bases.getForwardStrand(), start, start);
          else
            drag_range = new MarkerRange (bases.getForwardStrand(), dragStart, start);
    
          getSelection().setMarkerRange(drag_range);
          repaint();
    
        catch (OutOfRangeException e)
    
          e.printStackTrace();
    
        }
      }
      
      private Selection getSelection()
      {
        return selection;
      }
      
    
      private class CoveragePanel extends JPanel
      {
    	private static final long serialVersionUID = 1L;
    
        private int start;
    	private int end;
    	private float pixPerBase;
        
        public CoveragePanel()
        {
          super();
          setBackground(Color.white);
        }
        
    	/**
    	 * Override
    	 */
    	protected void paintComponent(Graphics g)
    	{
    	  super.paintComponent(g);
    	  Graphics2D g2 = (Graphics2D)g;
    	  
    	  if(readsInView == null)
    	    return;
    	  
    	  int windowSize = 10;
    	  int nBins = Math.round((end-start+1.f)/windowSize);
    
    	  int coverage[] = new int[nBins];
    
    	  for(int i=0; i<coverage.length; i++)
    
    	  for(int i=0; i<readsInView.size(); i++)
    	  {
    	    SAMRecord thisRead = readsInView.get(i);
    	    int length = thisRead.getReadLength();
    	    
    	    for(int j=0; j<length;j++)
    	    {
    	      int bin = 
    	        Math.round(((thisRead.getAlignmentStart()-start) + j) / windowSize);
    
    	      if(bin < 0 || bin > coverage.length-1)
    	        continue;   
    	      coverage[bin]+=1;
    	      if(coverage[bin] > max)
    	        max = coverage[bin];
    	    }
    	  }
    	  
    
    	  g2.setColor(lightBlue);
    
    	  GeneralPath shape = new GeneralPath();
    	  shape.moveTo(0,getHeight());
    	  for(int i=0; i<coverage.length; i++)
    	  {
    	    float xpos = ((i*(windowSize)) - windowSize/2.f)*pixPerBase;
    	    shape.lineTo(xpos,
    
    	        getHeight() - (((float)coverage[i]/(float)max)*getHeight()));
    
    	  }
    
    	  shape.lineTo(getWidth(),getHeight());
    	  g2.fill(shape);
    
    
    	  String maxStr = Integer.toString(max);
    	  FontMetrics fm = getFontMetrics(getFont());
    	  g2.setColor(Color.black);
    	  g2.drawString(maxStr, getWidth()-fm.stringWidth(maxStr), fm.getHeight());
    
    	}
    	
    	protected void setStartAndEnd(int start, int end)
    	{
    	  this.start = start;
    	  this.end = end;
    	}
    
    	public void setPixPerBase(float pixPerBase)
    	{
    	  this.pixPerBase = pixPerBase;
    	}
      }
      
    
    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(getPreferredSize().width, 15));
          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;
    
          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)
        {
          JamView.this.requestFocus();
    
          handleCanvasMouseDragOrClick(e);
    
        }
        
        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();
              createViewMenu(popup);
            }
    
            popup.show(e.getComponent(),
                    e.getX(), e.getY());
    
    tjc's avatar
    tjc committed
          }
    
    tjc's avatar
    tjc committed
      class SAMRecordComparator implements Comparator<Object>
    
    tjc's avatar
    tjc committed
      {
        public int compare(Object o1, Object o2) 
        {
    
    tjc's avatar
    tjc committed
          SAMRecord pr1 = (SAMRecord) o1;
          SAMRecord pr2 = (SAMRecord) o2;
    
    tjc's avatar
    tjc committed
          
    
    tjc's avatar
    tjc committed
          int cmp = pr1.getReadName().compareTo(pr2.getReadName());
          if(cmp == 0)
          {
            if(pr1.getAlignmentStart() < pr2.getAlignmentStart())
              return -1;
            else
              return 1;
    
    tjc's avatar
    tjc committed
          return cmp;
    
    tjc's avatar
    tjc committed
        }
      }
    
      
      
      class PairedReadComparator implements Comparator<Object>
      {
        public int compare(Object o1, Object o2) 
        {
          PairedRead pr1 = (PairedRead) o1;
          PairedRead pr2 = (PairedRead) o2;
          
          int start1 = pr1.sam1.getAlignmentStart();
          if(pr1.sam1.getAlignmentEnd() < start1)
            start1 = pr1.sam1.getAlignmentEnd();
          
          int start2 = pr2.sam1.getAlignmentStart();
          if(pr2.sam1.getAlignmentEnd() < start2)
            start2 = pr1.sam1.getAlignmentEnd();
            
          return start1-start2;
        }
      }
      
      class PairedRead
      {
        SAMRecord sam1;
        SAMRecord sam2;
      }
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
      public Dimension getPreferredScrollableViewportSize()
      {
        return getPreferredSize();
      }
    
      public int getScrollableBlockIncrement(Rectangle visibleRect,
          int orientation, int direction)
      {
        if (orientation == SwingConstants.HORIZONTAL)
          return visibleRect.width - maxUnitIncrement;
        else 
          return visibleRect.height - maxUnitIncrement;
      }
    
      public boolean getScrollableTracksViewportHeight()
      {
        return false;
      }
    
      public boolean getScrollableTracksViewportWidth()
      {
        return false;
      }
    
      public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
                                            int direction)
      {
      //Get the current position.
        int currentPosition = 0;
        if (orientation == SwingConstants.HORIZONTAL) 
            currentPosition = visibleRect.x;
        else 
            currentPosition = visibleRect.y;
    
        //Return the number of pixels between currentPosition
        //and the nearest tick mark in the indicated direction.
        if (direction < 0)
        {
          int newPosition = currentPosition -
                            (currentPosition / maxUnitIncrement)
                             * maxUnitIncrement;
          return (newPosition == 0) ? maxUnitIncrement : newPosition;
        } 
        else 
        {
          return ((currentPosition / maxUnitIncrement) + 1)