Last active
August 29, 2015 14:24
-
-
Save amergin/77d81f53f509bbc35e21 to your computer and use it in GitHub Desktop.
Stretch available color range to be used based on the values
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Specs: | |
// - As a default, the colour range should be scaled so, that at least 70% (..ish) of the colour range is available for the data shown. | |
// Example: we have a map with lowest positive correlation at r=0.85 and highest at r=0.99 while the negative correlations span from r=-0.2 to r=-0.35. The desired colour range would then be as follows: | |
// 100% red at r=0.99, | |
// 30% red at r=0.85, | |
// white at r=0, | |
// 30% blue at r=-0.2 and | |
// 100% blue at r=-0.35. | |
function CustomScale() { | |
var obj = {}, | |
priv = { | |
coordinates: [], | |
interpolated: {}, | |
lower: { | |
min: null, | |
max: null | |
}, | |
upper: { | |
min: null, | |
max: null | |
}, | |
constant: { | |
lower: null, | |
middle: null, | |
upper: null, | |
threshold: 0.3 | |
} | |
}; | |
function getName(coord, reverse) { | |
if(reverse) { | |
return [coord.y, coord.x].join("|"); | |
} else { | |
return [coord.x, coord.y].join("|"); | |
} | |
} | |
function computeInterpolated() { | |
var thre = priv.constant.threshold, | |
correlation; | |
_.each(priv.coordinates, function(coord) { | |
correlation = coord.corr; | |
if(correlation > 0) { | |
priv.interpolated[getName(coord)] = (thre) + (1-thre) * ( correlation - priv.upper.min ) / (priv.upper.max - priv.upper.min); | |
} | |
else if(correlation < 0) { | |
priv.interpolated[getName(coord)] = -(thre) - (1-thre) * ( correlation - priv.lower.min ) / (priv.lower.max - priv.lower.min); | |
} | |
}); | |
} | |
function computeMaxMin() { | |
var lowerExtent = d3.extent(priv.coordinates, function(d) { | |
if(d.corr > 0) { return undefined; } | |
return d.corr; | |
}); | |
var upperExtent = d3.extent(priv.coordinates, function(d) { | |
if(d.corr < 0) { return undefined; } | |
return d.corr; | |
}); | |
priv.lower.min = _.isUndefined(lowerExtent[0]) ? priv.constant.lower : lowerExtent[0]; | |
priv.lower.max = _.isUndefined(lowerExtent[1]) ? priv.constant.upper : lowerExtent[1]; | |
priv.upper.min = upperExtent[0]; | |
priv.upper.max = upperExtent[1]; | |
} | |
obj.lower = function(x) { | |
if(!arguments.length) { return priv.constant.lower; } | |
priv.constant.lower = x; | |
return obj; | |
}; | |
obj.middle = function(x) { | |
if(!arguments.length) { return priv.constant.middle; } | |
priv.constant.middle = x; | |
return obj; | |
}; | |
obj.upper = function(x) { | |
if(!arguments.length) { return priv.constant.upper; } | |
priv.constant.upper = x; | |
return obj; | |
}; | |
obj.threshold = function(x) { | |
if(!arguments.length) { return priv.constant.threshold; } | |
priv.constant.threshold = x; | |
return obj; | |
}; | |
// get color value | |
obj.color = function(obj) { | |
var red, green, blue, | |
interp = priv.interpolated[getName(obj)]; | |
interp = _.isUndefined(interp) ? priv.interpolated[getName(obj, true)] : interp; | |
if(interp > 0) { | |
// upper, red | |
red = 255; | |
green = 255 * (1 - interp); | |
blue = 255 * (1 - interp); | |
} else { | |
// lower, blue | |
red = 255 * (1 + interp); | |
green = 255 * (1 + interp); | |
blue = 255; | |
} | |
return d3.rgb(red, green, blue).toString(); | |
}; | |
obj.coordinates = function(x) { | |
if(!arguments.length) { return priv.coordinates; } | |
priv.coordinates = x; | |
computeMaxMin(); | |
computeInterpolated(); | |
return obj; | |
}; | |
return obj; | |
} | |
var scale = new CustomScale() | |
.lower(-1) | |
.middle(0) | |
.upper(1) | |
.threshold(0.25); | |
// call to get value | |
var color = scale.color(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment