First draft, make graphics work on shm primary index
This is a bit hacky (what with array indexing semantics being relative to the primary index's "start" value but it works. We'll likely want to somehow wrap this index finagling into an API soon.to_qpainterpath_and_beyond
parent
02b7d6cd19
commit
2568a2d2e9
|
@ -33,14 +33,15 @@ from ._style import (
|
||||||
_xaxis_at,
|
_xaxis_at,
|
||||||
hcolor,
|
hcolor,
|
||||||
_font,
|
_font,
|
||||||
|
_down_2_font_inches_we_like,
|
||||||
)
|
)
|
||||||
from ._axes import YAxisLabel, XAxisLabel, YSticky
|
from ._axes import YAxisLabel, XAxisLabel, YSticky
|
||||||
|
|
||||||
|
|
||||||
# XXX: these settings seem to result in really decent mouse scroll
|
# XXX: these settings seem to result in really decent mouse scroll
|
||||||
# latency (in terms of perceived lag in cross hair) so really be sure
|
# latency (in terms of perceived lag in cross hair) so really be sure
|
||||||
# there's an improvement if you want to change it.
|
# there's an improvement if you want to change it!
|
||||||
_mouse_rate_limit = 60 # calc current screen refresh rate?
|
_mouse_rate_limit = 60 # TODO; should we calc current screen refresh rate?
|
||||||
_debounce_delay = 1 / 2e3
|
_debounce_delay = 1 / 2e3
|
||||||
_ch_label_opac = 1
|
_ch_label_opac = 1
|
||||||
|
|
||||||
|
@ -53,6 +54,7 @@ class LineDot(pg.CurvePoint):
|
||||||
self,
|
self,
|
||||||
curve: pg.PlotCurveItem,
|
curve: pg.PlotCurveItem,
|
||||||
index: int,
|
index: int,
|
||||||
|
plot: 'ChartPlotWidget',
|
||||||
pos=None,
|
pos=None,
|
||||||
size: int = 2, # in pxs
|
size: int = 2, # in pxs
|
||||||
color: str = 'default_light',
|
color: str = 'default_light',
|
||||||
|
@ -64,6 +66,7 @@ class LineDot(pg.CurvePoint):
|
||||||
pos=pos,
|
pos=pos,
|
||||||
rotate=False,
|
rotate=False,
|
||||||
)
|
)
|
||||||
|
self._plot = plot
|
||||||
|
|
||||||
# TODO: get pen from curve if not defined?
|
# TODO: get pen from curve if not defined?
|
||||||
cdefault = hcolor(color)
|
cdefault = hcolor(color)
|
||||||
|
@ -83,6 +86,31 @@ class LineDot(pg.CurvePoint):
|
||||||
# keep a static size
|
# keep a static size
|
||||||
self.setFlag(self.ItemIgnoresTransformations)
|
self.setFlag(self.ItemIgnoresTransformations)
|
||||||
|
|
||||||
|
def event(
|
||||||
|
self,
|
||||||
|
ev: QtCore.QEvent,
|
||||||
|
) -> None:
|
||||||
|
# print((ev, type(ev)))
|
||||||
|
if not isinstance(ev, QtCore.QDynamicPropertyChangeEvent) or self.curve() is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# if ev.propertyName() == 'index':
|
||||||
|
# print(ev)
|
||||||
|
# # self.setProperty
|
||||||
|
|
||||||
|
(x, y) = self.curve().getData()
|
||||||
|
index = self.property('index')
|
||||||
|
# first = self._plot._ohlc[0]['index']
|
||||||
|
# first = x[0]
|
||||||
|
# i = index - first
|
||||||
|
i = index - x[0]
|
||||||
|
if i > 0:
|
||||||
|
newPos = (index, y[i])
|
||||||
|
QtGui.QGraphicsItem.setPos(self, *newPos)
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
_corner_anchors = {
|
_corner_anchors = {
|
||||||
'top': 0,
|
'top': 0,
|
||||||
|
@ -94,8 +122,10 @@ _corner_anchors = {
|
||||||
_corner_margins = {
|
_corner_margins = {
|
||||||
('top', 'left'): (-4, -5),
|
('top', 'left'): (-4, -5),
|
||||||
('top', 'right'): (4, -5),
|
('top', 'right'): (4, -5),
|
||||||
('bottom', 'left'): (-4, 5),
|
|
||||||
('bottom', 'right'): (4, 5),
|
# TODO: pretty sure y here needs to be 2x font height
|
||||||
|
('bottom', 'left'): (-4, 14),
|
||||||
|
('bottom', 'right'): (4, 14),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,15 +162,19 @@ class ContentsLabel(pg.LabelItem):
|
||||||
array: np.ndarray,
|
array: np.ndarray,
|
||||||
) -> None:
|
) -> None:
|
||||||
# this being "html" is the dumbest shit :eyeroll:
|
# this being "html" is the dumbest shit :eyeroll:
|
||||||
|
first = array[0]['index']
|
||||||
|
|
||||||
self.setText(
|
self.setText(
|
||||||
"<b>i</b>:{index}<br/>"
|
"<b>i</b>:{index}<br/>"
|
||||||
"<b>O</b>:{}<br/>"
|
"<b>O</b>:{}<br/>"
|
||||||
"<b>H</b>:{}<br/>"
|
"<b>H</b>:{}<br/>"
|
||||||
"<b>L</b>:{}<br/>"
|
"<b>L</b>:{}<br/>"
|
||||||
"<b>C</b>:{}<br/>"
|
"<b>C</b>:{}<br/>"
|
||||||
"<b>V</b>:{}".format(
|
"<b>V</b>:{}<br/>"
|
||||||
# *self._array[index].item()[2:8],
|
"<b>wap</b>:{}".format(
|
||||||
*array[index].item()[2:8],
|
*array[index - first][
|
||||||
|
['open', 'high', 'low', 'close', 'volume', 'bar_wap']
|
||||||
|
],
|
||||||
name=name,
|
name=name,
|
||||||
index=index,
|
index=index,
|
||||||
)
|
)
|
||||||
|
@ -152,8 +186,9 @@ class ContentsLabel(pg.LabelItem):
|
||||||
index: int,
|
index: int,
|
||||||
array: np.ndarray,
|
array: np.ndarray,
|
||||||
) -> None:
|
) -> None:
|
||||||
if index < len(array):
|
first = array[0]['index']
|
||||||
data = array[index][name]
|
if index < array[-1]['index'] and index > first:
|
||||||
|
data = array[index - first][name]
|
||||||
self.setText(f"{name}: {data:.2f}")
|
self.setText(f"{name}: {data:.2f}")
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,7 +285,7 @@ class CrossHair(pg.GraphicsObject):
|
||||||
) -> LineDot:
|
) -> LineDot:
|
||||||
# if this plot contains curves add line dot "cursors" to denote
|
# if this plot contains curves add line dot "cursors" to denote
|
||||||
# the current sample under the mouse
|
# the current sample under the mouse
|
||||||
cursor = LineDot(curve, index=len(plot._ohlc))
|
cursor = LineDot(curve, index=plot._ohlc[-1]['index'], plot=plot)
|
||||||
plot.addItem(cursor)
|
plot.addItem(cursor)
|
||||||
self.graphics[plot].setdefault('cursors', []).append(cursor)
|
self.graphics[plot].setdefault('cursors', []).append(cursor)
|
||||||
return cursor
|
return cursor
|
||||||
|
@ -312,8 +347,9 @@ class CrossHair(pg.GraphicsObject):
|
||||||
plot.update_contents_labels(ix)
|
plot.update_contents_labels(ix)
|
||||||
|
|
||||||
# update all subscribed curve dots
|
# update all subscribed curve dots
|
||||||
|
# first = plot._ohlc[0]['index']
|
||||||
for cursor in opts.get('cursors', ()):
|
for cursor in opts.get('cursors', ()):
|
||||||
cursor.setIndex(ix)
|
cursor.setIndex(ix) # - first)
|
||||||
|
|
||||||
# update the label on the bottom of the crosshair
|
# update the label on the bottom of the crosshair
|
||||||
self.xaxis_label.update_label(
|
self.xaxis_label.update_label(
|
||||||
|
@ -375,7 +411,7 @@ def lines_from_ohlc(row: np.ndarray, w: float) -> Tuple[QLineF]:
|
||||||
return [hl, o, c]
|
return [hl, o, c]
|
||||||
|
|
||||||
|
|
||||||
# @timeit
|
@timeit
|
||||||
@jit(
|
@jit(
|
||||||
# TODO: for now need to construct this manually for readonly arrays, see
|
# TODO: for now need to construct this manually for readonly arrays, see
|
||||||
# https://github.com/numba/numba/issues/4511
|
# https://github.com/numba/numba/issues/4511
|
||||||
|
@ -450,7 +486,7 @@ def path_arrays_from_ohlc(
|
||||||
@timeit
|
@timeit
|
||||||
def gen_qpath(
|
def gen_qpath(
|
||||||
data,
|
data,
|
||||||
start,
|
start, # XXX: do we need this?
|
||||||
w,
|
w,
|
||||||
) -> QtGui.QPainterPath:
|
) -> QtGui.QPainterPath:
|
||||||
|
|
||||||
|
@ -478,13 +514,16 @@ class BarItems(pg.GraphicsObject):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.last_bar = QtGui.QPicture()
|
self.last_bar = QtGui.QPicture()
|
||||||
self.history = QtGui.QPicture()
|
# self.history = QtGui.QPicture()
|
||||||
|
|
||||||
self.path = QtGui.QPainterPath()
|
self.path = QtGui.QPainterPath()
|
||||||
self._h_path = QtGui.QGraphicsPathItem(self.path)
|
# self._h_path = QtGui.QGraphicsPathItem(self.path)
|
||||||
|
|
||||||
self._pi = plotitem
|
self._pi = plotitem
|
||||||
|
|
||||||
|
self._xrange: Tuple[int, int]
|
||||||
|
self._yrange: Tuple[float, float]
|
||||||
|
|
||||||
# XXX: not sure this actually needs to be an array other
|
# XXX: not sure this actually needs to be an array other
|
||||||
# then for the old tina mode calcs for up/down bars below?
|
# then for the old tina mode calcs for up/down bars below?
|
||||||
# lines container
|
# lines container
|
||||||
|
@ -495,14 +534,15 @@ class BarItems(pg.GraphicsObject):
|
||||||
self._last_bar_lines: Optional[Tuple[QLineF, ...]] = None
|
self._last_bar_lines: Optional[Tuple[QLineF, ...]] = None
|
||||||
|
|
||||||
# track the current length of drawable lines within the larger array
|
# track the current length of drawable lines within the larger array
|
||||||
self.index: int = 0
|
self.start_index: int = 0
|
||||||
|
self.stop_index: int = 0
|
||||||
|
|
||||||
# @timeit
|
@timeit
|
||||||
def draw_from_data(
|
def draw_from_data(
|
||||||
self,
|
self,
|
||||||
data: np.ndarray,
|
data: np.ndarray,
|
||||||
start: int = 0,
|
start: int = 0,
|
||||||
):
|
) -> QtGui.QPainterPath:
|
||||||
"""Draw OHLC datum graphics from a ``np.ndarray``.
|
"""Draw OHLC datum graphics from a ``np.ndarray``.
|
||||||
|
|
||||||
This routine is usually only called to draw the initial history.
|
This routine is usually only called to draw the initial history.
|
||||||
|
@ -511,19 +551,37 @@ class BarItems(pg.GraphicsObject):
|
||||||
|
|
||||||
# save graphics for later reference and keep track
|
# save graphics for later reference and keep track
|
||||||
# of current internal "last index"
|
# of current internal "last index"
|
||||||
self.index = len(data)
|
# self.start_index = len(data)
|
||||||
|
index = data['index']
|
||||||
|
self._xrange = (index[0], index[-1])
|
||||||
|
self._yrange = (
|
||||||
|
np.nanmax(data['high']),
|
||||||
|
np.nanmin(data['low']),
|
||||||
|
)
|
||||||
|
|
||||||
# up to last to avoid double draw of last bar
|
# up to last to avoid double draw of last bar
|
||||||
self._last_bar_lines = lines_from_ohlc(data[-1], self.w)
|
self._last_bar_lines = lines_from_ohlc(data[-1], self.w)
|
||||||
|
|
||||||
# create pics
|
# create pics
|
||||||
self.draw_history()
|
# self.draw_history()
|
||||||
self.draw_last_bar()
|
self.draw_last_bar()
|
||||||
|
|
||||||
# trigger render
|
# trigger render
|
||||||
# https://doc.qt.io/qt-5/qgraphicsitem.html#update
|
# https://doc.qt.io/qt-5/qgraphicsitem.html#update
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
|
return self.path
|
||||||
|
|
||||||
|
# def update_ranges(
|
||||||
|
# self,
|
||||||
|
# xmn: int,
|
||||||
|
# xmx: int,
|
||||||
|
# ymn: float,
|
||||||
|
# ymx: float,
|
||||||
|
# ) -> None:
|
||||||
|
# ...
|
||||||
|
|
||||||
|
|
||||||
def draw_last_bar(self) -> None:
|
def draw_last_bar(self) -> None:
|
||||||
"""Currently this draws lines to a cached ``QPicture`` which
|
"""Currently this draws lines to a cached ``QPicture`` which
|
||||||
is supposed to speed things up on ``.paint()`` calls (which
|
is supposed to speed things up on ``.paint()`` calls (which
|
||||||
|
@ -535,17 +593,17 @@ class BarItems(pg.GraphicsObject):
|
||||||
p.drawLines(*tuple(filter(bool, self._last_bar_lines)))
|
p.drawLines(*tuple(filter(bool, self._last_bar_lines)))
|
||||||
p.end()
|
p.end()
|
||||||
|
|
||||||
@timeit
|
# @timeit
|
||||||
def draw_history(self) -> None:
|
# def draw_history(self) -> None:
|
||||||
# TODO: avoid having to use a ```QPicture` to calc the
|
# # TODO: avoid having to use a ```QPicture` to calc the
|
||||||
# ``.boundingRect()``, use ``QGraphicsPathItem`` instead?
|
# # ``.boundingRect()``, use ``QGraphicsPathItem`` instead?
|
||||||
# https://doc.qt.io/qt-5/qgraphicspathitem.html
|
# # https://doc.qt.io/qt-5/qgraphicspathitem.html
|
||||||
# self._h_path.setPath(self.path)
|
# # self._h_path.setPath(self.path)
|
||||||
|
|
||||||
p = QtGui.QPainter(self.history)
|
# p = QtGui.QPainter(self.history)
|
||||||
p.setPen(self.bars_pen)
|
# p.setPen(self.bars_pen)
|
||||||
p.drawPath(self.path)
|
# p.drawPath(self.path)
|
||||||
p.end()
|
# p.end()
|
||||||
|
|
||||||
@timeit
|
@timeit
|
||||||
def update_from_array(
|
def update_from_array(
|
||||||
|
@ -564,14 +622,42 @@ class BarItems(pg.GraphicsObject):
|
||||||
|
|
||||||
This routine should be made (transitively) as fast as possible.
|
This routine should be made (transitively) as fast as possible.
|
||||||
"""
|
"""
|
||||||
index = self.index
|
# index = self.start_index
|
||||||
length = len(array)
|
istart, istop = self._xrange
|
||||||
extra = length - index
|
|
||||||
|
index = array['index']
|
||||||
|
first_index, last_index = index[0], index[-1]
|
||||||
|
|
||||||
|
# length = len(array)
|
||||||
|
prepend_length = istart - first_index
|
||||||
|
append_length = last_index - istop
|
||||||
|
|
||||||
# TODO: allow mapping only a range of lines thus
|
# TODO: allow mapping only a range of lines thus
|
||||||
# only drawing as many bars as exactly specified.
|
# only drawing as many bars as exactly specified.
|
||||||
if extra > 0:
|
|
||||||
|
|
||||||
|
if prepend_length:
|
||||||
|
# breakpoint()
|
||||||
|
# new history was added and we need to render a new path
|
||||||
|
new_bars = array[:prepend_length]
|
||||||
|
prepend_path = gen_qpath(new_bars, 0, self.w)
|
||||||
|
|
||||||
|
# XXX: SOMETHING IS FISHY HERE what with the old_path
|
||||||
|
# y value not matching the first value from
|
||||||
|
# array[prepend_length + 1] ???
|
||||||
|
|
||||||
|
# update path
|
||||||
|
old_path = self.path
|
||||||
|
self.path = prepend_path
|
||||||
|
# self.path.moveTo(float(index - self.w), float(new_bars[0]['open']))
|
||||||
|
# self.path.moveTo(
|
||||||
|
# float(istart - self.w),
|
||||||
|
# # float(array[prepend_length + 1]['open'])
|
||||||
|
# float(array[prepend_length]['open'])
|
||||||
|
# )
|
||||||
|
self.path.addPath(old_path)
|
||||||
|
# self.draw_history()
|
||||||
|
|
||||||
|
if append_length:
|
||||||
# generate new lines objects for updatable "current bar"
|
# generate new lines objects for updatable "current bar"
|
||||||
self._last_bar_lines = lines_from_ohlc(array[-1], self.w)
|
self._last_bar_lines = lines_from_ohlc(array[-1], self.w)
|
||||||
self.draw_last_bar()
|
self.draw_last_bar()
|
||||||
|
@ -580,29 +666,61 @@ class BarItems(pg.GraphicsObject):
|
||||||
# path appending logic:
|
# path appending logic:
|
||||||
# we need to get the previous "current bar(s)" for the time step
|
# we need to get the previous "current bar(s)" for the time step
|
||||||
# and convert it to a sub-path to append to the historical set
|
# and convert it to a sub-path to append to the historical set
|
||||||
new_history_istart = length - 2
|
# new_bars = array[istop - 1:istop + append_length - 1]
|
||||||
to_history = array[new_history_istart:new_history_istart + extra]
|
new_bars = array[-append_length - 1:-1]
|
||||||
new_history_qpath = gen_qpath(to_history, 0, self.w)
|
append_path = gen_qpath(new_bars, 0, self.w)
|
||||||
|
self.path.moveTo(float(istop - self.w), float(new_bars[0]['open']))
|
||||||
|
self.path.addPath(append_path)
|
||||||
|
|
||||||
# move to position of placement for the next bar in history
|
# self.draw_history()
|
||||||
# and append new sub-path
|
|
||||||
new_bars = array[index:index + extra]
|
|
||||||
self.path.moveTo(float(index - self.w), float(new_bars[0]['open']))
|
|
||||||
self.path.addPath(new_history_qpath)
|
|
||||||
|
|
||||||
self.index += extra
|
self._xrange = first_index, last_index
|
||||||
|
|
||||||
self.draw_history()
|
# if extra > 0:
|
||||||
|
# index = array['index']
|
||||||
|
# first, last = index[0], indext[-1]
|
||||||
|
|
||||||
if just_history:
|
# # if first < self.start_index:
|
||||||
self.update()
|
# # length = self.start_index - first
|
||||||
return
|
# # prepend_path = gen_qpath(array[:sef:
|
||||||
|
|
||||||
|
# # generate new lines objects for updatable "current bar"
|
||||||
|
# self._last_bar_lines = lines_from_ohlc(array[-1], self.w)
|
||||||
|
# self.draw_last_bar()
|
||||||
|
|
||||||
|
# # generate new graphics to match provided array
|
||||||
|
# # path appending logic:
|
||||||
|
# # we need to get the previous "current bar(s)" for the time step
|
||||||
|
# # and convert it to a sub-path to append to the historical set
|
||||||
|
# new_history_istart = length - 2
|
||||||
|
|
||||||
|
# to_history = array[new_history_istart:new_history_istart + extra]
|
||||||
|
|
||||||
|
# new_history_qpath = gen_qpath(to_history, 0, self.w)
|
||||||
|
|
||||||
|
# # move to position of placement for the next bar in history
|
||||||
|
# # and append new sub-path
|
||||||
|
# new_bars = array[index:index + extra]
|
||||||
|
|
||||||
|
# # x, y coordinates for start of next open/left arm
|
||||||
|
# self.path.moveTo(float(index - self.w), float(new_bars[0]['open']))
|
||||||
|
|
||||||
|
# self.path.addPath(new_history_qpath)
|
||||||
|
|
||||||
|
# self.start_index += extra
|
||||||
|
|
||||||
|
# self.draw_history()
|
||||||
|
|
||||||
|
if just_history:
|
||||||
|
self.update()
|
||||||
|
return
|
||||||
|
|
||||||
# last bar update
|
# last bar update
|
||||||
i, o, h, l, last, v = array[-1][
|
i, o, h, l, last, v = array[-1][
|
||||||
['index', 'open', 'high', 'low', 'close', 'volume']
|
['index', 'open', 'high', 'low', 'close', 'volume']
|
||||||
]
|
]
|
||||||
assert i == self.index - 1
|
# assert i == self.start_index - 1
|
||||||
|
assert i == last_index
|
||||||
body, larm, rarm = self._last_bar_lines
|
body, larm, rarm = self._last_bar_lines
|
||||||
|
|
||||||
# XXX: is there a faster way to modify this?
|
# XXX: is there a faster way to modify this?
|
||||||
|
@ -660,12 +778,14 @@ class BarItems(pg.GraphicsObject):
|
||||||
|
|
||||||
# @timeit
|
# @timeit
|
||||||
def boundingRect(self):
|
def boundingRect(self):
|
||||||
# TODO: can we do rect caching to make this faster
|
# Qt docs: https://doc.qt.io/qt-5/qgraphicsitem.html#boundingRect
|
||||||
|
|
||||||
|
# TODO: Can we do rect caching to make this faster
|
||||||
# like `pg.PlotCurveItem` does? In theory it's just
|
# like `pg.PlotCurveItem` does? In theory it's just
|
||||||
# computing max/min stuff again like we do in the udpate loop
|
# computing max/min stuff again like we do in the udpate loop
|
||||||
# anyway.
|
# anyway. Not really sure it's necessary since profiling already
|
||||||
|
# shows this method is faf.
|
||||||
|
|
||||||
# Qt docs: https://doc.qt.io/qt-5/qgraphicsitem.html#boundingRect
|
|
||||||
# boundingRect _must_ indicate the entire area that will be
|
# boundingRect _must_ indicate the entire area that will be
|
||||||
# drawn on or else we will get artifacts and possibly crashing.
|
# drawn on or else we will get artifacts and possibly crashing.
|
||||||
# (in this case, QPicture does all the work of computing the
|
# (in this case, QPicture does all the work of computing the
|
||||||
|
@ -673,15 +793,15 @@ class BarItems(pg.GraphicsObject):
|
||||||
|
|
||||||
# compute aggregate bounding rectangle
|
# compute aggregate bounding rectangle
|
||||||
lb = self.last_bar.boundingRect()
|
lb = self.last_bar.boundingRect()
|
||||||
hb = self.history.boundingRect()
|
hb = self.path.boundingRect()
|
||||||
# hb = self._h_path.boundingRect()
|
# hb = self._h_path.boundingRect()
|
||||||
|
|
||||||
return QtCore.QRectF(
|
return QtCore.QRectF(
|
||||||
# top left
|
# top left
|
||||||
QtCore.QPointF(hb.topLeft()),
|
QtCore.QPointF(hb.topLeft()),
|
||||||
# total size
|
# total size
|
||||||
# QtCore.QSizeF(QtCore.QSizeF(lb.size()) + hb.size())
|
QtCore.QSizeF(QtCore.QSizeF(lb.size()) + hb.size())
|
||||||
QtCore.QSizeF(lb.size() + hb.size())
|
# QtCore.QSizeF(lb.size() + hb.size())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -834,7 +954,7 @@ class L1Labels:
|
||||||
chart: 'ChartPlotWidget', # noqa
|
chart: 'ChartPlotWidget', # noqa
|
||||||
digits: int = 2,
|
digits: int = 2,
|
||||||
size_digits: int = 0,
|
size_digits: int = 0,
|
||||||
font_size_inches: float = 4 / 53.,
|
font_size_inches: float = _down_2_font_inches_we_like,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
self.chart = chart
|
self.chart = chart
|
||||||
|
@ -888,7 +1008,9 @@ def level_line(
|
||||||
digits: int = 1,
|
digits: int = 1,
|
||||||
|
|
||||||
# size 4 font on 4k screen scaled down, so small-ish.
|
# size 4 font on 4k screen scaled down, so small-ish.
|
||||||
font_size_inches: float = 4 / 53.,
|
font_size_inches: float = _down_2_font_inches_we_like,
|
||||||
|
|
||||||
|
show_label: bool = True,
|
||||||
|
|
||||||
**linelabelkwargs
|
**linelabelkwargs
|
||||||
) -> LevelLine:
|
) -> LevelLine:
|
||||||
|
@ -908,6 +1030,7 @@ def level_line(
|
||||||
**linelabelkwargs
|
**linelabelkwargs
|
||||||
)
|
)
|
||||||
label.update_from_data(0, level)
|
label.update_from_data(0, level)
|
||||||
|
|
||||||
# TODO: can we somehow figure out a max value from the parent axis?
|
# TODO: can we somehow figure out a max value from the parent axis?
|
||||||
label._size_br_from_str(label.label_str)
|
label._size_br_from_str(label.label_str)
|
||||||
|
|
||||||
|
@ -923,4 +1046,7 @@ def level_line(
|
||||||
|
|
||||||
chart.plotItem.addItem(line)
|
chart.plotItem.addItem(line)
|
||||||
|
|
||||||
|
if not show_label:
|
||||||
|
label.hide()
|
||||||
|
|
||||||
return line
|
return line
|
||||||
|
|
Loading…
Reference in New Issue