Commit Graph

2120 Commits (eb2b844c2dce149c6eb0be98d8c8c1ef8c608808)

Author SHA1 Message Date
Tyler Goodlet f1f7241a1e Add "native" downsampling to our `FastAppendCurve`
Build out an interface that makes it super easy to downsample curves
using the m4 algorithm while keeping our incremental `QPainterPath`
update feature. A lot of hard work and tinkering went into getting this
working all in-thread correctly and there are quite a few details..

New interface methods:
- `.x_uppx()` which returns the x-axis "view units per pixel"
- `.px_width()` which returns the total (rounded) x-axis pixels spanned
    by the curve in view.
- `.should_ds_or_redraw()` a predicate which checks internal state to
  see if either downsampling of the curve should take place, or the curve
  should have all downsampling removed and be redrawn with source array
  data.
- `.downsample()` the actual ds processing routine which delegates into
  the m4 algo impl.
- `.maybe_downsample()` a simple update method which can be called by
  the view box when the user changes the zoom level.

Implementation details/changes:

- make `.update_from_array()` check for downsample (or revert to source
  aka de-downsample) conditions exist and then downsample and re-draw
  path graphics accordingly.
- in order to even further speed up path appends (since our main
  bottleneck is measured to be `QPainter.drawPath()` calls with large
  paths which are frequently updates), add a secondary path `.fast_path`
  which is the path that is real-time updates by incremental appends and
  which is painted separately for speed in `.pain()`.
- drop all the `QPolyLine` stuff since it was tested to be much slower
  in general and especially so for append-updates.
- stop disabling the cache settings on updates since it doesn't seem to
  be required any more?
- more move toward deprecating and removing all lingering interface
  requirements from `pg.PlotCurveItem` (like `.xData`/`.yData`).
- adjust `.paint()` and `.boundingRect()` to compensate for the new
  `.fast_path`
- add a butt-load of profiling B)
2022-04-16 15:38:26 -04:00
Tyler Goodlet 6af6449e8e Add no-path guard now that we can use a poly 2022-04-16 15:38:26 -04:00
Tyler Goodlet c55c0f5d8f First try, drop `FastAppendCurve` inheritance from `pg.PlotCurveItem` 2022-04-16 15:38:26 -04:00
Tyler Goodlet 8c2d375e0e Drop commented line from pq method copy/paste 2022-04-16 15:38:26 -04:00
Tyler Goodlet 889aa10d32 Show baseline bars length on in view read < 6 2022-04-16 15:38:26 -04:00
Tyler Goodlet eba92a8f20 Bump up resolution log scaling a mag 2022-04-16 15:38:26 -04:00
Tyler Goodlet d3d19a57c9 Always clear previous downsample curve on switch
Pretty sure this was most of the cause of the stale (more downsampled)
curves showing when zooming in and out from bars mode quickly. All this
stuff needs to get factored out into a new abstraction anyway, but
i think this get's mostly correct functionality.

Only draw new ds curve on uppx steps >= 4 and stop adding/removing
graphics objects from the scene; doesn't seem to speed anything up
afaict. Add better reporting of ds scale changes.
2022-04-16 15:38:26 -04:00
Tyler Goodlet ba4a526b8b Clear ds line graphics on switch back to bars 2022-04-16 15:38:26 -04:00
Tyler Goodlet 15922f4090 More ems resiliency: discard broken client dialogs 2022-04-16 15:38:26 -04:00
Tyler Goodlet f6136245f9 Allocate m4 output arrays in `numba` code, avoid segfaults? 2022-04-16 15:38:26 -04:00
Tyler Goodlet 44482cbc1b Only clear/redraw curve on uppx diffs > 2
Only if the uppx increases by more then 2 we redraw the entire line
otherwise just ds with previous params and update the current curve.
This *should* avoid strange lower sample rate artefacts from showing on
updates.

Summary:
- stash both uppx and px width in `._dsi` (downsample info)
- use the new `ohlc_to_m4_line()` flags
- add notes about using `.reserve()` and friends
- always delete last `._array` ref prior to line updates
2022-04-16 15:38:26 -04:00
Tyler Goodlet c745c9801f Try supporting reuse of path allocation 2022-04-16 15:38:26 -04:00
Tyler Goodlet 60b1c53d20 Add optional mxmn HL tracer support to m4 sampler 2022-04-16 15:38:26 -04:00
Tyler Goodlet 68779218ff Add our own `FastAppendCurve.clear()`, try mem reso
In an effort to try and make `QPainterPath.reserve()` work, add internal
logic to use the same object without de-allocating memory from
a previous path write/creation.

