Skip to content

Commit

Permalink
Interaction track improvements (#1635)
Browse files Browse the repository at this point in the history
* Reduce alpha from 0.05 to 0.02 for proportional arcs consistent with igv.js
* Add options to filter arcs with one or both ends out of view
  • Loading branch information
jrobinso authored Jan 5, 2025
1 parent 3a9ef80 commit bc00717
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/main/java/org/broad/igv/bedpe/BedPERenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
import java.util.List;

public interface BedPERenderer {
void render(List<BedPE> features, RenderContext context, Rectangle trackRectangle);
void render(List<BedPE> features, RenderContext context, Rectangle trackRectangle, InteractionTrack.ArcOption arcOption);
}
33 changes: 31 additions & 2 deletions src/main/java/org/broad/igv/bedpe/InteractionTrack.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,12 @@ enum Direction {UP, DOWN}

enum GraphType {BLOCK, NESTED_ARC, PROPORTIONAL_ARC}

enum ArcOption {ALL, ONE_END, BOTH_ENDS}

private Genome genome;
InteractionTrack.Direction direction = UP; //DOWN;
GraphType graphType; // GraphType.block; //
private ArcOption arcOption = ArcOption.ALL;
int thickness = 1;
boolean autoscale = true;
double maxScore = -1;
Expand Down Expand Up @@ -183,10 +186,10 @@ public void render(RenderContext context, Rectangle trackRectangle) {
drawScale(context, trackRectangle);
}

renderers.get(graphType).render(features, context, trackRectangle);
renderers.get(graphType).render(features, context, trackRectangle, this.arcOption);
}
if (showBlocks) {
renderers.get(GraphType.BLOCK).render(features, context, trackRectangle);
renderers.get(GraphType.BLOCK).render(features, context, trackRectangle, this.arcOption);
}

} finally {
Expand Down Expand Up @@ -291,6 +294,26 @@ public IGVPopupMenu getPopupMenu(TrackClickEvent te) {
menu.add(mm);
}

menu.addSeparator();
menu.add(new JLabel("<html><b>Arcs</b>"));
ButtonGroup group2 = new ButtonGroup();
Map<String, ArcOption> modes2 = new LinkedHashMap<>(4);
modes2.put("All", ArcOption.ALL);
modes2.put("One End In View", ArcOption.ONE_END);
modes2.put("Both Ends In View", ArcOption.BOTH_ENDS);
//modes.put("Blocks", GraphType.BLOCK);

for (final Map.Entry<String, ArcOption> entry : modes2.entrySet()) {
JRadioButtonMenuItem mm = new JRadioButtonMenuItem(entry.getKey());
mm.setSelected(InteractionTrack.this.arcOption == entry.getValue());
mm.addActionListener(evt -> {
InteractionTrack.this.arcOption = (entry.getValue());
repaint();
});
group2.add(mm);
menu.add(mm);
}

menu.addSeparator();
JCheckBoxMenuItem showBlocksCB = new JCheckBoxMenuItem("Show Blocks");
showBlocksCB.setSelected(showBlocks);
Expand Down Expand Up @@ -420,6 +443,7 @@ public void marshalXML(Document document, Element element) {
element.setAttribute("direction", String.valueOf(direction));
element.setAttribute("thickness", String.valueOf(thickness));
element.setAttribute("graphType", String.valueOf(graphType));
element.setAttribute("arcOption", String.valueOf(arcOption));
element.setAttribute("showBlocks", String.valueOf(showBlocks));
element.setAttribute("autoscale", String.valueOf(autoscale));
if (!autoscale) {
Expand All @@ -433,6 +457,10 @@ public void unmarshalXML(Element element, Integer version) {

super.unmarshalXML(element, version);

if (element.hasAttribute("arcOption")) {
String typeString = element.getAttribute("arcOption").toUpperCase();
this.arcOption = ArcOption.valueOf(typeString);
}
if (element.hasAttribute("direction"))
this.direction = Direction.valueOf(element.getAttribute("direction"));
if (element.hasAttribute("thickness"))
Expand Down Expand Up @@ -555,4 +583,5 @@ private List<BedPEFeature> downsampleWGFeatures(List<BedPEFeature> features) {

return sampledFeatures;
}

}
9 changes: 8 additions & 1 deletion src/main/java/org/broad/igv/bedpe/NestedArcRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public NestedArcRenderer(InteractionTrack track) {
this.track = track;
}

public void render(List<BedPE> features, RenderContext context, Rectangle trackRectangle) {
public void render(List<BedPE> features, RenderContext context, Rectangle trackRectangle, InteractionTrack.ArcOption arcOption) {

Graphics2D g = null;

Expand Down Expand Up @@ -76,6 +76,13 @@ public void render(List<BedPE> features, RenderContext context, Rectangle trackR
double pixelStart = (feature.getMidStart() - origin) / locScale;
double pixelEnd = (feature.getMidEnd() - origin) / locScale;

// Optionally filter arcs with one or both ends out of view
if(arcOption == InteractionTrack.ArcOption.ONE_END) {
if(pixelStart < trackRectangle.x && pixelEnd > trackRectangle.x + trackRectangle.width) continue;
} else if(arcOption == InteractionTrack.ArcOption.BOTH_ENDS) {
if(pixelStart < trackRectangle.x || pixelEnd > trackRectangle.x + trackRectangle.width) continue;
}

int w = (int) (pixelEnd - pixelStart);
if (w < 3) {
w = 3;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/broad/igv/bedpe/PEBlockRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public PEBlockRenderer(InteractionTrack track) {
}

@Override
public void render(List<BedPE> features, RenderContext context, Rectangle trackRectangle) {
public void render(List<BedPE> features, RenderContext context, Rectangle trackRectangle, InteractionTrack.ArcOption arcOption) {

Graphics2D g = null;

Expand Down
18 changes: 12 additions & 6 deletions src/main/java/org/broad/igv/bedpe/ProportionalArcRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
public class ProportionalArcRenderer implements BedPERenderer {


public static final float PROP_ALPHA = 0.02f;
private Map<Color, Color> alphaColors = new HashMap<>();

InteractionTrack track;
Expand All @@ -21,7 +22,7 @@ public ProportionalArcRenderer(InteractionTrack track) {
this.track = track;
}

public void render(List<BedPE> features, RenderContext context, Rectangle trackRectangle) {
public void render(List<BedPE> features, RenderContext context, Rectangle trackRectangle, InteractionTrack.ArcOption arcOption) {

Graphics2D g = null;

Expand All @@ -46,8 +47,6 @@ public void render(List<BedPE> features, RenderContext context, Rectangle trackR
int gap = track.gap;
int h = trackRectangle.height - gap;



if (track.maxScore > 0 && bedPE.getScore() > 0) {
double logMax = Math.log10(track.maxScore + 1);
h = (int) ((Math.log10(bedPE.getScore() + 1) / logMax) * h);
Expand All @@ -56,21 +55,28 @@ public void render(List<BedPE> features, RenderContext context, Rectangle trackR
if (bedPE.isSameChr()) {

BedPEFeature feature = bedPE.get();

Color fcolor = feature.color == null ? trackColor : feature.color;
if (fcolor != null) {
g.setColor(fcolor);
}

double pixelStart = (feature.getMidStart() - origin) / locScale;
double pixelEnd = (feature.getMidEnd() - origin) / locScale;

// Optionally filter arcs with one or both ends out of view
if(arcOption == InteractionTrack.ArcOption.ONE_END) {
if(pixelStart < trackRectangle.x && pixelEnd > trackRectangle.x + trackRectangle.width) continue;
} else if(arcOption == InteractionTrack.ArcOption.BOTH_ENDS) {
if(pixelStart < trackRectangle.x || pixelEnd > trackRectangle.x + trackRectangle.width) continue;
}

int w = (int) (pixelEnd - pixelStart);
if (w < 3) {
w = 3;
pixelStart--;
}



double y = direction == UP ? gap + trackRectangle.y + trackRectangle.height - h : gap + trackRectangle.y - h;
int angleSt = direction == UP ? 0 : 180;
Arc2D.Double arcPath = new Arc2D.Double(
Expand All @@ -84,7 +90,7 @@ public void render(List<BedPE> features, RenderContext context, Rectangle trackR
);

g.draw(arcPath);
Color shadedColor = getAlphaColor(fcolor, 0.05f);
Color shadedColor = getAlphaColor(fcolor, PROP_ALPHA);
g.setColor(shadedColor);
g.fill(arcPath);

Expand Down

0 comments on commit bc00717

Please sign in to comment.