Skip to content

Instantly share code, notes, and snippets.

@squarednob
Last active February 17, 2017 15:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save squarednob/959bac1f4eca03059e02dbd480982c60 to your computer and use it in GitHub Desktop.
Save squarednob/959bac1f4eca03059e02dbd480982c60 to your computer and use it in GitHub Desktop.
D3-electrophoresis: Customizing settings with DNA sequence.

D3-electrophoresis plugin example: Default text is a kind of DNA sequence. You can change text and words in text box.

Github: D3-electrophoresis

function electrophoresis(config){
// ---------------Dict arguments ----------------
var config = (config === undefined) ? {} : config;
config.DNA = (config.DNA === undefined) ? "AGCGCCCAATACGCAAACCGCCTCTCCCCGCGCGTTGGCCGATTCACGTTTACGAGTTGGAAACGA" : config.DNA;
config.enzymes = (config.enzymes === undefined) ? [[1,5,10,15,20,30,40,50,70,100],"CAAA","GTTGG","GGATCC", "GA",["GT","CCT"],"ACC", "GAAA"] : config.enzymes;
config.names = (config.names === undefined) ? ["marker", "1", "2", "3", "4", "5", "6", "7"]: config.names;
config.scale = (config.scale === undefined) ? d3.scaleSqrt(): config.scale;
config.lane_number = (config.lane_number === undefined) ? 8 : config.lane_number;
config.gel_margin = (config.gel_margin === undefined) ? {top: 40, right: 20, bottom: 30, left: 20} : config.gel_margin;
config.duration = (config.duration === undefined) ? 6000: config.duration;
config.band_width = (config.band_width === undefined) ? 38 : config.band_width;
config.band_blur = (config.band_blur === undefined) ? 2 : config.band_blur;
config.band_thick_min = (config.band_thick_min === undefined) ? 1 : config.band_thick_min;
config.band_thick_rate = (config.band_thick_rate === undefined) ? 0.04 : config.band_thick_rate;
config.tooltip_name_on = (config.tooltip_name_on === undefined) ? "on" : config.tooltip_name_on;
config.tooltip_name_size = (config.tooltip_name_size === undefined) ? 17 : config.tooltip_name_size;
config.tooltip_name_offsetX = (config.tooltip_name_offsetX === undefined) ? 0 : config.tooltip_name_offsetX;
config.tooltip_name_offsetY = (config.tooltip_name_offsetY === undefined) ? 20 : config.tooltip_name_offsetY;
config.tooltip_band_on = (config.tooltip_band_on === undefined) ? "on" : config.tooltip_band_on;
config.tooltip_band_size = (config.tooltip_band_size === undefined) ? 13 : config.tooltip_band_size;
config.tooltip_band_offsetX = (config.tooltip_band_offsetX === undefined) ? 0 : config.tooltip_band_offsetX;
config.tooltip_band_offsetY = (config.tooltip_band_offsetY === undefined) ? 0 : config.tooltip_band_offsetY;
function elect(selection){
// ---------------- Define functiions---------------
function makeLenList(fragments, enzyme){
var len_list = [];
var enzyme_half1 = Math.round(enzyme.length/2);
var enzyme_half2 = enzyme.length - enzyme_half1;
fragments.forEach(function(fragment){
var no_blank = fragment.replace(/\s*/g, "");
len_list.push(fragment.length);
});
// Distribute Enzyme strings at each cut end to fill the deleted parts by split().
if (len_list.length > 1){
len_list.forEach(function(d,i){
if (i != 0){
len_list[i] = len_list[i] + enzyme_half1;
}
if (i != len_list.length-1){
len_list[i] += enzyme_half2;
}
})
}
return len_list;
}
function cutDNA(DNA_seq, enzymes){
var len_list = [];
var fragments = [];
if(typeof DNA_seq === "string"){
DNA_seq = DNA_seq.toUpperCase();
}
// If enzyme is a list.
if (enzymes.constructor === Array){
var len_list_temp = [];
fragments = [DNA_seq];
enzymes.forEach(function(enzyme){
if (typeof enzyme == "number"){
len_list = len_list.concat(enzyme);
}
// Cut string by multiple strings.
if (typeof enzyme == "string"){
var fragments_temp = [];
fragments = fragments.map(function(frag){
enzyme = enzyme.toUpperCase();
return frag.split(enzyme);
});
// Flatten lists.
fragments = [].concat.apply([], fragments);
len_list_temp = len_list_temp.concat(makeLenList(fragments, enzyme));
}
});
len_list = len_list.concat(len_list_temp);
return len_list;
} // If enzyme is not a list.
else {
if (typeof enzymes === "number"){
len_list.push(enzymes);
return len_list;
}
if (typeof enzymes === "string"){
enzymes = enzymes.toUpperCase();
fragments = DNA_seq.split(enzymes);
len_list = makeLenList(fragments, enzymes);
return len_list;
}
}
}
// --------------- Make SVG ------------------
function electrify(len_list, name_list, lane_number, band_width, band_duration,
yScale, gel_margin, blur, thick_min, thick_rate,
tooltip_name_on, tooltip_name_size, tooltip_name_offsetX, tooltip_name_offsetY,
tooltip_band_on, tooltip_band_size, tooltip_band_offsetX,tooltip_band_offsetY) {
var gel_width = selection.attr("width") - gel_margin.left - gel_margin.right;
var gel_height = selection.attr("height") - gel_margin.top - gel_margin.bottom;
var max_value = d3.max(d3.merge(len_list));
yScale.domain([0, max_value]).range([gel_height,0]);
// Filter for blur.
var lane_filter = selection.append("defs").attr("class", "gel")
.append("filter").attr("id", "gel-filter").attr("height","500%").attr("widht","100%")
.append("feGaussianBlur").attr("in", "SourceGraphic").attr("stdDeviation", blur).attr("result", "blur")
.append("feOffset").attr("result","offsetBlur").attr("dx",0).attr("dy",-5)
.append("feBrend").attr("in","blur").attr("in2","offsetBlur").attr("mode","normal");
gel= selection.append("g")
.attr("class", "gel")
.attr("transform", "translate(" + gel_margin.left + "," + gel_margin.top + ")");
var lanes = gel.selectAll("g .gel-lane")
.data(len_list).enter()
.append("g")
.attr("class", "gel-lane")
.attr("transform", function(d,i){return "translate(" + i*(gel_width/lane_number) + "," + 0 + ")";});
var rects = lanes.selectAll("g .gel-band")
.data(function(d){return d;})
.enter()
.append("g")
.attr("class","gel-band");
var rectAttr = rects.append("rect")
.attr("x", function(d){return 2;})
.attr("y", function(d){return 0;})
.attr("width", band_width)
.attr("height", 12)
.attr("fill", "white")
.attr("filter", "url(#gel-filter)") // Apply blur filter.
.transition()
.attr("height", function(d){ return thick_min + ((gel_height-yScale(d)) * thick_rate); })
.attr("y", function(d){ return yScale(d);})
.duration(band_duration);
if(tooltip_name_on == "on"){
var tooltips_name = lanes.append("text")
.attr("class","gel-tooltip")
.attr("fill","white")
.attr("font-size",tooltip_name_size)
.attr("text-anchor", "middle")
.attr("x", (gel_width/lane_number/3) + tooltip_name_offsetX)
.attr("y",-(gel_margin.top - tooltip_name_offsetY))
.text(function(d,i){ return name_list[i]; })
.attr("opacity", 0);
tooltips_name.transition()
.duration(1000)
.delay(band_duration)
.attr("opacity", 1);
}
if(tooltip_band_on == "on"){
var tooltips_band = rects.append("text")
.attr("class","gel-tooltip")
.attr("fill","white")
.attr("font-size",tooltip_band_size)
.attr("x",tooltip_band_offsetX)
.attr("y",function(d){ return yScale(d) + tooltip_band_offsetY;})
.text(function(d){return d;})
.attr("opacity", 0);
tooltips_band.transition()
.duration(1500)
.delay(band_duration+800)
.attr("opacity", 1);
}
}
// ----------------- Execute ------------------
var len_list = [];
config.enzymes.forEach(function(enzyme){
len_list.push(cutDNA(config.DNA, enzyme));
});
electrify(len_list, config.names,
lane_number=config.lane_number,
band_width=config.band_width,band_duration=config.duration,
yScale=config.scale, gel_margin=config.gel_margin, blur=config.band_blur,
thick_min=config.band_thick_min, thick_rate=config.band_thick_rate,
tooltip_name_on=config.tooltip_name_on, tooltip_name_size=config.tooltip_name_size,
tooltip_name_offsetX=config.tooltip_name_offsetX, tooltip_name_offsetY=config.tooltip_name_offsetY,
tooltip_band_on=config.tooltip_band_on, tooltip_band_size=config.tooltip_band_size,
tooltip_band_offsetX=config.tooltip_band_offsetX, tooltip_band_offsetY=config.tooltip_band_offsetY);
}
// --------------- Method Chain --------------
// Make black background by .call() before make bands.
elect.makeGel = function(selection) {
selection.append("rect")
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "#222222");
return elect;
};
elect.DNA = function(value) {
if (!arguments.length) return config.DNA;
config.DNA = value;
return elect;
};
elect.enzymes = function(value) {
if (!arguments.length) return config.enzymes;
config.enzymes = value;
return elect;
};
elect.names = function(value) {
if (!arguments.length) return config.names;
config.names = value;
return elect;
};
elect.scale = function(value) {
if (!arguments.length) return config.scale;
config.scale = value;
return elect;
};
elect.lane_number = function(value) {
if (!arguments.length) return config.lane_number;
config.lane_number = value;
return elect;
};
elect.gel_margin = function(value) {
if (!arguments.length) return config.gel_margin;
config.gel_margin = value;
return elect;
};
elect.duration = function(value) {
if (!arguments.length) return config.duration;
config.duration = value;
return elect;
};
elect.band_width = function(value) {
if (!arguments.length) return config.band_width;
config.band_width = value;
return elect;
};
elect.band_blur = function(value) {
if (!arguments.length) return config.band_blur;
config.band_blur = value;
return elect;
};
elect.band_thick_min = function(value) {
if (!arguments.length) return config.band_thick_min;
config.band_thick_min = value;
return elect;
};
elect.band_thick_rate = function(value) {
if (!arguments.length) return config.band_thick_rate;
config.band_thick_rate = value;
return elect;
};
elect.tooltip_name_on = function(value) {
if (!arguments.length) return config.tooltip_name_on;
config.tooltip_name_on = value;
return elect;
};
elect.tooltip_name_size = function(value) {
if (!arguments.length) return config.tooltip_name_size;
config.tooltip_name_size = value;
return elect;
};
elect.tooltip_name_offsetX = function(value) {
if (!arguments.length) return config.tooltip_name_offsetX;
config.tooltip_name_offsetX = value;
return elect;
};
elect.tooltip_name_offsetY = function(value) {
if (!arguments.length) return config.tooltip_name_offsetY;
config.tooltip_name_offsetY = value;
return elect;
};
elect.tooltip_band_on = function(value) {
if (!arguments.length) return config.tooltip_band_on;
config.tooltip_band_on = value;
return elect;
};
elect.tooltip_band_size = function(value) {
if (!arguments.length) return config.tooltip_band_size;
config.tooltip_band_size = value;
return elect;
};
elect.tooltip_band_offsetX = function(value) {
if (!arguments.length) return config.tooltip_band_offsetX;
config.tooltip_band_offsetX = value;
return elect;
};
elect.tooltip_band_offsetY = function(value) {
if (!arguments.length) return config.tooltip_band_offsetY;
config.tooltip_band_offsetY = value;
return elect;
};
return elect;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Electrophoresis Generator</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js" charset="utf-8"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="d3-electrophoresis.js"></script>
</head>
<body>
<div id="gel-field"></div>
<div style="float:left;">
<input type="button" style="background-color:moccasin" value="Turn on" onclick="render()" />
</div>
<div>
&nbsp;
<input type="checkbox" id="smear" value="on" />
<label for="">Smear</label>
<input type="checkbox" id="blur" value="on" />
<label for="">Blur</label>
<input type="checkbox" id="slow" value="on" />
<label for="">Slow</label>
<input type="checkbox" id="no-tooltips" value="on" />
<label for="">No Tooltips</label>
</div>
<div>
&nbsp;
<input type="checkbox" id="scale_sqrt" value="on" checked="checked" />
<label for="">Square Root Scale </label>
</div>
<form method="post" id="textinput">
<b>DNA Text:</b><br/>
<textarea cols=100 rows=8 id="DNA_text">
AGCGCCCAATACGCAAACCGCCTCTCCCCGCGCGTTGGCCGATTCATTAATGCAGCTGGCACGACAGGTT
TCCCGACTGGAAAGCGGGCAGTGAGCGCAACGCAATTAATGTGAGTTAGCTCACTCATTAGGCACCCCAG
GCTTTACACTTTATGCTTCCGGCTCGTATGTTGTGTGGAATTGTGAGCGGATAACAATTTCACACAGGAA
ACAGCTATGACCATGATTACGCCAAGCTATTTAGGTGACACTATAGAATACTCAAGCTATGCATCAAGCT
TGGTACCGAGCTCGGATCCACTAGTAACGGCCGCCAGTGTGCTGGAATTCGGCTTAAGCCGAATTCTGCA
GATATCCATCACACTGGCGGCCGCTCGAGCATGCATCTAGAGGGCCCAATTCGCCCTATAGTGAGTCGTA
TTACAATTCACTGGCCGTCGTTTTACAACGTCGTGACTGGGAAAACCCTGGCGTTACCCAACTTAATCGC
CTTGCAGCACATCCCCCTTTCGCCAGCTGGCGTAATAGCGAAGAGGCCCGCACCGATCGCCCTTCCCAAC
AGTTGCGCAGCCTGAATGGCGAATGGACGCGCCCTGTAGCGGCGCATTAAGCGCGGCGGGTGTGGTGGTT
ACGCGCAGCGTGACCGCTACACTTGCCAGCGCCCTAGCGCCCGCTCCTTTCGCTTTCTTCCCTTCCTTTC
TCGCCACGTTCGCCGGCTTTCCCCGTCAAGCTCTAAATCGGGGGCTCCCTTTAGGGTTCCGATTTAGTGC
TTTACGGCACCTCGACCCCAAAAAACTTGATTAGGGTGATGGTTCACGTAGTGGGCCATCGCCCTGATAG
ACGGTTTTTCGCCCTTTGACGTTGGAGTCCACGTTCTTTAATAGTGGACTCTTGTTCCAAACTGGAACAA
CACTCAACCCTATCTCGGTCTATTCTTTTGATTTATAAGGGATTTTGCCGATTTCGGCCTATTGGTTAAA
AAATGAGCTGATTTAACAAAAATTTAACGCGAATTTTAACAAAATTCAGGGCGCAAGGGCTGCTAAAGGA
AGCGGAACACGTAGAAAGCCAGTCCGCAGAAACGGTGCTGACCCCGGATGAATGTCAGCTACTGGGCTAT
CTGGACAAGGGAAAACGCAAGCGCAAAGAGAAAGCAGGTAGCTTGCAGTGGGCTTACATGGCGATAGCTA
GACTGGGCGGTTTTATGGACAGCAAGCGAACCGGAATTGCCAGCTGGGGCGCCCTCTGGTAAGGTTGGGA
AGCCCTGCAAAGTAAACTGGATGGCTTTCTTGCCGCCAAGGATCTGATGGCGCAGGGGATCAAGATCTGA
TCAAGAGACAGGATGAGGATCGTTTCGCATGATTGAACAAGATGGATTGCACGCAGGTTCTCCGGCCGCT
TGGGTGGAGAGGCTATTCGGCTATGACTGGGCACAACAGACAATCGGCTGCTCTGATGCCGCCGTGTTCC
GGCTGTCAGCGCAGGGGCGCCCGGTTCTTTTTGTCAAGACCGACCTGTCCGGTGCCCTGAATGAACTGCA
GGACGAGGCAGCGCGGCTATCGTGGCTGGCCACGACGGGCGTTCCTTGCGCAGCTGTGCTCGACGTTGTC
ACTGAAGCGGGAAGGGACTGGCTGCTATTGGGCGAAGTGCCGGGGCAGGATCTCCTGTCATCCCACCTTG
CTCCTGCCGAGAAAGTATCCATCATGGCTGATGCAATGCGGCGGCTGCATACGCTTGATCCGGCTACCTG
CCCATTCGACCACCAAGCGAAACATCGCATCGAGCGAGCACGTACTCGGATGGAAGCCGGTCTTGTCGAT
CAGGATGATCTGGACGAAGAGCATCAGGGGCTCGCGCCAGCCGAACTGTTCGCCAGGCTCAAGGCGCGCA
TGCCCGACGGCGAGGATCTCGTCGTGACCCATGGCGATGCCTGCTTGCCGAATATCATGGTGGAAAATGG
CCGCTTTTCTGGATTCATCGACTGTGGCCGGCTGGGTGTGGCGGACCGCTATCAGGACATAGCGTTGGCT
ACCCGTGATATTGCTGAAGAGCTTGGCGGCGAATGGGCTGACCGCTTCCTCGTGCTTTACGGTATCGCCG
CTCCCGATTCGCAGCGCATCGCCTTCTATCGCCTTCTTGACGAGTTCTTCTGAATTGAAAAAGGAAGAGT
ATGAGTATTCAACATTTCCGTGTCGCCCTTATTCCCTTTTTTGCGGCATTTTGCCTTCCTGTTTTTGCTC
ACCCAGAAACGCTGGTGAAAGTAAAAGATGCTGAAGATCAGTTGGGTGCACGAGTGGGTTACATCGAACT
GGATCTCAACAGCGGTAAGATCCTTGAGAGTTTTCGCCCCGAAGAACGTTTTCCAATGATGAGCACTTTT
AAAGTTCTGCTATGTGGCGCGGTATTATCCCGTATTGACGCCGGGCAAGAGCAACTCGGTCGCCGCATAC
ACTATTCTCAGAATGACTTGGTTGAGTACTCACCAGTCACAGAAAAGCATCTTACGGATGGCATGACAGT
AAGAGAATTATGCAGTGCTGCCATAACCATGAGTGATAACACTGCGGCCAACTTACTTCTGACAACGATC
GGAGGACCGAAGGAGCTAACCGCTTTTTTGCACAACATGGGGGATCATGTAACTCGCCTTGATCGTTGGG
AACCGGAGCTGAATGAAGCCATACCAAACGACGAGCGTGACACCACGATGCCTGTAGCAATGGCAACAAC
GTTGCGCAAACTATTAACTGGCGAACTACTTACTCTAGCTTCCCGGCAACAATTAATAGACTGGATGGAG
GCGGATAAAGTTGCAGGACCACTTCTGCGCTCGGCCCTTCCGGCTGGCTGGTTTATTGCTGATAAATCTG
GAGCCGGTGAGCGTGGGTCTCGCGGTATCATTGCAGCACTGGGGCCAGATGGTAAGCCCTCCCGTATCGT
AGTTATCTACACGACGGGGAGTCAGGCAACTATGGATGAACGAAATAGACAGATCGCTGAGATAGGTGCC
TCACTGATTAAGCATTGGTAACTGTCAGACCAAGTTTACTCATATATACTTTAGATTGATTTAAAACTTC
ATTTTTAATTTAAAAGGATCTAGGTGAAGATCCTTTTTGATAATCTCATGACCAAAATCCCTTAACGTGA
GTTTTCGTTCCACTGAGCGTCAGACCCCGTAGAAAAGATCAAAGGATCTTCTTGAGATCCTTTTTTTCTG
CGCGTAATCTGCTGCTTGCAAACAAAAAAACCACCGCTACCAGCGGTGGTTTGTTTGCCGGATCAAGAGC
TACCAACTCTTTTTCCGAAGGTAACTGGCTTCAGCAGAGCGCAGATACCAAATACTGTTCTTCTAGTGTA
GCCGTAGTTAGGCCACCACTTCAAGAACTCTGTAGCACCGCCTACATACCTCGCTCTGCTAATCCTGTTA
CCAGTGGCTGCTGCCAGTGGCGATAAGTCGTGTCTTACCGGGTTGGACTCAAGACGATAGTTACCGGATA
AGGCGCAGCGGTCGGGCTGAACGGGGGGTTCGTGCACACAGCCCAGCTTGGAGCGAACGACCTACACCGA
ACTGAGATACCTACAGCGTGAGCTATGAGAAAGCGCCACGCTTCCCGAAGGGAGAAAGGCGGACAGGTAT
CCGGTAAGCGGCAGGGTCGGAACAGGAGAGCGCACGAGGGAGCTTCCAGGGGGAAACGCCTGGTATCTTT
ATAGTCCTGTCGGGTTTCGCCACCTCTGACTTGAGCGTCGATTTTTGTGATGCTCGTCAGGGGGGCGGAG
CCTATGGAAAAACGCCAGCAACGCGGCCTTTTTACGGTTCCTGGCCTTTTGCTGGCCTTTTGCTCACATG
TTCTTTCCTGCGTTATCCCCTGATTCTGTGGATAACCGTATTACCGCCTTTGAGTGAGCTGATACCGCTC
GCCGCAGCCGAACGACCGAGCGCAGCGAGTCAGTGAGCGAGGAAGCGGAAG
</textarea>
<br>
<b>Wells with restriction enzyme:</b><br/>
<input type="text" class="marker" style="width:150px" value=130,560,2020,2320,4360,6560,9420,23130></input>
<input type=text class = "wells" style="width:70px;" value="GAATTC"></input>
<input type=text class = "wells" style="width:70px;" value="AAGCTT"></input>
<input type=text class = "wells" style="width:70px;" value ="CAGCTG"></input>
<input type=text class = "wells" style="width:70px;" value="GTCGAC"></input>
<input type=text class = "wells" style="width:70px;" value="GCGGCCGC"></input>
<input type=text class = "wells" style="width:70px;" value = "GGATCC"></input>
<input type=text class = "wells" style="width:70px;" value = "GGCC"></input>
</form>
<br>
<script type="text/javascript">
var width = 480;
var height=500;
var gel = electrophoresis();
var svg = d3.select("#gel-field").append("svg")
.attr("width", width)
.attr("height", height)
.call(gel.makeGel); // Make black background first.
function render(){
// Make DNAtext.
var DNA_text = $("#DNA_text").val();
// Make maker list.
var marker_text = $(".marker").val().split(",");
var marker_list = [];
$.each(marker_text, function(i,d){ marker_list.push(parseInt(d)); });
// Make Well list.
var wells = [marker_list];
$(".wells").each(function(i,d){
wells.push(d.value);
})
// Make name list.
var names = ["(marker)", "EcoRI", "HindIII", "PvuII", "SalI", "NotI", "BamHI", "HaeIII"];
// Make parameters for dictionary input.
var scale;
var smear;
var blur;
var slow;
var no_tooltips;
if ($('#scale_sqrt').prop("checked") == true){
scale = d3.scaleSqrt();
}else{
scale = d3.scaleLinear();
}
if ($('#smear').prop("checked") == true){
smear = .2;
}else{
smear = undefined
}
if ($('#blur').prop("checked") == true){
blur = 3;
}else{
blur = undefined
}
if ($('#slow').prop("checked") == true){
slow = 10000;
}else{
slow = undefined;
}
if ($('#no-tooltips').prop("checked") == true){
no_tooltips = "off";
}else{
no_tooltips = "on";
}
var dict = {scale: scale, band_thick_rate:smear, band_blur:blur, duration:slow, tooltip_band_on:no_tooltips};
d3.selectAll(".gel").remove();
gel = electrophoresis(dict).DNA(DNA_text).enzymes(wells).names(names).tooltip_band_size(10).tooltip_name_size(14).tooltip_name_offsetX(3);
svg.call(gel)
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment