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
parent
cec08f20ba
commit
9321eab471
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue