Newer
Older
/* JamView
*
* created: 2009
*
* This file is part of Artemis
*
* Copyright(C) 2009 Genome Research Limited
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or(at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
import javax.swing.ButtonGroup;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JSeparator;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
tjc
committed
import org.apache.log4j.Level;
import net.sf.samtools.AlignmentBlock;
import net.sf.samtools.SAMFileHeader;
import net.sf.samtools.SAMFileReader;
import net.sf.samtools.SAMRecord;
import net.sf.samtools.SAMSequenceRecord;
import net.sf.samtools.SAMFileReader.ValidationStringency;
import net.sf.samtools.util.CloseableIterator;
import uk.ac.sanger.artemis.Entry;
import uk.ac.sanger.artemis.EntryGroup;
import uk.ac.sanger.artemis.FeatureVector;
import uk.ac.sanger.artemis.Selection;
import uk.ac.sanger.artemis.SelectionChangeEvent;
import uk.ac.sanger.artemis.SelectionChangeListener;
import uk.ac.sanger.artemis.components.DisplayAdjustmentEvent;
import uk.ac.sanger.artemis.components.DisplayAdjustmentListener;
import uk.ac.sanger.artemis.components.FeatureDisplay;
tjc
committed
import uk.ac.sanger.artemis.components.FileViewer;
import uk.ac.sanger.artemis.components.SwingWorker;
import uk.ac.sanger.artemis.components.variant.FeatureContigPredicate;
import uk.ac.sanger.artemis.editor.MultiLineToolTipUI;
import uk.ac.sanger.artemis.sequence.MarkerRange;
import uk.ac.sanger.artemis.sequence.NoSequenceException;
import uk.ac.sanger.artemis.util.Document;
import uk.ac.sanger.artemis.util.DocumentFactory;
import uk.ac.sanger.artemis.util.OutOfRangeException;
public class BamView extends JPanel
implements DisplayAdjustmentListener, SelectionChangeListener
private Hashtable<String, SAMFileReader> samFileReaderHash = new Hashtable<String, SAMFileReader>();
private Hashtable<String, Integer> seqLengths = new Hashtable<String, Integer>();
private Hashtable<String, Integer> offsetLengths;
tjc
committed
protected List<String> bamList;
private List<Integer> hideBamList = new Vector<Integer>();
private SAMRecordFlagPredicate samRecordFlagPredicate;
private boolean isSingle = false;
private boolean isSNPs = false;
private boolean isPairedStackView = false;
private FeatureDisplay feature_display;
private Selection selection;
private JPanel mainPanel;
private Ruler ruler;
private int startBase = -1;
private int endBase = -1;
private boolean showBaseAlignment = false;
private JMenu bamFilesMenu = new JMenu("BAM files");
private JCheckBoxMenuItem logMenuItem = new JCheckBoxMenuItem("Use Log Scale", logScale);
private JCheckBoxMenuItem checkBoxStackView = new JCheckBoxMenuItem("Stack View", isStackView);
private JCheckBoxMenuItem colourByCoverageColour = new JCheckBoxMenuItem("Coverage Plot Colours");
private JCheckBoxMenuItem baseQualityColour = new JCheckBoxMenuItem("Base Quality");
private JCheckBoxMenuItem markInsertions = new JCheckBoxMenuItem("Mark Insertions", true);
tjc
committed
private AlphaComposite translucent =
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f);
tjc
committed
private Color lightGrey = new Color(200, 200, 200);
private Color darkGreen = new Color(0, 150, 0);
private Color darkOrange = new Color(255,140,0);
private Color deepPink = new Color(139,10,80);
private Point lastMousePoint = null;
private SAMRecord mouseOverSAMRecord = null;
private SAMRecord highlightSAMRecord = null;
private String mouseOverInsertion;
// record of where a mouse drag starts
private int dragStart = -1;
private int maxHeight = 800;
tjc
committed
private int BASE_HEIGHT;
private PopupMessageFrame popFrame = new PopupMessageFrame();
private PopupMessageFrame waitingFrame = new PopupMessageFrame("waiting...");
public static org.apache.log4j.Logger logger4j =
org.apache.log4j.Logger.getLogger(BamView.class);
public BamView(List<String> bamList,
this.bamList = bamList;
// filter out unmapped reads by default
setSamRecordFlagPredicate(
new SAMRecordFlagPredicate(SAMRecordFlagPredicate.READ_UNMAPPED_FLAG));
try
{
getEntry(reference,entryGroup);
}
catch (NoSequenceException e)
{
e.printStackTrace();
}
}
try
{
readHeaderPicard();
}
catch(java.lang.UnsupportedClassVersionError err)
{
JOptionPane.showMessageDialog(null,
"This requires Java 1.6 or higher.",
"Check Java Version", JOptionPane.WARNING_MESSAGE);
}
catch (IOException e)
{
e.printStackTrace();
}
final javax.swing.plaf.FontUIResource font_ui_resource =
Options.getOptions().getFontUIResource();
while(keys.hasMoreElements())
{
Object key = keys.nextElement();
Object value = UIManager.get(key);
if(value instanceof javax.swing.plaf.FontUIResource)
UIManager.put(key, font_ui_resource);
}
setFont(Options.getOptions().getFont());
ALIGNMENT_PIX_PER_BASE = fm.charWidth('M');
BASE_HEIGHT = fm.getMaxAscent();
MultiLineToolTipUI.initialize();
setToolTipText("");
}
public String getToolTipText()
{
tjc
committed
if(mouseOverSAMRecord == null)
return null;
String msg =
mouseOverSAMRecord.getReadName() + "\n" +
mouseOverSAMRecord.getAlignmentStart() + ".." +
mouseOverSAMRecord.getAlignmentEnd() + "\nisize=" +
mouseOverSAMRecord.getInferredInsertSize() + "\nmapq=" +
mouseOverSAMRecord.getMappingQuality()+"\nrname="+
mouseOverSAMRecord.getReferenceName();
tjc
committed
if( mouseOverSAMRecord.getReadPairedFlag() &&
mouseOverSAMRecord.getProperPairFlag() &&
!mouseOverSAMRecord.getMateUnmappedFlag())
tjc
committed
{
msg = msg +
tjc
committed
(mouseOverSAMRecord.getReadNegativeStrandFlag() ? "-" : "+")+" / "+
(mouseOverSAMRecord.getMateNegativeStrandFlag() ? "-" : "+");
}
else
msg = msg +
tjc
committed
(mouseOverSAMRecord.getReadNegativeStrandFlag() ? "-" : "+");
if(msg != null && mouseOverInsertion != null)
msg = msg + "\nInsertion at:" +mouseOverInsertion;
return msg;
/**
* Get the BAM index file from the list
* @param bam
* @return
* @throws IOException
*/
private File getBamIndexFile(String bam) throws IOException
{
File bamIndexFile = null;
if (bam.startsWith("http"))
{
final URL urlBamIndexFile = new URL(bam + ".bai");
InputStream is = urlBamIndexFile.openStream();
// Create temp file.
bamIndexFile = File.createTempFile(urlBamIndexFile.getFile().replaceAll(
"[\\/\\s]", "_"), ".bai");
bamIndexFile.deleteOnExit();
FileOutputStream out = new FileOutputStream(bamIndexFile);
int c;
while ((c = is.read()) != -1)
out.write(c);
out.flush();
out.close();
is.close();
System.out.println("create... " + bamIndexFile.getAbsolutePath());
}
else
bamIndexFile = new File(bam + ".bai");
/**
* Get the SAM file reader.
* @param bam
* @return
* @throws IOException
*/
private SAMFileReader getSAMFileReader(final String bam) throws IOException
{
if(samFileReaderHash.containsKey(bam))
return samFileReaderHash.get(bam);
File bamIndexFile = getBamIndexFile(bam);
final SAMFileReader samFileReader;
if(!bam.startsWith("http"))
{
File bamFile = new File(bam);
samFileReader = new SAMFileReader(bamFile, bamIndexFile);
}
else
{
final URL urlBamFile = new URL(bam);
samFileReader = new SAMFileReader(urlBamFile, bamIndexFile, false);
samFileReader.setValidationStringency(ValidationStringency.SILENT);
samFileReaderHash.put(bam, samFileReader);
return samFileReader;
String bam = bamList.get(0);
final SAMFileReader inputSam = getSAMFileReader(bam);
//final SAMFileReader inputSam = new SAMFileReader(bamFile, indexFile);
SAMFileHeader header = inputSam.getFileHeader();
List<SAMSequenceRecord> readGroups = header.getSequenceDictionary().getSequences();
for(int i=0; i<readGroups.size(); i++)
{
seqLengths.put(readGroups.get(i).getSequenceName(),
readGroups.get(i).getSequenceLength());
seqNames.add(readGroups.get(i).getSequenceName());
}
private void readFromBamPicard(int start, int end, int bamIndex)
throws IOException
{
// Open the input file. Automatically detects whether input is SAM or BAM
// and delegates to a reader implementation for the appropriate format.
String bam = bamList.get(bamIndex);
final SAMFileReader inputSam = getSAMFileReader(bam);
//final SAMFileReader inputSam = new SAMFileReader(bamFile, indexFile);
if(concatSequences)
{
int len = 0;
int lastLen = 1;
for(int i=0; i<seqNames.size(); i++)
{
int thisLength = seqLengths.get(seqNames.get(i));
len += thisLength;
if( (lastLen >= start && lastLen < end) ||
(len >= start && len < end) ||
(start >= lastLen && start < len) ||
(end >= lastLen && end < len) )
{
int offset = getSequenceOffset(seqNames.get(i));
int thisStart = start - offset;
if(thisStart < 1)
thisStart = 1;
int thisEnd = end - offset;
if(thisEnd > thisLength)
thisEnd = thisLength;
//System.out.println("READ "+seqNames.get(i)+" "+thisStart+".."+thisEnd);
iterateOverBam(inputSam, seqNames.get(i), thisStart, thisEnd, bamIndex);
}
lastLen = len;
}
}
else
{
String refName = (String) combo.getSelectedItem();
iterateOverBam(inputSam, refName, start, end, bamIndex);
//System.out.println("readFromBamPicard "+start+".."+end);
//System.out.println("Reads in view ... "+readsInView.size());
}
/**
* Iterate over BAM file and load into the <code>List</code> of
* <code>SAMRecord</code>.
* @param inputSam
* @param refName
* @param start
* @param end
*/
private void iterateOverBam(final SAMFileReader inputSam,
String refName, int start, int end,
int bamIndex)
tjc
committed
boolean multipleBAM = false;
if(bamList.size() > 1)
multipleBAM = true;
CloseableIterator<SAMRecord> it = inputSam.queryOverlapping(refName, start, end);
MemoryMXBean memory = ManagementFactory.getMemoryMXBean();
if( samRecordFlagPredicate == null ||
!samRecordFlagPredicate.testPredicate(samRecord))
{
if(samRecordMapQPredicate == null ||
samRecordMapQPredicate.testPredicate(samRecord))
tjc
committed
if(multipleBAM)
samRecord.setAttribute("FL", bamIndex);
}
cnt = 0;
float heapFraction =
(float)((float)memory.getHeapMemoryUsage().getUsed()/
(float)memory.getHeapMemoryUsage().getMax());
logger4j.debug("Heap memory usage (used/max): "+heapFraction);
if(readsInView.size() > checkMemAfter*2 && !waitingFrame.isVisible())
waitingFrame.showWaiting("loading...", mainPanel);
if(heapFraction > 0.90)
"Using > 90 % of the maximum memory limit:"+
(memory.getHeapMemoryUsage().getMax()/1000000.f)+" Mb.\n"+
"Not all reads in this range have been read in. Zoom in or\n"+
"consider increasing the memory for this application.",
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
it.close();
}
private int getSequenceLength()
{
if(concatSequences)
{
int len = 0;
for(int i=0; i<seqNames.size(); i++)
len += seqLengths.get(seqNames.get(i));
return len;
}
else
return seqLengths.get((String) combo.getSelectedItem());
}
/**
* For BAM files with multiple references sequences, calculate
* the offset from the start of the concatenated sequence for
* a given reference.
* @param refName
* @return
*/
protected int getSequenceOffset(String refName)
{
if(!concatSequences)
return 0;
if(offsetLengths == null)
{
/* offsetLengths = new Hashtable<String, Integer>(combo.getItemCount());
int offset = 0;
for(int i=0; i<combo.getItemCount(); i++)
{
String thisSeqName = (String) combo.getItemAt(i);
offsetLengths.put(thisSeqName, offset);
offset += seqLengths.get(combo.getItemAt(i));
}*/
FeatureVector features = feature_display.getEntryGroup().getAllFeatures();
offsetLengths = new Hashtable<String, Integer>(seqNames.size());
for(int i=0; i<seqNames.size(); i++)
{
FeatureContigPredicate predicate = new FeatureContigPredicate(seqNames.get(i));
for(int j=0; j<features.size(); j++)
{
if(predicate.testPredicate(features.elementAt(j)))
{
offsetLengths.put(seqNames.get(i), features.elementAt(j).getFirstBase()-1);
break;
}
}
if(offsetLengths.size() != seqNames.size())
JOptionPane.showMessageDialog(this,
"There is a problem matching the reference sequences\n"+
"to the names in the BAM file. This may mean the labels\n"+
"on the reference features do not match those in the in\n"+
"the BAM file.",
"Problem Found", JOptionPane.WARNING_MESSAGE);
return offsetLengths.get(refName);
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
if(startBase > 0)
start = startBase;
else
if(endBase > 0)
end = endBase;
else
end = start + nbasesInView - 1;
if(end > seqLength)
end = seqLength;
boolean changeToStackView = false;
MemoryMXBean memory = ManagementFactory.getMemoryMXBean();
synchronized (this)
try
{
float heapFractionUsedBefore = (float) ((float) memory.getHeapMemoryUsage().getUsed() /
(float) memory.getHeapMemoryUsage().getMax());
if(readsInView == null)
readsInView = new Vector<SAMRecord>();
else
readsInView.clear();
for(int i=0; i<bamList.size(); i++)
{
if(!hideBamList.contains(i))
readFromBamPicard(start, end, i);
}
float heapFractionUsedAfter = (float) ((float) memory.getHeapMemoryUsage().getUsed() /
(float) memory.getHeapMemoryUsage().getMax());
// System.out.println("Heap Max : "+memory.getHeapMemoryUsage().getMax());
// System.out.println("Heap Used : "+memory.getHeapMemoryUsage().getUsed());
// System.out.println("Heap memory used "+heapFractionUsedAfter);
if ((heapFractionUsedAfter - heapFractionUsedBefore) > 0.06
&& !isStackView && heapFractionUsedAfter > 0.8)
{
checkBoxStackView.setSelected(true);
isStackView = true;
changeToStackView = true;
}
if ((!isStackView && !isStrandStackView)
|| pixPerBase * 1.08f >= ALIGNMENT_PIX_PER_BASE)
{
Collections.sort(readsInView, new SAMRecordComparator());
}
else if( (isStackView || isStrandStackView) &&
bamList.size() > 1)
{
// merge multiple BAM files
Collections.sort(readsInView, new SAMRecordPositionComparator(BamView.this));
}
catch (OutOfMemoryError ome)
JOptionPane.showMessageDialog(this, "Out of Memory");
readsInView.clear();
return;
catch(IOException me)
{
me.printStackTrace();
}
catch(net.sf.samtools.util.RuntimeIOException re)
{
JOptionPane.showMessageDialog(this, re.getMessage());
}
//System.out.println(start+".."+end+" " +
// "sequence length = "+getSequenceLength()+
// " pixPerBase="+pixPerBase);
if(showBaseAlignment)
drawStackView(g2, seqLength, pixPerBase, start, end);
else if(isPairedStackView)
drawPairedStackView(g2, seqLength, pixPerBase, start, end);
else if(isStrandStackView)
drawStrandStackView(g2, seqLength, pixPerBase, start, end);
else
drawLineView(g2, seqLength, pixPerBase, start, end);
if(isCoverage)
{
coveragePanel.setStartAndEnd(start, end);
coveragePanel.setPixPerBase(pixPerBase);
coveragePanel.repaint();
}
if(isSNPplot)
{
snpPanel.setStartAndEnd(start, end);
snpPanel.setPixPerBase(pixPerBase);
snpPanel.repaint();
}
if(changeToStackView)
{
"Note :: Changed to the stack view to save memory.\n"+
"Currently this is using "+
(memory.getHeapMemoryUsage().getUsed()/1000000.f)+" Mb "+
"and the maximum\nmemory limit is "+
(memory.getHeapMemoryUsage().getMax()/1000000.f)+" Mb.",
return (float)mainPanel.getWidth() / (float)nbasesInView;
{
if(feature_display == null)
return seqLength+nbasesInView/3;
/**
* Draw the zoomed-in base view.
* @param g2
* @param seqLength
* @param pixPerBase
* @param start
* @param end
*/
private void drawBaseAlignment(Graphics2D g2,
int seqLength,
float pixPerBase,
final int start,
tjc
committed
end = start + ( mainPanel.getWidth() * ALIGNMENT_PIX_PER_BASE );
if(bases != null)
{
// draw the reference sequence
ypos+=11;
if(seqEnd > bases.getLength())
seqEnd = bases.getLength();
bases.getSubSequence(new Range(refSeqStart, seqEnd), Bases.FORWARD).toUpperCase();
tjc
committed
g2.setColor(lightGrey);
g2.fillRect(0, ypos-11, mainPanel.getWidth(), 11);
drawSelectionRange(g2, ALIGNMENT_PIX_PER_BASE, start, end);
}
catch (OutOfRangeException e)
{
e.printStackTrace();
}
}
drawSelectionRange(g2, ALIGNMENT_PIX_PER_BASE, start, end);
g2.setStroke(new BasicStroke (2.f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND));
Rectangle r = jspView.getViewport().getViewRect();
int nreads = readsInView.size();
ypos += 11;
SAMRecord thisRead = readsInView.get(i);
if (ypos < r.getMaxY() || ypos > r.getMinY())
drawSequence(g2, thisRead, ypos, refSeq, refSeqStart);
drawn[i] = true;
int thisEnd = thisRead.getAlignmentEnd();
if (thisEnd == 0)
thisEnd = thisRead.getAlignmentStart() + thisRead.getReadLength();
for (int j = i + 1; j < nreads; j++)
SAMRecord nextRead = readsInView.get(j);
int nextStart = nextRead.getAlignmentStart();
if (nextStart > thisEnd + 1)
{
if (ypos < r.getMaxY() || ypos > r.getMinY())
drawSequence(g2, nextRead, ypos, refSeq, refSeqStart);
drawn[j] = true;
thisEnd = nextRead.getAlignmentEnd();
if (thisEnd == 0)
thisEnd = nextStart + nextRead.getReadLength();
}
else if (ypos > r.getMaxY() || ypos < r.getMinY())
break;
catch (ArrayIndexOutOfBoundsException ae)
{
System.err.println(readsInView.size()+" "+nreads);
ae.printStackTrace();
}
Dimension d = getPreferredSize();
d.setSize(getPreferredSize().getWidth(), ypos);
setPreferredSize(d);
/**
* Draw the query sequence
* @param g2
* @param read
* @param pixPerBase
* @param ypos
*/
private void drawSequence(Graphics2D g2, SAMRecord samRecord,
int ypos, String refSeq, int refSeqStart)
if (!samRecord.getReadPairedFlag() || // read is not paired in sequencing
samRecord.getMateUnmappedFlag() ) // mate is unmapped ) // mate is unmapped
int len = 0;
int refPos = 0;
String readSeq = samRecord.getReadString();
int offset = getSequenceOffset(samRecord.getReferenceName());
byte[] phredQuality = null;
if(baseQualityColour.isSelected())
phredQuality = samRecord.getBaseQualities();
Hashtable<Integer, String> insertions = null;
List<AlignmentBlock> blocks = samRecord.getAlignmentBlocks();
for(int i=0; i<blocks.size(); i++)
AlignmentBlock block = blocks.get(i);
int blockStart = block.getReadStart();
for(int j=0; j<block.getLength(); j++)
int readPos = blockStart-1+j;
xpos = block.getReferenceStart() - 1 + j + offset;
refPos = xpos - refSeqStart + 1;
setColourByBaseQuality(g2, phredQuality[readPos]);
if(isSNPs && refSeq != null && refPos > 0 && refPos < refSeq.length())
if(readSeq.charAt(readPos) != refSeq.charAt(refPos))
g2.setColor(Color.red);
else
g2.setColor(col);
}
g2.drawString(readSeq.substring(readPos, readPos+1),
refPos*ALIGNMENT_PIX_PER_BASE, ypos);
// look for insertions
if(markInsertions.isSelected() && i < blocks.size()-1)
{
int blockEnd = blockStart+block.getLength();
int nextBlockStart = blocks.get(i+1).getReadStart();
int insertSize = nextBlockStart - blockEnd;
if(insertSize > 0)
{
if(insertions == null)
insertions = new Hashtable<Integer, String>();
tjc
committed
(refPos+refSeqStart+1)+" "+
readSeq.substring(blockEnd-1, nextBlockStart-1));
g2.drawLine(xscreen, ypos, xscreen, ypos-BASE_HEIGHT);
// mark on reference sequence as well
if(bases != null)
g2.drawLine(xscreen, 11, xscreen, 11-BASE_HEIGHT);
g2.setColor(col);
}
}
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
// highlight
if(highlightSAMRecord != null &&
highlightSAMRecord.getReadName().equals(samRecord.getReadName()))
{
refPos = block.getReferenceStart() + offset - refSeqStart;
int xstart = refPos*ALIGNMENT_PIX_PER_BASE;
int width = block.getLength()*ALIGNMENT_PIX_PER_BASE;
Color col1 = g2.getColor();
g2.setColor(Color.red);
g2.drawRect(xstart, ypos-BASE_HEIGHT, width, BASE_HEIGHT);
if(i < blocks.size()-1)
{
int nextStart =
(blocks.get(i+1).getReferenceStart() + offset - refSeqStart)*ALIGNMENT_PIX_PER_BASE;
g2.drawLine(xstart+width, ypos-(BASE_HEIGHT/2), nextStart, ypos-(BASE_HEIGHT/2));
}
g2.setColor(col1);
}
else if(i < blocks.size()-1)
{
refPos = block.getReferenceStart() + offset - refSeqStart;
int xstart = refPos*ALIGNMENT_PIX_PER_BASE;
int width = block.getLength()*ALIGNMENT_PIX_PER_BASE;
int nextStart =
(blocks.get(i+1).getReferenceStart() + offset - refSeqStart)*ALIGNMENT_PIX_PER_BASE;
g2.drawLine(xstart+width, ypos-(BASE_HEIGHT/2), nextStart, ypos-(BASE_HEIGHT/2));
}
if(lastMousePoint != null && blocks.size() > 0)
refPos = blocks.get(0).getReferenceStart()+offset-refSeqStart;
refPos = blocks.get(blocks.size()-1).getReferenceStart()+
blocks.get(blocks.size()-1).getLength()+offset-refSeqStart;
if(lastMousePoint.getY() > ypos-11 && lastMousePoint.getY() < ypos)
if(lastMousePoint.getX() > xstart &&
lastMousePoint.getX() < xend)
{
mouseOverSAMRecord = samRecord;
if(insertions != null)
mouseOverInsertion = insertions.get((int)lastMousePoint.getX());
/**
* Colour bases on their mapping quality.
* @param g2
* @param baseQuality
*/
private void setColourByBaseQuality(Graphics2D g2, byte baseQuality)
{
if (baseQuality < 10)
g2.setColor(Color.blue);
else if (baseQuality < 20)
g2.setColor(darkGreen);
else if (baseQuality < 30)
g2.setColor(darkOrange);
else
g2.setColor(Color.black);
}
/**
* Draw zoomed-out view.
* @param g2
* @param seqLength
* @param pixPerBase
* @param start
* @param end
*/
private void drawLineView(Graphics2D g2, int seqLength, float pixPerBase, int start, int end)
{
drawSelectionRange(g2, pixPerBase,start, end);
if(showScale)
drawScale(g2, start, end, pixPerBase, getHeight());
new BasicStroke (1.3f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
int scaleHeight;
if(isShowScale())
scaleHeight = 15;
else
scaleHeight = 0;
int baseAtStartOfView = getBaseAtStartOfView();
Rectangle r = jspView.getViewport().getViewRect();
SAMRecord samRecord = readsInView.get(i);
SAMRecord samNextRecord = null;
if( !samRecord.getReadPairedFlag() || // read is not paired in sequencing
int ypos = getYPos(scaleHeight, samRecord.getReadString().length()); // (getHeight() - scaleHeight) - samRecord.getReadString().length();
if(ypos > r.getMaxY() || ypos < r.getMinY())
drawRead(g2, samRecord, pixPerBase, ypos, baseAtStartOfView);
int ypos = getYPos(scaleHeight, Math.abs(samRecord.getInferredInsertSize()));
if( (ypos > r.getMaxY() || ypos < r.getMinY()) && ypos > 0 )
if(samRecord.getReadName().equals(samNextRecord.getReadName()))
if(samRecord.getAlignmentEnd() < samNextRecord.getAlignmentStart() &&
(samNextRecord.getAlignmentStart()-samRecord.getAlignmentEnd())*pixPerBase > 2.f)
drawTranslucentLine(g2,
(int)((samRecord.getAlignmentEnd()-getBaseAtStartOfView())*pixPerBase),
(int)((samNextRecord.getAlignmentStart()-getBaseAtStartOfView())*pixPerBase), ypos);
if(colourByCoverageColour.isSelected())
g2.setColor(getColourByCoverageColour(samRecord));
else if( samRecord.getReadNegativeStrandFlag() && // strand of the query (1 for reverse)
samNextRecord.getReadNegativeStrandFlag() )
g2.setColor(Color.red);
else
g2.setColor(Color.blue);
drawRead(g2, samRecord, pixPerBase, ypos, baseAtStartOfView);
drawRead(g2, samNextRecord, pixPerBase, ypos, baseAtStartOfView);
drawLoneRead(g2, samRecord, ypos, pixPerBase, baseAtStartOfView, scaleHeight);
drawLoneRead(g2, samRecord, ypos, pixPerBase, baseAtStartOfView, scaleHeight);
private int getYPos(int scaleHeight, int size)
{
int ypos;
if(!logScale)
ypos = (getHeight() - scaleHeight) - size;
else
{
int logInfSize = (int)( Math.log(size) * 100);
ypos = (getHeight() - scaleHeight) - logInfSize;
}
return ypos;
}
tjc
committed
/**
* Draw the reads as lines in vertical stacks. The reads are colour
* coded as follows:
*
* blue - reads are unique and are paired with a mapped mate
* black - reads are unique and are not paired or have an unmapped mate
* green - reads are duplicates
tjc
committed
*
* @param g2
* @param seqLength
* @param pixPerBase
* @param start
* @param end
*/
private void drawStackView(Graphics2D g2,
int seqLength,
float pixPerBase,
int start,
int end)
{
drawSelectionRange(g2, pixPerBase,start, end);
if(isShowScale())
BasicStroke stroke = new BasicStroke(
1.3f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER);
int scaleHeight;
if(isShowScale())
scaleHeight = 15;
else
scaleHeight = 0;
int ypos = (getHeight() - scaleHeight);
tjc
committed
int maxEnd = 0;
int lstStart = 0;
int lstEnd = 0;
int baseAtStartOfView = getBaseAtStartOfView();
Rectangle r = jspView.getViewport().getViewRect();
for(int i=0; i<readsInView.size(); i++)
{
SAMRecord samRecord = readsInView.get(i);
int offset = getSequenceOffset(samRecord.getReferenceName());
tjc
committed
int recordStart = samRecord.getAlignmentStart()+offset;
int recordEnd = samRecord.getAlignmentEnd()+offset;
if(colourByCoverageColour.isSelected() ||
lstStart != recordStart || lstEnd != recordEnd)
tjc
committed
{
if(colourByCoverageColour.isSelected())
g2.setColor(getColourByCoverageColour(samRecord));
else if (!samRecord.getReadPairedFlag() || // read is not paired in sequencing
samRecord.getMateUnmappedFlag() ) // mate is unmapped ) // mate is unmapped
tjc
committed
g2.setColor(Color.black);
else
g2.setColor(Color.blue);
if(maxEnd < recordStart)
{
ypos = (getHeight() - scaleHeight)-2;
maxEnd = recordEnd+2;
}
else
ypos = ypos-2;
tjc
committed
g2.setColor(darkGreen);
tjc
committed
lstStart = recordStart;
lstEnd = recordEnd;
if(ypos > r.getMaxY() || ypos < r.getMinY())
continue;
drawRead(g2, samRecord, pixPerBase, ypos, baseAtStartOfView);
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
/**
* Draw the reads as lines in vertical stacks. The reads are colour
* coded as follows:
*
* blue - reads are unique and are paired with a mapped mate
* black - reads are unique and are not paired or have an unmapped mate
* green - reads are duplicates
*
* @param g2
* @param seqLength
* @param pixPerBase
* @param start
* @param end
*/
private void drawStrandStackView(Graphics2D g2,
int seqLength,
float pixPerBase,
int start,
int end)
{
drawSelectionRange(g2, pixPerBase,start, end);
BasicStroke stroke = new BasicStroke(
1.3f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER);
int scaleHeight = 15;
drawScale(g2, start, end, pixPerBase, ((getHeight()+scaleHeight)/2));
int ymid = (getHeight()/ 2);
// positive strand
drawStrand(g2, false, scaleHeight, ymid-(scaleHeight/2), -2, pixPerBase, stroke);
// negative strand
drawStrand(g2, true, scaleHeight, ymid+(scaleHeight/2), 2, pixPerBase, stroke);
}
private void drawStrand(Graphics2D g2,
boolean isStrandNegative,
int scaleHeight,
int ymid,
int ystep,
float pixPerBase,
Stroke stroke)
{
int ypos = (getHeight() - scaleHeight);
int maxEnd = 0;
int lstStart = 0;
int lstEnd = 0;
int baseAtStartOfView = getBaseAtStartOfView();
Rectangle r = jspView.getViewport().getViewRect();
for(int i=0; i<readsInView.size(); i++)
{
SAMRecord samRecord = readsInView.get(i);
if( samRecord.getReadNegativeStrandFlag() == isStrandNegative )
{
int offset = getSequenceOffset(samRecord.getReferenceName());
int recordStart = samRecord.getAlignmentStart()+offset;
int recordEnd = samRecord.getAlignmentEnd()+offset;
if(colourByCoverageColour.isSelected() ||
lstStart != recordStart || lstEnd != recordEnd)
if(colourByCoverageColour.isSelected())
g2.setColor(getColourByCoverageColour(samRecord));
else if (!samRecord.getReadPairedFlag() || // read is not paired in sequencing
samRecord.getMateUnmappedFlag() ) // mate is unmapped
g2.setColor(Color.black);
else
g2.setColor(Color.blue);
if(maxEnd < recordStart)
{
ypos = ymid + ystep;
maxEnd = recordEnd+2;
}
else
ypos = ypos + ystep;
}
else
g2.setColor(darkGreen);
lstStart = recordStart;
lstEnd = recordEnd;
if(ypos > r.getMaxY() || ypos < r.getMinY())
continue;
drawRead(g2, samRecord, pixPerBase, ypos, baseAtStartOfView);
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
/**
* Draw the reads as lines in vertical stacks. The reads are colour
* coded as follows:
*
* blue - reads are unique and are paired with a mapped mate
* black - reads are unique and are not paired or have an unmapped mate
* green - reads are duplicates
*
* @param g2
* @param seqLength
* @param pixPerBase
* @param start
* @param end
*/
private void drawPairedStackView(Graphics2D g2,
int seqLength,
float pixPerBase,
int start,
int end)
{
drawSelectionRange(g2, pixPerBase,start, end);
if(isShowScale())
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
Vector<PairedRead> pairedReads = new Vector<PairedRead>();
for(int i=0; i<readsInView.size(); i++)
{
SAMRecord samRecord = readsInView.get(i);
if( !samRecord.getReadPairedFlag() || // read is not paired in sequencing
samRecord.getMateUnmappedFlag() ) // mate is unmapped
continue;
SAMRecord samNextRecord = null;
if(i < readsInView.size()-1)
{
samNextRecord = readsInView.get(++i);
PairedRead pr = new PairedRead();
if(samRecord.getReadName().equals(samNextRecord.getReadName()))
{
if(samRecord.getAlignmentStart() < samNextRecord.getAlignmentStart())
{
pr.sam1 = samRecord;
pr.sam2 = samNextRecord;
}
else
{
pr.sam2 = samRecord;
pr.sam1 = samNextRecord;
}
}
else
{
--i;
pr.sam1 = samRecord;
pr.sam2 = null;
}
pairedReads.add(pr);
}
}
Collections.sort(pairedReads, new PairedReadComparator());
Stroke originalStroke = new BasicStroke (1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
Stroke stroke =
new BasicStroke (1.3f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
int scaleHeight;
if(isShowScale())
scaleHeight = 15;
else
scaleHeight = 0;
int ypos = getHeight() - scaleHeight - 3;
int lastEnd = 0;
int baseAtStartOfView = getBaseAtStartOfView();
Rectangle r = jspView.getViewport().getViewRect();
for(int i=0; i<pairedReads.size(); i++)
{
PairedRead pr = pairedReads.get(i);
if(pr.sam1.getAlignmentStart() > lastEnd)
{
ypos = getHeight() - scaleHeight - 3;
if(pr.sam2 != null)
{
lastEnd = pr.sam2.getAlignmentEnd();
}
else
lastEnd = pr.sam1.getAlignmentEnd();
}
else
ypos = ypos - 3;
if(ypos > r.getMaxY() || ypos < r.getMinY())
g2.setStroke(originalStroke);
g2.setColor(Color.LIGHT_GRAY);
if(pr.sam2 != null)
{
int offset1 = getSequenceOffset(pr.sam1.getReferenceName());
int offset2 = getSequenceOffset(pr.sam2.getReferenceName());
drawTranslucentJointedLine(g2,
(int)((pr.sam1.getAlignmentEnd()+offset1-getBaseAtStartOfView())*pixPerBase),
(int)((pr.sam2.getAlignmentStart()+offset2-getBaseAtStartOfView())*pixPerBase), ypos);
}
else
{
if(!pr.sam1.getMateUnmappedFlag() &&
pr.sam1.getMateReferenceName().equals(pr.sam1.getReferenceName()))
{
int prStart;
if(pr.sam1.getAlignmentStart() > pr.sam1.getMateAlignmentStart())
prStart = pr.sam1.getAlignmentEnd();
else
prStart = pr.sam1.getAlignmentStart();
int offset = getSequenceOffset(pr.sam1.getReferenceName());
drawTranslucentJointedLine(g2,
(int)( (prStart+offset-getBaseAtStartOfView())*pixPerBase),
(int)( (pr.sam1.getMateAlignmentStart()+offset-getBaseAtStartOfView())*pixPerBase), ypos);
if(colourByCoverageColour.isSelected())
g2.setColor(getColourByCoverageColour(pr.sam1));
else if( pr.sam1.getReadNegativeStrandFlag() && // strand of the query (1 for reverse)
( pr.sam2 != null && pr.sam2.getReadNegativeStrandFlag() ) )
g2.setColor(Color.red);
else
g2.setColor(Color.blue);
drawRead(g2, pr.sam1, pixPerBase, ypos, baseAtStartOfView);
if(pr.sam2 != null)
drawRead(g2, pr.sam2, pixPerBase, ypos, baseAtStartOfView);
}
}
/**
* Draw a read that apparently has a read mate that is not in view.
* @param g2
* @param thisRead
* @param ypos
* @param pixPerBase
* @param originalStroke
* @param stroke
*/
private void drawLoneRead(Graphics2D g2, SAMRecord samRecord, int ypos,
float pixPerBase, int baseAtStartOfView, int scaleHeight)
boolean offTheTop = false;
int offset = getSequenceOffset(samRecord.getReferenceName());
int thisStart = samRecord.getAlignmentStart()+offset;
int thisEnd = thisStart + samRecord.getReadString().length() -1;
if(ypos <= 0)
{
offTheTop = true;
ypos = samRecord.getReadString().length();
}
if(samRecord.getInferredInsertSize() <= 0)
{
offTheTop = true;
ypos = getHeight() - scaleHeight - 5;
}
if(samRecord.getInferredInsertSize() > 0 &&
Math.abs(samRecord.getMateAlignmentStart()-samRecord.getAlignmentEnd())*pixPerBase > 2.f)
{
g2.setColor(Color.LIGHT_GRAY);
if(samRecord.getAlignmentEnd() < samRecord.getMateAlignmentStart())
{
(int)((samRecord.getMateAlignmentStart()-getBaseAtStartOfView()+offset)*pixPerBase);
drawTranslucentLine(g2,
(int)((thisEnd-getBaseAtStartOfView())*pixPerBase), nextStart, ypos);
int nextStart =
(int)((samRecord.getMateAlignmentStart()-getBaseAtStartOfView()+offset)*pixPerBase);
drawTranslucentLine(g2,
(int)((thisStart-getBaseAtStartOfView())*pixPerBase), nextStart, ypos);
if(colourByCoverageColour.isSelected())
g2.setColor(getColourByCoverageColour(samRecord));
else if(offTheTop)
g2.setColor(darkOrange);
tjc
committed
else if(samRecord.getReadNegativeStrandFlag() &&
samRecord.getMateNegativeStrandFlag()) // strand of the query (1 for reverse)
g2.setColor(Color.red);
else
g2.setColor(Color.blue);
drawRead(g2, samRecord, pixPerBase, ypos, baseAtStartOfView);
showSNPsOnReads(g2, samRecord, pixPerBase, ypos, offset);
private void drawScale(Graphics2D g2, int start, int end, float pixPerBase, int ypos)
g2.drawLine( 0, ypos-14,
(int)((end - getBaseAtStartOfView())*pixPerBase), ypos-14);
private void drawTicks(Graphics2D g2, int start, int end, float pixPerBase, int division, int ypos)
int markStart = (Math.round(start/division)*division);
if(markStart < 1)
markStart = 1;
g2.drawString(Integer.toString(m), x, ypos-1);
g2.drawLine((int)x, ypos-14,(int)x, ypos-11);
/**
* Draw a y-scale for inferred size (isize) of reads.
* @param g2
* @param xScaleHeight
*/
private void drawYScale(Graphics2D g2, int xScaleHeight)
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;
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
float pixPerBase,
int ypos,
int baseAtStartOfView)
int offset = getSequenceOffset(thisRead.getReferenceName());
int thisStart = thisRead.getAlignmentStart()+offset-baseAtStartOfView;
int thisEnd = thisRead.getAlignmentEnd()+offset-baseAtStartOfView;
if(highlightSAMRecord != null &&
highlightSAMRecord.getReadName().equals(thisRead.getReadName()))
Stroke originalStroke = g2.getStroke();
Stroke stroke =
new BasicStroke (3.f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
Color c = g2.getColor();
g2.setColor(Color.black);
g2.drawLine((int)( thisStart * pixPerBase), ypos,
(int)( thisEnd * pixPerBase), ypos);
g2.setColor(c);
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)
drawArrow(g2, thisRead, thisStart, thisEnd, pixPerBase, ypos);
// 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;
}
}
showSNPsOnReads(g2, thisRead, pixPerBase, ypos, offset);
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
/**
* Draw arrow on the read to indicate orientation.
* @param g2
* @param thisRead
* @param thisStart
* @param thisEnd
* @param pixPerBase
* @param ypos
*/
private void drawArrow(Graphics2D g2,
SAMRecord thisRead,
int thisStart,
int thisEnd,
float pixPerBase,
int ypos)
{
if(thisRead.getReadNegativeStrandFlag())
{
int apos = ypos + 2;
g2.drawLine((int)( (thisStart+5) * pixPerBase), apos,
(int)( thisStart * pixPerBase), ypos);
}
else
{
int apos = ypos - 2;
g2.drawLine((int)( (thisEnd-5) * pixPerBase), apos,
(int)( thisEnd * pixPerBase), ypos);
}
}
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
/**
* 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-getBaseAtStartOfView()));
int width = (int) (pixPerBase*(rangeEnd-rangeStart+1));
g2.setColor(Color.pink);
g2.fillRect(x, 0, width, getHeight());
}
}
}
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
/**
* 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);
}
/**
* Display the SNPs for the given read.
* @param g2
* @param thisRead
* @param pixPerBase
* @param ypos
*/
private void showSNPsOnReads(Graphics2D g2, SAMRecord thisRead,
{
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();
new Range(thisStart+offset, thisEnd+offset), Bases.FORWARD);
offset = offset - getBaseAtStartOfView();
for(int i=0; i<blocks.size(); i++)
AlignmentBlock block = blocks.get(i);
for(int j=0; j<block.getLength(); j++)
int readPos = block.getReadStart()-1+j;
int refPos = block.getReferenceStart()+j;
if (Character.toUpperCase(refSeq[refPos-thisStart]) != readSeq[readPos])
{
g2.drawLine((int) ((refPos+offset) * pixPerBase), ypos + 2,
(int) ((refPos+offset) * pixPerBase), ypos - 2);
g2.setColor(col);
}
catch (OutOfRangeException e)
{
e.printStackTrace();
/**
* 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,
final boolean autohide,
final FeatureDisplay feature_display)
if(feature_display != null)
{
this.feature_display = feature_display;
this.selection = feature_display.getSelection();
topPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
}
else
{
topPanel = new JMenuBar();
frame.setJMenuBar((JMenuBar)topPanel);
JMenu fileMenu = new JMenu("File");
topPanel.add(fileMenu);
JMenuItem readBam = new JMenuItem("Open new BamView ...");
fileMenu.add(readBam);
readBam.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String[] s = new String[0];
BamView.main(s);
}
});
JMenuItem close = new JMenuItem("Close");
fileMenu.add(close);
close.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
BamView.this.setVisible(false);
Component comp = BamView.this;
while( !(comp instanceof JFrame) )
comp = comp.getParent();
((JFrame)comp).dispose();
}
});
JMenuItem exit = new JMenuItem("Exit");
fileMenu.add(exit);
exit.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
int status = JOptionPane.showConfirmDialog(BamView.this,
JOptionPane.OK_CANCEL_OPTION);
if(status != JOptionPane.OK_OPTION)
return;
System.exit(0);
}
});
if(seqNames.size() > 1)
{
int len = 0;
for(int i=0; i<seqNames.size(); i++)
len += seqLengths.get(seqNames.get(i));
if(feature_display != null &&
len == feature_display.getSequenceLength())
concatSequences = true;
else if(bases != null &&
len == bases.getLength() )
concatSequences = true;
}
final JCheckBox buttonAutoHide = new JCheckBox("Hide", autohide);
buttonAutoHide.setToolTipText("Auto-Hide");
final MouseMotionListener mouseMotionListener = new MouseMotionListener()
}
public void mouseMoved(MouseEvent e)
{
int thisHgt = HEIGHT;
if (thisHgt < 5)
thisHgt = 15;
int y = (int) (e.getY() - jspView.getViewport().getViewRect().getY());
if (y < thisHgt)
}
mainPanel.repaint();
mainPanel.revalidate();
}
};
addMouseMotionListener(mouseMotionListener);
combo = new JComboBox(seqNames);
combo.setEditable(false);
combo.setMaximumRowCount(20);
combo.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent e)
{
laststart = -1;
lastend = -1;
if(feature_display != null)
setZoomLevel(feature_display.getMaxVisibleBases());
else
setZoomLevel(BamView.this.nbasesInView);
goTo.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
try
{
int basePosition = Integer.parseInt(baseText.getText());
}
catch (NumberFormatException nfe)
{
JOptionPane.showMessageDialog(BamView.this,
"Expecting a base number!", "Number Format",
JOptionPane.WARNING_MESSAGE);
}
JButton zoomIn = new JButton("-");
Insets ins = new Insets(1,1,1,1);
zoomIn.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
{
setZoomLevel((int) (BamView.this.nbasesInView * 1.1));
JButton zoomOut = new JButton("+");
zoomOut.setMargin(ins);
zoomOut.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
{
if (showBaseAlignment)
return;
setZoomLevel((int) (BamView.this.nbasesInView * .9));
jspView = new JScrollPane(this,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
setDisplay(1, nbasesInView, null);
mainPanel.setLayout(new BorderLayout());
if(topPanel instanceof JPanel)
mainPanel.add(topPanel, BorderLayout.NORTH);
mainPanel.add(jspView, BorderLayout.CENTER);
JPanel bottomPanel = new JPanel(new BorderLayout());
coveragePanel = new CoveragePanel(this);
bottomPanel.add(coveragePanel, BorderLayout.CENTER);
//
snpPanel = new SnpPanel(this, bases);
bottomPanel.add(snpPanel, BorderLayout.NORTH);
if(feature_display == null)
{
scrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 1, nbasesInView, 1,
getMaxBasesInPanel(getSequenceLength()));
scrollBar.setUnitIncrement(nbasesInView/20);
scrollBar.addAdjustmentListener(new AdjustmentListener()
{
public void adjustmentValueChanged(AdjustmentEvent e)
{
repaint();
if(coveragePanel != null)
coveragePanel.repaint();
if(snpPanel != null)
snpPanel.repaint();
}
});
bottomPanel.add(scrollBar, BorderLayout.SOUTH);
}
mainPanel.add(bottomPanel, BorderLayout.SOUTH);
coveragePanel.setPreferredSize(new Dimension(900, 100));
coveragePanel.setVisible(false);
snpPanel.setPreferredSize(new Dimension(900, 100));
snpPanel.setVisible(false);
jspView.getVerticalScrollBar().setValue(
jspView.getVerticalScrollBar().getMaximum());
jspView.getVerticalScrollBar().setUnitIncrement(maxUnitIncrement);
public void keyPressed(final KeyEvent event)
setZoomLevel((int) (BamView.this.nbasesInView * 1.1));
setZoomLevel((int) (BamView.this.nbasesInView * .9));
addMouseListener(new PopupListener());
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
private void addToViewMenu(final int thisBamIndex)
{
File f = new File(bamList.get(thisBamIndex));
final JCheckBoxMenuItem cbBam = new JCheckBoxMenuItem(
f.getName(), true);
bamFilesMenu.add(cbBam);
cbBam.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(cbBam.isSelected())
hideBamList.remove(new Integer(thisBamIndex));
else
hideBamList.add(new Integer(thisBamIndex));
laststart = -1;
lastend = -1;
repaint();
}
});
}
{
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");
List<String> bamFiles = bamFileSelection.getFiles(".*\\.bam$");
int count = bamList.size();
bamList.addAll(bamFileSelection.getFiles(".*\\.bam$"));
for(int i=0; i<bamFiles.size(); i++)
addToViewMenu(i+count);
laststart = -1;
lastend = -1;
repaint();
}
});
bamFilesMenu.setFont(addBam.getFont());
menu.add(bamFilesMenu);
for(int i=0; i<bamList.size(); i++)
addToViewMenu(i);
menu.add(new JSeparator());
final JCheckBoxMenuItem checkBoxPairedStackView = new JCheckBoxMenuItem("Paired Stack View");
final JCheckBoxMenuItem checkBoxStrandStackView = new JCheckBoxMenuItem("Strand Stack View");
final JCheckBoxMenuItem checkIsizeStackView = new JCheckBoxMenuItem("Inferred Size View", false);
checkBoxStackView.setFont(checkIsizeStackView.getFont());
baseQualityColour.setFont(checkIsizeStackView.getFont());
colourByCoverageColour.setFont(checkIsizeStackView.getFont());
markInsertions.setFont(checkIsizeStackView.getFont());
group.add(checkBoxStackView);
group.add(checkBoxPairedStackView);
group.add(checkBoxStrandStackView);
group.add(checkIsizeStackView);
checkIsizeStackView.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
laststart = -1;
lastend = -1;
if(checkIsizeStackView.isSelected())
{
isStackView = false;
isPairedStackView = false;
isStrandStackView = false;
checkBoxStackView.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
laststart = -1;
lastend = -1;
isStackView = !isStackView;
if(isStackView)
{
isPairedStackView = !isStackView;
checkBoxPairedStackView.setSelected(!isStackView);
{
laststart = -1;
lastend = -1;
isPairedStackView = !isPairedStackView;
if(isPairedStackView)
{
isStackView = !isPairedStackView;
checkBoxStackView.setSelected(!isPairedStackView);
}
repaint();
}
});
checkBoxStrandStackView.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
laststart = -1;
lastend = -1;
isStrandStackView = !isStrandStackView;
if(isStrandStackView)
{
isStackView = !isStrandStackView;
isPairedStackView = !isStrandStackView;
checkBoxStackView.setSelected(!isStrandStackView);
checkBoxPairedStackView.setSelected(!isStrandStackView);
setViewportMidPoint();
viewMenu.add(checkBoxStrandStackView);
menu.add(viewMenu);
final JCheckBoxMenuItem checkBoxSNPs = new JCheckBoxMenuItem("SNP marks");
//
JMenu colourMenu = new JMenu("Colour By");
colourMenu.add(colourByCoverageColour);
baseQualityColour.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(baseQualityColour.isSelected())
{
checkBoxSNPs.setSelected(false);
isSNPs = false;
}
repaint();
}
});
colourMenu.add(baseQualityColour);
menu.add(colourMenu);
//
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);
JCheckBoxMenuItem checkBoxCoverage = new JCheckBoxMenuItem("Coverage");
checkBoxCoverage.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
isCoverage = !isCoverage;
coveragePanel.setVisible(isCoverage);
repaint();
}
});
graphMenu.add(checkBoxCoverage);
JCheckBoxMenuItem checkBoxSNP = new JCheckBoxMenuItem("SNP");
checkBoxSNP.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
isSNPplot = !isSNPplot;
snpPanel.setVisible(isSNPplot);
repaint();
}
});
graphMenu.add(checkBoxSNP);
menu.add(graphMenu);
final JCheckBoxMenuItem checkBoxSync =
new JCheckBoxMenuItem("Asynchronous", asynchronous);
checkBoxSync.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
{
asynchronous = checkBoxSync.isSelected();
}
});
JMenu maxHeightMenu = new JMenu("BamView Height");
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());
logMenuItem.setFont(checkIsizeStackView.getFont());
menu.add(logMenuItem);
logMenuItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
logScale = logMenuItem.isSelected();
repaint();
}
});
JMenuItem filter = new JMenuItem("Filter by Flag...");
menu.add(filter);
filter.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
new SAMRecordFilter(BamView.this);
}
});
}
public void setVisible(boolean visible)
{
super.setVisible(visible);
mainPanel.setVisible(visible);
private void setViewportMidPoint()
{
Point p = jspView.getViewport().getLocation();
p.y = (getHeight() - jspView.getViewport().getViewRect().height)/2;
jspView.getViewport().setViewPosition(p);
}
if(feature_display != null)
return feature_display.getForwardBaseAtLeftEdge();
else
return scrollBar.getValue();
}
/**
* Set the panel size based on the number of bases visible
* and repaint.
* @param nbasesInView
*/
if(pixPerBase*1.08f >= ALIGNMENT_PIX_PER_BASE)
this.nbasesInView = (int)(mainPanel.getWidth()/pixPerBase);
if(ruler == null)
ruler = new Ruler();
jspView.setColumnHeaderView(ruler);
showBaseAlignment = true;
markInsertions.setEnabled(true);
}
else if(jspView != null)
{
jspView.setColumnHeaderView(null);
if(!isStrandStackView)
jspView.getVerticalScrollBar().setValue(
jspView.getVerticalScrollBar().getMaximum());
markInsertions.setEnabled(false);
{
scrollBar.setValues(startValue, nbasesInView, 1,
getMaxBasesInPanel(getSequenceLength()));
scrollBar.setUnitIncrement(nbasesInView/20);
scrollBar.setBlockIncrement(nbasesInView);
}
* Set the start and end base positions to display.
* @param start
* @param end
* @param event
public void setDisplay(int start,
int end,
DisplayAdjustmentEvent event)
this.startBase = start;
this.endBase = end;
else
{
if(feature_display == null)
pixPerBase = 1000.f/(float)(end-start+1);
else
pixPerBase = feature_display.getWidth()/(float)(end-start+1);
}
if(event == null)
{
this.startBase = -1;
this.endBase = -1;
}
/**
* 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);
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();
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;
}
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
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.
**/
if(event.getButton() == MouseEvent.BUTTON3 || bases == null)
tjc
committed
highlightSAMRecord = null;
if(event.getClickCount() > 1)
{
getSelection().clear();
repaint();
return;
}
highlightRange(event,
MouseEvent.BUTTON1_DOWN_MASK & MouseEvent.BUTTON2_DOWN_MASK);
}
/**
*
* @param event
* @param onmask
*/
private void highlightRange(MouseEvent event, int onmask)
{
int start = (int) ( ( (event.getPoint().getX())/pixPerBase) + getBaseAtStartOfView() );
if(start < 1)
start = 1;
if(start > seqLength)
start = seqLength;
if (dragStart < 0 && (event.getModifiersEx() & onmask) == onmask)
dragStart = start;
else if((event.getModifiersEx() & onmask) != onmask)
dragStart = -1;
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();
/**
* Get the colour for the given read given to it by the coverage plot.
* @param samRecord
* @return
*/
private Color getColourByCoverageColour(SAMRecord samRecord)
{
LineAttributes lines[] = CoveragePanel.getLineAttributes(bamList.size());
int fileIndex = 0;
if(bamList.size()>1)
fileIndex = (Integer) samRecord.getAttribute("FL");
return lines[fileIndex].getLineColour();
}
private Selection getSelection()
{
return selection;
}
protected int getBasesInView()
{
return nbasesInView;
}
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
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;
}
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;
}
public Object construct()
{
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
if(event.getStart() != ((FeatureDisplay)event.getSource()).getForwardBaseAtLeftEdge())
{
waitingFrame.showWaiting("waiting...", mainPanel);
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;
lastend = -1;
BamView.this.startBase = event.getStart();
BamView.this.endBase = event.getEnd();
int width = feature_display.getMaxVisibleBases();
setZoomLevel(width);
repaint();
if(coveragePanel != null && coveragePanel.isVisible())
{
coveragePanel.setStartAndEnd(BamView.this.startBase, BamView.this.endBase);
coveragePanel.setPixPerBase(getPixPerBaseByWidth());
{
snpPanel.setStartAndEnd(BamView.this.startBase, BamView.this.endBase);
snpPanel.setPixPerBase(getPixPerBaseByWidth());
}
else
{
setDisplay(event.getStart(),
event.getStart()+feature_display.getMaxVisibleBases(), event);
repaint();
if(coveragePanel != null && coveragePanel.isVisible())
coveragePanel.repaint();
if(snpPanel != null && snpPanel.isVisible())
snpPanel.repaint();
public void selectionChanged(SelectionChangeEvent event)
{
repaint();
setPreferredSize(new Dimension(mainPanel.getWidth(), 15));
setBackground(Color.white);
setFont(getFont().deriveFont(11.f));
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
drawBaseScale(g2, start, end, 12);
}
private void drawBaseScale(Graphics2D g2, int start, int end, int ypos)
{
int startMark = (((int)(start/10))*10)+1;
if(end > getSequenceLength())
end = getSequenceLength();
g2.drawString(Integer.toString(i), xpos, ypos);
xpos+=(ALIGNMENT_PIX_PER_BASE/2);
g2.drawLine(xpos, ypos+1, xpos, ypos+5);
}
}
/**
* Popup menu listener
*/
class PopupListener extends MouseAdapter
{
JMenuItem gotoMateMenuItem;
tjc
committed
JMenuItem showDetails;
public void mouseClicked(MouseEvent e)
{
if(e.isPopupTrigger() ||
e.getButton() == MouseEvent.BUTTON3)
return;
BamView.this.requestFocus();
if(e.getClickCount() > 1)
getSelection().clear();
else if(e.getButton() == MouseEvent.BUTTON1)
highlightSAMRecord = mouseOverSAMRecord;
else
highlightRange(e, MouseEvent.BUTTON2_DOWN_MASK);
repaint();
}
public void mousePressed(MouseEvent e)
{
maybeShowPopup(e);
}
public void mouseReleased(MouseEvent e)
{
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e)
{
if(e.isPopupTrigger())
if(gotoMateMenuItem != null)
popup.remove(gotoMateMenuItem);
tjc
committed
if(showDetails != null)
popup.remove(showDetails);
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
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);
tjc
committed
}
if( mouseOverSAMRecord != null)
{
final SAMRecord thisSAMRecord = mouseOverSAMRecord;
showDetails = new JMenuItem("Show details of : "+
thisSAMRecord.getReadName());
showDetails.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
FileViewer viewDetail = new FileViewer(thisSAMRecord.getReadName(), true, false);
appendToDetailView(thisSAMRecord, viewDetail);
}
});
popup.add(showDetails);
}
popup.show(e.getComponent(),
e.getX(), e.getY());
tjc
committed
private void appendToDetailView(SAMRecord thisSAMRecord, 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);
viewDetail.appendString("Mapping Quality "+thisSAMRecord.getMappingQuality()+"\n", Level.DEBUG);
tjc
committed
if(thisSAMRecord.getReadPairedFlag() && thisSAMRecord.getProperPairFlag() && !thisSAMRecord.getMateUnmappedFlag())
tjc
committed
{
viewDetail.appendString("Mate Reference Name "+thisSAMRecord.getMateReferenceName()+"\n", Level.DEBUG);
viewDetail.appendString("Mate Start Coordinate "+thisSAMRecord.getMateAlignmentStart()+"\n", Level.DEBUG);
viewDetail.appendString("Strand (read/mate) "+
(thisSAMRecord.getReadNegativeStrandFlag() ? "-" : "+")+" / "+
(thisSAMRecord.getMateNegativeStrandFlag() ? "-" : "+"), Level.DEBUG);
}
else
{
viewDetail.appendString("Strand (read) "+
(thisSAMRecord.getReadNegativeStrandFlag() ? "-" : "+"), Level.DEBUG);
}
viewDetail.appendString("\n\nCigar String "+thisSAMRecord.getCigarString(), Level.DEBUG);
viewDetail.appendString("\n\nFlags:", Level.INFO);
viewDetail.appendString("\nDuplicate Read "+
(thisSAMRecord.getDuplicateReadFlag() ? "yes" : "no"), Level.DEBUG);
viewDetail.appendString("\nRead Paired "+
(thisSAMRecord.getReadPairedFlag() ? "yes" : "no"), Level.DEBUG);
if(thisSAMRecord.getReadPairedFlag())
{
viewDetail.appendString("\nFirst of Pair "+
tjc
committed
(thisSAMRecord.getFirstOfPairFlag() ? "yes" : "no"), Level.DEBUG);
tjc
committed
(thisSAMRecord.getMateUnmappedFlag() ? "yes" : "no"), Level.DEBUG);
tjc
committed
(thisSAMRecord.getProperPairFlag() ? "yes" : "no"), Level.DEBUG);
tjc
committed
viewDetail.appendString("\nRead Fails Vendor\nQuality Check "+
(thisSAMRecord.getReadFailsVendorQualityCheckFlag() ? "yes" : "no"), Level.DEBUG);
viewDetail.appendString("\nRead Unmapped "+
(thisSAMRecord.getReadUnmappedFlag() ? "yes" : "no"), Level.DEBUG);
if(thisSAMRecord.getReadPairedFlag())
viewDetail.appendString("\nSecond Of Pair "+
tjc
committed
(thisSAMRecord.getSecondOfPairFlag() ? "yes" : "no"), Level.DEBUG);
viewDetail.appendString("\n\nRead Bases:\n", Level.INFO);
viewDetail.appendString(new String(thisSAMRecord.getReadBases()), Level.DEBUG);
tjc
committed
}
protected SAMRecordFlagPredicate getSamRecordFlagPredicate()
{
return samRecordFlagPredicate;
}
protected void setSamRecordFlagPredicate(
SAMRecordFlagPredicate samRecordFlagPredicate)
{
laststart = -1;
lastend = -1;
this.samRecordFlagPredicate = samRecordFlagPredicate;
}
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;
if(args.length == 0 && BamFrame.isMac())
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e1) {}
if(args.length == 0)
{
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;
{
System.err.println("No files found.");
else if(!args[0].startsWith("-"))
{
for(int i=0; i< args.length; i++)
bam.add(args[i]);
}
int nbasesInView = 1000;
{
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);
}
else if(args[i].equals("-r"))
reference = args[++i];
else if(args[i].equals("-v"))
nbasesInView = Integer.parseInt(args[++i]);
else if(args[i].equals("-s"))
System.setProperty("samtoolDir", args[++i]);
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)");
System.out.println("-v\t number of bases to display in the view (optional)");
/*System.out.println("-s\t samtool directory");*/
final BamView view = new BamView(bam, reference, nbasesInView);
// translucent
//frame.getRootPane().putClientProperty("Window.alpha", new Float(0.9f));
frame.addWindowFocusListener(new WindowFocusListener()
{
public void windowGainedFocus(WindowEvent e)
{
view.requestFocus();
}
public void windowLostFocus(WindowEvent e){}
});
view.addJamToPanel((JPanel)frame.getContentPane(), frame, false, null);
view.jspView.getVerticalScrollBar().setValue(
view.jspView.getVerticalScrollBar().getMaximum());