Note this required the addition of a `._redraw` flag (to be used in
`.clear()` and a small patch to `pyqtgraph.functions.arrayToQPath` to
allow passing in an existing path (thus reusing the same underlying mem
alloc) which will likely be first pushed to our fork.
2022-04-16 15:38:26 -04:00
Tyler Goodlet 9726ed1a42 Add optional uppx log scaling to m4 sampler
We were previously ad-hoc scaling up the px count/width to get more
detail at lower uppx values. Add a log scaling sigmoid that range scales
between 1 < px_width < 16.

Add in a flag to use the mxmn OH tracer in `ohlc_flatten()` if desired.
2022-04-16 15:38:26 -04:00
Tyler Goodlet 69cb8156a2 Delegate to m4 ohlc helper for curve, only ds on uppx steps > 2 2022-04-16 15:38:26 -04:00
Tyler Goodlet 97efb865d4 Add OHLC to m4 line converters
Helpers to quickly convert ohlc struct-array sequences into lines
for consumption by the m4 downsampler. Strip trailing zero entries
from the `ds_m4()` output if found (avoids lines back to origin).
2022-04-16 15:38:26 -04:00
Tyler Goodlet 2f99fd35e5 M4 workin bishhhhh 2022-04-16 15:38:26 -04:00
Tyler Goodlet 2e25357ed0 Call default view on symbol switch 2022-04-16 15:38:26 -04:00
Tyler Goodlet c1bdf0e26d Make a derivs intrustment type table for alloc config checks 2022-04-16 15:38:26 -04:00
Tyler Goodlet d3587263db Even more correct "default view" snap-to-pp-marker
This makes the `'r'` hotkey snap the last bar to the middle of the pp
line arrow marker no matter the zoom level. Now we also boot with
approximately the most number of x units on screen that keep the bars
graphics drawn in full (just before downsampling to a line).

Moved some internals around to get this all in place,
- drop `_anchors.marker_right_points()` and move it to a chart method.
- change `.pre_l1_x()` -> `.pre_l1_xs()` and just have it return the
  two view-mapped x values from the former method.
2022-04-16 15:38:26 -04:00
Tyler Goodlet 6bf4cdaa24 Make `ChartPlotWidget.default_view()` pin to L1
Instead of using a guess about how many x-indexes to reset the last
datum in-view to, calculate and shift the latest index such that it's
just before any L1 spread labels on the y-axis. This makes the view
placement "widget aware" and gives a much more cross-display UX.

Summary:
- add `ChartPlotWidget.pre_l1_x()` which returns a `tuple` of
  x view-coord points for the absolute x-pos and length of any L1
  line/labels
- make `.default_view()` only shift to see the xlast just outside
  the l1 but keep whatever view range xfirst as the first datum in view
- drop `LevelLine.right_point()` since this is now just a
  `.pre_l1_x()` call and can be retrieved from the line's internal chart
  ref
- drop `._style.bars_from/to_..` vars since we aren't using hard coded
  offsets any more
2022-04-16 15:38:26 -04:00
Tyler Goodlet e95896722f Pass in fqsn from chart UI components 2022-04-16 15:38:26 -04:00
Tyler Goodlet 8a4f124a48 Use units by default for continuous futes 2022-04-16 15:38:26 -04:00
Tyler Goodlet a3817d7644 WIP add non-working m4 ds code to ohlc graphic 2022-04-16 15:38:26 -04:00
Tyler Goodlet 6d1a3dfdc5 Use service cancel method for graceful teardown 2022-04-16 15:38:26 -04:00
Tyler Goodlet acba4e8f02 Add curve px width getter
`ChartPlotWidget.curve_width_pxs()` now can be used to get the total
horizontal (x) pixels on screen that are occupied by the current curve
graphics for a given chart. This will be used for downsampling large
data sets to the pixel domain using M4.
2022-04-16 15:38:26 -04:00
Tyler Goodlet d86320848f Add display loop profiling
Probably the best place to root the profiler since we can get a better
top down view of bottlenecks in the graphics stack.

More,
- add in draft M4 downsampling code (commented) after getting it mostly
  working; next step is to move this processing into an FSP subactor.
- always update the vlm chart last y-axis sticky
- set call `.default_view()` just before inf sleep on startup
2022-04-16 15:38:26 -04:00
Tyler Goodlet bed52639d0 Profiler format, code stretch 2022-04-16 15:38:26 -04:00
Tyler Goodlet 4cd3f8c531 Fix x-range -> # of frames calculation
Obviously determining the x-range from indices was wrong and was the
reason for the incorrect (downsampled) output size XD. Instead correctly
determine the x range and start value from the *values of* the input
x-array. Pretty sure this makes the implementation nearly production
ready.

Relates to #109
2022-04-16 15:38:26 -04:00
Tyler Goodlet e3739f0c84 Add `ChartPlotWidget.in_view()` shm-compatible array slicer 2022-04-16 15:38:26 -04:00
Tyler Goodlet 6d54137ff1 Add (ostensibly) working first attempt at M4 algo
All the refs are in the comments and original sample code from infinite
has been reworked to expect the input x/y arrays to already be sliced
(though we can later support passing in the start-end indexes if
desired).

The new routines are `ds_m4()` the python top level API and `_m4()` the
fast `numba` implementation.
2022-04-16 15:38:26 -04:00
Tyler Goodlet 39b1edf847 Array diff lengths must be int 2022-04-16 15:38:26 -04:00
Tyler Goodlet 482c46acd0 Limit real-time chart updates in "big data" cases
- the chart's uppx (units-per-pixel) is > 4 (i.e. zoomed out a lot)
- don't shift the chart (to keep the most recent step in view) if the
  last datum isn't in view (aka the user is probably looking at history)
2022-04-16 15:38:26 -04:00
Tyler Goodlet 850f664de9 Only trigger downsampling on manual changes, add a uppx method 2022-04-16 15:38:26 -04:00
Tyler Goodlet 5ba13d5677 Add for a `BarItems` to display a line on high uppx
When a bars graphic is zoomed out enough you get a high uppx, datum
units-per-pixel, and there is no point in drawing the 6-lines in each
bar element-graphic if you can't see them on the screen/display device.

Instead here we offer converting to a `FastAppendCurve` which traces
the high-low outline and instead display that when it's impossible to see the
details of bars - approximately when the uppx >= 2.

There is also some draft-commented code in here for downsampling the
outlines as zoom level increases but it's not fully working and should
likely be factored out into a higher level api anyway.
2022-04-16 15:38:26 -04:00
Tyler Goodlet 603d61be39 Original index offset was right 2022-04-16 15:38:26 -04:00
Tyler Goodlet cd14a2b598 Add an ohlcv high/low tracer with optional downsampling 2022-04-16 15:38:26 -04:00
Tyler Goodlet d2b49bd1fe Pass linked charts into `BarItems` so that graphics can be cycled on downsample 2022-04-16 15:38:26 -04:00
Tyler Goodlet abf399a73a Move graphics compression routines to new module 2022-04-16 15:38:26 -04:00
Tyler Goodlet ca7808a887 Use 12Hz as default fps throttle 2022-04-16 15:38:26 -04:00
Tyler Goodlet 78c8a843e4 Add comment on how to enable `pyqtgraph` profiling 2022-04-16 15:38:26 -04:00
Tyler Goodlet 93d2c715e7 Add basic optional polyline support, draft out downsampling routine 2022-04-16 15:38:26 -04:00
Tyler Goodlet da5d2ef331 Add a downsampled line-curve support to `BarItems`
In effort to start getting some graphics speedups as detailed in #109,
this adds a `FastAppendCurve`to every `BarItems` as a `._ds_line` which
is only displayed (instead of the normal mult-line bars curve) when the
"width" of a bar is indistinguishable on screen from a line -> so once
the view coordinates map to > 2 pixels on the display device.
`BarItems.maybe_paint_line()` takes care of this scaling detection logic and is
called by the associated view's `.sigXRangeChanged` signal handler.
2022-04-16 15:38:26 -04:00
Tyler Goodlet a6c103a850 Add detailed `.addItem()`` comment 2022-04-16 15:38:26 -04:00
Tyler Goodlet 0d062bfe66 Add guard for real-time-not-active last line is `None` case 2022-04-16 15:38:26 -04:00
Tyler Goodlet fd296fa762 Indefinitely wait on feed hack for windows? 2022-04-16 15:38:26 -04:00
Tyler Goodlet 0e1656978b Establish stream before `fsp_compute` so that backfill updates work again.. 2022-04-16 15:38:26 -04:00
Tyler Goodlet 4378974b59 Pass in fqsn from chart UI components 2022-04-16 15:38:26 -04:00
Tyler Goodlet 6d9ffc532e Add a `trigger_all` arg to update cycle func; allows hard history updates 2022-04-16 15:38:26 -04:00