Power Chart axes not repositioning correctly after removing a pen

For our water utility project we have a large number of historized tags (flow, level, pressure, valves, pumps) spread across many UDT instances. The stock Tag Browser next to the Power Chart works, but for our operators it's not great: tags are grouped by UDT/folder structure rather than by measurement type, the labels are raw tag names instead of something readable, and there's no way to show "already selected" state at a glance.

So I built a custom navigation tree (Perspective Tree component) driven by a script transform that browses [default] with system.tag.browse, groups tags into categories (Portata, Livello, Pressione, Valvole, Pompe, etc.) based on tag name/path patterns, and labels each leaf as <assetID> - <Component_Desc>. Clicking a leaf toggles a pen on/off on a PowerChart_1 component sitting next to the tree, instead of dragging tags manually.

The pen add/remove logic (below) dynamically manages props.pens, props.plots and props.axes on the Power Chart so that:

  • each distinct axis gets its own plot row
  • pens sharing the same axis (e.g. two flow meters both using Flow_Axis) share the same row
  • rows are always compacted (no gaps) after a pen is removed

When I remove a pen whose axis is used by no other pen (so an entire row needs to disappear and everything below it needs to shift up by one), the row disappears correctly, but the axis label of pens that had to change their plot index does not move to its new row — it stays visually merged with a different row, even though props.pens[].plot, props.plots and props.axes are all provably correct at the moment of the write.

I tried this

  1. Add 4 pens, each on its own axis: Flow_Axis→plot 0, Level_Axis→plot 1, Valve_Axis→plot 2 (only pen on this axis), Pump_Axis→plot 3.
  2. Remove the pen on Valve_Axis (the only one using that axis).
  3. Recompute plots so that: Flow_Axis→0, Level_Axis→1, Pump_Axis→2 (was 3), and write props.plots (3 rows) / props.axes (3 axes) / props.pens in one consolidated write.
  4. Expected: 3 rows, Pump_Axis now occupies row 2.
  5. Actual: Pump_Axis renders squeezed together with plot #0.

Relevant code (TOGGLE OFF branch — pen removal)

if already_exists:
    del current_pens[existing_pen_index]

    if tag_path in selected_curves:
        selected_curves.remove(tag_path)
    self.view.getChild("root").custom.selectedCurves = selected_curves

    plot_ancora_usati = sorted(set(p.get('plot', 0) for p in current_pens))
    remap = {old: new for new, old in enumerate(plot_ancora_usati)}

    for p in current_pens:
        p['plot'] = remap[p.get('plot', 0)]

    distinct_plots_count = len(set(p.get('plot', 0) for p in current_pens))
    nuovi_plots = costruisci_plots(distinct_plots_count)  # rebuilds plots array from scratch, 1 row per distinct plot value
    nuovi_axes = ricalcola_axes_attivi(current_pens, master_axes)  # filters master axis list by name still in use

    chart.props.pens = current_pens
    chart.props.plots = nuovi_plots
    chart.props.axes = nuovi_axes


def costruisci_plots(numero_pen):
    if numero_pen <= 0:
        return [{"color": "#ffffff00", "relativeWeight": 1, "style":  {"classes": ""}, "markers": []}]
    return [{"color": "#ffffff00", "relativeWeight": 1, "style": {"classes": ""}, "markers": []} for _ in range(numero_pen)]

def ricalcola_axes_attivi(pens_correnti, master_axes_list):
    assi_usati = set(p.get('axis') for p in pens_correnti if p.get('axis'))
    return [ax for ax in master_axes_list if ax.get('name') in assi_usati]



Debug log

[DEBUG] plot_ancora_usati = [0, 1, 2, 4]
[DEBUG] remap dict = {0: 0, 1: 1, 2: 2, 4: 3}
[DEBUG] PRIMA - Pump pen plot=4
[DEBUG] DOPO - Pump pen old=4 new=3
[DEBUG] distinct_plots_count = 4
[DEBUG] nuovi_plots lunghezza = 4
[REMOVE] axes che verranno scritti: ["Flow_Axis","Level_Axis","Pressure_Axis","Pump_Axis"]

Is there a known limitation in how Power Chart associates an axis entry with the correct row when a pen's plot index changes after the pen (and its axis) were already rendered once? I notice the axis objects themselves (props.axes[]) have no plot/row reference at all — the only link is via pens[].plot + pens[].axis. Is there an internal caching/diffing step on the component's frontend that doesn't fully recompute axis layout when only plot values change on existing pens (as opposed to adding a brand-new pen, which always renders correctly in my testing)?

Happy to share the full script. Thanks in advance for any pointers.

Great report! Sounds like a bug. You should open a support ticket.