-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
[Feature][Proposal] create_annotated_heatmap for JS #4116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
CodePen: https://codepen.io/mafar/pen/RXBpXO?editors=0010 Implementation:
I am sure it can be now easily integrated in plotly 'use strict';
//
// https://github.com/plotly/plotly.js/issues/4116
// [Feature][Proposal] create_annotated_heatmap for JS
//
/*
copied from _annotated_heatmap.py
src: https://github.com/plotly/plotly.py/blob/master/packages/python/plotly/plotly/figure_factory/_annotated_heatmap.py
*/
//
// copied from _annotated_heatmap.py
//
function get_z_mid(z) {
var z_max = Math.max.apply(
null,
z.map(function (row) {
return Math.max.apply(Math, row);
})
);
var z_min = Math.min.apply(
null,
z.map(function (row) {
return Math.min.apply(Math, row);
})
);
var z_mid = (z_max + z_min) / 2;
return z_mid;
}
// custom function
function hexToRgb(hex) {
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function (m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
var r = parseInt(result[1], 16);
var g = parseInt(result[2], 16);
var b = parseInt(result[3], 16);
return result ? [r, g, b] : null;
}
//
// copied from _annotated_heatmap.py
//
function to_rgb_color_list(color_str, Default) {
if (color_str.includes('rgb')) {
return color_str.replace(/[^0-9.,]+/g, '').split(',');
} else if (color_str.includes('#')) {
return hexToRgb(color_str);
} else {
return Default;
}
}
//
// copied from _annotated_heatmap.py
//
function should_use_black_text(background_color) {
return (
background_color[0] * 0.299 +
background_color[1] * 0.587 +
background_color[2] * 0.114
) > 186;
}
//
// copied from _annotated_heatmap.py
//
function get_text_color(colorscale, reversescale) {
var white = '#FFFFFF';
var black = '#000000';
var colorscales = ['Greys', 'Greens', 'Blues', 'YIGnBu', 'YIOrRd', 'RdBu', 'Picnic', 'Jet', 'Hot', 'Blackbody', 'Earth', 'Electric', 'Viridis', 'Cividis'];
var colorscales_reverse = ['Reds'];
var min_text_color = black;
var max_text_color = black;
if ((colorscales.indexOf(colorscale) > -1) && reversescale) {
min_text_color = black;
max_text_color = white;
} else if ((colorscales.indexOf(colorscale) > -1)) {
min_text_color = white;
max_text_color = black;
} else if ((colorscales_reverse.indexOf(colorscale) > -1) && reversescale) {
min_text_color = white;
max_text_color = black;
} else if ((colorscales_reverse.indexOf(colorscale) > -1)) {
min_text_color = black;
max_text_color = white;
} else if (Array.isArray(colorscale)) {
var _min_col = to_rgb_color_list(colorscale.slice(0)[0][1], [255, 255, 255]);
var _max_col = to_rgb_color_list(colorscale.slice(-1)[0][1], [255, 255, 255]);
var min_col = _min_col;
var max_col = _max_col;
if (reversescale) {
// swap min max
min_col = _max_col;
max_col = _min_col;
}
if (should_use_black_text(min_col)) {
min_text_color = black;
} else {
min_text_color = white;
}
if (should_use_black_text(max_col)) {
max_text_color = black;
} else {
max_text_color = white;
}
}
return [min_text_color, max_text_color];
}
//
// copied from _annotated_heatmap.py
//
function make_annotations(_x, _y, _z, colorscale) {
var text_colors = get_text_color(colorscale);
var min_text_color = text_colors[0];
var max_text_color = text_colors[1];
var z_mid = get_z_mid(_z);
var annotations = [];
for (var n = 0; n < _z.length; n++) {
var row = _z[n];
for (var m = 0; m < row.length; m++) {
var val = row[m];
var font_color = (val < z_mid) ? min_text_color : max_text_color;
annotations.push({
xref: 'x1',
yref: 'y1',
x: _x[m],
y: _y[n],
text: _z[n][m],
font: {
family: 'Arial',
size: 12,
color: font_color
},
showarrow: false
});
}
}
return annotations;
}
//
// Draw Plot
//
var xValues = ['A', 'B', 'C', 'D', 'E'];
var yValues = ['W', 'X', 'Y', 'Z'];
var zValues = [
[0.0, 0.0, 0.75, 0.75, 0.0],
[0.0, 0.0, 0.75, 0.75, 0.0],
[0.75, 0.75, 0.75, 0.75, 0.75],
[0.0, 0.0, 0.0, 0.75, 0.0]
];
var colorscale = [
[0, '#3D9970'],
[1, '#001f3f']
];
//var colorscale = 'Viridis';
var data = [{
x: xValues,
y: yValues,
z: zValues,
type: 'heatmap',
colorscale: colorscale,
showscale: false
}];
var layout = {
title: 'Correlation Matrix auto_annotated',
annotations: make_annotations(xValues, yValues, zValues, colorscale)
};
Plotly.newPlot('myDiv', data, layout); |
duplicate of #1116 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Dear Devs,
For Correlation matrix Graph, It is important that annotations are always displayed inside heatmap
like these
https://plot.ly/~cvillamil/4/annotated-heatmap/#/
https://codepen.io/plotly/pen/RPdwaz
Python Support:
Since there is nice function in python already,
ff.create_annotated_heatmap(z)
Javascript Support:
Same should be supported in javascript , instead of workaround where one has to loop throught and create annotations manually
My suggestion would be to create a new Trace type
Correlation
which could be sub type of heatmap originThe text was updated successfully, but these errors were encountered: