From 2ef4411923eb9a0ed452fa797a209af76e53d78c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Wed, 15 Jun 2016 18:09:55 -0400 Subject: [PATCH 1/5] update only varying fields in merge selection --- src/traces/heatmap/plot.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/traces/heatmap/plot.js b/src/traces/heatmap/plot.js index 93a721f1fb1..3b777110006 100644 --- a/src/traces/heatmap/plot.js +++ b/src/traces/heatmap/plot.js @@ -373,16 +373,19 @@ function plotOne(gd, plotinfo, cd) { var image3 = plotgroup.selectAll('image') .data(cd); - image3.enter().append('svg:image'); - image3.exit().remove(); - image3.attr({ + image3.enter().append('svg:image').attr({ xmlns: xmlnsNamespaces.svg, 'xlink:href': canvas.toDataURL('image/png'), + preserveAspectRatio: 'none' + }); + + image3.attr({ height: imageHeight, width: imageWidth, x: left, - y: top, - preserveAspectRatio: 'none' + y: top }); + + image3.exit().remove(); } From 90d7a94dd089ecd361495a1d4f3220b0914b026b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Wed, 15 Jun 2016 18:10:25 -0400 Subject: [PATCH 2/5] make sure off-srceen heatmap traces are disposes --- src/traces/heatmap/plot.js | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/traces/heatmap/plot.js b/src/traces/heatmap/plot.js index 3b777110006..d2710bded24 100644 --- a/src/traces/heatmap/plot.js +++ b/src/traces/heatmap/plot.js @@ -137,10 +137,24 @@ function plotOne(gd, plotinfo, cd) { var imageWidth = Math.round(right - left), imageHeight = Math.round(bottom - top); - // now redraw + // setup image nodes // if image is entirely off-screen, don't even draw it - if(imageWidth <= 0 || imageHeight <= 0) return; + var isOffScreen = (imageWidth <= 0 || imageHeight <= 0); + + var plotgroup = plotinfo.plot.select('.imagelayer') + .selectAll('g.hm.' + id) + .data(isOffScreen ? [] : [0]); + + plotgroup.enter().append('g') + .classed('hm', true) + .classed(id, true); + + plotgroup.exit().remove(); + + if(isOffScreen) return; + + // generate image data var canvasW, canvasH; if(zsmooth === 'fast') { @@ -363,14 +377,6 @@ function plotOne(gd, plotinfo, cd) { gd._hmpixcount = (gd._hmpixcount||0) + pixcount; gd._hmlumcount = (gd._hmlumcount||0) + pixcount * avgColor.getLuminance(); - var plotgroup = plotinfo.plot.select('.imagelayer') - .selectAll('g.hm.' + id) - .data([0]); - plotgroup.enter().append('g') - .classed('hm', true) - .classed(id, true); - plotgroup.exit().remove(); - var image3 = plotgroup.selectAll('image') .data(cd); From 48dc1912cb995f85ed403e0155df05118ea91abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 16 Jun 2016 13:25:40 -0400 Subject: [PATCH 3/5] require MAXDIST from cartesian constants not Fx --- src/traces/heatmap/hover.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/traces/heatmap/hover.js b/src/traces/heatmap/hover.js index 64bab8457b2..828a9033066 100644 --- a/src/traces/heatmap/hover.js +++ b/src/traces/heatmap/hover.js @@ -12,10 +12,12 @@ var Fx = require('../../plots/cartesian/graph_interact'); var Lib = require('../../lib'); +var MAXDIST = require('../../plots/cartesian/constants').MAXDIST; + module.exports = function hoverPoints(pointData, xval, yval, hovermode, contour) { // never let a heatmap override another type as closest point - if(pointData.distance < Fx.MAXDIST) return; + if(pointData.distance < MAXDIST) return; var cd0 = pointData.cd[0], trace = cd0.trace, @@ -46,8 +48,8 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, contour) return; } } - else if(Fx.inbox(xval - x[0], xval - x[x.length - 1]) > Fx.MAXDIST || - Fx.inbox(yval - y[0], yval - y[y.length - 1]) > Fx.MAXDIST) { + else if(Fx.inbox(xval - x[0], xval - x[x.length - 1]) > MAXDIST || + Fx.inbox(yval - y[0], yval - y[y.length - 1]) > MAXDIST) { return; } else { @@ -69,10 +71,12 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, contour) nx = Math.max(0, Math.min(x2.length - 2, Lib.findBin(xval, x2))); ny = Math.max(0, Math.min(y2.length - 2, Lib.findBin(yval, y2))); } + var x0 = xa.c2p(x[nx]), x1 = xa.c2p(x[nx + 1]), y0 = ya.c2p(y[ny]), y1 = ya.c2p(y[ny + 1]); + if(contour) { x1 = x0; xl = x[nx]; @@ -99,7 +103,7 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, contour) return [Lib.extendFlat(pointData, { index: [ny, nx], // never let a 2D override 1D type as closest point - distance: Fx.MAXDIST + 10, + distance: MAXDIST + 10, x0: x0, x1: x1, y0: y0, From 221a5a12551ab7853daf11c7469a1a5b136c88cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 16 Jun 2016 14:50:47 -0400 Subject: [PATCH 4/5] add multi-trace heatmap mock --- test/image/baselines/heatmap_multi-trace.png | Bin 0 -> 23575 bytes test/image/mocks/heatmap_multi-trace.json | 193 +++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 test/image/baselines/heatmap_multi-trace.png create mode 100644 test/image/mocks/heatmap_multi-trace.json diff --git a/test/image/baselines/heatmap_multi-trace.png b/test/image/baselines/heatmap_multi-trace.png new file mode 100644 index 0000000000000000000000000000000000000000..27ab01075b4b6c5d1689e6ca41c5af5052b7883e GIT binary patch literal 23575 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 Ye7)O*#$7qM@S9Fo%TTjG{kKd14>OrHL;wH) literal 0 HcmV?d00001 diff --git a/test/image/mocks/heatmap_multi-trace.json b/test/image/mocks/heatmap_multi-trace.json new file mode 100644 index 00000000000..4bd6f5d065b --- /dev/null +++ b/test/image/mocks/heatmap_multi-trace.json @@ -0,0 +1,193 @@ +{ + "data": [ + { + "x": [ + 1, + 1, + 1, + 1, + 1, + 1 + ], + "y": [ + 0, + 1, + 2, + 3, + 4, + 5 + ], + "z": [ + 3, + 4, + 2, + 5, + 3, + 1 + ], + "type": "heatmap", + "showlegend": false, + "showscale": false, + "zmax": 5, + "zmin": 1 + }, + { + "x": [ + 2, + 2, + 2, + 2, + 2 + ], + "y": [ + 0.2, + 1.2, + 2.2, + 3.2, + 4.2 + ], + "z": [ + 6, + 1, + 3, + 2, + 4 + ], + "type": "heatmap", + "showlegend": false, + "showscale": false, + "zmax": 6, + "zmin": 1 + }, + { + "x": [ + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3 + ], + "y": [ + 0, + 0.5, + 1, + 1.5, + 2, + 2.5, + 3, + 3.5, + 4, + 4.5, + 5 + ], + "z": [ + 6, + 1, + 3, + 2, + 4, + 2, + 7, + 4, + 3, + 2, + 5 + ], + "type": "heatmap", + "showlegend": false, + "showscale": false, + "zmax": 7, + "zmin": 1 + }, + { + "x": [ + 4, + 4, + 4, + 4, + 4, + 4 + ], + "y": [ + 0, + 0.2, + 0.5, + 1.2, + 3.5, + 4 + ], + "z": [ + 2, + 4, + 7, + 3, + 2, + 1 + ], + "type": "heatmap", + "showlegend": false, + "showscale": false, + "zmax": 7, + "zmin": 1 + }, + { + "x": [ + 5.2, + 5.2, + 5.2, + 5.2, + 5.2, + 5.2 + ], + "y": [ + 0, + 0.2, + 0.5, + 1.2, + 3.5, + 4 + ], + "z": [ + 2, + 4, + 7, + 3, + 2, + 1 + ], + "type": "heatmap", + "showlegend": false, + "showscale": true, + "zmax": 10, + "zmin": 0 + } + ], + "layout": { + "hovermode": "closest", + "xaxis": { + "type": "linear", + "range": [ + 0.5, + 5.7 + ], + "autorange": true + }, + "yaxis": { + "type": "linear", + "range": [ + -0.5, + 5.5 + ], + "autorange": true + }, + "height": 450, + "width": 1100, + "autosize": true + } +} From 5084daf240a10869891d524faf28c434eaf9fd2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 16 Jun 2016 14:54:18 -0400 Subject: [PATCH 5/5] add heatmap plot and hover tests --- test/jasmine/tests/heatmap_test.js | 98 ++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/test/jasmine/tests/heatmap_test.js b/test/jasmine/tests/heatmap_test.js index dae549a81b0..32c6aea150a 100644 --- a/test/jasmine/tests/heatmap_test.js +++ b/test/jasmine/tests/heatmap_test.js @@ -1,9 +1,13 @@ +var Plotly = require('@lib/index'); var Plots = require('@src/plots/plots'); var Lib = require('@src/lib'); var convertColumnXYZ = require('@src/traces/heatmap/convert_column_xyz'); var Heatmap = require('@src/traces/heatmap'); +var d3 = require('d3'); +var createGraphDiv = require('../assets/create_graph_div'); +var destroyGraphDiv = require('../assets/destroy_graph_div'); var customMatchers = require('../assets/custom_matchers'); @@ -299,3 +303,97 @@ describe('heatmap calc', function() { expect(out.z).toBeCloseTo2DArray([[1, 2, 3], [3, 1, 2]]); }); }); + +describe('heatmap plot', function() { + 'use strict'; + + afterEach(destroyGraphDiv); + + it('should not draw traces that are off-screen', function(done) { + var mock = require('@mocks/heatmap_multi-trace.json'), + mockCopy = Lib.extendDeep({}, mock), + gd = createGraphDiv(); + + function assertImageCnt(cnt) { + var images = d3.selectAll('.hm').select('image'); + + expect(images.size()).toEqual(cnt); + } + + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + assertImageCnt(5); + + return Plotly.relayout(gd, 'xaxis.range', [2, 3]); + }).then(function() { + assertImageCnt(2); + + return Plotly.relayout(gd, 'xaxis.autorange', true); + }).then(function() { + assertImageCnt(5); + + done(); + }); + }); +}); + +describe('heatmap hover', function() { + 'use strict'; + + var gd; + + beforeAll(function(done) { + jasmine.addMatchers(customMatchers); + + gd = createGraphDiv(); + + var mock = require('@mocks/heatmap_multi-trace.json'), + mockCopy = Lib.extendDeep({}, mock); + + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + }); + + afterAll(destroyGraphDiv); + + function _hover(gd, xval, yval) { + var fullLayout = gd._fullLayout, + calcData = gd.calcdata, + hoverData = []; + + for(var i = 0; i < calcData.length; i++) { + var pointData = { + index: false, + distance: 20, + cd: calcData[i], + trace: calcData[i][0].trace, + xa: fullLayout.xaxis, + ya: fullLayout.yaxis + }; + + var hoverPoint = Heatmap.hoverPoints(pointData, xval, yval); + if(hoverPoint) hoverData.push(hoverPoint[0]); + } + + return hoverData; + } + + function assertLabels(hoverPoint, xLabel, yLabel, zLabel) { + expect(hoverPoint.xLabelVal).toEqual(xLabel, 'have correct x label'); + expect(hoverPoint.yLabelVal).toEqual(yLabel, 'have correct y label'); + expect(hoverPoint.zLabelVal).toEqual(zLabel, 'have correct z label'); + } + + it('should find closest point (case 1) and should', function() { + var pt = _hover(gd, 0.5, 0.5)[0]; + + expect(pt.index).toEqual([1, 0], 'have correct index'); + assertLabels(pt, 1, 1, 4); + }); + + it('should find closest point (case 2) and should', function() { + var pt = _hover(gd, 1.5, 0.5)[0]; + + expect(pt.index).toEqual([0, 0], 'have correct index'); + assertLabels(pt, 2, 0.2, 6); + }); + +});