diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 90f7b288de5..914e111f8db 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -1558,7 +1558,8 @@ function autoTickRound(ax) { var rangeexp = Math.floor(Math.log(maxend) / Math.LN10 + 0.01); var minexponent = ax.minexponent === undefined ? 3 : ax.minexponent; if(Math.abs(rangeexp) > minexponent) { - if(isSIFormat(ax.exponentformat) && !beyondSI(rangeexp)) { + if((isSIFormat(ax.exponentformat) && ax.exponentformat !== 'SI extended' && !beyondSI(rangeexp)) || + (isSIFormat(ax.exponentformat) && ax.exponentformat === 'SI extended' && !beyondSIExtended(rangeexp))) { ax._tickexponent = 3 * Math.round((rangeexp - 1) / 3); } else ax._tickexponent = rangeexp; } @@ -1904,7 +1905,8 @@ function formatLog(ax, out, hover, extraPrecision, hideexp) { var p = Math.round(x); var absP = Math.abs(p); var exponentFormat = ax.exponentformat; - if(exponentFormat === 'power' || (isSIFormat(exponentFormat) && beyondSI(p))) { + if(exponentFormat === 'power' || (isSIFormat(exponentFormat) && exponentFormat !== 'SI extended' && beyondSI(p)) || + (isSIFormat(exponentFormat) && exponentFormat === 'SI extended' && beyondSIExtended(p))) { if(p === 0) out.text = 1; else if(p === 1) out.text = '10'; else out.text = '10' + (p > 1 ? '' : MINUS_SIGN) + absP + ''; @@ -2049,8 +2051,11 @@ function num2frac(num) { // also automatically switch to sci. notation var SIPREFIXES = ['f', 'p', 'n', 'μ', 'm', '', 'k', 'M', 'G', 'T']; +// extending SI prefixes +var SIPREFIXES_EXTENDED = ['q', 'r', 'y', 'z', 'a', 'f', 'p', 'n', 'μ', 'm', '', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q']; + function isSIFormat(exponentFormat) { - return exponentFormat === 'SI' || exponentFormat === 'B'; + return exponentFormat === 'SI' || exponentFormat === 'SI extended' || exponentFormat === 'B'; } // are we beyond the range of common SI prefixes? @@ -2064,6 +2069,10 @@ function beyondSI(exponent) { return exponent > 14 || exponent < -15; } +function beyondSIExtended(exponent) { + return exponent > 32 || exponent < -30; +} + function numFormat(v, ax, fmtoverride, hover) { var isNeg = v < 0; // max number of digits past decimal point to show @@ -2139,7 +2148,8 @@ function numFormat(v, ax, fmtoverride, hover) { // add exponent if(exponent && exponentFormat !== 'hide') { - if(isSIFormat(exponentFormat) && beyondSI(exponent)) exponentFormat = 'power'; + if((isSIFormat(exponentFormat) && exponentFormat !== 'SI extended' && beyondSI(exponent)) || + (isSIFormat(exponentFormat) && exponentFormat === 'SI extended' && beyondSIExtended(exponent))) exponentFormat = 'power'; var signedExponent; if(exponent < 0) signedExponent = MINUS_SIGN + -exponent; @@ -2153,7 +2163,11 @@ function numFormat(v, ax, fmtoverride, hover) { } else if(exponentFormat === 'B' && exponent === 9) { v += 'B'; } else if(isSIFormat(exponentFormat)) { - v += SIPREFIXES[exponent / 3 + 5]; + if(exponentFormat !== 'SI extended') { + v += SIPREFIXES[exponent / 3 + 5]; + } else if(exponentFormat === 'SI extended') { + v += SIPREFIXES_EXTENDED[exponent / 3 + 10]; + } } } diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index 32afc99457a..a55c3821854 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -897,7 +897,7 @@ module.exports = { }, exponentformat: { valType: 'enumerated', - values: ['none', 'e', 'E', 'power', 'SI', 'B'], + values: ['none', 'e', 'E', 'power', 'SI', 'B', 'SI extended'], dflt: 'B', editType: 'ticks', description: [ @@ -908,7 +908,12 @@ module.exports = { 'If *E*, 1E+9.', 'If *power*, 1x10^9 (with 9 in a super script).', 'If *SI*, 1G.', - 'If *B*, 1B.' + 'If *B*, 1B.', + + '*SI* uses prefixes from "femto" f (10^-15) to "tera" T (10^12).', + '*SI extended* covers instead the full SI range from "quecto" q (10^-30) to "quetta" Q (10^30).', + 'If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule', + 'will automatically be switched to the power notation.' ].join(' ') }, minexponent: { diff --git a/src/traces/carpet/axis_attributes.js b/src/traces/carpet/axis_attributes.js index 688f1a11a50..95583ddda30 100644 --- a/src/traces/carpet/axis_attributes.js +++ b/src/traces/carpet/axis_attributes.js @@ -234,7 +234,7 @@ module.exports = { }, exponentformat: { valType: 'enumerated', - values: ['none', 'e', 'E', 'power', 'SI', 'B'], + values: ['none', 'e', 'E', 'power', 'SI', 'B', 'SI extended'], dflt: 'B', editType: 'calc', description: [ diff --git a/test/image/baselines/20.png b/test/image/baselines/20.png index 32da2fb249a..05cc733bd25 100644 Binary files a/test/image/baselines/20.png and b/test/image/baselines/20.png differ diff --git a/test/image/mocks/20.json b/test/image/mocks/20.json index b2601cef1b7..078f4d66429 100644 --- a/test/image/mocks/20.json +++ b/test/image/mocks/20.json @@ -8,7 +8,7 @@ }, { "x": [2, 3, 4], - "y": [40, 50, 60], + "y": [4000000000000, 5000000000000, 6000000000000], "name": "yaxis2 data", "yaxis": "y2", "type": "scatter" @@ -36,7 +36,7 @@ }, { "x": [6, 7, 8], - "y": [4000000, 5000000, 6000000], + "y": [400000000000000000000000000000000, 500000000000000000000000000000000, 600000000000000000000000000000000], "name": "yaxis6 data", "yaxis": "y6", "type": "scatter" @@ -111,6 +111,7 @@ "tickfont": { "color": "#ff7f0e" }, + "exponentformat": "SI", "linecolor": "rgba(255,127,14,0.4)", "linewidth": 6, "anchor": "free", @@ -189,7 +190,7 @@ "tickfont": { "color": "#8c564b" }, - "exponentformat": "SI", + "exponentformat": "SI extended", "linecolor": "rgba(140,86,75,0.5)", "anchor": "free", "side": "right",