Commit Graph

2794 Commits (59483dc8e86b8ea7ee4893cc89d54cd42eaf2dcc)

Author SHA1 Message Date
Tyler Goodlet 99e100cd6b Make `.increment_view()` take in a `datums: int` and always scale it by sample step size 2023-01-10 12:42:26 -05:00
Tyler Goodlet 8e300a3aed Make `Viz.incr_info()` do treading with time-index, and appending with array-index 2023-01-10 12:42:26 -05:00
Tyler Goodlet 89352a3b3b Rename `reset` -> `reset_cache` 2023-01-10 12:42:26 -05:00
Tyler Goodlet d4c2aeb4e0 Fix gap detection on RHS; always bin-search on overshot time range 2023-01-10 12:42:26 -05:00
Tyler Goodlet ddf8fa7b7a Add type annots to vars inside `Render.render()` 2023-01-10 12:42:26 -05:00
Tyler Goodlet abac60a0f4 Drop coordinate cacheing from `BarItems`, causes weird jitter on pan 2023-01-10 12:42:26 -05:00
Tyler Goodlet 6e6c6484fc Fix f-str in duplicate frame msg print 2023-01-10 12:42:26 -05:00
Tyler Goodlet 134b8129b5 `ib`: fix position log msg 2023-01-10 12:42:26 -05:00
Tyler Goodlet f7cfb848c5 Add `ChartPlotWidget.main_viz: Viz` convenience `@property` 2023-01-10 12:42:26 -05:00
Tyler Goodlet fd02a60ab0 Make `Viz.incr_info()` sample rate agnostic
Mainly it was the global (should we )increment logic that needs to be
independent for the fast vs. slow chart such that the slow isn't
update-shifted by the fast and vice versa. We do this using a new
`'i_last_slow'` key in the `DisplayState.globalz: dict` which is
singleton for each sample-rate-specific chart and works for both time
and array indexing.

Also, we drop some old commented `graphics.draw_last_datum()` code that
never ended up being needed again inside the coordinate cache reset
bloc.
2023-01-10 12:42:26 -05:00
Tyler Goodlet de585d2dc1 Use array-`int`-indexing on single feed
Might as well since it makes the chart look less gappy and we can easily
flip the index switch now B)

Also adds a new `'i_slow_last'` key to `DisplayState` for a singleton
across all slow charts and thus no more need for special case logic in
`viz.incr_info()`.
2023-01-10 12:42:26 -05:00
Tyler Goodlet 4b76f9ec9a Align step curves the same as OHLC bars 2023-01-10 12:42:26 -05:00
Tyler Goodlet 28d9c781e8 Add `IncrementalFormatter.x_offset: np.ndarray`
Define the x-domain coords "offset" (determining the curve graphics
per-datum placement) for each formatter such that there's only on place
to change it when needed. Obviously each graphics type has it's own
dimensionality and this is reflected by the array shapes on each
subtype.
2023-01-10 12:42:26 -05:00
Tyler Goodlet 6756ca5931 Adjust OHLC bar x-offsets to be time span matched
Previously we were drawing with the middle of the bar on each index with
arms to either side: +/- some arm length. Instead this changes so that
each bar is drawn *after* each index/timestamp such that in graphics
coords the bar span more correctly matches the time span in the
x-domain. This makes the linked region between slow and fast chart
directly match (without any transform) for epoch-time indexing such that
the last x-coord in view on the fast chart is no more then the
next time step in (downsampled) slow view.

Deats:
- adjust in `._pathops.path_arrays_from_ohlc()` and take an `bar_w` bar
  width input (normally taken from the data step size).
- change `.ui._ohlc.bar_from_ohlc_row()` and
  `BarItems.draw_last_datum()` to match.
2023-01-10 12:42:26 -05:00
Tyler Goodlet ef6a1167b0 `Viz._index_field` a `typing.Literal[str]` 2023-01-10 12:42:25 -05:00
Tyler Goodlet 325fe1ca67 Set `path_arrays_from_ohlc(use_time_index=True)` on epoch indexing
Allows easily switching between normal array `int` indexing and time
indexing by just flipping the `Viz._index_field: str`.

Also, guard all the x-data audit breakpoints with a time indexing
condition.
2023-01-10 12:42:25 -05:00
Tyler Goodlet 0316304e3d Ugh, use `bool` flag to determine index field.. 2023-01-10 12:42:25 -05:00
Tyler Goodlet 72c6b5f646 Make `LinearRegion` link using epoch-time index
Turned out to be super simple to get the first draft to work since the
fast and slow chart now use the same domain, however, it seems like
maybe there's an offset issue still where the fast may be a couple
minutes ahead of the slow?

Need to dig in a bit..
2023-01-10 12:42:25 -05:00
Tyler Goodlet 1f356b6e10 `ib`: Add treasury yield futs to adhoc fqsn set 2023-01-10 12:42:25 -05:00
Tyler Goodlet 1059520212 Add global `i_step` per overlay to `DisplayState`
Using a global "last index step" (via module var) obviously has problems
when working with multiple feed sets in a single global app instance:
any separate feed-set will be incremented according to an app-global
index-step and thus won't correctly calc per-feed-set-step update info.

Impl deatz:
- drop `DisplayState.incr_info()` (since previously moved to `Viz`) and
  call that method on each appropriate `Viz` instance where necessary;
  further ensure the appropriate `DisplayState` instance is passed in to
  each call and make sure to pass a `state: DisplayState`.
- add `DisplayState.hist_vars: dict` for history chart (sets) to
  determine the per-feed (not set) current slow chart (time) step.
- add `DisplayState.globalz: dict` to house a common per-feed-set state
  and use it inside the new `Viz.incr_info()` such that
  a `should_increment: bool` can be returned and used by the display
  loop to determine whether to x-shift the current chart.
2023-01-10 12:42:25 -05:00
Tyler Goodlet 2a4fafcf21 Move `DisplayState.incr_info()` -> `Viz` 2023-01-10 12:42:25 -05:00
Tyler Goodlet e363f102a3 Drop `tractor` assert bug note 2023-01-10 12:42:25 -05:00
Tyler Goodlet d2b7cb7b35 Move `Viz` layer to new `.ui` mod 2023-01-10 12:42:25 -05:00
Tyler Goodlet 81d6d1d80b Fix line -> bars on 6x UPPX
Read the `Viz.index_step()` directly to avoid always reading 1 on the
slow chart; this was completely broken before and resulting in not
rendering the bars graphic on the slow chart until at a true uppx of
1 which obviously doesn't work for 60 width bars XD

Further cleanups to `._render` module:
- drop `array` output from `Renderer.render()`, `read_from_key` input
  and fix type annot.
- drop `should_line`, `changed_to_line` and `render_kwargs` from
  `render_baritems()` outputs and instead calc `should_redraw` logic
  inside the func body and return as output.
2023-01-10 12:42:25 -05:00
Tyler Goodlet 57264f87c6 Drop unused `read_src_from_key: bool` to `.format_to_1d()` 2023-01-10 12:42:25 -05:00
Tyler Goodlet cd7d36d2d8 Right, do index lookup for int-index as well.. 2023-01-10 12:42:25 -05:00
Tyler Goodlet 30b9130be6 Fix formatter xy ndarray first prepend case
First allocation vs. first "prepend" of source data to an xy `ndarray`
format **must be mutex** in order to avoid a double prepend.

Previously when both blocks were executed we'd end up with
a `.xy_nd_start` that was decremented (at least) twice as much as it
should be on the first `.format_to_1d()` call which is obviously
incorrect (and causes problems for m4 downsampling as discussed below).
Further, since the underlying `ShmArray` buffer indexing is managed
(i.e. write-updated) completely independently from the incremental
formatter updates and internal xy indexing, we can't use
`ShmArray._first.value` and instead need to use the particular `.diff()`
output's prepend length value to decrement the `.xy_nd_start` on updates
after initial alloc.

Problems this resolves with m4:
- m4 uses a x-domain diff to calculate the number of "frames" to
  downsample to, this is normally based on the ratio of pixel columns on
  screen vs. the size of the input xy data.
- previously using an int-index (not epoch time) the max diff between
  first and last index would be the size of the input buffer and thus
  would never cause a large mem allocation issue (though it may have
  been inefficient in terms of needed size).
- with an epoch time index this max diff could explode if you had some
  near-now epoch time stamp **minus** an x-allocation value: generally
  some value in `[0.5, -0.5]` which would result in a massive frames and
  thus internal `np.ndarray()` allocation causing either a crash in
  `numba` code or actual system mem over allocation.

Further, put in some more x value checks that trigger breakpoints if we
detect values that caused this issue - we'll remove em after this has
been tested enough.
2023-01-10 12:42:25 -05:00
Tyler Goodlet abf3b08328 Handle time-indexing for fill arrows
Call into a reworked `Flume.get_index()` for both the slow and fast
chart and do time index clipping to last datum where necessary.
2023-01-10 12:42:25 -05:00
Tyler Goodlet 95b9ae66b2 Restore coord-cache resetting
Turns out we can't seem to avoid the artefacts when click-drag-scrolling
(results in weird repeated "smeared" curve segments) so just go back to
the original code.
2023-01-10 12:42:25 -05:00
Tyler Goodlet ac6a1b1521 ib: ignore throttles on `.get_head_time()` 2023-01-10 12:42:25 -05:00
Tyler Goodlet 734c818ed0 Add some commented debug prints for default fmtr 2023-01-10 12:42:25 -05:00
Tyler Goodlet 1546ff0001 Slicec to an extra index around each timestamp input 2023-01-10 12:42:25 -05:00
Tyler Goodlet b4384209b6 Ensure FSPs last 2 times are synced with its source 2023-01-10 12:42:25 -05:00
Tyler Goodlet de791e62c8 Drop passing `render_data` to `Curve.draw_last_datum()` 2023-01-10 12:42:25 -05:00
Tyler Goodlet de26fecff4 Add back `.default_view()` slice logic for `int` indexing 2023-01-10 12:42:25 -05:00
Tyler Goodlet ff34ac9ae7 Block out `do_print` stuff inside `Viz.maxmin()` 2023-01-10 12:42:25 -05:00
Tyler Goodlet 69681347a4 Implement `stop_t` gap adjustments; the good lord said it is the problem 2023-01-10 12:42:25 -05:00
Tyler Goodlet 26a79d667e Draw last datums on boot
Ensures that a "last datum" graphics object exists so that zooming can
read it using `.x_last()`. Also, disable the linked region stuff for now
since it's totally borked after flipping to the time indexing.
2023-01-10 12:42:25 -05:00
Tyler Goodlet d5a4dcea70 Use `Curve.x_last()` for zoom focal point 2023-01-10 12:42:25 -05:00
Tyler Goodlet 7ef6219d01 Delegate to `Viz.default_view()` on chart
Also add a rage print to not forget about the global index
tracking/diffing in the display loop we still need to change.
2023-01-10 12:42:25 -05:00
Tyler Goodlet 5976d68bb2 Re-implement `.default_view()` on `Viz`
Since we don't really need it defined on the "chart widget" move it to
a viz method and rework it to hell:

- always discard the invalid view l > r case.
- use the graphic's UPPX to determine UI-to-scene coordinate scaling for
  the L1-label collision detection, if there is no L1 just offset by
  a few (index step scaled) datums; this allows us to drop the 2x
  x-range calls as was hacked previous.
- handle no-data-in-view cases explicitly and error if we get any
  ostensibly impossible cases.
- expect caller to trigger a graphics cycle if needed.

Further support this includes a rework a slew of other important
details:

- add `Viz.index_step`, an idempotent computed, index (presumably uniform)
  step value which is needed for variable sample rate graphics displayed
  on an epoch (second) time index.
- rework `Viz.datums_range()` to pass view x-endpoints as first and last
  elements in return `tuple`; tighten up snap-to-data edge case logic
  using `max()`/`min()` calls and better internal var naming.
- adjust all calls to `slice_from_time()` to not expect an "abs" slice.
- drop all `.yrange` resetting since we can just have the `Renderer` do
  it when necessary.
2023-01-10 12:42:25 -05:00
Tyler Goodlet 3a0cbe518e Add gap detection for `stop_t`, though only report atm 2023-01-10 12:42:25 -05:00
Tyler Goodlet aaa1bccd60 Add `.x_last()` meth to flow graphics 2023-01-10 12:42:25 -05:00
Tyler Goodlet 14bcba367e Drop `Flume.view_data()` 2023-01-10 12:42:25 -05:00
Tyler Goodlet 1b95668309 Drop old breakpoint 2023-01-10 12:42:25 -05:00
Tyler Goodlet 688d7d7f2f Drop `_slice_from_time()` 2023-01-10 12:42:25 -05:00
Tyler Goodlet 5c417fe815 Use uniform step arithmetic in `slice_from_time()`
If we presume that time indexing using a uniform step we can calculate
the exact index (using `//`) for the input time presuming the data
set has zero gaps. This gives a massive speedup over `numpy` fancy
indexing and (naive) `numba` iteration. Further in the case where time
gaps are detected, we can use `numpy.searchsorted()` to binary search
for the nearest expected index at lower latency.

Deatz,
- comment-disable the call to the naive `numba` scan impl.
- add a optional `step: int` input (calced if not provided).
- add todos for caching binary search results in the gap detection
  cases.
- drop returning the "absolute buffer indexing" slice since the caller
  can always just use the read-relative slice to acquire it.
2023-01-10 12:42:25 -05:00
Tyler Goodlet 94e0f48f39 Make `.default_view()` time step aware
When we use an epoch index and any sample rate > 1s we need to scale the
"number of bars" to that step in order to place the view correctly in
x-domain terms. For now we're calcing the step in-method but likely,
longer run, we'll pull this from elsewhere (like a ``Viz`` attr).
2023-01-10 12:42:25 -05:00
Tyler Goodlet aa404ab18b Flip over to epoch-time based x-domain indexing 2023-01-10 12:42:25 -05:00
Tyler Goodlet 3e62832580 Adjust all `slice_from_time()` calls to not expect mask 2023-01-10 12:42:25 -05:00
Tyler Goodlet 352bd4a1f7 Rewrite `slice_from_time()` using `numba`
Gives approx a 3-4x speedup using plain old iterate-with-for-loop style
though still not really happy with this .5 to 1 ms latency..

Move the core `@njit` part to a `_slice_from_time()` with a pure python
func with orig name around it. Also, drop the output `mask` array since
we can generally just use the slices in the caller to accomplish the
same input array slicing, duh..
2023-01-10 12:42:25 -05:00
Tyler Goodlet f18247b855 Use index (time) step to calc OHLC bar/line uppx threshold 2023-01-10 12:42:25 -05:00
Tyler Goodlet 92a71293ac Use step size to determine bar gaps 2023-01-10 12:42:25 -05:00
Tyler Goodlet 6829daa79c Use step size to determine last datum bar gap 2023-01-10 12:42:25 -05:00
Tyler Goodlet cd58bfb8cf Move `Flume.slice_from_time()` to `.data._pathops` mod func 2023-01-10 12:42:25 -05:00
Tyler Goodlet 49ea4e1ef6 Drop `index_field` input to renders, add `.read()` profiling 2023-01-10 12:42:25 -05:00
Tyler Goodlet d8f325ddd9 Delegate formatter `.index_field` to the parent `Viz` 2023-01-10 12:42:25 -05:00
Tyler Goodlet 2e6f14afb3 Facepalm**2: fix array-read-slice, like actually..
We need to subtract the first index in the array segment read, not the
first index value in the time-sliced output, to get the correct offset
into the non-absolute (`ShmArray.array` read) array..

Further we **do** need the `&` between the advance indexing conditions
and this adds profiling to see that it is indeed real slow (like 20ms
ish even when using `np.where()`).
2023-01-10 12:42:25 -05:00
Tyler Goodlet a2f75a83b6 TOSQUASH 4eb5fe0dd96 (FSP copy time from src -> dst)
Slice up to history's length worth of (latest) time stamps from source
series read at the start of the history init phase.
2023-01-10 12:42:25 -05:00
Tyler Goodlet faecd6f0e0 Markup OHLC->path gen with `numba` issue # 2023-01-10 12:42:25 -05:00
Tyler Goodlet 69d4fe9fef Facepalm: put graphics cycle in `do_ds: bool` block.. 2023-01-10 12:42:25 -05:00
Tyler Goodlet 6ce9872530 TOSQUASH: 552a8c298cd (return index for arrow..) 2023-01-10 12:42:25 -05:00
Tyler Goodlet c5a352bc64 Facepalm: actually return latest index on time slice fail.. 2023-01-10 12:42:25 -05:00
Tyler Goodlet 787fa53aa9 Go with explicit `.data._m4` mod name
Since it's a notable and self-contained graphics compression algo, might
as well give it a dedicated module B)
2023-01-10 12:42:25 -05:00
Tyler Goodlet 8de8a40a1e Move (unused) path gen routines to `.ui._pathops` 2023-01-10 12:42:25 -05:00
Tyler Goodlet a2d23244e7 Move qpath-ops routines back to separate mod 2023-01-10 12:42:25 -05:00
Tyler Goodlet 4ca8e23b5b Rename `.ui._pathops.py` -> `.ui._formatters.py 2023-01-10 12:42:25 -05:00
Tyler Goodlet 95ee69c119 Look up "index field" in display cycles
Again, to make epoch indexing a flip-of-switch for testing look up the
`Viz.index_field: str` value when updating labels.

Also, drops the legacy tick-type set tracking which we no longer use
thanks to the new throttler subsys and it's framing msgs.
2023-01-10 12:42:25 -05:00
Tyler Goodlet cab75217dd Fix from-time index slicing?
Apparently we want an `|` for the advanced indexing logic?
Also, fix `read_slc` start to not always be 0 XD
2023-01-10 12:42:25 -05:00
Tyler Goodlet 59766f53cf Move old label sizing cruft to label mod 2023-01-10 12:42:25 -05:00
Tyler Goodlet 3098d12221 Move path ops routines to top of mod
Planning to put the formatters into a new mod and aggregate all path
gen/op helpers into this module.

Further tweak include:
- moving `path_arrays_from_ohlc()` back to module level
- slice out the last xy datum for `OHLCBarsAsCurveFmtr` 1d formatting
- always copy the new x-value from the source to `.x_nd`
2023-01-10 12:42:25 -05:00
Tyler Goodlet b1ad1f2af1 Drop diff state tracking in formatter
This was a major cause of error (particularly trying to get epoch
indexing working) and really isn't necessary; instead just have
`.diff()` always read from the underlying source array for current
index-step diffing and append/prepend slice construction.

Allows us to,
- drop `._last_read` state management and thus usage.
- better handle startup indexing by setting `.xy_nd_start/stop` to
  `None` initially so that the first update can be done in one large
  prepend.
- better understand and document the step curve "slice back to previous
  level" logic which is now heavily commented B)
- drop all the `slice_to_head` stuff from and instead allow each
  formatter to choose it's 1d segmenting.
2023-01-10 12:42:25 -05:00
Tyler Goodlet 1bee6e3150 Explicitly enable chart widget yranging in display init 2023-01-10 12:42:25 -05:00
Tyler Goodlet ede2edc85c Enable/disable vlm chart yranging (TO SQUASH) 2023-01-10 12:42:25 -05:00
Tyler Goodlet 27b2daa448 Don't disable non-enabled vlm chart y-autoranging 2023-01-10 12:42:25 -05:00
Tyler Goodlet 620152d783 Comment out bps for time indexing 2023-01-10 12:42:25 -05:00
Tyler Goodlet a13b7aab7c Call `Viz.bars_range()` from display loop 2023-01-10 12:42:25 -05:00
Tyler Goodlet 5cff7a7193 TOSQUASH: f5dcf1dc (viz index field) 2023-01-10 12:42:25 -05:00
Tyler Goodlet 83b3cac807 Fix `.default_view()` to view-left-of-data 2023-01-10 12:42:25 -05:00
Tyler Goodlet 166f97c8af Add `Viz.index_field: str`, pass to graphics objs
In an effort to make it easy to override the indexing scheme.

Further, this repairs the `.datums_range()` special case to handle when
the view box is to-the-right-of the data set (i.e. l > datum_start).
2023-01-10 12:42:25 -05:00
Tyler Goodlet 0751f51cfa Expect `index_field: str` in all graphics objects 2023-01-10 12:42:25 -05:00
Tyler Goodlet 3096b206d9 TOSQUASH: 2dc706aa (.default_view w time) 2023-01-10 12:42:25 -05:00
Tyler Goodlet 16d5ea5b33 Frame ticks in helper routine
Wow, turns out tick framing was totally borked since we weren't framing
on "greater then throttle period long waits" XD

This moves all the framing logic into a common func and calls it in
every case:
- every (normal) "pre throttle period expires" quote receive
- each "no new quote before throttle period expires" (slow case)
- each "no clearing tick yet received" / only burst on clears case
2023-01-10 12:42:25 -05:00
Tyler Goodlet ac0166f936 Facepalm: pass correct flume to each FSP chart group.. 2023-01-10 12:42:25 -05:00
Tyler Goodlet 925849b5e4 Attempt to make `.default_view()` time-index ready
As in make the call to `Flume.slice_from_time()` to try and convert any
time index values from the view range to array-indices; all untested
atm.

Also drop some old/unused/moved methods:
- `._set_xlimits()`
- `.bars_range()`
- `.curve_width_pxs()`

and fix some `flow` -> `viz` var naming.
2023-01-10 12:42:25 -05:00
Tyler Goodlet bd2abcb91f Simplify formatter update methodology
Don't expect values (array + slice) to be returned and applied by
`.incr_update_xy_nd()` and instead presume this will implemented
internally in each (sub)formatter.

Attempt to simplify some incr-update routines, (particularly in the step
curve formatter, though most of it was reverted to just a simpler form
of the original implementation XD) including:
- dropping the need for the `slice_to_head: int` control.
- using the `xy_nd_start/stop` index counters over custom lookups.
2023-01-10 12:42:25 -05:00
Tyler Goodlet 97feb195e6 TOSQUASH: f3d757c2 (flow->viz) 2023-01-10 12:42:25 -05:00
Tyler Goodlet c084a1122a First attempt, field-index agnostic formatting
Remove harcoded `'index'` field refs from all formatters in a first
attempt at moving towards epoch-time alignment (though don't actually
use it it yet).

Adjustments to the formatter interface:
- property for `.xy_nd` the x/y nd arrays.
- property for and `.xy_slice` the nd format array(s) start->stop index
  slice.

Internal routine tweaks:
- drop `read_src_from_key` and always pass full source array on updates
  and adjust handlers to expect to have to index the data field of
  interest.
- set `.last_read` right after update calls instead of after 1d
  conversion.
- drop `slice_to_head` array read slicing.
- add some debug points for testing 'time' indexing (though not used
  here yet).
- add `.x_nd` array update logic for when the `.index_field` is not
  'index' - i.e. when we begin to try and support epoch time.
- simplify some new y_nd updates to not require use of `np.broadcast()`
  where possible.
2023-01-10 12:42:25 -05:00
Tyler Goodlet 1b9f6a7152 Pepper render routines with time-slice calls 2023-01-10 12:42:25 -05:00
Tyler Goodlet 3574548fe2 Add `Viz.bars_range()` (moved from chart API)
Call it from view kb loop.
2023-01-10 12:42:25 -05:00
Tyler Goodlet 598b1e2787 Make `Viz.slice_from_time()` take input array
Probably means it doesn't need to be a `Flume` method but it's
convenient to expect the caller to pass in the `np.ndarray` with
a `'time'` field instead of a `timeframe: str` arg; also, return the
slice mask instead of the sliced array as output (again allowing the
caller to do any slicing). Also, handle the slice-outside-time-range
case by just returning the entire index range with a `None` mask.

Adjust `Viz.view_data()` to instead do timeframe (for rt vs. hist shm
array) lookup and equiv array slicing with the returned mask.
2023-01-10 12:42:25 -05:00
Tyler Goodlet cb85079cf1 Add breakpoint on -ve range for now 2023-01-10 12:42:25 -05:00
Tyler Goodlet 670ba169e9 Copy timestamps from source to FSP dest buffer 2023-01-10 12:06:03 -05:00
Tyler Goodlet 3cf590eedf `Order.symbol` is a `str`.. 2023-01-10 12:06:03 -05:00
Tyler Goodlet d839fcb8e7 Avoid key error on already popped cancel 2023-01-10 12:06:03 -05:00
Tyler Goodlet 42faaa9870 Go back to hard-coded index field
Turns out https://github.com/numba/numba/issues/8622 is real
and the suggested `numba.literally` hack doesn't seem to work..
2023-01-10 12:05:57 -05:00
Tyler Goodlet b078235414 Move `ui._compression`/`._pathops` to `.data` subpkg
Since these modules no longer contain Qt specific code we might
as well include them in the data sub-package.

Also, add `IncrementalFormatter.index_field` as single point to def the
indexing field that should be used for all x-domain graphics-data
rendering.
2023-01-10 12:05:57 -05:00
Tyler Goodlet 03e6a00efd Add some data-flows jargon notes (re: #270) 2023-01-10 12:05:57 -05:00
Tyler Goodlet 1bfcda70ae Rename `.ui._flows.py` -> `.ui._render.py` 2023-01-10 12:05:57 -05:00
Tyler Goodlet 498ed8757c Rename `._flumes.py` -> `.flows.py` 2023-01-10 12:05:57 -05:00