Add custom `.formatter` support to our `PriceAxis`

Allow passing in a formatter function for processing tick values on an
axis. This makes it easy to for example, `piker.calc.humanize()` dollar
volume on a subchart.

Factor `set_min_tick()` into the `PriceAxis` since it's not used on any
x-axis data thus far.
vlm_plotz
Tyler Goodlet 2022-01-15 19:36:23 -05:00
parent cec08f20ba
commit 9321eab471
1 changed files with 24 additions and 20 deletions

View File

@ -19,7 +19,7 @@ Chart axes graphics and behavior.
""" """
from functools import partial from functools import partial
from typing import List, Tuple, Optional from typing import List, Tuple, Optional, Callable
from math import floor from math import floor
import pandas as pd import pandas as pd
@ -29,7 +29,6 @@ from PyQt5.QtCore import QPointF
from ._style import DpiAwareFont, hcolor, _font from ._style import DpiAwareFont, hcolor, _font
from ..data._source import float_digits from ..data._source import float_digits
from ..calc import humanize
_axis_pen = pg.mkPen(hcolor('bracket')) _axis_pen = pg.mkPen(hcolor('bracket'))
@ -43,7 +42,6 @@ class Axis(pg.AxisItem):
self, self,
linkedsplits, linkedsplits,
typical_max_str: str = '100 000.000', typical_max_str: str = '100 000.000',
min_tick: int = 2,
**kwargs **kwargs
) -> None: ) -> None:
@ -53,7 +51,6 @@ class Axis(pg.AxisItem):
# self.setCacheMode(QtWidgets.QGraphicsItem.DeviceCoordinateCache) # self.setCacheMode(QtWidgets.QGraphicsItem.DeviceCoordinateCache)
self.linkedsplits = linkedsplits self.linkedsplits = linkedsplits
self._min_tick = min_tick
self._dpi_font = _font self._dpi_font = _font
self.setTickFont(_font.font) self.setTickFont(_font.font)
@ -84,9 +81,6 @@ class Axis(pg.AxisItem):
def size_to_values(self) -> None: def size_to_values(self) -> None:
pass pass
def set_min_tick(self, size: int) -> None:
self._min_tick = size
def txt_offsets(self) -> Tuple[int, int]: def txt_offsets(self) -> Tuple[int, int]:
return tuple(self.style['tickTextOffset']) return tuple(self.style['tickTextOffset'])
@ -96,26 +90,34 @@ class PriceAxis(Axis):
def __init__( def __init__(
self, self,
*args, *args,
humanize: bool = True, min_tick: int = 2,
digits: int = 2, formatter: Optional[Callable[[float], str]] = None,
**kwargs **kwargs
) -> None: ) -> None:
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.humanize = humanize self.formatter = formatter
self.digits = digits self._min_tick: int = min_tick
def set_min_tick(
self,
size: int
) -> None:
self._min_tick = size
def size_to_values(self) -> None: def size_to_values(self) -> None:
# self.typical_br = _font._qfm.boundingRect(typical_max_str)
self.setWidth(self.typical_br.width()) self.setWidth(self.typical_br.width())
# XXX: drop for now since it just eats up h space # XXX: drop for now since it just eats up h space
def tickStrings( def tickStrings(
self, self,
vals, vals: tuple[float],
scale, scale: float,
spacing, spacing: float,
):
) -> list[str]:
# TODO: figure out how to enforce min tick spacing by passing it # TODO: figure out how to enforce min tick spacing by passing it
# into the parent type # into the parent type
digits = max( digits = max(
@ -126,7 +128,7 @@ class PriceAxis(Axis):
# print(f'vals: {vals}\nscale: {scale}\nspacing: {spacing}') # print(f'vals: {vals}\nscale: {scale}\nspacing: {spacing}')
# print(f'digits: {digits}') # print(f'digits: {digits}')
if not self.humanize: if not self.formatter:
return [ return [
('{value:,.{digits}f}').format( ('{value:,.{digits}f}').format(
digits=digits, digits=digits,
@ -134,7 +136,7 @@ class PriceAxis(Axis):
).replace(',', ' ') for v in vals ).replace(',', ' ') for v in vals
] ]
else: else:
return list(map(partial(humanize, digits=self.digits), vals)) return list(map(self.formatter, vals))
class DynamicDateAxis(Axis): class DynamicDateAxis(Axis):
@ -154,6 +156,7 @@ class DynamicDateAxis(Axis):
def _indexes_to_timestrs( def _indexes_to_timestrs(
self, self,
indexes: List[int], indexes: List[int],
) -> List[str]: ) -> List[str]:
chart = self.linkedsplits.chart chart = self.linkedsplits.chart
@ -183,9 +186,10 @@ class DynamicDateAxis(Axis):
def tickStrings( def tickStrings(
self, self,
values: tuple[float], values: tuple[float],
scale, scale: float,
spacing, spacing: float,
):
) -> list[str]:
# info = self.tickStrings.cache_info() # info = self.tickStrings.cache_info()
# print(info) # print(info)
return self._indexes_to_timestrs(values) return self._indexes_to_timestrs(values)