Skip to content
Snippets Groups Projects
Commit df7ccbf5 authored by “kpepper”'s avatar “kpepper”
Browse files

Initial BAM View changes to fix selection issues, zooming into secondary...

Initial BAM View changes to fix selection issues, zooming into secondary alignments, erroneous collapsing of reads with same start/end position and display of SNPs - related to RT ticket 597652
parent 98746e43
Branches
Tags
No related merge requests found
......@@ -350,6 +350,9 @@
<jvmarg value="-Djava.awt.headless=true" />
<batchtest fork="yes" todir="${junit.reports.dir}">
<fileset dir="${evosuite.tests.src.dir}">
<!--include name="**/*BamView_ESTest.java" if="${do.run.evosuite.tests}" /-->
<include name="**/*_ESTest.java" if="${do.run.evosuite.tests}" />
<!-- Exclude classes that currently produce broken tests -->
......@@ -382,7 +385,7 @@
</target>
<!-- Create Jacoco reports -->
<target name="jacoco-coverage-report">
<target name="jacoco-coverage-report" depends="run-manual-tests">
<delete dir="${coverage.report.jacoco.dir}" />
<mkdir dir="${coverage.report.jacoco.dir}" />
......
......@@ -362,5 +362,28 @@ class BamUtils
}
return featureReadCount;
}
/**
* Check whether two SAM records are the same.
* @param bamRec1 SamViewRecord
* @param bamRec2 SamViewRecord
* @return boolean - true if equality holds.
*/
public static boolean samRecordEqualityCheck(SAMRecord rec1, SAMRecord rec2)
{
boolean result = false;
if (rec1 == null && rec2 == null)
return true;
result = (
(rec1.getReadName().equals(rec2.getReadName())) &&
(rec1.getAlignmentStart() == rec2.getAlignmentStart()) &&
(rec1.getAlignmentEnd() == rec2.getAlignmentEnd()) &&
(rec1.getFlags() == rec2.getFlags())
);
return result;
}
}
......@@ -220,6 +220,7 @@ public class BamView extends JPanel
private JCheckBoxMenuItem colourByCoverageColour = new JCheckBoxMenuItem("Coverage Plot Colours");
private JCheckBoxMenuItem baseQualityColour = new JCheckBoxMenuItem("Base Quality");
private JCheckBoxMenuItem markInsertions = new JCheckBoxMenuItem("Mark Insertions", true);
private AlphaComposite translucent =
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f);
......@@ -234,9 +235,11 @@ public class BamView extends JPanel
private static Color DARK_ORANGE = new Color(255,140,0);
private static Color DEEP_PINK = new Color(139,10,80);
private static Color NON_SELECTED_READ_HIGHLIGHT_COLOUR = new Color(189,103,107);
private Point lastMousePoint = null;
private BamViewRecord mouseOverSAMRecord = null;
private BamViewRecord highlightSAMRecord = null;
private volatile BamViewRecord mouseOverSAMRecord = null;
private volatile BamViewRecord highlightSAMRecord = null;
private String mouseOverInsertion;
// record of where a mouse drag starts
protected int dragStart = -1;
......@@ -1202,7 +1205,7 @@ public class BamView extends JPanel
int xpos;
int len = 0;
int refPos = 0;
final String readSeq = samRecord.getReadString();
SAMRecordSequenceString readSeq = new SAMRecordSequenceString(samRecord.getReadString());
final int offset = getSequenceOffset(samRecord.getReferenceName());
byte[] phredQuality = null;
......@@ -1222,12 +1225,15 @@ public class BamView extends JPanel
xpos = block.getReferenceStart() - 1 + j + offset;
refPos = xpos - refSeqStart + 1;
if(phredQuality != null)
if(phredQuality != null && phredQuality.length > 0)
setColourByBaseQuality(g2, phredQuality[readPos]);
if(isSNPs && refSeq != null && refPos > 0 && refPos < refSeq.length())
{
if(Character.toUpperCase(readSeq.charAt(readPos)) != refSeq.charAt(refPos))
if(
(!readSeq.isSecondaryAlignment()) &&
(Character.toUpperCase(readSeq.charAt(readPos)) != refSeq.charAt(refPos))
)
g2.setColor(Color.red);
else
g2.setColor(col);
......@@ -1266,15 +1272,26 @@ public class BamView extends JPanel
}
}
// highlight
if(highlightSAMRecord != null &&
highlightSAMRecord.sam.getReadName().equals(samRecord.getReadName()))
highlightSAMRecord.sam.getReadName().equals(bamViewRecord.sam.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.setColor(Color.red);
if (isThisBamRecordHighlighted(bamViewRecord) )
{
// Selected read alignment
g2.setColor(Color.black);
}
else
{
// For a read with the same name as selected one.
g2.setColor(NON_SELECTED_READ_HIGHLIGHT_COLOUR);
}
g2.drawRect(xstart, ypos-BASE_HEIGHT, width, BASE_HEIGHT);
if(i < blocks.size()-1)
{
......@@ -1494,8 +1511,6 @@ public class BamView extends JPanel
if(isOrientation)
ydiff= 2*ydiff;
int maxEnd = 0;
int lstStart = 0;
int lstEnd = 0;
final int baseAtStartOfView = getBaseAtStartOfView();
g2.setColor(Color.blue);
final Rectangle r = jspView.getViewport().getViewRect();
......@@ -1503,6 +1518,7 @@ public class BamView extends JPanel
for(BamViewRecord bamViewRecord: readsInView)
{
SAMRecord samRecord = bamViewRecord.sam;
int offset = getSequenceOffset(samRecord.getReferenceName());
int recordStart = samRecord.getAlignmentStart()+offset;
......@@ -1510,11 +1526,6 @@ public class BamView extends JPanel
List<Integer> snps = getSNPs(samRecord);
if(colourByCoverageColour.isSelected() ||
colourByStrandTag.isSelected() ||
colourByReadGrp.isSelected() ||
lstStart != recordStart || lstEnd != recordEnd || snps != null)
{
if(colourByStrandTag.isSelected())
{
if(samRecord.getAttribute("XS") == null)
......@@ -1530,6 +1541,8 @@ public class BamView extends JPanel
g2.setColor(getColourByCoverageColour(bamViewRecord));
else if(colourByReadGrp.isSelected())
g2.setColor(getReadGroupFrame().getReadGroupColour(readGroups, samRecord.getReadGroup()));
else if (samRecord.getDuplicateReadFlag())
g2.setColor(DARK_GREEN); // Duplicate
else if (!samRecord.getReadPairedFlag() || // read is not paired in sequencing
samRecord.getMateUnmappedFlag() ) // mate is unmapped ) // mate is unmapped
g2.setColor(Color.black);
......@@ -1543,20 +1556,10 @@ public class BamView extends JPanel
}
else
ypos = ypos-ydiff;
}
else
g2.setColor(DARK_GREEN);
if(snps != null)
lstStart = -1;
else
{
lstStart = recordStart;
lstEnd = recordEnd;
}
if(ypos > r.getMaxY() || ypos < r.getMinY())
continue;
drawRead(g2, bamViewRecord, pixPerBase, ypos, baseAtStartOfView, snps, ydiff);
}
}
......@@ -1614,8 +1617,6 @@ public class BamView extends JPanel
int hgt = getHeight();
int ypos = (hgt - scaleHeight);
int maxEnd = 0;
int lstStart = 0;
int lstEnd = 0;
int baseAtStartOfView = getBaseAtStartOfView();
g2.setColor(Color.blue);
Rectangle r = jspView.getViewport().getViewRect();
......@@ -1623,6 +1624,7 @@ public class BamView extends JPanel
for(BamViewRecord bamViewRecord: readsInView)
{
SAMRecord samRecord = bamViewRecord.sam;
if( isNegativeStrand(samRecord, colourByStrandTag.isSelected()) == isStrandNegative )
{
final int offset = getSequenceOffset(samRecord.getReferenceName());
......@@ -1630,11 +1632,6 @@ public class BamView extends JPanel
final int recordEnd = samRecord.getAlignmentEnd()+offset;
List<Integer> snps = getSNPs(samRecord);
if(colourByCoverageColour.isSelected() ||
colourByStrandTag.isSelected() ||
colourByReadGrp.isSelected() ||
lstStart != recordStart || lstEnd != recordEnd || snps != null)
{
if(colourByStrandTag.isSelected())
{
if(samRecord.getAttribute("XS") == null)
......@@ -1650,6 +1647,8 @@ public class BamView extends JPanel
g2.setColor(getColourByCoverageColour(bamViewRecord));
else if(colourByReadGrp.isSelected())
g2.setColor(getReadGroupFrame().getReadGroupColour(readGroups, samRecord.getReadGroup()));
else if (samRecord.getDuplicateReadFlag())
g2.setColor(DARK_GREEN); // Duplicate
else if (!samRecord.getReadPairedFlag() || // read is not paired in sequencing
samRecord.getMateUnmappedFlag() ) // mate is unmapped
g2.setColor(Color.black);
......@@ -1663,17 +1662,6 @@ public class BamView extends JPanel
}
else
ypos = ypos + ystep;
}
else
g2.setColor(DARK_GREEN);
if(snps != null)
lstStart = -1;
else
{
lstStart = recordStart;
lstEnd = recordEnd;
}
if(ypos > r.getMaxY() || ypos < r.getMinY())
continue;
......@@ -2142,13 +2130,25 @@ public class BamView extends JPanel
new BasicStroke (readLnHgt*1.6f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
g2.setStroke(stroke);
Color c = g2.getColor();
if (isThisBamRecordHighlighted(bamViewRecord) )
{
// Selected read alignment
g2.setColor(Color.black);
}
else
{
// For a read with the same name as selected one.
g2.setColor(NON_SELECTED_READ_HIGHLIGHT_COLOUR);
}
g2.drawLine((int)( thisStart * pixPerBase), ypos,
(int)( thisEnd * pixPerBase), ypos);
g2.setColor(c);
g2.setStroke(originalStroke);
}
if(thisRead.getCigar().getCigarElements().size() == 1)
g2.drawLine((int)( thisStart * pixPerBase), ypos,
(int)( thisEnd * pixPerBase), ypos);
......@@ -2182,15 +2182,17 @@ public class BamView extends JPanel
// test if the mouse is over this read
if(lastMousePoint != null)
{
if(lastMousePoint.getY()+2 > ypos && lastMousePoint.getY()-2 < ypos)
if(lastMousePoint.getY() > ypos-(Math.abs(ydiff)/2) && lastMousePoint.getY() < ypos+(Math.abs(ydiff)/2))
{
if(lastMousePoint.getX() > thisStart * pixPerBase &&
lastMousePoint.getX() < thisEnd * pixPerBase)
{
mouseOverSAMRecord = bamViewRecord;
}
}
}
if (isSNPs && snps != null)
if (isSNPs && snps != null && snps.size() > 0)
showSNPsOnReads(snps, g2, pixPerBase, ypos);
}
......@@ -2341,6 +2343,12 @@ public class BamView extends JPanel
new Range(rbeg+offset, rend+offset), Bases.FORWARD);
final byte[] readSeq = samRecord.getReadBases();
if (readSeq == null || readSeq.length == 0)
{
// Can occur for secondary alignments
return null;
}
offset = offset - getBaseAtStartOfView();
final List<AlignmentBlock> blocks = samRecord.getAlignmentBlocks();
for(AlignmentBlock block: blocks)
......@@ -2843,8 +2851,12 @@ public class BamView extends JPanel
colourMenu.add(baseQualityColour);
menu.add(colourMenu);
//
// =============
// Show Menu
// =============
JMenu showMenu = new JMenu("Show");
JCheckBoxMenuItem checkBoxOrientation = new JCheckBoxMenuItem("Orientation");
checkBoxOrientation.addActionListener(new ActionListener()
{
......@@ -3199,6 +3211,10 @@ public class BamView extends JPanel
if (buttonAutoHide.isSelected() && topPanel.isVisible())
topPanel.setVisible(false);
}
// KJP - added these to make selecting work properly.
mainPanel.repaint();
mainPanel.revalidate();
}
};
addMouseMotionListener(mouseMotionListener);
......@@ -3506,7 +3522,10 @@ public class BamView extends JPanel
if(event.getButton() == MouseEvent.BUTTON3 || bases == null)
return;
highlightSAMRecord = null;
// KJP: Removed this as it causes selection issues and
// doesn't seems strictly necessary.
// highlightSAMRecord = null;
if(event.getClickCount() > 1)
{
getSelection().clear();
......@@ -3906,18 +3925,30 @@ public class BamView extends JPanel
if(isCoverageView(getPixPerBaseByWidth()))
coverageView.singleClick(e.isShiftDown(),
e.getPoint().y-getJspView().getViewport().getViewPosition().y);
else
highlightSAMRecord = mouseOverSAMRecord;
//else
//{
// mouseHighlightSelectionMade.set(true);
// highlightSAMRecord = null;
//}
}
else
highlightRange(e, MouseEvent.BUTTON2_DOWN_MASK);
repaint();
//repaint();
}
public void mousePressed(MouseEvent e)
public void mousePressed(final MouseEvent e)
{
highlightSAMRecord = mouseOverSAMRecord;
repaint();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
maybeShowPopup(e);
}
});
}
public void mouseReleased(MouseEvent e)
{
......@@ -3988,6 +4019,9 @@ public class BamView extends JPanel
mouseOverSAMRecord.sam.getReadPairedFlag() &&
!mouseOverSAMRecord.sam.getMateUnmappedFlag() )
{
// KJP: new
highlightSAMRecord = mouseOverSAMRecord;
final BamViewRecord thisSAMRecord = mouseOverSAMRecord;
gotoMateMenuItem = new JMenuItem("Go to mate of : "+
thisSAMRecord.sam.getReadName());
......@@ -4015,6 +4049,9 @@ public class BamView extends JPanel
if( mouseOverSAMRecord != null)
{
// KJP: new
highlightSAMRecord = mouseOverSAMRecord;
final BamViewRecord thisSAMRecord = mouseOverSAMRecord;
showDetails = new JMenuItem("Show details of : "+
thisSAMRecord.sam.getReadName());
......@@ -4195,6 +4232,21 @@ public class BamView extends JPanel
return concatSequences;
}
/**
* Check whether the given BAM record is highlighted currently.
* @param bamRec BamViewRecord
* @return boolean - true if highlighted
*/
protected boolean isThisBamRecordHighlighted(BamViewRecord bamRec)
{
if (highlightSAMRecord == null)
{
return false;
}
return BamUtils.samRecordEqualityCheck(highlightSAMRecord.sam, bamRec.sam);
}
class PairedRead
{
BamViewRecord sam1;
......
package uk.ac.sanger.artemis.components.alignment;
/**
* Utility class that handles operations on an alignment block
* string taking into account the possibility that it could be
* a secondary alignment.
*
* @author kp11
*
*/
public class SAMRecordSequenceString
{
public final static char SECONDARY_ALIGNMENT_BASE_CHAR = '=';
public final static char SECONDARY_ALIGNMENT_MARKER = '*';
private String sequence;
private boolean isSecondaryAlignment;
public SAMRecordSequenceString(String sequence)
{
this.sequence = sequence;
this.isSecondaryAlignment = (String.valueOf(SECONDARY_ALIGNMENT_MARKER).equals(sequence));
}
public String substring(int beginIdx, int endIdx)
{
String result = null;
if (!isSecondaryAlignment())
{
result = sequence.substring(beginIdx, endIdx);
}
else
{
result = new String(new char[endIdx-beginIdx]).replace('\0', SECONDARY_ALIGNMENT_BASE_CHAR);
}
return result;
}
public char charAt(int idx)
{
char result;
if (!isSecondaryAlignment())
{
result = sequence.charAt(idx);
}
else
{
result = SECONDARY_ALIGNMENT_BASE_CHAR;
}
return result;
}
public String getSequence()
{
return sequence;
}
public int length()
{
return sequence.length();
}
public boolean isSecondaryAlignment() {
return isSecondaryAlignment;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment