Skip to content

Instantly share code, notes, and snippets.

@imoutsatsos
Created July 26, 2019 21:11
Show Gist options
  • Save imoutsatsos/23f484f7f2ff89b779cbf1c7ba3170bc to your computer and use it in GitHub Desktop.
Save imoutsatsos/23f484f7f2ff89b779cbf1c7ba3170bc to your computer and use it in GitHub Desktop.
Expeiments with D3 brushing using an assay plate heat map
<!DOCTYPE html>
<meta charset="utf-8">
<html>
<head>
<style>
rect.bordered {
stroke: #E6E6E6;
stroke-width:2px;
}
text.mono {
font-size: 9pt;
font-family: Consolas, courier;
fill: #aaa;
}
text.axis-workweek {
fill: #000;
}
text.axis-worktime {
fill: #000;
}
.selected{
fill: rgb(128, 126, 0) !important;
}
</style>
<script src="http://d3js.org/d3.v4.js"></script>
</head>
<body>
<div id="chart"></div>
<div id="dataset-picker">
</div>
<script type="text/javascript">
//This works, and updates correctly when user clicks on dataset buttons
//Last Update NOV-24-2015
var margin = { top: 50, right: 0, bottom: 50, left: 30 },
width = 960 - margin.left - margin.right,
height = 720 - margin.top - margin.bottom,
gridSize = Math.floor(width / 48),
legendElementWidth = gridSize*2,
buckets = 9,
colors = ["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"], // alternatively colorbrewer.YlGnBu[9]
days = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32"]
//["A", "B", "C", "D", "E", "F", "G","H", "I", "J", "K", "L", "M", "N","O","P"];
times = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48"];
datasets = ["VB00009708", "VB00009778"];
var thisDataset=new Array()
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("id","svgChart" )
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var dayLabels = svg.selectAll(".dayLabel")
.data(days)
.enter().append("text")
.text(function (d) { return d; })
.attr("x", 0)
.attr("y", function (d, i) { return i * gridSize; })
.style("text-anchor", "end")
.attr("transform", "translate(-6," + gridSize / 1.5 + ")")
.attr("class", function (d, i) { return ((i >= 0 && i <= 32) ? "dayLabel mono axis axis-workweek" : "dayLabel mono axis"); });
var timeLabels = svg.selectAll(".timeLabel")
.data(times)
.enter().append("text")
.text(function(d) { return d; })
.attr("x", function(d, i) { return i * gridSize; })
.attr("y", 0)
.style("text-anchor", "middle")
.attr("transform", "translate(" + gridSize / 2 + ", -6)")
.attr("class", function(d, i) { return ((i >= 1 && i <= 48) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis"); });
var heatmapChart = function(csvFilter, thisDataset) {
if (thisDataset.length==0){
console.log('Starting fresh thisDataset!')
}else{
console.log('old content thisDataset!')
};
d3.csv("data.dlm",
function(csv) {
data=csv.filter(function(row) { return row['Metadata_Barcode'] == csvFilter ; })
console.log(data.length, csvFilter);
/* create new dataset from filtered data */
data.forEach(function (d) {
var el= {
Metadata_Barcode: d.Metadata_Barcode,
Metadata_RowNumber: +d.Metadata_RowNumber,
Metadata_Column: +d.Metadata_Column,
value: +d.Count_CELLS
};
thisDataset.push(el)
}
) //end for each
console.log('This data is: ',csvFilter, thisDataset.length)
/* call function for chart initialization */
initialize(thisDataset);
}
);
} //end heatmapChart
// Function that is triggered when brushing is performed
var updateChart = function () {
// Get the selection coordinate
d = d3.event.selection // looks like [ [12,11], [132,178]]
st=d[[0],[0]] //start
stX=st[[0],[0]]
stY=st[[0],[1]]
en=d[[0],[1]] //end
enX=en[[0],[0]]
enY=en[[0],[1]]
dwidth=enX-stX
dheight=enY-stY
//margins needed for correct determination of brushed objects
var margin = { top: 50, right: 0, bottom: 50, left: 30 }
console.log('Brushing logic',d,stX,stY,enX,enY,dwidth,dheight)
d3.selectAll('rect').each(function(rect_data,i){
//console.log('Rect data:',rect_data)
if(
!d3.select( this).classed("selected") &&
this.x.animVal.value+margin.left>=stX &&
this.x.animVal.value+margin.left+this.width.animVal.value<=enX &&
this.y.animVal.value+margin.top>=stY &&
this.y.animVal.value+margin.top+this.height.animVal.value<=enY
) {
console.log('Rect Object xyValue:',this.x.animVal.value, this.y.animVal.value)
d3.select(this)
.classed("selected",true);
}
});
}
var initialize= function(data) {
console.log('initializing: ', data.length)
//add brushing
// d3.select("#svgChart")
var margin = { top: 50, right: 0, bottom: 50, left: 30 }
var width = 960 - margin.left - margin.right
var height = 720 - margin.top - margin.bottom
var ch= height + margin.top + margin.bottom
var cw= width + margin.left + margin.right
theHeatMap=d3.select("#svgChart")
theHeatMap.call(d3.brush()
.extent([[22,50],[950,660]])
.on("start end", updateChart))
var colorScale = d3.scaleQuantile()
.domain([0, buckets - 1, d3.max(data, function (d) { return d.value; })])
.range(colors);
var cards = svg.selectAll(".well")
.data(data, function(d) {return d.Metadata_RowNumber+':'+d.Metadata_Column;});
cards.append("title");
cards.enter().append("rect")
.attr("x", function(d) { return (d.Metadata_Column - 1) * gridSize; })
.attr("y", function(d) { return (d.Metadata_RowNumber - 1) * gridSize; })
.attr("rx", 4)
.attr("ry", 4)
.attr("class", "well bordered")
.attr("width", gridSize)
.attr("height", gridSize)
.style("fill", colors[0]);
// Join newly formed rect to data
//d3.selectAll('rect').data(data)
cards.transition().duration(1000)
.style("fill", function(d) { return colorScale(d.value); });
cards.select("title").text(function(d) { return d.value+":"+d.Metadata_Barcode+":"+d.Metadata_RowNumber+":"+d.Metadata_Column });
cards.exit().remove();
var legend = svg.selectAll(".legend")
.data([0].concat(colorScale.quantiles()), function(d) { return d; });
legend.enter().append("g")
.attr("class", "legend");
legend.append("rect")
.attr("x", function(d, i) { return legendElementWidth * i; })
.attr("y", height)
.attr("width", legendElementWidth)
.attr("height", gridSize / 2)
.style("fill", function(d, i) { return colors[i]; });
legend.append("text")
.attr("class", "mono")
.text(function(d) { return "? " + Math.round(d); })
.attr("x", function(d, i) { return legendElementWidth * i; })
.attr("y", height + gridSize);
legend.exit().remove();
};
heatmapChart(datasets[0], thisDataset);
var datasetpicker = d3.select("#dataset-picker").selectAll(".dataset-button")
.data(datasets);
datasetpicker.enter()
.append("input")
.attr("value", function(d){ return "Dataset " + d })
.attr("type", "button")
.attr("class", "dataset-button")
.on("click", function(d) {
thisDataset.length=0 //reset the global value array
heatmapChart(d, thisDataset);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment