Skip to content

Commit 3b00e8a

Browse files
committed
Add optional 'base' keyword to SigFigFormatter
1 parent 2ab77e4 commit 3b00e8a

1 file changed

Lines changed: 29 additions & 13 deletions

File tree

proplot/ticker.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -396,8 +396,8 @@ def _fix_small_number(self, x, string, precision_offset=2):
396396
# Format with precision below floating point error
397397
x -= getattr(self, 'offset', 0) # guard against API change
398398
x /= 10 ** getattr(self, 'orderOfMagnitude', 0) # guard against API change
399-
precision_true = int(abs(np.log10(abs(x)) // 1))
400-
precision_max = np.finfo(type(x)).precision - precision_offset
399+
precision_true = max(0, self._decimal_place(x))
400+
precision_max = max(0, np.finfo(type(x)).precision - precision_offset)
401401
precision = min(precision_true, precision_max)
402402
string = ('{:.%df}' % precision).format(x)
403403

@@ -426,6 +426,17 @@ def _get_default_decimal_point(use_locale=None):
426426
use_locale = _not_none(use_locale, rc['formatter.use_locale'])
427427
return locale.localeconv()['decimal_point'] if use_locale else '.'
428428

429+
@staticmethod
430+
def _decimal_place(x):
431+
"""
432+
Return the decimal place of the number (e.g., 100 is -2 and 0.01 is 2).
433+
"""
434+
if x == 0:
435+
digits = 0
436+
else:
437+
digits = -int(np.log10(abs(x)) // 1)
438+
return digits
439+
429440
@staticmethod
430441
def _minus_format(string):
431442
"""
@@ -542,31 +553,36 @@ class SigFigFormatter(mticker.Formatter):
542553
Format numbers by retaining the specified number of significant digits.
543554
"""
544555
@docstring._snippet_manager
545-
def __init__(self, sigfig=3, zerotrim=None):
556+
def __init__(self, sigfig=None, zerotrim=None, base=None):
546557
"""
547558
Parameters
548559
----------
549560
sigfig : float, optional
550-
The number of significant digits.
561+
The number of significant digits. Default is ``3``.
551562
%(ticker.zerotrim)s
563+
base : float, optional
564+
The base unit for rounding. Default is ``1``. For example
565+
``SigFigFormatter(2, base=5)`` rounds to the nearest 5 with
566+
up to 2 significant digits (e.g., 87 --> 85, 8.7 --> 8.5).
552567
"""
553-
self._sigfig = sigfig
568+
self._sigfig = _not_none(sigfig, 3)
554569
self._zerotrim = _not_none(zerotrim, rc['formatter.zerotrim'])
570+
self._base = _not_none(base, 1)
555571

556572
@docstring._snippet_manager
557573
def __call__(self, x, pos=None): # noqa: U100
558574
"""
559575
%(ticker.call)s
560576
"""
561-
# Limit digits to significant figures
562-
if x == 0:
563-
digits = 0
564-
else:
565-
digits = -int(np.log10(abs(x)) // 1)
577+
# Limit to significant figures
578+
digits = AutoFormatter._decimal_place(x) + self._sigfig - 1
579+
scale = self._base * 10 ** -digits
580+
x = scale * round(x / scale)
581+
582+
# Create the string
566583
decimal_point = AutoFormatter._get_default_decimal_point()
567-
digits += self._sigfig - 1
568-
x = np.round(x, digits)
569-
string = ('{:.%df}' % max(0, digits)).format(x)
584+
precision = max(0, digits) + max(0, AutoFormatter._decimal_place(self._base))
585+
string = ('{:.%df}' % precision).format(x)
570586
string = string.replace('.', decimal_point)
571587

572588
# Custom string formatting

0 commit comments

Comments
 (0)