diff --git a/draftlogs/6625_fix.md b/draftlogs/6625_fix.md new file mode 100644 index 00000000000..b97c3ef3b0d --- /dev/null +++ b/draftlogs/6625_fix.md @@ -0,0 +1 @@ + - Fix contour plot colorscale domain (take account of [zmin, zmax] and [cmin, cmax]) [[#6625](https://github.com/plotly/plotly.js/pull/6625)], with thanks to @lvlte for the contribution! diff --git a/src/components/colorbar/draw.js b/src/components/colorbar/draw.js index f0b551781ec..1aed5caaf13 100644 --- a/src/components/colorbar/draw.js +++ b/src/components/colorbar/draw.js @@ -512,7 +512,7 @@ function drawColorBar(g, opts, gd) { .data(fillLevels); fills.enter().append('rect') .classed(cn.cbfill, true) - .style('stroke', 'none'); + .attr('style', ''); fills.exit().remove(); var zBounds = zrange diff --git a/src/traces/contour/make_color_map.js b/src/traces/contour/make_color_map.js index 46cc9f10a28..628d14bb05d 100644 --- a/src/traces/contour/make_color_map.js +++ b/src/traces/contour/make_color_map.js @@ -29,10 +29,10 @@ module.exports = function makeColorMap(trace) { var si, i; - if(contours.coloring === 'heatmap') { - var zmin0 = cOpts.min; - var zmax0 = cOpts.max; + var zmin0 = cOpts.min; + var zmax0 = cOpts.max; + if(contours.coloring === 'heatmap') { for(i = 0; i < len; i++) { si = scl[i]; domain[i] = si[0] * (zmax0 - zmin0) + zmin0; @@ -60,11 +60,37 @@ module.exports = function makeColorMap(trace) { range.push(range[range.length - 1]); } } else { + var zRangeInput = trace._input && ( + typeof trace._input.zmin === 'number' && typeof trace._input.zmax === 'number' + ); + + // If zmin/zmax are explicitly set, consider case where user specifies a + // narrower z range than that of the contours start/end. + if(zRangeInput && (start <= zmin0 || end >= zmax0)) { + if(start <= zmin0) start = zmin0; + if(end >= zmax0) end = zmax0; + nc = Math.floor((end - start) / cs) + 1; + extra = 0; + } + for(i = 0; i < len; i++) { si = scl[i]; domain[i] = (si[0] * (nc + extra - 1) - (extra / 2)) * cs + start; range[i] = si[1]; } + + // Make the colorscale fit the z range except if contours are explicitly + // set BUT NOT zmin/zmax. + if(zRangeInput || trace.autocontour) { + if(domain[0] > zmin0) { + domain.unshift(zmin0); + range.unshift(range[0]); + } + if(domain[domain.length - 1] < zmax0) { + domain.push(zmax0); + range.push(range[range.length - 1]); + } + } } return Colorscale.makeColorScaleFunc( diff --git a/test/image/baselines/25.png b/test/image/baselines/25.png index 1f4b2559637..58d6eebf76f 100644 Binary files a/test/image/baselines/25.png and b/test/image/baselines/25.png differ diff --git a/test/image/baselines/airfoil.png b/test/image/baselines/airfoil.png index 43af2ef7660..fc54f8d49c7 100644 Binary files a/test/image/baselines/airfoil.png and b/test/image/baselines/airfoil.png differ diff --git a/test/image/baselines/axes_breaks-contour1d.png b/test/image/baselines/axes_breaks-contour1d.png index 198ddf4efc7..bca25228582 100644 Binary files a/test/image/baselines/axes_breaks-contour1d.png and b/test/image/baselines/axes_breaks-contour1d.png differ diff --git a/test/image/baselines/axes_breaks-contour2d.png b/test/image/baselines/axes_breaks-contour2d.png index ceaba1b0d41..2f47465c593 100644 Binary files a/test/image/baselines/axes_breaks-contour2d.png and b/test/image/baselines/axes_breaks-contour2d.png differ diff --git a/test/image/baselines/cheater_contour.png b/test/image/baselines/cheater_contour.png index 35797b708a4..47145b31256 100644 Binary files a/test/image/baselines/cheater_contour.png and b/test/image/baselines/cheater_contour.png differ diff --git a/test/image/baselines/colorbar_tick_prefix_suffix.png b/test/image/baselines/colorbar_tick_prefix_suffix.png index bb90ed014c3..b3c554cc744 100644 Binary files a/test/image/baselines/colorbar_tick_prefix_suffix.png and b/test/image/baselines/colorbar_tick_prefix_suffix.png differ diff --git a/test/image/baselines/colorbar_tickformat.png b/test/image/baselines/colorbar_tickformat.png index a10a26ad90d..bade0882381 100644 Binary files a/test/image/baselines/colorbar_tickformat.png and b/test/image/baselines/colorbar_tickformat.png differ diff --git a/test/image/baselines/colorscale_opacity.png b/test/image/baselines/colorscale_opacity.png index c83fac98f0d..ae24116449f 100644 Binary files a/test/image/baselines/colorscale_opacity.png and b/test/image/baselines/colorscale_opacity.png differ diff --git a/test/image/baselines/contour_label-formatting-via-colorbar.png b/test/image/baselines/contour_label-formatting-via-colorbar.png index 8711a66fa01..18cc961a474 100644 Binary files a/test/image/baselines/contour_label-formatting-via-colorbar.png and b/test/image/baselines/contour_label-formatting-via-colorbar.png differ diff --git a/test/image/baselines/contour_lines_coloring.png b/test/image/baselines/contour_lines_coloring.png index e39ad45508b..e21c91daeaf 100644 Binary files a/test/image/baselines/contour_lines_coloring.png and b/test/image/baselines/contour_lines_coloring.png differ diff --git a/test/image/baselines/contour_match_edges.png b/test/image/baselines/contour_match_edges.png index b1f09ff50d3..c450a0058ad 100644 Binary files a/test/image/baselines/contour_match_edges.png and b/test/image/baselines/contour_match_edges.png differ diff --git a/test/image/baselines/contour_nolines.png b/test/image/baselines/contour_nolines.png index 4dc0d43d79a..0f3afcb3e9c 100644 Binary files a/test/image/baselines/contour_nolines.png and b/test/image/baselines/contour_nolines.png differ diff --git a/test/image/baselines/contour_transposed.png b/test/image/baselines/contour_transposed.png index 643b12cf919..fe5e3894aac 100644 Binary files a/test/image/baselines/contour_transposed.png and b/test/image/baselines/contour_transposed.png differ diff --git a/test/image/baselines/contour_valid_ses.png b/test/image/baselines/contour_valid_ses.png index 839cddf381d..84abddb11fe 100644 Binary files a/test/image/baselines/contour_valid_ses.png and b/test/image/baselines/contour_valid_ses.png differ diff --git a/test/image/baselines/contour_xyz-gaps-on-sides.png b/test/image/baselines/contour_xyz-gaps-on-sides.png index 69bd93bc06b..017b24f5aec 100644 Binary files a/test/image/baselines/contour_xyz-gaps-on-sides.png and b/test/image/baselines/contour_xyz-gaps-on-sides.png differ diff --git a/test/image/baselines/h-colorbar_airfoil.png b/test/image/baselines/h-colorbar_airfoil.png index ce648549155..2d914afe645 100644 Binary files a/test/image/baselines/h-colorbar_airfoil.png and b/test/image/baselines/h-colorbar_airfoil.png differ diff --git a/test/image/baselines/h-colorbar_contour_xyz-gaps-on-sides.png b/test/image/baselines/h-colorbar_contour_xyz-gaps-on-sides.png index abb80ad29d6..31855cc95b3 100644 Binary files a/test/image/baselines/h-colorbar_contour_xyz-gaps-on-sides.png and b/test/image/baselines/h-colorbar_contour_xyz-gaps-on-sides.png differ diff --git a/test/image/baselines/h-colorbar_tickformat.png b/test/image/baselines/h-colorbar_tickformat.png index d1aadf86992..5c61b93e7dd 100644 Binary files a/test/image/baselines/h-colorbar_tickformat.png and b/test/image/baselines/h-colorbar_tickformat.png differ diff --git a/test/image/baselines/h-colorbar_tickformat_with-border.png b/test/image/baselines/h-colorbar_tickformat_with-border.png index 50319979079..6ba06d30518 100644 Binary files a/test/image/baselines/h-colorbar_tickformat_with-border.png and b/test/image/baselines/h-colorbar_tickformat_with-border.png differ diff --git a/test/image/baselines/heatmap_multicategory.png b/test/image/baselines/heatmap_multicategory.png index 17bd9f3b79a..5c8de53afe6 100644 Binary files a/test/image/baselines/heatmap_multicategory.png and b/test/image/baselines/heatmap_multicategory.png differ diff --git a/test/image/baselines/histogram2dcontour_bingroup-coloraxis.png b/test/image/baselines/histogram2dcontour_bingroup-coloraxis.png index 79f69be2935..9d69e5b39b0 100644 Binary files a/test/image/baselines/histogram2dcontour_bingroup-coloraxis.png and b/test/image/baselines/histogram2dcontour_bingroup-coloraxis.png differ diff --git a/test/image/baselines/multicategory_histograms.png b/test/image/baselines/multicategory_histograms.png index aceced2218c..88def1eb978 100644 Binary files a/test/image/baselines/multicategory_histograms.png and b/test/image/baselines/multicategory_histograms.png differ diff --git a/test/image/baselines/shared_coloraxes_contour.png b/test/image/baselines/shared_coloraxes_contour.png index 2ed8e505cf8..06e03a9c943 100644 Binary files a/test/image/baselines/shared_coloraxes_contour.png and b/test/image/baselines/shared_coloraxes_contour.png differ diff --git a/test/jasmine/tests/colorbar_test.js b/test/jasmine/tests/colorbar_test.js index 99329d1d52e..99fa90e5e5b 100644 --- a/test/jasmine/tests/colorbar_test.js +++ b/test/jasmine/tests/colorbar_test.js @@ -529,19 +529,19 @@ describe('Test colorbar:', function() { return attrs; } - var z = [[1, 10], [100, 1000]]; + var mock = require('../../image/mocks/contour_transposed'); + var z = mock.data[0].z; var expectedAttrs; var actualAttrs; - Plotly.newPlot(gd, [{type: 'contour', z: z}]) + Plotly.newPlot(gd, mock) .then(function() { expectedAttrs = getCBFillAttributes(); - - return Plotly.newPlot(gd, [{type: 'heatmap', z: z}]) - .then(function() { - return Plotly.react(gd, [{type: 'contour', z: z}]); - }); + return Plotly.newPlot(gd, [{type: 'heatmap', z: z}]); + }) + .then(function() { + return Plotly.react(gd, mock); }) .then(function() { actualAttrs = getCBFillAttributes(); diff --git a/test/jasmine/tests/contour_test.js b/test/jasmine/tests/contour_test.js index e31f333f637..ae098a30702 100644 --- a/test/jasmine/tests/contour_test.js +++ b/test/jasmine/tests/contour_test.js @@ -120,7 +120,22 @@ describe('contour defaults', function() { describe('contour makeColorMap', function() { 'use strict'; - it('should make correct color map function (\'fill\' coloring case)', function() { + function _makeColorMap(trace) { + trace.type = 'contour'; + if(trace.z === undefined) { + trace.z = [[0]]; // dummy data for calc to work properly + } + var gd = { data: [trace] }; + supplyAllDefaults(gd); + + var fullTrace = gd._fullData[0]; + fullTrace._extremes = {}; + Contour.calc(gd, fullTrace); + + return makeColorMap(fullTrace); + } + + it('should make correct color map function (\'fill\' coloring case 1)', function() { var trace = { contours: { coloring: 'fill', @@ -141,7 +156,7 @@ describe('contour makeColorMap', function() { ]] }; - var colorMap = makeColorMap(trace); + var colorMap = _makeColorMap(trace); expect(colorMap.domain()).toEqual( [-1.75, -0.75, 0.25, 1.25, 2.25] @@ -151,6 +166,56 @@ describe('contour makeColorMap', function() { 'rgb(12,51,131)', 'rgb(10,136,186)', 'rgb(242,211,56)', 'rgb(242,143,56)', 'rgb(217,30,30)' ]); + + // Set lower/upper bounds of the color domain via zmin/zmax + trace.zmin = -5; + trace.zmax = 5; + + colorMap = _makeColorMap(trace); + + expect(colorMap.domain()).toEqual( + [-5, -1.75, -0.75, 0.25, 1.25, 2.25, 5] + ); + + expect(colorMap.range()).toEqual([ + 'rgb(12,51,131)', 'rgb(12,51,131)', 'rgb(10,136,186)', 'rgb(242,211,56)', + 'rgb(242,143,56)', 'rgb(217,30,30)', 'rgb(217,30,30)' + ]); + }); + + it('should make correct color map function (\'fill\' coloring case 2)', function() { + var trace = { + z: [[0, 1]], + autocontour: true, + contours: { + coloring: 'fill' + }, + colorscale: colorScales.RdBu, + }; + + var colorMap = _makeColorMap(trace); + var domain = colorMap.domain(); + var range = colorMap.range(); + + expect(domain[0]).toBe(0); + expect(domain[domain.length - 1]).toBe(1); + + expect(range[0]).toBe('rgb(5,10,172)'); + expect(range[range.length - 1]).toBe('rgb(178,10,28)'); + + // Set lower/upper bounds of the color domain via zmin/zmax + trace.zmin = -1; + trace.zmax = 2; + + colorMap = _makeColorMap(trace); + domain = colorMap.domain(); + range = colorMap.range(); + + expect(domain[0]).toBe(trace.zmin); + expect(domain[domain.length - 1]).toBe(trace.zmax); + + expect(range[0]).toBe('rgb(5,10,172)'); + expect(range[range.length - 1]).toBe('rgb(178,10,28)'); }); it('should make correct color map function (\'heatmap\' coloring case)', function() { @@ -166,7 +231,7 @@ describe('contour makeColorMap', function() { zmax: 6 }; - var colorMap = makeColorMap(trace); + var colorMap = _makeColorMap(trace); expect(colorMap.domain()).toEqual( [1, 2.75, 3.5, 4, 4.5, 6] @@ -189,7 +254,7 @@ describe('contour makeColorMap', function() { colorscale: colorScales.RdBu }; - var colorMap = makeColorMap(trace); + var colorMap = _makeColorMap(trace); expect(colorMap.domain()).toEqual( [1.5, 2.9, 3.5, 3.9, 4.3, 5.5]