Genome browser for phamerator.org
forked from scresawn's block: genome browser
Genome browser for phamerator.org
forked from scresawn's block: genome browser
[{ | |
"name": 1, | |
"start": 50, | |
"stop": 2000, | |
"direction": "forward", | |
"family": "7", | |
"sequence": "ATGCGCGCCCCCCCGATGATCGGCGCGATATGGGGGGGGGGGCGCGATCGAGCT" | |
}, | |
{ | |
"name": 2, | |
"start": 2150, | |
"stop": 2900, | |
"direction": "reverse", | |
"family": "201", | |
"sequence": "TAGCGACGTATATTAGCGCGGCATATACGATGGGGGGGGGGGGCGTGGGCTA" | |
}, | |
{ | |
"name": 3, | |
"start": 3000, | |
"stop": 4550, | |
"direction": "forward", | |
"family": "90", | |
"sequence": "ACTGTCTATGCGCGCGATATTAGCATGCTACGTGTAGCTAGTCGTTATGCGCGGCACTACTGACTGTAC" | |
}, | |
{ | |
"name": 4, | |
"start": 4700, | |
"stop": 7550, | |
"direction": "forward", | |
"family": "3752", | |
"sequence": "GCGCGATCTACGGCGCGCGATCTACTATGCGCGCGCGATCGACGTAGCGC" | |
} | |
] |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"> | |
</script> | |
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.0.min.js"> | |
</script> | |
<script src="aminoacidseq.js" type="text/javascript"> | |
</script> | |
<!-- Latest compiled and minified CSS --> | |
<link crossorigin="anonymous" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" rel="stylesheet"> | |
<!-- Optional theme --> | |
<link crossorigin="anonymous" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" rel="stylesheet"> | |
<!-- Latest compiled and minified JavaScript --> | |
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"> | |
</script> | |
<style> | |
#myModal { | |
font-family: arial; | |
font-size: 14px; | |
text-align: left; | |
vertical-align: middle; | |
word-wrap: break-word; | |
} | |
body{ | |
font-family:Arial; | |
} | |
</style> | |
<title></title> | |
</head> | |
<body> | |
<!-- Trigger the modal with a button --> | |
<!-- Modal --> | |
<div class="modal fade" id="myModal" role="dialog"> | |
<div class="modal-dialog" id="chicken"> | |
<!-- Modal content--> | |
<div class="modal-content"> | |
<div class="modal-header"> | |
<button class="close" data-dismiss="modal" type="button">×</button> | |
<h4 class="modal-title">Information</h4> | |
</div> | |
<div class="modal-body"></div> | |
<div class="modal-footer"></div> | |
</div> | |
</div> | |
</div> | |
<script> | |
$(document).ready(function() { | |
$.getJSON("genes.json.txt", function(data) { | |
var maxLength = 0; | |
for (i = 0; i < data.length; i++) { | |
if (data[i].stop > maxLength) { | |
maxLength = data[i].stop; | |
} | |
} | |
genomelength = maxLength + maxLength / 50; | |
function calc(form) { | |
var aminoSeq = []; | |
var sequence = data[form - 1].sequence; | |
var aminoArray = []; | |
var startNuc = 0; | |
var reverse = ""; | |
var gCount = 0; | |
var cCount = 0; | |
var aCount = 0; | |
var tCount = 0; | |
for (i = 1; i < sequence.length / 3; i++) { | |
aminoArray.push(sequence.substring(startNuc, startNuc + 3)); | |
startNuc = i * 3; | |
} | |
//Matches sequence to amino acid | |
for (i = 0; i < aminoArray.length; i++) { | |
switch (aminoArray[i]) { | |
case 'GCA': | |
case 'GCC': | |
case 'GCG': | |
case 'GCT': | |
aminoSeq.push("Ala") | |
break; | |
case 'AAC': | |
case 'AAT': | |
case 'GAC': | |
case 'GAT': | |
aminoSeq.push("Asx") | |
break; | |
case 'TGC': | |
case 'TGT': | |
aminoSeq.push("Cys") | |
break; | |
case 'GAC': | |
case 'GAT': | |
aminoSeq.push("Asp") | |
break; | |
case 'GAA': | |
case 'GAG': | |
aminoSeq.push("Glu") | |
break; | |
case 'TTC': | |
case 'TTT': | |
aminoSeq.push("Phe") | |
break; | |
case 'GGA': | |
case 'GGC': | |
case 'GGG': | |
case 'GGT': | |
aminoSeq.push("Gly") | |
break; | |
case 'CAC': | |
case 'CAT': | |
aminoSeq.push("His") | |
break; | |
case 'ATA': | |
case 'ATC': | |
case 'ATT': | |
aminoSeq.push("Ile") | |
break; | |
case 'AAA': | |
case 'AAG': | |
aminoSeq.push("Lys") | |
break; | |
case 'CTA': | |
case 'CTC': | |
case 'CTG': | |
case 'CTT': | |
case 'TTA': | |
case 'TTG': | |
aminoSeq.push("Leu") | |
break; | |
case 'ATG': | |
aminoSeq.push("Met") | |
break; | |
case 'AAC': | |
case 'AAT': | |
aminoSeq.push("Asn") | |
break; | |
case 'CCA': | |
case 'CCC': | |
case 'CCG': | |
case 'CCT': | |
aminoSeq.push("Pro") | |
break; | |
case 'CAA': | |
case 'CAG': | |
aminoSeq.push("Gln") | |
break; | |
case 'AGA': | |
case 'AGG': | |
case 'CGA': | |
case 'CGC': | |
case 'CGG': | |
case 'CGT': | |
aminoSeq.push("Arg") | |
break; | |
case 'AGC': | |
case 'AGT': | |
case 'TCA': | |
case 'TCC': | |
case 'TCG': | |
case 'TCT': | |
aminoSeq.push("Ser") | |
break; | |
case 'ACA': | |
case 'ACC': | |
case 'ACG': | |
case 'ACT': | |
aminoSeq.push("Thr") | |
break; | |
case 'GTA': | |
case 'GTC': | |
case 'GTG': | |
case 'GTT': | |
aminoSeq.push("Val") | |
break; | |
case 'TGG': | |
aminoSeq.push("Trp") | |
break; | |
case 'TAC': | |
case 'TAT': | |
aminoSeq.push("Tyr") | |
break; | |
case 'CAA': | |
case 'CAG': | |
case 'GAA': | |
case 'GAG': | |
aminoSeq.push("Glx") | |
break; | |
case 'TAA': | |
case 'TAG': | |
case 'TGA': | |
aminoSeq.push("STOP") | |
break; | |
} | |
} | |
var aminoOrg = aminoSeq.join("-") | |
for (i = 0; i < sequence.length; i++) { | |
switch (sequence[i]) { | |
case "A": | |
reverse = reverse + "T" | |
break; | |
case "G": | |
reverse = reverse + "C" | |
break; | |
case "C": | |
reverse = reverse + "G" | |
break; | |
case "T": | |
reverse = reverse + "A" | |
break; | |
} | |
} | |
for (i = 0; i < sequence.length; i++) { | |
switch (sequence[i]) { | |
case "A": | |
break; | |
case "T": | |
break; | |
case "C": | |
cCount++ | |
break; | |
case "G": | |
gCount++ | |
break; | |
} | |
} | |
var gcPcnt = Number(((gCount + cCount) / sequence.length).toFixed(3)) | |
var soln = { | |
sequence: sequence, | |
aminoSeq: aminoOrg, | |
reverse: reverse, | |
gcPcnt: gcPcnt | |
}; | |
return ("<p><b>Sequence: <\/b>" + soln.sequence + "<br>" + "<b>Reverse: <\/b>" + soln.reverse + "<br>" + "<b>Amino-chain: <\/b>" + soln.aminoSeq + "<br>" + "<b>GC%: <\/b>" + soln.gcPcnt * 100 + "%<\/p>"); | |
} | |
//Tick mark object | |
var tickMarks = { | |
thousand: [], | |
fivehundred: [], | |
onehundred: [] | |
}; | |
//Array with numbers from 1->genomelength | |
var genome_positions = []; | |
for (var i = 1; i <= genomelength; i++) { | |
genome_positions.push(i); | |
} | |
//Creates 1000, 500 and 100 bp ticks | |
genome_positions.forEach(function(currentValue, index, myArray) { | |
if (currentValue % 1000 === 0) { | |
tickMarks.thousand.push(currentValue); | |
} else if (currentValue % 500 === 0) { | |
tickMarks.fivehundred.push(currentValue); | |
} else if (currentValue % 100 === 0) { | |
tickMarks.onehundred.push(currentValue); | |
} | |
}); | |
var svg = d3.select("body").append("svg").attr({ | |
height: 500, | |
width: genomelength / 10 | |
}); | |
svg.append("g") | |
.append("rect") | |
.attr({ | |
x: 0, | |
y: 100, | |
width: genomelength / 10, | |
height: 30 | |
}) | |
.style({ | |
"stroke-width": "2px", | |
"fill": "white", | |
"stroke": "black" | |
}); | |
d3.json("genes.json.txt", function(error, json) { | |
if (error) return console.warn(error); | |
var rects = svg.selectAll(".genes") | |
.data(json) | |
.enter() | |
.append("rect"); | |
var rectAttributes = rects | |
.attr("width", function(d) { | |
return (d.stop - d.start) / 10; | |
}) | |
.style({ | |
"stroke": "black", | |
"stroke-width": "2px", | |
"fill-opacity": 0.5 | |
}) | |
.attr("y", function(d) { | |
if (d.direction == "reverse" && d.name % 2 == 0) { | |
return 130 | |
} else if (d.direction == "reverse" && d.name % 2 != 0) { | |
return 160 | |
} else if (d.direction == "forward" && d.name % 2 != 0) { | |
return 70 | |
} else { | |
return 40 | |
}; | |
}) | |
.attr("x", function(d) { | |
if (d.direction == "forward") { | |
return (0 - ((d.stop - d.start) / 10)) - 2; | |
} else if (d.direction == "reverse") { | |
return (genomelength / 10) + 2; | |
} | |
}) | |
.style({ | |
"fill": function(d) { | |
if (d.direction == "forward") { | |
return "green" | |
} else if (d.direction == "reverse") { | |
return "red" | |
} | |
} | |
}) | |
//Transition .transition().duration(2000) | |
.attr("x", function(d) { | |
return d.start / 10; | |
}) | |
.attr("height", function(d) { | |
return 30; | |
}) | |
.attr("id", function(d) { | |
return d.name | |
}) | |
.on("click", function(d) { | |
$('#myModal').modal('show') | |
var infodiv = d3.select(".modal-body").data(json).html(calc(d.name)) | |
}) | |
.on("mouseover", function(d){ | |
d3.select("body").style({"cursor":"pointer"}) | |
}) | |
.on("mouseout",function(d){ | |
d3.select("body").style({"cursor":"default"}) | |
}) | |
var text = svg.selectAll(".genes") | |
.data(json) | |
.enter() | |
.append("text"); | |
var nameText = text | |
.text((function(d) { | |
var countC = d.sequence.match(/C/g); | |
var countG = d.sequence.match(/G/g); | |
return Math.round(((countC.length + countG.length) / d.sequence.length) * 100) + "%"; | |
})) | |
.attr("y", function(d) { | |
if (d.direction == "reverse" && d.name % 2 == 0) { | |
return 150 | |
} else if (d.direction == "reverse" && d.name % 2 != 0) { | |
return 180 | |
} else if (d.direction == "forward" && d.name % 2 != 0) { | |
return 90 | |
} else { | |
return 60 | |
} | |
}) | |
.attr("x", function(d) { | |
return ((d.start + (d.stop - d.start) / 2) / 10) | |
}) | |
.attr("font-size", "20px") | |
.append("svg:title") | |
.text(function(d) { | |
return "The direction of the gene is " + d.direction + "."; | |
}) | |
.style({"text-align":"center"}) | |
var text2 = svg.selectAll(".genes") | |
.data(json) | |
.enter() | |
.append("text"); | |
var familyText = text2 | |
.text(function(d) { | |
return d.family | |
}) | |
.attr("y", function(d) { | |
if (d.direction == "reverse" && d.name % 2 == 0) { | |
return 175 | |
} else if (d.direction == "reverse" && d.name % 2 != 0) { | |
return 205 | |
} else if (d.direction == "forward" && d.name % 2 != 0) { | |
return 65 | |
} else { | |
return 35 | |
} | |
}) | |
.attr("x", function(d) { | |
return ((d.start + (d.stop - d.start) / 2) / 10) | |
}) | |
.attr("font-size", "20px") | |
}); | |
var group = svg.selectAll(".a") | |
.data(tickMarks.thousand) | |
.enter() | |
.append("g"); | |
group.append("rect") | |
.style({ | |
"fill": "black" | |
}) | |
.attr({ | |
x: 0, | |
y: 100, | |
width: "1px", | |
height: 30 | |
}) | |
.attr("transform", function(d) { | |
return "translate(" + d / 10 + ",0)"; | |
}); | |
group.append("text") | |
.text(function(d) { | |
return d / 1000 | |
}) | |
.attr("x", function(d) { | |
return d / 10 + 1.5 | |
}) | |
.attr("y", 110) | |
.attr("font-size", "10px") | |
var group2 = svg.selectAll(".b") | |
.data(tickMarks.fivehundred) | |
.enter() | |
.append("g"); | |
group2.append("rect") | |
.style({ | |
"fill": "black" | |
}) | |
.attr({ | |
x: 0, | |
y: 100, | |
width: "1px", | |
height: 15 | |
}) | |
.attr("transform", function(d) { | |
return "translate(" + d / 10 + ",0)"; | |
}); | |
var group3 = svg.selectAll(".c") | |
.data(tickMarks.onehundred) | |
.enter() | |
.append("g"); | |
group3.append("rect") | |
.style({ | |
"fill": "black" | |
}) | |
.attr({ | |
x: 0, | |
y: 115, | |
width: "1px", | |
height: 15 | |
}) | |
.attr("transform", function(d) { | |
return "translate(" + d / 10 + ",0)"; | |
}); | |
} | |
) | |
}, false); | |
</script> | |
<div id="infodiv"> | |
<p></p> | |
</div> | |
</body> | |
</html> |