Skip to content

Commit 52ac7f4

Browse files
committed
better treatment of exponents beyond SI prefixes
- don't round to factors of 3 - use 'power' (x10<sup>18</sup>) instead of 'e' (e+18)
1 parent 98ff194 commit 52ac7f4

File tree

2 files changed

+129
-7
lines changed

2 files changed

+129
-7
lines changed

src/plots/cartesian/axes.js

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,7 +1056,7 @@ function autoTickRound(ax) {
10561056

10571057
var rangeexp = Math.floor(Math.log(maxend) / Math.LN10 + 0.01);
10581058
if(Math.abs(rangeexp) > 3) {
1059-
if(ax.exponentformat === 'SI' || ax.exponentformat === 'B') {
1059+
if(isSIFormat(ax.exponentformat) && !beyondSI(rangeexp)) {
10601060
ax._tickexponent = 3 * Math.round((rangeexp - 1) / 3);
10611061
}
10621062
else ax._tickexponent = rangeexp;
@@ -1300,8 +1300,9 @@ function formatLog(ax, out, hover, extraPrecision, hideexp) {
13001300
out.text = numFormat(Math.pow(10, x), ax, hideexp, extraPrecision);
13011301
}
13021302
else if(isNumeric(dtick) || ((dtick.charAt(0) === 'D') && (Lib.mod(x + 0.01, 1) < 0.1))) {
1303-
if(['e', 'E', 'power'].indexOf(ax.exponentformat) !== -1) {
1304-
var p = Math.round(x);
1303+
var p = Math.round(x);
1304+
if(['e', 'E', 'power'].indexOf(ax.exponentformat) !== -1 ||
1305+
(isSIFormat(ax.exponentformat) && beyondSI(p))) {
13051306
if(p === 0) out.text = 1;
13061307
else if(p === 1) out.text = '10';
13071308
else if(p > 1) out.text = '10<sup>' + p + '</sup>';
@@ -1360,6 +1361,21 @@ function formatLinear(ax, out, hover, extraPrecision, hideexp) {
13601361
// also automatically switch to sci. notation
13611362
var SIPREFIXES = ['f', 'p', 'n', 'μ', 'm', '', 'k', 'M', 'G', 'T'];
13621363

1364+
function isSIFormat(exponentFormat) {
1365+
return exponentFormat === 'SI' || exponentFormat === 'B';
1366+
}
1367+
1368+
// are we beyond the range of common SI prefixes?
1369+
// 10^-16 -> 1x10^-16
1370+
// 10^-15 -> 1f
1371+
// ...
1372+
// 10^14 -> 100T
1373+
// 10^15 -> 1x10^15
1374+
// 10^16 -> 1x10^16
1375+
function beyondSI(exponent) {
1376+
return exponent > 14 || exponent < -15;
1377+
}
1378+
13631379
function numFormat(v, ax, fmtoverride, hover) {
13641380
// negative?
13651381
var isNeg = v < 0,
@@ -1437,14 +1453,14 @@ function numFormat(v, ax, fmtoverride, hover) {
14371453

14381454
// add exponent
14391455
if(exponent && exponentFormat !== 'hide') {
1456+
if(isSIFormat(exponentFormat) && beyondSI(exponent)) exponentFormat = 'power';
1457+
14401458
var signedExponent;
14411459
if(exponent < 0) signedExponent = MINUS_SIGN + -exponent;
14421460
else if(exponentFormat !== 'power') signedExponent = '+' + exponent;
14431461
else signedExponent = String(exponent);
14441462

1445-
if(exponentFormat === 'e' ||
1446-
((exponentFormat === 'SI' || exponentFormat === 'B') &&
1447-
(exponent > 12 || exponent < -15))) {
1463+
if(exponentFormat === 'e') {
14481464
v += 'e' + signedExponent;
14491465
}
14501466
else if(exponentFormat === 'E') {
@@ -1456,7 +1472,7 @@ function numFormat(v, ax, fmtoverride, hover) {
14561472
else if(exponentFormat === 'B' && exponent === 9) {
14571473
v += 'B';
14581474
}
1459-
else if(exponentFormat === 'SI' || exponentFormat === 'B') {
1475+
else if(isSIFormat(exponentFormat)) {
14601476
v += SIPREFIXES[exponent / 3 + 5];
14611477
}
14621478
}

test/jasmine/tests/axes_test.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,6 +1929,112 @@ describe('Test axes', function() {
19291929
});
19301930
}
19311931

1932+
it('reverts to "power" for SI/B exponentformat beyond the prefix range (linear case)', function() {
1933+
var textOut = mockCalc({
1934+
type: 'linear',
1935+
tickmode: 'linear',
1936+
exponentformat: 'B',
1937+
showexponent: 'all',
1938+
tick0: 0,
1939+
dtick: 1e13,
1940+
range: [8.5e13, 11.5e13]
1941+
});
1942+
1943+
expect(textOut).toEqual([
1944+
'90T', '100T', '110T'
1945+
]);
1946+
1947+
textOut = mockCalc({
1948+
type: 'linear',
1949+
tickmode: 'linear',
1950+
exponentformat: 'B',
1951+
showexponent: 'all',
1952+
tick0: 0,
1953+
dtick: 1e14,
1954+
range: [8.5e14, 11.5e14]
1955+
});
1956+
1957+
expect(textOut).toEqual([
1958+
'0.9×10<sup>15</sup>',
1959+
'1×10<sup>15</sup>',
1960+
'1.1×10<sup>15</sup>'
1961+
]);
1962+
1963+
textOut = mockCalc({
1964+
type: 'linear',
1965+
tickmode: 'linear',
1966+
exponentformat: 'SI',
1967+
showexponent: 'all',
1968+
tick0: 0,
1969+
dtick: 1e-16,
1970+
range: [8.5e-16, 11.5e-16]
1971+
});
1972+
1973+
expect(textOut).toEqual([
1974+
'0.9f', '1f', '1.1f'
1975+
]);
1976+
1977+
textOut = mockCalc({
1978+
type: 'linear',
1979+
tickmode: 'linear',
1980+
exponentformat: 'SI',
1981+
showexponent: 'all',
1982+
tick0: 0,
1983+
dtick: 1e-17,
1984+
range: [8.5e-17, 11.5e-17]
1985+
});
1986+
1987+
expect(textOut).toEqual([
1988+
'0.9×10<sup>\u221216</sup>',
1989+
'1×10<sup>\u221216</sup>',
1990+
'1.1×10<sup>\u221216</sup>'
1991+
]);
1992+
});
1993+
1994+
it('reverts to "power" for SI/B exponentformat beyond the prefix range (log case)', function() {
1995+
var textOut = mockCalc({
1996+
type: 'log',
1997+
tickmode: 'linear',
1998+
exponentformat: 'B',
1999+
showexponent: 'all',
2000+
tick0: 0,
2001+
dtick: 1,
2002+
range: [-18.5, 18.5]
2003+
});
2004+
2005+
expect(textOut).toEqual([
2006+
'10<sup>\u221218</sup>',
2007+
'10<sup>\u221217</sup>',
2008+
'10<sup>\u221216</sup>',
2009+
'1f', '10f', '100f', '1p', '10p', '100p', '1n', '10n', '100n',
2010+
'1μ', '10μ', '100μ', '0.001', '0.01', '0.1', '1', '10', '100',
2011+
'1000', '10k', '100k', '1M', '10M', '100M', '1B', '10B', '100B',
2012+
'1T', '10T', '100T',
2013+
'10<sup>15</sup>',
2014+
'10<sup>16</sup>',
2015+
'10<sup>17</sup>',
2016+
'10<sup>18</sup>'
2017+
]);
2018+
2019+
textOut = mockCalc({
2020+
type: 'log',
2021+
tickmode: 'linear',
2022+
exponentformat: 'SI',
2023+
showexponent: 'all',
2024+
tick0: 0,
2025+
dtick: 'D2',
2026+
range: [7.9, 12.1]
2027+
});
2028+
2029+
expect(textOut).toEqual([
2030+
'100M', '2', '5',
2031+
'1G', '2', '5',
2032+
'10G', '2', '5',
2033+
'100G', '2', '5',
2034+
'1T'
2035+
]);
2036+
});
2037+
19322038
it('provides a new date suffix whenever the suffix changes', function() {
19332039
var ax = {
19342040
type: 'date',

0 commit comments

Comments
 (0)