Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/org/igv/sam/AlignmentDataManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ AlignmentInterval loadInterval(String chr, int start, int end, AlignmentTrack.Re
SpliceJunctionHelper spliceJunctionHelper = new SpliceJunctionHelper();

AlignmentTileLoader.AlignmentTile t = getLoader().loadTile(seqName, start, end, spliceJunctionHelper,
downsampleOptions, peStats, bisulfiteContext, renderOptions);
downsampleOptions, peStats, bisulfiteContext, renderOptions, getPreferences());
List<Alignment> alignments = t.getAlignments();
List<DownsampledInterval> downsampledIntervals = t.getDownsampledIntervals();
this.updateBaseModfications(alignments);
Expand Down
34 changes: 17 additions & 17 deletions src/main/java/org/igv/sam/AlignmentTileLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@

import htsjdk.samtools.SAMFileHeader;
import htsjdk.samtools.util.CloseableIterator;
import org.igv.event.IGVEvent;
import org.igv.logging.*;
import org.igv.Globals;
import org.igv.event.IGVEvent;
import org.igv.event.IGVEventBus;
import org.igv.event.IGVEventObserver;
import org.igv.event.StopEvent;
import org.igv.logging.LogManager;
import org.igv.logging.Logger;
import org.igv.prefs.IGVPreferences;
import org.igv.prefs.PreferencesManager;
import org.igv.sam.reader.AlignmentReader;
import org.igv.sam.reader.ReadGroupFilter;
import org.igv.ui.IGV;
import org.igv.event.IGVEventBus;
import org.igv.event.IGVEventObserver;
import org.igv.event.StopEvent;
import org.igv.ui.util.MessageUtils;
import org.igv.util.ObjectCache;
import org.igv.util.RuntimeUtils;
Expand Down Expand Up @@ -100,21 +101,21 @@ AlignmentTile loadTile(String chr,
AlignmentDataManager.DownsampleOptions downsampleOptions,
Map<String, PEStats> peStats,
AlignmentTrack.BisulfiteContext bisulfiteContext,
AlignmentTrack.RenderOptions renderOptions) {
AlignmentTrack.RenderOptions renderOptions,
IGVPreferences preferences) {

final IGVPreferences prefMgr = PreferencesManager.getPreferences();
boolean filterFailedReads = prefMgr.getAsBoolean(SAM_FILTER_FAILED_READS);
boolean filterSecondaryAlignments = prefMgr.getAsBoolean(SAM_FILTER_SECONDARY_ALIGNMENTS);
boolean filterSupplementaryAlignments = prefMgr.getAsBoolean(SAM_FILTER_SUPPLEMENTARY_ALIGNMENTS);
boolean filterFailedReads = preferences.getAsBoolean(SAM_FILTER_FAILED_READS);
boolean filterSecondaryAlignments = preferences.getAsBoolean(SAM_FILTER_SECONDARY_ALIGNMENTS);
boolean filterSupplementaryAlignments = preferences.getAsBoolean(SAM_FILTER_SUPPLEMENTARY_ALIGNMENTS);
ReadGroupFilter filter = ReadGroupFilter.getFilter();
boolean filterDuplicates = renderOptions != null
? renderOptions.getDuplicatesOption() == AlignmentTrack.DuplicatesOption.FILTER
: prefMgr.getAsBoolean(SAM_FILTER_DUPLICATES);
: preferences.getAsBoolean(SAM_FILTER_DUPLICATES);

int qualityThreshold = prefMgr.getAsInt(SAM_QUALITY_THRESHOLD);
int alignmentScoreTheshold = prefMgr.getAsInt(SAM_ALIGNMENT_SCORE_THRESHOLD);
int qualityThreshold = preferences.getAsInt(SAM_QUALITY_THRESHOLD);
int alignmentScoreTheshold = preferences.getAsInt(SAM_ALIGNMENT_SCORE_THRESHOLD);

boolean reducedMemory = prefMgr.getAsBoolean(SAM_REDUCED_MEMORY_MODE);
boolean reducedMemory = preferences.getAsBoolean(SAM_REDUCED_MEMORY_MODE);

AlignmentTile t = new AlignmentTile(start, end, spliceJunctionHelper, downsampleOptions, bisulfiteContext, reducedMemory);

Expand Down Expand Up @@ -254,8 +255,8 @@ AlignmentTile loadTile(String chr,
// Compute peStats
if (peStats != null) {
// TODO -- something smarter re the percentiles. For small samples these will revert to min and max
double minPercentile = prefMgr.getAsFloat(SAM_MIN_INSERT_SIZE_PERCENTILE);
double maxPercentile = prefMgr.getAsFloat(SAM_MAX_INSERT_SIZE_PERCENTILE);
double minPercentile = preferences.getAsFloat(SAM_MIN_INSERT_SIZE_PERCENTILE);
double maxPercentile = preferences.getAsFloat(SAM_MAX_INSERT_SIZE_PERCENTILE);
for (PEStats stats : peStats.values()) {
stats.computeInsertSize(minPercentile, maxPercentile);
stats.computeExpectedOrientation();
Expand All @@ -274,7 +275,6 @@ AlignmentTile loadTile(String chr,
}
t.finish();

// TODO -- make this optional (on a preference)
InsertionManager.getInstance().processAlignments(chr, t.alignments);


Expand Down
18 changes: 18 additions & 0 deletions src/main/java/org/igv/sam/AlignmentTrackMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,27 @@ class AlignmentTrackMenu extends IGVPopupMenu {
}
renderOptions.setHideSmallIndels(smallIndelsItem.isSelected());
alignmentTrack.repaint();
IGV.getInstance().repaintHeaderPanels();
}));
add(smallIndelsItem);

// Indel size setting
JMenuItem indelSizeItem = new JMenuItem("Set indel size threshold...");
indelSizeItem.setEnabled(renderOptions.isHideSmallIndels());
indelSizeItem.addActionListener(aEvt -> UIUtilities.invokeOnEventThread(() -> {
String sith = MessageUtils.showInputDialog("Small indel threshold: ", String.valueOf(renderOptions.getSmallIndelThreshold()));
if (sith != null) {
try {
renderOptions.setSmallIndelThreshold(Integer.parseInt(sith));
alignmentTrack.repaint();
IGV.getInstance().repaintHeaderPanels();
} catch (NumberFormatException exc) {
log.error("Error setting small indel threshold - not an integer", exc);
}
}
}));
add(indelSizeItem);

// Paired end items
if (dataManager.isPairedEnd()) {
addSeparator();
Expand Down
7 changes: 0 additions & 7 deletions src/main/java/org/igv/sam/InsertionManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,10 @@ public synchronized void processAlignments(String chr, List<Alignment> alignment
insertionMaps.put(chr, insertionMap);
}

int minLength = 0;
final IGVPreferences preferences = PreferencesManager.getPreferences(Constants.THIRD_GEN);
if(preferences.getAsBoolean(SAM_HIDE_SMALL_INDEL)) {
minLength = preferences.getAsInt(SAM_SMALL_INDEL_BP_THRESHOLD);
}

for (Alignment a : alignments) {
AlignmentBlock[] blocks = a.getInsertions();
if (blocks != null) {
for (AlignmentBlock block : blocks) {
if (block.getBasesLength() < minLength) continue;
Integer key = block.getStart();
InsertionMarker insertionMarker = insertionMap.get(key);
if (insertionMarker == null) {
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/org/igv/ui/IGV.java
Original file line number Diff line number Diff line change
Expand Up @@ -1767,7 +1767,6 @@ private static void startCommandsServer(Main.IGVArgs igvArgs, IGVPreferences pre
}
}


/**
* Swing worker class to startup IGV
*/
Expand Down Expand Up @@ -2157,6 +2156,15 @@ public void repaint(Track track) {
}
}

/**
* Repaint all header panels. Used to force update of insertion markers.
*/
public void repaintHeaderPanels() {
getMainPanel().repaintHeaderPanels();
}




private volatile boolean isLoading = false;
private Set<Track> pendingTracks = null;
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/org/igv/ui/panel/MainPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -577,5 +577,9 @@ public int getSnapshotHeight(boolean batch) {
}
}

public void repaintHeaderPanels() {
headerPanelContainer.repaint();
}


}
64 changes: 49 additions & 15 deletions src/main/java/org/igv/ui/panel/RulerPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
*/
package org.igv.ui.panel;

import org.igv.logging.*;
import org.igv.Globals;
import org.igv.feature.Chromosome;
import org.igv.feature.genome.ChromosomeCoordinate;
import org.igv.feature.genome.Genome;
import org.igv.feature.genome.GenomeManager;
import org.igv.logging.LogManager;
import org.igv.logging.Logger;
import org.igv.prefs.PreferencesManager;
import org.igv.sam.AlignmentTrack;
import org.igv.sam.InsertionManager;
Expand All @@ -35,7 +36,7 @@
import java.util.List;
import java.util.function.Consumer;

import static org.igv.prefs.Constants.*;
import static org.igv.prefs.Constants.DEFAULT_GENOME;

/**
* @author jrobinso
Expand All @@ -48,28 +49,31 @@ public class RulerPanel extends JPanel {
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat();

private static final int INSERTION_ROW_HEIGHT = 9;

public static final String WHOLE_GENOME_TOOLTIP = "<html>Click on a chromosome number to jump to that chromosome," +
"<br>or click and drag to zoom in.";

public static final String CHROM_TOOLTIP = "Click and drag to zoom in.";

private final boolean darkMode;

// TODO -- get from preferences
boolean drawSpan = true;
private Font tickFont = FontManager.getFont(10);
private Font spanFont = FontManager.getFont(Font.BOLD, 12);

private boolean showInsertions = false;
private List<ClickLink> clickLinks = new ArrayList();

private static Color dragColor = new Color(.5f, .5f, 1f, .3f);
private static Color zoomBoundColor = new Color(0.5f, 0.5f, 0.5f);

private Color expandedInsertionColor = Color.BLUE;
private Color collapsedInsertionColor = Color.BLACK;
private Color zoomedoutInsertionColor = ColorUtilities.modifyAlpha(Color.LIGHT_GRAY, 50);
private Color expandedInsertionColor = Globals.isDarkMode() ? Color.BLUE.brighter() : Color.BLUE;
private Color collapsedInsertionColor = Globals.isDarkMode() ? Color.WHITE : Color.BLACK;
private Color zoomedoutInsertionColor = Globals.isDarkMode() ? Color.darkGray : ColorUtilities.modifyAlpha(collapsedInsertionColor, 20);

boolean dragging = false;
int dragStart;
int dragEnd;
public static final String WHOLE_GENOME_TOOLTIP = "<html>Click on a chromosome number to jump to that chromosome," +
"<br>or click and drag to zoom in.";
public static final String CHROM_TOOLTIP = "Click and drag to zoom in.";

ReferenceFrame frame;

Expand All @@ -88,7 +92,7 @@ protected void paintComponent(Graphics g) {

super.paintComponent(g);

if(darkMode) {
if (darkMode) {
setBackground(UIManager.getColor("Panel.background"));
expandedInsertionColor = Color.CYAN;
collapsedInsertionColor = Color.WHITE;
Expand Down Expand Up @@ -132,7 +136,10 @@ private void render(Graphics g) {
Collection<AlignmentTrack> tracks = IGV.getInstance().getAlignmentTracks();
int maxVizWindow = tracks.size() == 0 ? 0 : tracks.stream().mapToInt(t -> t.getVisibilityWindow()).max().getAsInt();
if (!frame.getChrName().equals(Globals.CHR_ALL) && (frame.getEnd() - frame.getOrigin()) <= maxVizWindow) {
showInsertions = true;
drawInsertionMarkers(g);
} else {
showInsertions = false;
}
}
}
Expand Down Expand Up @@ -300,13 +307,24 @@ private void drawInsertionMarkers(Graphics g) {

if (insertionMarkers == null) return;

int minLength = Integer.MAX_VALUE;
boolean hideSmallIndels = false;
for (AlignmentTrack track : IGV.getInstance().getAlignmentTracks()) {
hideSmallIndels = hideSmallIndels || track.getRenderOptions().isHideSmallIndels();
minLength = Math.min(minLength, track.getRenderOptions().getSmallIndelThreshold());
}

InsertionMarker expanded = frame.getExpandedInsertion();

int w = (int) ((1.41 * INSERTION_ROW_HEIGHT) / 2);
int y = getHeight() - INSERTION_ROW_HEIGHT - 1;

for (InsertionMarker insertionMarker : insertionMarkers) {

if (hideSmallIndels && insertionMarker.size < minLength) {
continue;
}

int x0;
int x1;
Polygon p;
Expand All @@ -332,9 +350,10 @@ private void drawInsertionMarkers(Graphics g) {
p = new Polygon(new int[]{x0 - w, x1 + w, x0},
new int[]{y, y, y + INSERTION_ROW_HEIGHT}, 3);


double expandedInsertionWidth = insertionMarker.size / frame.getScale();

if (expandedInsertionWidth > 5) {
if (expandedInsertionWidth > 1) {
c = collapsedInsertionColor;
String tooltipText = "Click to expand insertion (" + (insertionMarker.size + "bases)");
Rectangle clickArea = p.getBounds();
Expand All @@ -349,7 +368,7 @@ private void drawInsertionMarkers(Graphics g) {
}
}

if (x1 + w >= 0 && x0 - w <= getWidth()) {
if (x1 + w >= 0 && x0 - w <= getWidth() && c != null) {
g.setColor(c);
g.fillPolygon(p);
}
Expand Down Expand Up @@ -419,9 +438,12 @@ public void mouseMoved(MouseEvent e) {
return;
}
}
if(inInsertionArea(e)) {
// In insertion area
return;
}
setCursor(Cursor.getDefaultCursor());
setToolTipText(isWholeGenomeView() ? WHOLE_GENOME_TOOLTIP : CHROM_TOOLTIP);

}

@Override
Expand All @@ -437,6 +459,9 @@ public void mouseEntered(MouseEvent e) {

@Override
public void mouseDragged(MouseEvent e) {
if(inInsertionArea(e)) {
return;
}
if (Math.abs(e.getPoint().getX() - dragStart) > 1) {
dragEnd = e.getX();
dragging = true;
Expand All @@ -449,12 +474,13 @@ public void mousePressed(final MouseEvent e) {
if (e.isPopupTrigger()) {
// ignore
} else {
dragStart = e.getX();
if(!inInsertionArea(e)){
dragStart = e.getX();
}
mouseDown = e;
}
}


@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
Expand All @@ -472,6 +498,10 @@ public void mouseReleased(MouseEvent e) {
}
}

private boolean inInsertionArea(MouseEvent e) {
return showInsertions && e.getY() >= getHeight() - INSERTION_ROW_HEIGHT - 1;
}

private double distance(MouseEvent e1, MouseEvent e2) {
double dx = e1.getX() - e2.getX();
double dy = e1.getY() - e2.getY();
Expand All @@ -497,6 +527,10 @@ public void doMouseClick(MouseEvent evt) {
clickHandled = true;
}
}
if(showInsertions && e.getY() >= getHeight() - INSERTION_ROW_HEIGHT) {
// In insertion area
return;
}
if (!clickHandled && !isWholeGenomeView()) {
double newLocation = frame.getChromosomePosition(e);
frame.centerOnLocation(newLocation);
Expand Down
5 changes: 4 additions & 1 deletion src/test/java/org/igv/sam/AlignmentTileLoaderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.igv.AbstractHeadlessTest;
import org.igv.prefs.Constants;
import org.igv.prefs.IGVPreferences;
import org.igv.prefs.PreferencesManager;
import org.igv.sam.reader.AlignmentReader;
import org.igv.sam.reader.AlignmentReaderFactory;
Expand Down Expand Up @@ -79,7 +80,9 @@ private AlignmentTileLoader.AlignmentTile tstKeepPairsDownsample(String path, St

AlignmentDataManager.DownsampleOptions downsampleOptions = new AlignmentDataManager.DownsampleOptions(true, 50, actMaxDepth);

AlignmentTileLoader.AlignmentTile tile = loader.loadTile(sequence, start, end, null, downsampleOptions, null, null, null);
IGVPreferences preferences = new IGVPreferences();
AlignmentTileLoader.AlignmentTile tile = loader.loadTile(sequence, start, end, null,
downsampleOptions, null, null, null, preferences);
List<Alignment> alignments = tile.getAlignments();
int count = 0;
Map<String, Integer> pairedReads = new HashMap<String, Integer>();
Expand Down
Loading