From 765ca5a62b88eb94bf64dfe32f1eb364d5aff0cb Mon Sep 17 00:00:00 2001 From: archmoj Date: Fri, 26 Jul 2019 11:07:16 -0400 Subject: [PATCH 1/4] avoid log 0 --- src/plots/cartesian/axes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 423a856809c..30eaf41a153 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -839,7 +839,7 @@ function autoTickRound(ax) { // 2 digits past largest digit of dtick ax._tickround = 2 - Math.floor(Math.log(dtick) / Math.LN10 + 0.01); - var maxend = Math.max(Math.abs(rng[0]), Math.abs(rng[1])); + var maxend = Math.max(Math.abs(rng[0]), Math.abs(rng[1])) || 1; var rangeexp = Math.floor(Math.log(maxend) / Math.LN10 + 0.01); if(Math.abs(rangeexp) > 3) { From f96d43d06724af326e2001b6e5ef8b77e5bc1be1 Mon Sep 17 00:00:00 2001 From: archmoj Date: Fri, 26 Jul 2019 11:18:57 -0400 Subject: [PATCH 2/4] add new test to lock issue 4080 --- test/jasmine/tests/parcoords_test.js | 43 ++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/test/jasmine/tests/parcoords_test.js b/test/jasmine/tests/parcoords_test.js index 526f8c5c3df..270143137dc 100644 --- a/test/jasmine/tests/parcoords_test.js +++ b/test/jasmine/tests/parcoords_test.js @@ -360,7 +360,7 @@ describe('parcoords edge cases', function() { it('@gl Works fine with one panel only', function(done) { var mockCopy = Lib.extendDeep({}, mock2); - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + Plotly.plot(gd, mockCopy).then(function() { expect(gd.data.length).toEqual(1); expect(gd.data[0].dimensions.length).toEqual(2); expect(document.querySelectorAll('.axis').length).toEqual(2); @@ -378,7 +378,7 @@ describe('parcoords edge cases', function() { it('@gl Do something sensible if there is no panel i.e. dimension count is less than 2', function(done) { var mockCopy = Lib.extendDeep({}, mock1); - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + Plotly.plot(gd, mockCopy).then(function() { expect(gd.data.length).toEqual(1); expect(gd.data[0].dimensions.length).toEqual(1); expect(document.querySelectorAll('.axis').length).toEqual(1); // sole axis still shows up @@ -395,7 +395,7 @@ describe('parcoords edge cases', function() { it('@gl Does not error with zero dimensions', function(done) { var mockCopy = Lib.extendDeep({}, mock0); - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + Plotly.plot(gd, mockCopy).then(function() { expect(gd.data.length).toEqual(1); expect(gd.data[0].dimensions.length).toEqual(0); expect(document.querySelectorAll('.axis').length).toEqual(0); @@ -404,13 +404,32 @@ describe('parcoords edge cases', function() { .then(done); }); + it('@gl Does not error with dimensions including only 0', function(done) { + Plotly.plot(gd, { + data: [{ + type: 'parcoords', + dimensions: [{ + label: 'all zero', + values: [0, 0] + }] + }], + layout: {} + }).then(function() { + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(1); + expect(document.querySelectorAll('.axis').length).toEqual(1); + }) + .catch(failTest) + .then(done); + }); + it('@gl Works with duplicate dimension labels', function(done) { var mockCopy = Lib.extendDeep({}, mock2); mockCopy.layout.width = 320; mockCopy.data[0].dimensions[1].label = mockCopy.data[0].dimensions[0].label; - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + Plotly.plot(gd, mockCopy).then(function() { expect(gd.data.length).toEqual(1); expect(gd.data[0].dimensions.length).toEqual(2); expect(document.querySelectorAll('.axis').length).toEqual(2); @@ -434,7 +453,7 @@ describe('parcoords edge cases', function() { } } - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + Plotly.plot(gd, mockCopy).then(function() { expect(gd.data.length).toEqual(1); expect(gd.data[0].dimensions.length).toEqual(2); expect(document.querySelectorAll('.axis').length).toEqual(2); @@ -456,7 +475,7 @@ describe('parcoords edge cases', function() { dim.values = []; } - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + Plotly.plot(gd, mockCopy).then(function() { expect(gd.data.length).toEqual(1); expect(gd.data[0].dimensions.length).toEqual(2); expect(document.querySelectorAll('.axis').length).toEqual(0); @@ -482,7 +501,7 @@ describe('parcoords edge cases', function() { } } - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + Plotly.plot(gd, mockCopy).then(function() { expect(gd.data.length).toEqual(1); expect(gd.data[0].dimensions.length).toEqual(2); expect(document.querySelectorAll('.axis').length).toEqual(2); @@ -511,7 +530,7 @@ describe('parcoords edge cases', function() { mockCopy.data[0].dimensions[i] = newDimension; } - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + Plotly.plot(gd, mockCopy).then(function() { expect(gd.data.length).toEqual(1); expect(gd.data[0].dimensions.length).toEqual(60); expect(document.querySelectorAll('.axis').length).toEqual(60); @@ -537,7 +556,7 @@ describe('parcoords edge cases', function() { mockCopy.data[0].dimensions[i] = newDimension; } - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + Plotly.plot(gd, mockCopy).then(function() { expect(gd.data.length).toEqual(1); expect(gd.data[0].dimensions.length).toEqual(60); expect(document.querySelectorAll('.axis').length).toEqual(60); @@ -564,7 +583,7 @@ describe('parcoords edge cases', function() { mockCopy.data[0].dimensions[i] = newDimension; } - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + Plotly.plot(gd, mockCopy).then(function() { expect(gd.data.length).toEqual(1); expect(gd.data[0].dimensions.length).toEqual(60); expect(document.querySelectorAll('.axis').length).toEqual(60); @@ -595,7 +614,7 @@ describe('parcoords edge cases', function() { mockCopy.data[0].dimensions[0] = 'This is not a plain object'; mockCopy.data[0].dimensions[1].values = 'This is not an array'; - Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + Plotly.plot(gd, mockCopy).then(function() { expect(gd.data.length).toEqual(1); expect(gd.data[0].dimensions.length).toEqual(5); // it's still five, but ... expect(document.querySelectorAll('.axis').length).toEqual(3); // only 3 axes shown @@ -921,7 +940,7 @@ describe('parcoords basic use', function() { reversedMockCopy.data[0].dimensions.forEach(function(d) {d.id = 'R_' + d.id;}); reversedMockCopy.data[0].dimensions.forEach(function(d) {d.label = 'R_' + d.label;}); - Plotly.plot(gd, reversedMockCopy.data, reversedMockCopy.layout).then(function() { + Plotly.plot(gd, reversedMockCopy).then(function() { expect(gd.data.length).toEqual(2); expect(gd.data[0].dimensions.length).toEqual(11); From fde0d320b747abbb3f92da79bd0fc7bbd1624509 Mon Sep 17 00:00:00 2001 From: archmoj Date: Fri, 26 Jul 2019 12:08:58 -0400 Subject: [PATCH 3/4] add extra check for parcoords ranges --- src/traces/parcoords/parcoords.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/traces/parcoords/parcoords.js b/src/traces/parcoords/parcoords.js index ce340d87805..2c0144ade6a 100644 --- a/src/traces/parcoords/parcoords.js +++ b/src/traces/parcoords/parcoords.js @@ -32,19 +32,20 @@ function findExtreme(fn, values, len) { } function findExtremes(values, len) { - return [ + return fixExtremes( findExtreme(Math.min, values, len), findExtreme(Math.max, values, len) - ]; + ); } function dimensionExtent(dimension) { var range = dimension.range; - if(!range) range = findExtremes(dimension.values, dimension._length); - - var lo = range[0]; - var hi = range[1]; + return range ? + fixExtremes(range[0], range[1]) : + findExtremes(dimension.values, dimension._length); +} +function fixExtremes(lo, hi) { if(isNaN(lo) || !isFinite(lo)) { lo = 0; } @@ -404,8 +405,15 @@ function calcAllTicks(cd) { var dim = dimensions[k]._ax; if(dim) { - if(!dim.range) dim.range = findExtremes(values, trace._length); - if(!dim.dtick) dim.dtick = 0.01 * (Math.abs(dim.range[1] - dim.range[0]) || 1); + if(!dim.range) { + dim.range = findExtremes(values, trace._length); + } else { + dim.range = fixExtremes(dim.range[0], dim.range[1]); + } + + if(!dim.dtick) { + dim.dtick = 0.01 * (Math.abs(dim.range[1] - dim.range[0]) || 1); + } dim.tickformat = dimensions[k].tickformat; Axes.calcTicks(dim); From 096ed736d27392563f47741fc482a52937bfa118 Mon Sep 17 00:00:00 2001 From: archmoj Date: Fri, 26 Jul 2019 14:00:22 -0400 Subject: [PATCH 4/4] revert commit 765ca5a62b88eb94bf64dfe32f1eb364d5aff0cb --- src/plots/cartesian/axes.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 30eaf41a153..b84e49be255 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -839,8 +839,7 @@ function autoTickRound(ax) { // 2 digits past largest digit of dtick ax._tickround = 2 - Math.floor(Math.log(dtick) / Math.LN10 + 0.01); - var maxend = Math.max(Math.abs(rng[0]), Math.abs(rng[1])) || 1; - + var maxend = Math.max(Math.abs(rng[0]), Math.abs(rng[1])); var rangeexp = Math.floor(Math.log(maxend) / Math.LN10 + 0.01); if(Math.abs(rangeexp) > 3) { if(isSIFormat(ax.exponentformat) && !beyondSI(rangeexp)) {