diff --git a/src/traces/heatmap/calc.js b/src/traces/heatmap/calc.js index 32a82f76d3c..9b362500b05 100644 --- a/src/traces/heatmap/calc.js +++ b/src/traces/heatmap/calc.js @@ -67,10 +67,10 @@ module.exports = function calc(gd, trace) { y = trace.y ? ya.makeCalcdata(trace, 'y') : []; } - x0 = trace.x0 || 0; - dx = trace.dx || 1; - y0 = trace.y0 || 0; - dy = trace.dy || 1; + x0 = trace.x0; + dx = trace.dx; + y0 = trace.y0; + dy = trace.dy; z = clean2dArray(zIn, trace.transpose); diff --git a/src/traces/heatmap/make_bound_array.js b/src/traces/heatmap/make_bound_array.js index 84e09b1ce43..7abc1f6cd2e 100644 --- a/src/traces/heatmap/make_bound_array.js +++ b/src/traces/heatmap/make_bound_array.js @@ -63,20 +63,20 @@ module.exports = function makeBoundArray(trace, arrayIn, v0In, dvIn, numbricks, } } else { - dv = dvIn || 1; - var calendar = trace[ax._id.charAt(0) + 'calendar']; - if(isHist || ax.type === 'category' || ax.type === 'multicategory') { - v0 = ax.r2c(v0In, 0, calendar) || 0; - } else if(isArrayOrTypedArray(arrayIn) && arrayIn.length === 1) { + if(isArrayOrTypedArray(arrayIn) && arrayIn.length === 1) { v0 = arrayIn[0]; } else if(v0In === undefined) { v0 = 0; + } else if(isHist || ax.type === 'category' || ax.type === 'multicategory') { + v0 = ax.r2c(v0In, 0, calendar); } else { v0 = ax.d2c(v0In, 0, calendar); } + dv = dvIn || 1; + for(i = (isContour || isGL2D) ? 0 : -0.5; i < numbricks; i++) { arrayOut.push(v0 + dv * i); } diff --git a/test/image/baselines/heatmap-with-zero-category.png b/test/image/baselines/heatmap-with-zero-category.png new file mode 100644 index 00000000000..765ce76bd2a Binary files /dev/null and b/test/image/baselines/heatmap-with-zero-category.png differ diff --git a/test/image/mocks/heatmap-with-zero-category.json b/test/image/mocks/heatmap-with-zero-category.json new file mode 100644 index 00000000000..1280d125837 --- /dev/null +++ b/test/image/mocks/heatmap-with-zero-category.json @@ -0,0 +1,32 @@ +{ + "data": [ + { + "x": [ 3, 2, 1, 0 ], + "y": [ 3, 2, 1, 0 ], + "z": [ + [ 98, 97, 96, null ], + [ 88, 87, 86, null ], + [ 78, 77, 76, null ], + [ null, null, null, null ] + ], + "type": "heatmap", + "colorscale": [ + [ 0, "#3D9970" ], + [ 1, "#001f3f" ] + ], + "showscale": false, + "xgap": 1, + "ygap": 1 + } + ], + "layout": { + "height": 450, + "width": 650, + "xaxis": { + "type": "category" + }, + "yaxis": { + "type": "category" + } + } +} diff --git a/test/jasmine/tests/heatmap_test.js b/test/jasmine/tests/heatmap_test.js index c6db00e0da5..0ae0005be82 100644 --- a/test/jasmine/tests/heatmap_test.js +++ b/test/jasmine/tests/heatmap_test.js @@ -287,10 +287,11 @@ describe('heatmap convertColumnXYZ', function() { describe('heatmap calc', function() { 'use strict'; - function _calc(opts) { + function _calc(opts, layout) { var base = { type: 'heatmap' }; var trace = Lib.extendFlat({}, base, opts); var gd = { data: [trace] }; + if(layout) gd.layout = layout; supplyAllDefaults(gd); var fullTrace = gd._fullData[0]; @@ -408,6 +409,20 @@ describe('heatmap calc', function() { expect(out.z).toBeCloseTo2DArray([[17, 18, 19]]); }); + it('should handle the category case (edge case with a *0* category)', function() { + var out = _calc({ + x: ['a', 'b', 0], + y: ['z', 0, 'y'], + z: [[17, 18, 19], [10, 20, 30], [40, 30, 20]] + }, { + xaxis: {type: 'category'}, + yaxis: {type: 'category'} + }); + + expect(out.x).toBeCloseToArray([-0.5, 0.5, 1.5, 2.5]); + expect(out.y).toBeCloseToArray([-0.5, 0.5, 1.5, 2.5]); + }); + it('should handle the category x/y/z/ column case', function() { var out = _calc({ x: ['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c'],