Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@nbremer
Last active June 12, 2016 08:32
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 nbremer/0d2e658691a4f93cad92 to your computer and use it in GitHub Desktop.
Save nbremer/0d2e658691a4f93cad92 to your computer and use it in GitHub Desktop.
A SOM Clustering of block Colors - Including HSL & RGB
height: 860

All of the custom colors found in d3.js blocks were used as input. The data was taken from enjalot's block and includes 3250 different blocks. He parsed out hex codes, hsl(a) and rgb(a) in any html, js or coffee file found in each block and I converted all of these to their hex, rgb and hsl values. There were 24700 different color statements in these blocks that make up 4350 unique colors. The clustering grouped similar colors together in 600 hexagons (based on their RGB and HSL values, thus 6 variables in total). The map below displays the "average" hex value and the size of each hexagon is scaled to the number of (the 24700) colors that are grouped in each hexagon. The biggest one, pure black, #000000, has 1500 entries

Another version, based on a clustering of only the rgb values can be found here

A collection of blocks scanned with blockscanner for the bl.ocksplorer.org project with some further processing. Based on enjalot's block: block colors

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Block Color Clustering</title>
<script type="text/javascript" src="http://d3js.org/d3.v3.js"></script>
<script type="text/javascript" src="http://d3js.org/d3.hexbin.v0.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.js"></script>
<!-- jQuery -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<link href='http://fonts.googleapis.com/css?family=Open+Sans:700,400,300' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Lora' rel='stylesheet' type='text/css'>
<style>
body {
text-align: center;
}
.header {
font-family: 'Montserrat', sans-serif;
margin-top: 20px;
margin-left: 40px;
padding-bottom: 20px;
font-size: 34px;
text-align: left;
max-width: 900px;
color: #525252;
}
.hint {
font-family: 'Lora', serif;
margin-top: 10px;
color: #AAAAAA;
font-size: 12px;
max-width: 750px;
}
.popover{
font-family: 'Montserrat', sans-serif;
font-size: 12px;
font-weight: 400;
color: #525252;
text-align: center;
}
.btn {
font-family: 'Lora', serif;
color: #525252;
}
</style>
</head>
<body>
<div class="header">
A Self Organizing Map Clustering of block Colors
<div class="hint">
<p>All of the custom colors found in d3.js blocks were used as input. The data was taken from the <a href="http://bl.ocks.org/enjalot/de262983e3ba0c0f89c1">enjalot's block</a> and includes 3250 different blocks.
He parsed out hex codes, hsl(a) and rgb(a) in any html, js or coffee file found in each block and I converted all of these to their hex, rgb and hsl values. There were 24700 different color statements in these blocks that make up 4350 unique colors.</p>
<p>The clustering grouped similar colors together in 600 hexagons (based on their RGB and HSL values, thus 6 variables in total). The map below displays the "average" hex value and the size of each hexagon is scaled to the number of (the 24700) colors that are grouped in each hexagon.
The biggest one, pure black, #000000, has 1500 entries. In essence it is an exercise in trying to map a 3D color space into a 2D plane while also looking at the nuances in colors used in blocks :)</p>
</div>
</div>
<div id="chart"></div>
<div id="button" class="btn-group" data-toggle="buttons">
<label id="diffSizeButton" class="btn btn-default active"><input type="radio" class="btn-options"> Sized hexagons </label>
<label id="sameSizeButton" class="btn btn-default"><input type="radio" class="btn-options"> Unsized hexagons </label>
</div>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
///////////////////////////////////////////////////////////////////////////
/////////////////////////////// SOM Data //////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//The color of each hexagon
var color = ["#D9D9D9", "#DCDCDC", "#DDDDDD", "#E7E7E7", "#F1F1F1", "#F6F6F6", "#FCFCFC", "#FFFEFE", "#FFF7F7", "#FFF5F0", "#FFFAF1", "#FCFFF5", "#F2FFF9", "#E9FFFF", "#F4FAFF", "#F3F4FF", "#BDC0FF", "#EEEEF7", "#F1EFF6", "#F9F5FA", "#E9D3D8", "#FEE3F0", "#FEB9C3", "#FF66B4", "#FE01FD", "#FA0E8D", "#FD004C", "#F32E4B", "#D2001C", "#A1001E", "#D0D0D0", "#DADADA", "#E5E5E5", "#EEEEEE", "#F2F2F2", "#F9F9F9", "#FFFFFF", "#F3E2E2", "#FFE3E1", "#FFF5EA", "#FFFFF0", "#FAFFEA", "#EDFFEE", "#CDEAFF", "#DAF0FC", "#E6E6FA", "#CCD6E9", "#DADAEB", "#EAE3F0", "#E2CFE5", "#EFB6D8", "#F7B6D3", "#F98EBD", "#F96898", "#E52F92", "#E01E73", "#D71348", "#DD191D", "#B8002A", "#70001D", "#CCCCCC", "#CDCDCD", "#D4D4D4", "#EBEBEB", "#F0F0F0", "#F2F0EE", "#FEFEFD", "#FEFEFD", "#FBF0DE", "#FEECE0", "#FFF8DC", "#FFFFDF", "#FDFBE8", "#F0F9ED", "#EAF6FA", "#DEEBF7", "#D7E3F2", "#E1E5E6", "#CECEE5", "#CCBEDB", "#D6BAD8", "#DD9FD9", "#EE7EF1", "#E7969B", "#D97190", "#D03E77", "#D2384B", "#D52728", "#A51422", "#980041", "#C0C0C0", "#C6C6C6", "#DAD9D7", "#E5E5DF", "#F2F2EE", "#FCFCFA", "#F4F4DC", "#FBF2E9", "#FEF0D9", "#FFEDD1", "#FFFACD", "#FFFFCE", "#FAF9D0", "#F5FBEF", "#D6F8F1", "#D8E8F2", "#C6DBEF", "#BBD3E6", "#BDBCDB", "#C3AFD4", "#C1A4CE", "#C895C0", "#E276B9", "#BE6B8B", "#D6606C", "#A9494B", "#A9273F", "#C81885", "#B00279", "#8C0355", "#BCBCBC", "#B6B6B6", "#ADADAD", "#DEDAD1", "#D9DBCC", "#ECEDE0", "#F4F0E9", "#F1E2CD", "#F8DFCE", "#FEE6C8", "#FFF5BD", "#FFFFBF", "#F7FCB8", "#E6F5CC", "#E3F4DE", "#CBEAE6", "#AFE0E6", "#AEC7E8", "#B4C6DE", "#C4CED4", "#B1ABD1", "#B884C0", "#D970D6", "#CC6DBA", "#AB8998", "#9F5075", "#52132E", "#912566", "#9901D6", "#820082", "#B2B2B2", "#AAAAAA", "#ACACA9", "#CAC7B9", "#E1E5CD", "#E6D8C1", "#EEE8AB", "#F5E1B8", "#FEDFD0", "#FFDFB7", "#FFEEA7", "#FFFFB3", "#EEF8B0", "#DBECBC", "#BAE4BD", "#B0EDEE", "#A6D9E6", "#9FCBE1", "#A1BCD9", "#A0B1C3", "#9C97C7", "#AA78D3", "#BB55D3", "#A15DBD", "#AA579B", "#7E5195", "#73446D", "#762E89", "#7B0F77", "#46007C", "#A4A4A4", "#A0A0A0", "#A2A2A0", "#ABB09C", "#C4D2A7", "#CEDB9C", "#DADA8B", "#F3CEB0", "#FBC4C0", "#FECEAD", "#FFDDAB", "#FFFF98", "#DCFF9E", "#C7E9B4", "#C6E8BF", "#A4ECC9", "#ACDEDC", "#9ED5DE", "#91C3DD", "#88A8B6", "#8D9BC9", "#A0A0DE", "#B064E2", "#9F33CA", "#934CA0", "#9B6AA4", "#796686", "#663D99", "#502189", "#3D0046", "#939393", "#989898", "#A39B98", "#B7AB98", "#D7C5AA", "#E1DAAC", "#E7C893", "#EEBA9B", "#FCB49F", "#FDD1A0", "#FEDF8E", "#F0E68C", "#DDF195", "#B1EDA3", "#9FEFA7", "#BAE0D2", "#A3C1C1", "#91D5C8", "#80BFCF", "#79ADD1", "#6988D2", "#9475DD", "#912DE8", "#7636BC", "#9169BA", "#8559A5", "#66529C", "#49408B", "#1B1B6E", "#21181B", "#7F7F7F", "#888888", "#A18280", "#C39793", "#D49685", "#D1B589", "#DEBB84", "#F3A682", "#FE9997", "#FDBD85", "#FBCC8B", "#FEDA76", "#F2E76C", "#80FF80", "#99FB99", "#7AE094", "#A4DCB5", "#9CBAAD", "#7ECCC0", "#67A9CE", "#6BAED6", "#89A6E7", "#7D67EF", "#4A43FB", "#6B66CC", "#7C75B0", "#5758A3", "#435F87", "#393B77", "#141F3B", "#777777", "#7A7A7A", "#A5967D", "#BC906E", "#BDB66B", "#DAB165", "#E9987E", "#F79984", "#FFA07A", "#FEBC75", "#FFCB61", "#FFEE6A", "#CCFE63", "#67FF68", "#90EE90", "#A4D99D", "#BCCABB", "#7CC1A6", "#65CBCC", "#62C6E0", "#89CEEB", "#9B8CFF", "#6573FF", "#4169E2", "#5B7EBB", "#5264AF", "#677489", "#4E4C68", "#302B40", "#141922", "#737373", "#6D6D6D", "#797B6C", "#969263", "#AC884E", "#C0A05E", "#DD7B72", "#F08080", "#FC9272", "#FDAD66", "#FDB662", "#FDDB5D", "#F0FF64", "#9CFF63", "#80E064", "#B6E08D", "#98DE8A", "#69BF85", "#66C6A7", "#41B6C2", "#5BBAE8", "#8DCBFC", "#62A5FE", "#6495ED", "#5C97D1", "#467DB4", "#5C819F", "#778695", "#545E66", "#34404D", "#666666", "#7B615C", "#9A6A56", "#9E615D", "#BE6D5F", "#D25B54", "#E56358", "#FA8072", "#FD8F5E", "#F4A560", "#EBCF68", "#F0ED38", "#AEFF2C", "#BCE26E", "#ACD46A", "#A7CB80", "#78C579", "#8EB78D", "#5DB7AE", "#43D8CE", "#76D6EE", "#A0FAFA", "#62D7FF", "#49B1D3", "#4392C5", "#669EB7", "#689E9E", "#728B86", "#3D6359", "#2D4949", "#535353", "#5E5E5E", "#756951", "#8D564A", "#A17340", "#CB7C38", "#DB713A", "#FF6E64", "#FE7F53", "#EC8C5E", "#E9BE50", "#FEB94D", "#FFFE32", "#C0EE3B", "#A7D752", "#93CA60", "#66CF62", "#66BD65", "#5CA963", "#3ABDAD", "#6CE7CC", "#75FFD0", "#61FBF8", "#34D0E7", "#3FA0CB", "#3592BC", "#468CAD", "#44A39F", "#358E89", "#1B4A64", "#454545", "#544F41", "#7A5A3C", "#8C6B31", "#A7761E", "#D16E1F", "#F26945", "#FD6549", "#FC8E3D", "#F0A442", "#FDBF34", "#FED931", "#FCFD00", "#CED03D", "#99CE32", "#7DBF41", "#84B560", "#4EAC4B", "#40AA5B", "#4ECD87", "#63FFA0", "#30F4C4", "#00FEFC", "#389BFB", "#2BA0D8", "#2E82BB", "#3881B8", "#376DAF", "#36669A", "#2B3796", "#3B3B3B", "#404040", "#863C39", "#6B591E", "#A5542A", "#B55F19", "#E24936", "#FC4B35", "#F77725", "#FD9D2E", "#F8961F", "#FFBA05", "#FED400", "#EDCB22", "#BDBF22", "#8AAB33", "#8CA154", "#637263", "#4C8869", "#3FB074", "#22DA65", "#01FC8D", "#00CCD1", "#01BCFB", "#1390FC", "#1A93C8", "#2D6CCC", "#208E9B", "#2262AA", "#293BC5", "#333333", "#3B2D26", "#8C4B13", "#862A22", "#A42E2C", "#C54238", "#EF3825", "#F25A29", "#E67B15", "#FF7F0F", "#FF8C00", "#FFA300", "#D8A522", "#BDA039", "#A29D2C", "#709843", "#5D7134", "#427D41", "#309956", "#2AA660", "#05C356", "#03C58E", "#17BECF", "#00A3D6", "#017EC9", "#167AC1", "#2075B4", "#0E53CE", "#0257FE", "#0300FF", "#2C2C2C", "#252525", "#3D291A", "#864709", "#AC361D", "#B32322", "#D72F25", "#DC3C13", "#E55B0E", "#FF6801", "#FF7F00", "#F69C09", "#E8AD03", "#D4B111", "#9BB80F", "#6B9B21", "#4E9121", "#438832", "#238C21", "#208040", "#19974B", "#199D75", "#20B1A9", "#00A3B2", "#0084B1", "#066FAD", "#116D96", "#236688", "#003EC1", "#0223F3", "#222222", "#22251D", "#5B2C05", "#8F2E03", "#A83403", "#C12116", "#E81C16", "#E64408", "#F55300", "#E77800", "#DF8801", "#D39A00", "#C9A900", "#7A7D01", "#6FAE05", "#4FAA28", "#34CE34", "#2EA02C", "#2A631A", "#11381E", "#018C3A", "#00966B", "#009299", "#018989", "#005FA0", "#08509B", "#012F8B", "#0F2887", "#1F1194", "#0200CB", "#1A1A1A", "#111111", "#040101", "#270500", "#7D1F12", "#B30000", "#E40F09", "#FF1F1D", "#FB4300", "#EC6400", "#C07704", "#B9860B", "#BFB500", "#AFC200", "#7AE400", "#65EE00", "#2FFA0B", "#2BCE16", "#129418", "#116213", "#004C1D", "#006732", "#016855", "#00807B", "#077D96", "#035A8C", "#0B437E", "#073068", "#091D4E", "#02018E", "#080808", "#000000", "#0A0606", "#7A0100", "#8F0100", "#CB0500", "#FF0100", "#FC2E00", "#D34901", "#D95F02", "#B25A05", "#9D9700", "#A0D000", "#8FDB00", "#7EFE01", "#4BF600", "#00FD00", "#04B501", "#058400", "#026402", "#053C00", "#00402F", "#01625B", "#006374", "#024E7D", "#014461", "#013555", "#05041F", "#05045A", "#00017F"];
var counts = [65, 35, 224, 26, 1, 91, 23, 1, 38, 49, 31, 1, 27, 55, 68, 52, 18, 5, 55, 37, 7, 86, 66, 36, 49, 79, 22, 12, 24, 47, 28, 4, 50, 195, 36, 52, 1415, 11, 51, 36, 25, 1, 28, 42, 7, 25, 15, 55, 40, 32, 43, 31, 38, 27, 56, 34, 50, 107, 45, 54, 446, 4, 40, 8, 46, 2, 1, 1, 54, 24, 39, 66, 14, 1, 66, 40, 6, 27, 30, 1, 60, 60, 36, 30, 38, 19, 35, 45, 49, 47, 40, 50, 1, 1, 2, 125, 35, 30, 15, 54, 26, 46, 32, 35, 3, 34, 84, 49, 66, 73, 15, 28, 96, 21, 40, 40, 21, 69, 15, 20, 150, 23, 2, 15, 14, 3, 2, 13, 6, 58, 23, 47, 17, 28, 57, 31, 34, 32, 38, 13, 14, 37, 29, 39, 14, 22, 18, 19, 40, 102, 24, 221, 1, 17, 17, 17, 30, 41, 40, 63, 37, 48, 29, 21, 17, 29, 73, 96, 38, 62, 53, 7, 27, 19, 57, 29, 70, 29, 18, 57, 14, 10, 1, 19, 7, 27, 33, 5, 15, 16, 40, 34, 9, 18, 84, 14, 34, 3, 40, 20, 31, 36, 3, 36, 50, 36, 35, 29, 46, 46, 7, 255, 1, 21, 30, 14, 47, 8, 38, 59, 68, 26, 64, 1, 2, 22, 9, 44, 1, 64, 11, 32, 33, 4, 59, 28, 75, 30, 43, 21, 77, 88, 5, 69, 8, 34, 37, 23, 46, 55, 19, 29, 2, 1, 27, 6, 27, 2, 53, 18, 83, 8, 27, 17, 63, 132, 58, 20, 38, 35, 282, 9, 24, 8, 34, 16, 35, 1, 25, 47, 36, 39, 38, 59, 28, 94, 11, 5, 13, 6, 33, 9, 29, 29, 21, 51, 26, 19, 17, 29, 36, 17, 20, 12, 10, 6, 8, 26, 13, 79, 42, 27, 28, 28, 2, 66, 36, 3, 62, 31, 25, 51, 37, 28, 23, 72, 6, 61, 18, 35, 235, 4, 4, 50, 18, 52, 20, 57, 67, 27, 17, 14, 27, 44, 67, 7, 91, 41, 17, 56, 12, 16, 29, 30, 64, 17, 47, 21, 16, 36, 135, 12, 21, 36, 12, 77, 14, 17, 33, 19, 48, 57, 23, 2, 24, 26, 7, 53, 22, 7, 4, 53, 52, 1, 16, 24, 4, 21, 33, 14, 129, 11, 12, 32, 30, 34, 55, 45, 76, 36, 18, 23, 56, 7, 37, 35, 13, 34, 19, 5, 36, 1, 53, 16, 27, 155, 46, 22, 44, 47, 14, 25, 35, 14, 60, 27, 31, 45, 11, 33, 10, 10, 53, 2, 42, 8, 34, 9, 10, 43, 12, 64, 37, 46, 55, 32, 21, 17, 45, 7, 299, 4, 32, 13, 45, 23, 50, 17, 39, 55, 54, 46, 35, 36, 5, 10, 66, 17, 74, 29, 15, 5, 35, 42, 26, 3, 127, 5, 12, 93, 11, 42, 16, 27, 20, 31, 74, 11, 65, 17, 36, 7, 34, 5, 6, 60, 17, 7, 28, 52, 49, 46, 30, 17, 18, 73, 4, 30, 15, 8, 249, 8, 32, 51, 18, 3, 11, 3, 42, 51, 50, 46, 40, 32, 28, 15, 35, 60, 23, 15, 21, 17, 14, 45, 27, 70, 25, 27, 7, 52, 31, 72, 1, 17, 15, 62, 6, 24, 61, 54, 6, 27, 43, 53, 58, 52, 13, 9, 10, 4, 30, 66, 25, 45, 5, 25, 25, 61, 36, 52, 27, 1497, 1, 60, 75, 30, 201, 35, 51, 36, 15, 6, 45, 48, 52, 45, 70, 30, 60, 48, 15, 42, 24, 1, 28, 11, 25, 23, 11, 31];
//svg sizes and margins
var margin = {left: 50, top: 50, right: 0, bottom: -30},
width = 920,
height = 550;
//The number of columns and rows of the heatmap
var MapColumns = 30,
MapRows = 20;
///////////////////////////////////////////////////////////////////////////
/////////////////////// Create hexagon variables //////////////////////////
///////////////////////////////////////////////////////////////////////////
//The maximum radius the hexagons can have to still fit the screen
var hexRadius = d3.min([width/(Math.sqrt(3)*(MapColumns+3)),
height/((MapRows+3)*1.5)]);
//Set the new height and width based on the max possible
//width = MapColumns*hexRadius*Math.sqrt(3);
//heigth = MapRows*1.5*hexRadius;//+0.5*hexRadius;
//Scale for the min and max hex sizes, based on circular sqrt
var hexSize = d3.scale.sqrt()
.range([hexRadius*0.1,hexRadius*4])
.domain([d3.min(counts), d3.max(counts)]);
//Initiate hexbin
var hexbin = d3.hexbin()
.radius(hexRadius)
.size([width, height])
.x(function(d) { return d.xPos; })
.y(function(d) { return d.yPos; });
//Calculate the center positions of each hexagon
var points = [],
counter = 0;
for (var i = 0; i < MapRows; i++) {
for (var j = 0; j < MapColumns; j++) {
points[counter] = {
xPos: hexRadius * j * 1.75,
yPos: hexRadius * i * 1.5,
color: color[counter],
counts: counts[counter]
}
counter = counter + 1;
}//for j
}//for i
///////////////////////////////////////////////////////////////////////////
////////////////////////////// Initiate SVG ///////////////////////////////
///////////////////////////////////////////////////////////////////////////
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
///////////////////////////////////////////////////////////////////////////
////////////////////// Draw hexagons and color them ///////////////////////
///////////////////////////////////////////////////////////////////////////
//Create the hexbin data
var hexData = hexbin(points);
//Add extra data to the hexbin result
hexData.forEach(function(d,i) {
d.color = points[i].color;
d.counts = points[i].counts;
});
//Sort from biggest to smallest hexbin
hexData.sort(function(a, b) { return b.counts - a.counts; })
//Start drawing the hexagons
svg.append("g")
.selectAll(".hexagon")
.data(hexData)
.enter().append("path")
.attr("class", "hexagon")
.attr("d", function (d,i) {return "M" + d.x + "," + d.y + hexbin.hexagon(hexSize(d.counts)); })
.attr("stroke", function (d,i) { return d3.rgb(d.color).darker(1.5); })
.attr("stroke-opacity", "0.5")
.attr("stroke-width", "1px")
.style("fill", function (d,i) { return d.color; })
.on("mouseover", mover)
.on("mouseout", mout);
///////////////////////////////////////////////////////////////////////////
///////////////// Mouse over and Mouse out functions //////////////////////
///////////////////////////////////////////////////////////////////////////
//Function to call when you mouseover a node
function mover(d,i) {
$(this).popover({
placement: 'auto top', //place the tooltip above the item
container: '#chart', //the name (class or id) of the container
trigger: 'manual',
html : true,
content: function() { //the html content to show inside the tooltip
return "<span>" + d.color + "</span>"; }
});
$(this).popover('show');
}
//Mouseout function
function mout(d,i) {
//Hide the tooltip
$('.popover').each(function() {
$(this).remove();
});
};
////////////////////////////////////////////////////////////
////////////////// Button Activity /////////////////////////
////////////////////////////////////////////////////////////
/* Activate the buttons and link to data sets */
d3.select("#diffSizeButton").on("click", function () {
d3.selectAll(".hexagon")
.transition().duration(500)
.attr("d", function (d,i) {return "M" + d.x + "," + d.y + hexbin.hexagon(hexSize(d.counts)); })
.attr("stroke", function (d,i) { return d3.rgb(d.color).darker(1.5); })
.attr("stroke-opacity", "0.5");
});
d3.select("#sameSizeButton").on("click", function() {
d3.selectAll(".hexagon")
.transition().duration(500)
.attr("d", function (d,i) {return "M" + d.x + "," + d.y + hexbin.hexagon(); })
.attr("stroke", function (d,i) { return d.color })
.attr("stroke-opacity", "1");
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment