Skip to content

Instantly share code, notes, and snippets.

@lairdm
Last active March 12, 2021 20:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lairdm/6a770c94c6793eee660d to your computer and use it in GitHub Desktop.
Save lairdm/6a770c94c6793eee660d to your computer and use it in GitHub Desktop.
GenomeD3 Circular Plot Demo

A basic circular plot demo.

Some basic functionality of GenomeD3Plot is shown for a circular plot, tracks can be added/removed via the checkboxes, and resizing of the plot is enabled via a button and the dragbar in the lower right corner of the plot.

A demo of the linear plot can be found at this gist.

A demo of the circular and linear plots with their panning features linked together can be found at this gist.

Track definitions are imported via a separate json file

All the dependant libraries can be see at a separate shared Gist

// Sample routines to initialize the plot for rendering
// and add some basic functionality.
// Initialize the defaults for the chart such as
// the genome size, the div container to put the
// SVG object in, what function to call during a
// double click and the initial chart size.
var genomesize = 6264404;
var circularlayout = {genomesize: genomesize,
container: "#circularchart",
dblclick: "doubleClick",
w: 550, h: 550
};
// The actual initialization call which takes two
// parameters, the layout (above) for the plot and
// the dataset to visualize (from data.js, a json
// data structure)
var cTrack = new circularTrack(circularlayout, tracks);
// If we're showing both a circular and linear chart,
// and have a linear brush, attach it (see combo plot demo)
if('undefined' !== typeof linearTrack) {
console.log("Attaching linear track");
cTrack.attachBrush(linearTrack);
cTrack.showBrush();
}
if('undefined' !== typeof brush) {
console.log("Attaching linear track brush");
cTrack.attachBrush(brush);
}
// Now some callbacks to make the interactive functionality work.
// Attached to the onchange callback for the GC Plot checkbox,
// call the plot to add/remove the GC Plot as needed
function updateGC(cb) {
if(cb.checked) {
cTrack.showTrack("gcplot");
} else {
cTrack.hideTrack("gcplot");
}
}
// Attached to strand track checkbox, call the plot to
// add/remove the inner stranded track
function updateStrand(cb) {
if(cb.checked) {
cTrack.showTrack("track1");
} else {
cTrack.hideTrack("track1");
}
}
// Attached to the contig gap checkbox, call the plot to
// add/remove the contig gap squiggles
function updateGaps(cb) {
if(cb.checked) {
cTrack.showTrack("gapTrack");
} else {
cTrack.hideTrack("gapTrack");
}
}
// Attached to the ADB glyph checkbox, call the plot to
// add/remove only the ADB type of glyph
function updateAdb(cb) {
if(cb.checked) {
cTrack.showGlyphTrackType("track5", "adb");
} else {
cTrack.hideGlyphTrackType("track5", "adb");
}
}
// Attached to the resize plot button, call the plot to
// resize the plot to 650px diameter
function resizePlot() {
cTrack.resize(650);
}
function saveImage() {
cTrack.savePlot(4.0, "islandviewer.png", "tracks.css", 'png');
}
// Demo of the hover over timer, we had to
// do it this way to get around IE <9 not supporting
// parameters to the function called by setTimeout()
//
// If you have over an island, the console log will
// display the callback parameters when the timer expires
//
// The callback for hover (along with click) are defined in
// the data definition for each track in the dataset (data.js)
var timer;
var d_callback;
function islandPopup(d) {
d_callback = d;
timer = setTimeout(function() {console.log(d_callback);}, 1000);
}
function islandPopupClear(d) {
clearTimeout(timer);
}
// Callback defined at the top of this file, for
// double clicks on the plot
function doubleClick(plotid, bp) {
// If we have an attached linear plot, we're going
// to refocus the zoomed area, otherwise we'll just
// alert the user that a double click happened
if('undefined' !== typeof linearTrack) {
var halfBP = (cTrack.brushEndBP - cTrack.brushStartBP) /2;
var newStart = Math.max(0, (bp - halfBP));
var newEnd = Math.min(genomesize, (bp + halfBP));
console.log("Moving zoom area to: " + newStart + ", " + newEnd);
cTrack.moveBrushbyBP(newStart,
newEnd);
linearTrack.update(newStart, newEnd);
} else {
alert("Double click! From " + plotid + " at " + bp + " bp" )
console.log("double click!");
console.log(plotid);
console.log(bp);
}
}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>GenomeD3Plot Circularplot Example</title>
<script src="/lairdm/raw/bdd7410698e06970a9ff/d3.min.js"></script>
<script src="/lairdm/raw/bdd7410698e06970a9ff/d3-tip.js"></script>
<style>
body {
overflow: hidden;
margin: 0;
font-size: 14px;
font-family: "Helvetica Neue", Helvetica;
}
#circularchart {
position: absolute;
top: 0px;
left: 125px;
}
</style>
<link href="tracks.css" rel="stylesheet">
</head>
<body>
<div id="plotbody">
<!-- The container that will hold the SVG of the plot -->
<div id="circularchart"></div>
</div>
<!-- Libraries needed for save feature -->
<script type="text/javascript" src="/lairdm/raw/bdd7410698e06970a9ff/rgbcolor.js"></script>
<script type="text/javascript" src="/lairdm/raw/bdd7410698e06970a9ff/canvg.js"></script>
<script type="text/javascript" src="/lairdm/raw/bdd7410698e06970a9ff/FileSaver.js"></script>
<!-- Sample data to be rendered -->
<script type="text/javascript" src="/lairdm/raw/bdd7410698e06970a9ff/data.simple.js"></script>
<!-- Circular plot library -->
<script type="text/javascript" src="/lairdm/raw/bdd7410698e06970a9ff/circularplot.js"></script>
<!-- Initialization code to initialize the plot, this is what you would write
and place in your application. -->
<script type="text/javascript" src="circularsample.js"></script>
<!-- Controls on the demo -->
<div id="demo-controls">
<div class="control-item"><input type="checkbox" name="showGC" onchange="updateGC(this); return false" checked>Show GC plot</div>
<div class="control-item"><input type="checkbox" name="showStrand" onchange="updateStrand(this); return false" checked>Show stranded track</div>
<div class="control-item"><input type="checkbox" name="showvfdb" onchange="updateAdb(this); return false" checked>Show ADB glyph type</div>
<div class="control-item"><input type="checkbox" name="showgaps" onchange="updateGaps(this); return false" checked>Show contig gap region type</div>
<div class="control-item"><button name="saveImage" onclick="saveImage(); return false">Save Image</button></div>
<div class="control-item"><input type="button" onClick="resizePlot(); return false;" value="Resize plot diameter"></button></div>
</div>
<script type="text/javascript">
// Hack to make this example display correctly in an iframe on bl.ocks.org
d3.select(self.frameElement).style("height", "650px");
</script>
</body>
</html>
/* Classes for the demo's controls */
#demo-controls {
padding: 10px;
}
.control-item {
padding: 5px;
}
/* Render the chart as cleanly as possible */
#circularchart {
shape-rendering: geometricPrecision;
}
/* Text on the demo */
.mini text {
font: 9px sans-serif;
}
.main text {
font: 12px sans-serif;
}
/* Definitions for the plot resize dragger, and
resizing shadow */
.dragbar-line {
stroke-width: 1;
stroke: lightgrey;
pointer-events: inherit;
}
.dragbar-shadow {
stroke-width: 1;
stroke: lightgrey;
fill: transparent;
}
/* Style for the plot move arrow if active */
.move-cross {
stroke-width: 1;
stroke: lightgrey;
fill: lightgrey;
cursor:move;
}
.move-shadow {
cursor:move !important;
}
/* For resizing the linear chart */
#linearchart {
cursor: -webkit-grab; cursor: -moz-grab;
}
#linearchart:active {
cursor: -webkit-grabbing; cursor: -moz-grabbing;
}
.mainTrack {
cursor: pointer;
cursor: hand;
}
/* Definitions for first stranded track, colour, stroke */
.track1_pos {
fill: darksalmon;
stroke: #d1876d;
stroke-opacity: 0.8;
stroke-width: 1;
}
.track1_neg {
fill: #FFCC00;
fill-opacity: .7;
/*stroke-width: 1;
stroke: #4c602a;*/
}
/* In a linear track if an intergenic
region is defined, give it a colour */
.track1_none {
fill: #cccccc;
fill-opacity: .7;
stroke-width: 1;
}
/* And we want to show the user as they hover
over a track, change the colour */
.track1_pos:hover {
fill: red;
stroke-width: 1;
stroke: 1;
}
.track1_neg:hover {
fill: red;
fill-opacity: .9;
stroke-width: 1;
stroke: red;
}
/* In a linear track, if there are regulatory
elements such as transcription factors and
terminators, give them a colour for the stroke */
.track1_arrow_pos, .track1_arrow_neg, .track3_arrow {
stroke-width: 1;
stroke: black;
}
/* Labels on the linear track */
.track1_text {
fill: white;
font-weight: bold;
font: 12px arial;
}
/* Track 2 is also a stranded track, give it
a different set of colours */
.track2_pos {
fill: #000099;
fill-opacity: .7;
}
/* When a linear track is zoomed to the point
it's text is visible an extra class is added
to the element we can hook in to */
.track2_pos_zoomed {
stroke-width: 1px;
stroke: #647381;
}
.track2_neg {
fill: #006600;
fill-opacity: .7;
}
.track2_neg_zoomed {
stroke-width: 1px;
stroke: #007300;
stroke-opacity: 0.7;
}
.track2_text {
fill: white;
font-weight: bold;
font: 12px arial;
}
/* Track 3 is a non-stranded track, so no _pos
and _neg modifiers on the classes */
.track3 {
fill: #3399FF;
fill-opacity: .7;
}
.track3:hover {
fill: blue;
fill-opacity: .9;
}
.track3_text {
fill: white;
font-weight: bold;
font: 12px arial;
}
/* The GC Plot type track, give the stroke a colour */
.gcplot {
stroke: black;
}
/* Track 5 is the glyphs, classes of a concatenation
of the track name and the type of glyph in the track */
.track5_vfdb {
fill: #663300;
}
.track5_adb {
fill: #FF9933;
}
/* Give a colour to the glyph track's stroke */
.gapTrack {
stroke: grey;
}
/* Set the stroke width of the axis lines */
.trackAxis .domain {
stroke-width: 1;
}
/* In a linear track, we need to set the
colours for the drag brush */
.brush .background {
stroke: black;
stroke-width: 2;
fill: slategray;
fill-opacity: .3;
}
.brush .extent {
stroke: gray;
fill: dodgerblue;
fill-opacity: .365;
}
/* In a circular plot if there's a
drag brush for zoomed region, define the
colours and style */
.polarbrush {
fill: lightgrey;
opacity: 0.5;
}
/* In the circular plot, the circular end points
for the drag brush */
.brushEnd {
fill: "red";
}
.brushStart {
fill: "green";
}
/* If we need to set an element to hidden, give
ourselves a class */
.linear_hidden {
visibility: hidden;
}
/* For regulatory elements in a linear plot,
define the colours and stroke for the lollipop
head (terminator site) */
.lollipophead {
stroke:#000000;
stroke-opacity: 1;
fill: none;
}
.lollipopstemstart {
fill:none;
stroke:#000000;
stroke-width: 1px;
stroke-linecap:butt;
stroke-linejoin:miter;
stroke-dasharray: 5,5;
}
.lollipopstemend {
fill:none;
stroke:#000000;
stroke-width: 1px;
stroke-linecap:butt;
stroke-linejoin:miter;
}
/* For our tooltips, how should we display them? */
.d3-tip {
line-height: 1;
font: 12px arial;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment