Drawings and plot parity
Plan to make user drawing tools and Pine plot/drawing outputs match PYNE and render with correct pane, color, geometry, and settings.
This page
Drawings and plot parity
AXIS has two independent render paths:
| Path | Source | Paint |
|---|---|---|
| User drawings | Toolbar tools | DrawingLayer user SVG group, editable |
| Pine output | PYNE RunResult | plots → LWC series; shapes/barcolor → candle markers; bgcolor → histogram; fill → SVG; line/label/box/polyline/linefill → script SVG; tables → HUD |
This plan is the work list from a four-agent audit of AXIS (src/chart, src/results, src/indicators/runner.ts) against PYNE (pynescript drawing.py, evaluator.py, host.py).
Phases
P0 — AXIS correctness (this pass)
User tools and apply-pipeline bugs that do not wait on a PYNE export change.
- 1-point body-move —
shiftDrawingonly special-casedtext/priceLabel. Shift any drawing withp1(andpoints[]when present): note, flag, crossline, anchoredText, arrowMarkUp/Down. - p3 / extra vertex handles —
hitTestHandle/resizeDrawingonly p1/p2. Addp3(and remainingpoints[i]as p3 for the third anchor). Paint extra handles after registry paint. - Linefill GC —
garbageCollectScriptDrawingsearly-return ignoredskip.linefill. - Polyline / linefill overlay — copy
force_overlayand polylinefill_color→bgcolor. - Stale SVG — silent live re-run with
drawings: []must clear script drawings. - Pane routing —
bgcolorandfill()use the script pane whenoverlay=false(syncBgcolorBands(paneId),ensureScriptPaneLayerfor fills).plotshape/plotchar/plotarrowattach to a series on that pane when possible; otherwise stay on price (LWC markers need a host series).
P1 — User-tool settings (AXIS)
Done:
- Shared style bar: color (presets + custom), width, dash, fill for shapes / ranges / fib / highlighter / positions.
- Per-tool extras via
src/chart/drawings/tool-settings.ts+ settings popover (axis-drawing-settings). - Last-used style per kind (
drawingPrefs.byKind). extendLeft/extendRightUI + paint (trend, ray, extend, info line, channel, fib).- Fib level editor, reverse, show % / price, fill between levels.
- Text re-edit (popover + double-click), font size.
- Per-drawing lock in the style bar (unlock bypasses
updateSelectedlock gate). - Long/short risk-reward (
meta.rr). - Highlighter width honors
style.width(create default 8). - hray: 1-click (price only).
- xabcd / headShoulders: commit on 5th point.
P2 — PYNE export (pynescript repo)
AXIS cannot paint fields the engine never serializes.
| Gap | Where | Needed on the wire |
|---|---|---|
Table cell keys (row,col) vs (col,row) | drawing.py table.cell vs cell_set_* | One index order |
| Table style | export_for_api | halign, valign, width, tooltip, text_size, borders |
table.cell kwargs | ctor | width, halign, valign, size |
plotshape Y / location.absolute | _coerce_plot_shape | keep numeric series (or {y, on} cells) |
| plotbar / plotcandle | evaluator | open/high/low/close (or sibling titles in plot_meta) |
fill() compile / untitled plots | host + evaluator | plot1/plot2 series keys + per-bar fill color column |
Positional plot(..., linewidth) | evaluator.py ~425 | Pine order: series, title, color, linewidth, style |
| plotarrow | evaluator | colorup / colordown / minheight / maxheight |
offset, force_overlay, histbase | _pack_interpret_plot_columns | remaining plot_meta fields (display is packed) |
| Polyline | export | fill_color, curved, force_overlay |
| Box / label extras | export | closed, extend, text_*, tooltip, border |
P3 — Remaining Pine paint
Done this pass:
- Hide-drawings toggle includes script SVG + fill bands (all pane layers).
- Label
ylocpad (8px off wick);label.style_text_outlineas outlined text. - First
addIndicatorre-owns plot fills / script drawings / plotshape (EDITOR_RUN_KEY→ script id). - Histogram
histbasefromplot_meta(default 0). PYNE still needs to serialize it for live values. - Pine
display.*(none/pane/data_window/price_scale/status_line/all) on plot, hline, shapes, fill, bgcolor, barcolor.
Still open:
location.top/bottom= pane edges, not bar (LWC markers only have above/below/in bar).- Per-bar
plot(..., color=expr), plotarrow length (colorup/colordown/minheight/maxheightwait on PYNE).
Invariants
- User drawings ≠ Pine drawings. Do not share hit-testing or magnet with script SVG (
pointer-events: none). overlay=falseplots, fills, bgcolor, and shapes belong onind_*unlessforce_overlay.barcolor()stays on price candles.- Color sanitize:
#rgb(a),#rrggbb(aa),rgb/rgba. Unknown → VOID indigo for user tools; Pine should keep engine hex (including#RRGGBBAA). - GC caps match Pine: 50 default, 500 lines/labels/boxes, 100 polylines. Linefill cap is AXIS-only until PYNE emits
max_lines_fills_count.
Tests
shiftDrawing/resizeDrawingfor 1-pt and 3-pt kinds.- Linefill GC overflow.
- Polyline
force_overlay+fill_color. - Runner: bgcolor/fill target pane when
overlay=false(unit with a fake manager if needed). - PYNE: table cell key, fill meta, plotshape Y (in the pynescript repo).