-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PlotItemOverlay
: an alt approach for #1359
#2162
base: master
Are you sure you want to change the base?
Conversation
This is still very much a WIP/testing patch but on my current use case (real time updates to a 40k+ datums set at around display rate) results in approximately a 2x speedup according to the profiler output included here.
WIP: refine the layout sequencing and wrap everything in an error handler for the moment as the details get worked out for axis management per `PlotItem`. - ensure use of instance vars to avoid global overlays XD - pass a default linked axes dimension so a user can choose to link one or all axes to the "focussed" view box. - remove axis items from original `PlotItem` and its scene before adding to the "focussed" layout. - add back in the `ViewBox.sigResized()` geo handler even though I'm pretty sure we don't need it? - ensure overlay count is non-zero
|
||
#self.setCacheMode(self.DeviceCoordinateCache) | ||
|
||
if lru_cache_tick_strings: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ignore this stuff since it's from the history in #2160.
PlotItemOverlay
: an alt approach for #1359
return axis | ||
|
||
# NOTE: seriously.. y'all | ||
# Why do we need to always have all axes created? I don't understand |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a pretty serious design thing I noticed.
I don't grok at all why all axes must always be created other then that when you don't create them the 'bottom'
axis geometry seems to still be used to in the view calculations resulting in .viewRect()
style calcs to compute wrong?!
# the view box geometry still computes as though the space for the | ||
# `'bottom'` axis is always there **UNLESS** you always add that | ||
# axis but hide it? Why in tf would this be the case!?!? | ||
def setAxisItems( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The semantics of set
IMO should be write, not mutate. If you want to add then we should have a addAxisItems()
.
# Note that it does not matter that this adds | ||
# some values to visibleAxes a second time | ||
|
||
# XXX: uhhh wat^ ..? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand any of these comments.
There's weird defaults for weird defaults, special cases for skipping this axis and that axis.
It's all highly confusing and doesn't represent the semantics of the method name.
@@ -235,6 +252,26 @@ def __init__(self, parent=None, border=None, lockAspect=False, enableMouse=True, | |||
if name is None: | |||
self.updateViewLists() | |||
|
|||
self.allow_signal_relay: bool = allow_signal_relay | |||
|
|||
# TODO: make this a decorator so that sub-types |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can probably just call a decorator version of this around all (user-defined) signal handlers right?
root_plotitem: PlotItem | ||
) -> None: | ||
self.root_plotitem: PlotItem = root_plotitem | ||
root_plotitem.vb.allow_signal_relay |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woops was supposed to be set to False
; though I guess that's default 😂
|
||
# Remove old axis | ||
# plotitem.removeAxis(axis, unlink=False) | ||
if not axis.isVisible(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to drop this if we make PlotItem.setAxisItems()
actually be a pure write operation.
# if scene: | ||
# scene.removeItem(axis) | ||
|
||
# XXX: DON'T unlink it since we the original ``ViewBox`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can all be dropped.
|
||
# vb.sigStateChanged.emit(vb) | ||
|
||
# focus state sanity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can also all be dropped.
Gah missing some patches from #1359, notably |
Lol, Ok so apparently the history from #1359 was more extensive then I thought and is needed to make the example work out of the box. Might try to get this working on master if not will bring in that history. |
There it's back to where I expected. |
Ahh think I know what this is; we need a relay signal for axis adjustments and likely independently as in #1359 as well. Though I'm confused why it didn't work on that history either? |
@@ -3235,3 +3236,59 @@ def __enter__(self): | |||
def __exit__(self, *args): | |||
if self.reconnect: | |||
self.signal.connect(self.slot) | |||
|
|||
def connect_lambda(bound_signal, self, func, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pulled verbatim from original commit on #1359.
Still need to cherry the last couple commits from that branch that adjusted docs iirc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, so now having tested this a bunch in a parent project, I'm pretty sure it's not needed?
@0000matteo0000 what was the original leak you found which motivated using this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
storing self in a lambda or in any object and then storing that object in self (self.var = {"self": self}
) will break python garbage collection. this is how i test it:
import weakref
import gc
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtWidgets
app = pg.mkQApp()
pg.setConfigOption('background', 'w')
pg.setConfigOption('foreground', 'k')
mpw = pg.MultiAxisPlotWidget()
# LEGEND
mpw.addLegend(offset=(0, 0))
# TITLE
mpw.setTitle('MultiAxisPlotWidget Example')
# AXYS
mpw.addAxis('sx1', 'bottom', text='Samples1', units='sx1')
mpw.addAxis('sx2', 'bottom', text='Samples2', units='sx2')
mpw.addAxis('sx3', 'bottom', text='Samples3', units='sx3')
mpw.addAxis('sy1', 'left', text='Data1', units='sy1')
mpw.addAxis('sy2', 'left', text='Data2', units='sy2')
mpw.addAxis('sy3', 'left', text='Data3', units='sy3')
# CHARTS
mpw.addChart('Dataset 1', xAxisName='sx1', yAxisName='sy1')[0].setData(np.array(np.sin(np.linspace(0, 2 * np.pi, num=1000))))
mpw.addChart('Dataset 2', xAxisName='sx2', yAxisName='sy1')[0].setData(np.array(np.sin(np.linspace(0, 2 * np.pi, num=1000))) * 2)
mpw.addChart('Dataset 3', xAxisName='sx2', yAxisName='sy2')[0].setData(np.array(np.sin(np.linspace(0, 4 * np.pi, num=500))) * 3)
mpw.addChart('Dataset 4', xAxisName='sx3', yAxisName='sy3')[0].setData(np.array(np.sin(np.linspace(0, 4 * np.pi, num=500))) * 3)
# make and display chart
mpw.makeLayout()
mpw.update()
mpw.show()
pg.exec()
refs = [
weakref.ref(mpw),
weakref.ref(mpw.pi),
weakref.ref(mpw.vb),
weakref.ref(mpw.layout),
weakref.ref(mpw.pi.legend),
weakref.ref(mpw.charts['Dataset 1']),
weakref.ref(mpw.axes['sx1']),
]
del mpw
for ref in refs:
print(ref(), 'should be None')
gc.collect()
for ref in refs:
print(ref(), 'should be None')
from the underlying associated ``ViewBox``. | ||
|
||
If the ``unlink: bool`` is set to ``False`` then the axis will | ||
stay linked to its view and will only be removed from the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: duplicate wording.
# so remove the existing entry. | ||
self.removeAxis(name) | ||
|
||
# elif name not in axisItems: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to see it work like this.
i looked at your code and tested your example, it seems it needs some work still, and it's not quite mature, but i think there is some good intent. |
Thanks 🏄🏼 !
Yes! I totally agree. I actually have narrowed down the main issue to a couple things:
Totally agree. This was exactly my original quiff with the other PR. We already have APIs for all the axis management and graph annotations/labels - we should leverage that and just make the event and layout system work around it.
I haven't pushed it yet, but the signals you added for mouse drag and wheel I think should be
Yup exactly. I would prefer to call it
Sounds good 😎 . I want to keep working on this anyway just to improve my own knowledge of the I'll keep you posted on progress for sure :) |
Yeah just to clarify the main problem that i'm seeing with the event loop even just to remind myself:
|
This is a huge commit which moves a bunch of code around in order to simplify some of our UI modules as well as support our first official mult-axis chart: overlaid volume and "dollar volume". A good deal of this change set is to make startup fast such that volume data which is often shipped alongside OHLC history is loaded and shown asap and FSPs are loaded in an actor cluster with their graphics overlayed concurrently as each responsible worker generates plottable output. For everything to work this commit requires use of a draft `pyqtgraph` PR: pyqtgraph/pyqtgraph#2162 Change summary: - move remaining FSP actor cluster helpers into `.ui._fsp` mod as well as fsp specific UI managers (`maybe_open_vlm_display()`, `start_fsp_displays()`). - add an `FspAdmin` API for starting fsp chains on the cluster concurrently allowing for future work toward reload/unloading. - bring FSP config dict into `start_fsp_displays()` and `.started()`-deliver both the fsp admin and any volume chart back up to the calling display loop code. ToDo: - repair `ChartView` click-drag interactions - auto-range on $ vlm needs to use `ChartPlotWidget._set_yrange()` - a lot better styling for the $_vlm overlay XD
This brings in the WIP components developed as part of pyqtgraph/pyqtgraph#2162. Most of the history can be understood from that issue and effort but the TL;DR is, - add an event handler wrapper system which can be used to wrap `ViewBox` methods such that multiple views can be overlayed and a single event stream broadcast from one "main" view to others which are overlaid with it. - add in 2 relay `Signal` attrs to our `ViewBox` subtype (`Chartview`) to accomplish per event `MouseEvent.emit()` style broadcasting to multiple (sub-)views. - Add a `PlotItemOverlay` api which does all the work of overlaying the actual chart graphics and arranging multiple-axes without collision as well as tying together all the event/signalling so that only a single "focussed" view relays to all overlays.
This syncs with a dev branch in our `pyqtgraph` fork: pyqtgraph/pyqtgraph#2162 The main idea is to get mult-yaxis display fully functional with multiple view boxes running in a "relay mode" where some focussed view relays signals to overlaid views which may have independent axes. This preps us for both displaying independent codomain-set FSP output as well as so called "aggregate" feeds of multiple fins underlyings on the same chart (eg. options and futures over top of ETFs and underlying stocks). The eventual desired UX is to support fast switching of instruments for order mode trading without requiring entirely separate charts as well as simple real-time anal of associated instruments. The first effort here is to display vlm and $_vlm alongside each other as a built-in FSP subchart.
This is a huge commit which moves a bunch of code around in order to simplify some of our UI modules as well as support our first official mult-axis chart: overlaid volume and "dollar volume". A good deal of this change set is to make startup fast such that volume data which is often shipped alongside OHLC history is loaded and shown asap and FSPs are loaded in an actor cluster with their graphics overlayed concurrently as each responsible worker generates plottable output. For everything to work this commit requires use of a draft `pyqtgraph` PR: pyqtgraph/pyqtgraph#2162 Change summary: - move remaining FSP actor cluster helpers into `.ui._fsp` mod as well as fsp specific UI managers (`maybe_open_vlm_display()`, `start_fsp_displays()`). - add an `FspAdmin` API for starting fsp chains on the cluster concurrently allowing for future work toward reload/unloading. - bring FSP config dict into `start_fsp_displays()` and `.started()`-deliver both the fsp admin and any volume chart back up to the calling display loop code. ToDo: - repair `ChartView` click-drag interactions - auto-range on $ vlm needs to use `ChartPlotWidget._set_yrange()` - a lot better styling for the $_vlm overlay XD
This brings in the WIP components developed as part of pyqtgraph/pyqtgraph#2162. Most of the history can be understood from that issue and effort but the TL;DR is, - add an event handler wrapper system which can be used to wrap `ViewBox` methods such that multiple views can be overlayed and a single event stream broadcast from one "main" view to others which are overlaid with it. - add in 2 relay `Signal` attrs to our `ViewBox` subtype (`Chartview`) to accomplish per event `MouseEvent.emit()` style broadcasting to multiple (sub-)views. - Add a `PlotItemOverlay` api which does all the work of overlaying the actual chart graphics and arranging multiple-axes without collision as well as tying together all the event/signalling so that only a single "focussed" view relays to all overlays.
This syncs with a dev branch in our `pyqtgraph` fork: pyqtgraph/pyqtgraph#2162 The main idea is to get mult-yaxis display fully functional with multiple view boxes running in a "relay mode" where some focussed view relays signals to overlaid views which may have independent axes. This preps us for both displaying independent codomain-set FSP output as well as so called "aggregate" feeds of multiple fins underlyings on the same chart (eg. options and futures over top of ETFs and underlying stocks). The eventual desired UX is to support fast switching of instruments for order mode trading without requiring entirely separate charts as well as simple real-time anal of associated instruments. The first effort here is to display vlm and $_vlm alongside each other as a built-in FSP subchart.
This is a huge commit which moves a bunch of code around in order to simplify some of our UI modules as well as support our first official mult-axis chart: overlaid volume and "dollar volume". A good deal of this change set is to make startup fast such that volume data which is often shipped alongside OHLC history is loaded and shown asap and FSPs are loaded in an actor cluster with their graphics overlayed concurrently as each responsible worker generates plottable output. For everything to work this commit requires use of a draft `pyqtgraph` PR: pyqtgraph/pyqtgraph#2162 Change summary: - move remaining FSP actor cluster helpers into `.ui._fsp` mod as well as fsp specific UI managers (`maybe_open_vlm_display()`, `start_fsp_displays()`). - add an `FspAdmin` API for starting fsp chains on the cluster concurrently allowing for future work toward reload/unloading. - bring FSP config dict into `start_fsp_displays()` and `.started()`-deliver both the fsp admin and any volume chart back up to the calling display loop code. ToDo: - repair `ChartView` click-drag interactions - auto-range on $ vlm needs to use `ChartPlotWidget._set_yrange()` - a lot better styling for the $_vlm overlay XD
This brings in the WIP components developed as part of pyqtgraph/pyqtgraph#2162. Most of the history can be understood from that issue and effort but the TL;DR is, - add an event handler wrapper system which can be used to wrap `ViewBox` methods such that multiple views can be overlayed and a single event stream broadcast from one "main" view to others which are overlaid with it. - add in 2 relay `Signal` attrs to our `ViewBox` subtype (`Chartview`) to accomplish per event `MouseEvent.emit()` style broadcasting to multiple (sub-)views. - Add a `PlotItemOverlay` api which does all the work of overlaying the actual chart graphics and arranging multiple-axes without collision as well as tying together all the event/signalling so that only a single "focussed" view relays to all overlays.
This syncs with a dev branch in our `pyqtgraph` fork: pyqtgraph/pyqtgraph#2162 The main idea is to get mult-yaxis display fully functional with multiple view boxes running in a "relay mode" where some focussed view relays signals to overlaid views which may have independent axes. This preps us for both displaying independent codomain-set FSP output as well as so called "aggregate" feeds of multiple fins underlyings on the same chart (eg. options and futures over top of ETFs and underlying stocks). The eventual desired UX is to support fast switching of instruments for order mode trading without requiring entirely separate charts as well as simple real-time anal of associated instruments. The first effort here is to display vlm and $_vlm alongside each other as a built-in FSP subchart.
This brings in the WIP components developed as part of pyqtgraph/pyqtgraph#2162. Most of the history can be understood from that issue and effort but the TL;DR is, - add an event handler wrapper system which can be used to wrap `ViewBox` methods such that multiple views can be overlayed and a single event stream broadcast from one "main" view to others which are overlaid with it. - add in 2 relay `Signal` attrs to our `ViewBox` subtype (`Chartview`) to accomplish per event `MouseEvent.emit()` style broadcasting to multiple (sub-)views. - Add a `PlotItemOverlay` api which does all the work of overlaying the actual chart graphics and arranging multiple-axes without collision as well as tying together all the event/signalling so that only a single "focussed" view relays to all overlays.
This syncs with a dev branch in our `pyqtgraph` fork: pyqtgraph/pyqtgraph#2162 The main idea is to get mult-yaxis display fully functional with multiple view boxes running in a "relay mode" where some focussed view relays signals to overlaid views which may have independent axes. This preps us for both displaying independent codomain-set FSP output as well as so called "aggregate" feeds of multiple fins underlyings on the same chart (eg. options and futures over top of ETFs and underlying stocks). The eventual desired UX is to support fast switching of instruments for order mode trading without requiring entirely separate charts as well as simple real-time anal of associated instruments. The first effort here is to display vlm and $_vlm alongside each other as a built-in FSP subchart.
This brings in the WIP components developed as part of pyqtgraph/pyqtgraph#2162. Most of the history can be understood from that issue and effort but the TL;DR is, - add an event handler wrapper system which can be used to wrap `ViewBox` methods such that multiple views can be overlayed and a single event stream broadcast from one "main" view to others which are overlaid with it. - add in 2 relay `Signal` attrs to our `ViewBox` subtype (`Chartview`) to accomplish per event `MouseEvent.emit()` style broadcasting to multiple (sub-)views. - Add a `PlotItemOverlay` api which does all the work of overlaying the actual chart graphics and arranging multiple-axes without collision as well as tying together all the event/signalling so that only a single "focussed" view relays to all overlays.
This is a huge commit which moves a bunch of code around in order to simplify some of our UI modules as well as support our first official mult-axis chart: overlaid volume and "dollar volume". A good deal of this change set is to make startup fast such that volume data which is often shipped alongside OHLC history is loaded and shown asap and FSPs are loaded in an actor cluster with their graphics overlayed concurrently as each responsible worker generates plottable output. For everything to work this commit requires use of a draft `pyqtgraph` PR: pyqtgraph/pyqtgraph#2162 Change summary: - move remaining FSP actor cluster helpers into `.ui._fsp` mod as well as fsp specific UI managers (`maybe_open_vlm_display()`, `start_fsp_displays()`). - add an `FspAdmin` API for starting fsp chains on the cluster concurrently allowing for future work toward reload/unloading. - bring FSP config dict into `start_fsp_displays()` and `.started()`-deliver both the fsp admin and any volume chart back up to the calling display loop code. ToDo: - repair `ChartView` click-drag interactions - auto-range on $ vlm needs to use `ChartPlotWidget._set_yrange()` - a lot better styling for the $_vlm overlay XD
I ended up taking a slightly different approach with the label stacking (since I personally think the defaults are far too big and invasive) but for all other intents and purposes this is working as expected minus one outstanding issue: when you link all the axes panning via click-drag results in For those interested the first draft implementation is in pikers/piker#257. Please feel free to reach out when ready and we'll do our best to resume this 😄 |
This syncs with a dev branch in our `pyqtgraph` fork: pyqtgraph/pyqtgraph#2162 The main idea is to get mult-yaxis display fully functional with multiple view boxes running in a "relay mode" where some focussed view relays signals to overlaid views which may have independent axes. This preps us for both displaying independent codomain-set FSP output as well as so called "aggregate" feeds of multiple fins underlyings on the same chart (eg. options and futures over top of ETFs and underlying stocks). The eventual desired UX is to support fast switching of instruments for order mode trading without requiring entirely separate charts as well as simple real-time anal of associated instruments. The first effort here is to display vlm and $_vlm alongside each other as a built-in FSP subchart.
This brings in the WIP components developed as part of pyqtgraph/pyqtgraph#2162. Most of the history can be understood from that issue and effort but the TL;DR is, - add an event handler wrapper system which can be used to wrap `ViewBox` methods such that multiple views can be overlayed and a single event stream broadcast from one "main" view to others which are overlaid with it. - add in 2 relay `Signal` attrs to our `ViewBox` subtype (`Chartview`) to accomplish per event `MouseEvent.emit()` style broadcasting to multiple (sub-)views. - Add a `PlotItemOverlay` api which does all the work of overlaying the actual chart graphics and arranging multiple-axes without collision as well as tying together all the event/signalling so that only a single "focussed" view relays to all overlays.
This is a huge commit which moves a bunch of code around in order to simplify some of our UI modules as well as support our first official mult-axis chart: overlaid volume and "dollar volume". A good deal of this change set is to make startup fast such that volume data which is often shipped alongside OHLC history is loaded and shown asap and FSPs are loaded in an actor cluster with their graphics overlayed concurrently as each responsible worker generates plottable output. For everything to work this commit requires use of a draft `pyqtgraph` PR: pyqtgraph/pyqtgraph#2162 Change summary: - move remaining FSP actor cluster helpers into `.ui._fsp` mod as well as fsp specific UI managers (`maybe_open_vlm_display()`, `start_fsp_displays()`). - add an `FspAdmin` API for starting fsp chains on the cluster concurrently allowing for future work toward reload/unloading. - bring FSP config dict into `start_fsp_displays()` and `.started()`-deliver both the fsp admin and any volume chart back up to the calling display loop code. ToDo: - repair `ChartView` click-drag interactions - auto-range on $ vlm needs to use `ChartPlotWidget._set_yrange()` - a lot better styling for the $_vlm overlay XD
This is a huge commit which moves a bunch of code around in order to simplify some of our UI modules as well as support our first official mult-axis chart: overlaid volume and "dollar volume". A good deal of this change set is to make startup fast such that volume data which is often shipped alongside OHLC history is loaded and shown asap and FSPs are loaded in an actor cluster with their graphics overlayed concurrently as each responsible worker generates plottable output. For everything to work this commit requires use of a draft `pyqtgraph` PR: pyqtgraph/pyqtgraph#2162 Change summary: - move remaining FSP actor cluster helpers into `.ui._fsp` mod as well as fsp specific UI managers (`maybe_open_vlm_display()`, `start_fsp_displays()`). - add an `FspAdmin` API for starting fsp chains on the cluster concurrently allowing for future work toward reload/unloading. - bring FSP config dict into `start_fsp_displays()` and `.started()`-deliver both the fsp admin and any volume chart back up to the calling display loop code. ToDo: - repair `ChartView` click-drag interactions - auto-range on $ vlm needs to use `ChartPlotWidget._set_yrange()` - a lot better styling for the $_vlm overlay XD
Fork out our patch set submitted to upstream in multiple PRs (since they aren't moving and/or aren't a priority to core) which can be seen in full from the following diff: pyqtgraph/pyqtgraph@master...pikers:pyqtgraph:graphics_pin Move these type extensions into the internal `.ui._pg_overrides` module. The changes are related to both `pyqtgraph.PlotItem` and `.AxisItem` and were driven for our need for multi-view overlays (overlaid charts with optionally synced axis and interaction controls) as documented in the PR to upstream: pyqtgraph/pyqtgraph#2162 More specifically, - wrt to `AxisItem` we added lru caching of tick values as per: pyqtgraph/pyqtgraph#2160. - wrt to `PlotItem` we adjusted some of the axis management code, namely adding a standalone `.removeAxis()` and modifying the `.setAxisItems()` logic to use it in: pyqtgraph/pyqtgraph#2162 as well as some tweaks to `.updateGrid()` to loop through all possible axes when grid setting.
As an update, I've reworked this original code to discard all signal/slot rewiring to instead use a python broadcast loop in pikers/piker#414. This turned out to be vastly easier to understand and implement and appears to have zero performance hit. |
Fork out our patch set submitted to upstream in multiple PRs (since they aren't moving and/or aren't a priority to core) which can be seen in full from the following diff: pyqtgraph/pyqtgraph@master...pikers:pyqtgraph:graphics_pin Move these type extensions into the internal `.ui._pg_overrides` module. The changes are related to both `pyqtgraph.PlotItem` and `.AxisItem` and were driven for our need for multi-view overlays (overlaid charts with optionally synced axis and interaction controls) as documented in the PR to upstream: pyqtgraph/pyqtgraph#2162 More specifically, - wrt to `AxisItem` we added lru caching of tick values as per: pyqtgraph/pyqtgraph#2160. - wrt to `PlotItem` we adjusted some of the axis management code, namely adding a standalone `.removeAxis()` and modifying the `.setAxisItems()` logic to use it in: pyqtgraph/pyqtgraph#2162 as well as some tweaks to `.updateGrid()` to loop through all possible axes when grid setting.
Fork out our patch set submitted to upstream in multiple PRs (since they aren't moving and/or aren't a priority to core) which can be seen in full from the following diff: pyqtgraph/pyqtgraph@master...pikers:pyqtgraph:graphics_pin Move these type extensions into the internal `.ui._pg_overrides` module. The changes are related to both `pyqtgraph.PlotItem` and `.AxisItem` and were driven for our need for multi-view overlays (overlaid charts with optionally synced axis and interaction controls) as documented in the PR to upstream: pyqtgraph/pyqtgraph#2162 More specifically, - wrt to `AxisItem` we added lru caching of tick values as per: pyqtgraph/pyqtgraph#2160. - wrt to `PlotItem` we adjusted some of the axis management code, namely adding a standalone `.removeAxis()` and modifying the `.setAxisItems()` logic to use it in: pyqtgraph/pyqtgraph#2162 as well as some tweaks to `.updateGrid()` to loop through all possible axes when grid setting.
This is a competing approach to #1359 for "multi-axis" support.
The main difference is not introducing any new apis or inherited types (
PlotWidget
) and to instead use existing subsystems (with minor internal changes) and a composedPlotItem
overlay approach which keeps support for custom user defined subtypes (such asViewBox
, otherGraphicsObject
, etc.).Notes:
'left'
,'bottom'
axis layout stacking yet (but this is trivial)QGraphicsAnchorLayout
is the right tool for this job 😉ViewBox
-AxisItem
rats nest of "linked" handlers 😂Improvements over #1359
ViewBox
which means multiple implementations can be use together (or passed in by the user)The current issues there last I checked were:
ViewBox
, the details of why this is an issue is gets fairly involved:ViewBox.linkView()
does it's own set of signal/slot-broadcasting configuration which can result in handlers being called twice, which in this case is true sinceViewBox.linkView()
will also call.setXRange()
..Afaict both of these are solved in this approach. Minus unimplemented features, the only bug here is the axis click-drag support which seems to be an internal bug to do with signal relaying.
The trick for overlaying view box code was definitely used from #1359 which you'll see commented.
See the list of out-standings in the module for more details.
Changes to
ViewBox
andPlotItem
I will make comments alongside the code below.
Very interested to get a detailed discussion on this approach 🏄🏼 😂 🥸
ping @j9ac9k @outofculture @pijyoi