Skip to content

Give chart types public names, in registries that plugins can add to - #2803

Open
Flix6x wants to merge 29 commits into
mainfrom
chart-type-registry
Open

Flix6x wants to merge 29 commits into
mainfrom
chart-type-registry

Conversation

@Flix6x

@Flix6x Flix6x commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Description

Part of #2795: registries of named asset and sensor chart types, planned for v1.2.0.

So far, an asset's or sensor's chart-type was the name of a function in belief_charts. This PR gives each chart type a public, kebab-case name, plus a label, a description, and the assets or sensors it applies to; an asset chart type also has its layout (the graphs it draws, in the sensors_to_show format). They live in two registries (one for assets, one for sensors) in flexmeasures/data/models/charts/chart_types.py, which share their registration and lookup (ChartTypeRegistry).

  • The registry holds two built-in chart types:

    • default (was chart_for_multiple_sensors);
    • charge-point-sessions (was chart_for_chargepoint_sessions), which applies only to assets with charge points.

    Which graphs the Charge Points chart draws below its sessions is now decided in one place.

  • AssetChartTypeField validates chart-type on GET /api/v3_0/assets/<id>/chart against the registry as it is at request time.

    • The old function names are still accepted, and the docs call them deprecated.
    • The OpenAPI enum lists the built-in types.
  • The asset page asks for its charts by public name and builds its chart picker from the registry.

  • Plugins can register asset chart types through register_asset_chart_type, the same function that registers the built-in ones.

    • It refuses names that are already taken.
    • The chart type's fields are marked provisional.
    • documentation/plugin/customisation.rst has a short section on it.
  • Sensor chart types get the same treatment:

    • bar-chart (was bar_chart), histogram, daily-heatmap (was daily_heatmap) and weekly-heatmap (was weekly_heatmap); the old names stay accepted (sessions, bookmarked URLs).
    • GET /api/ui/sensor/<id>/chart validates chart-type against the registry at request time (unknown names still get the 422 from Build only the listed chart types, and leave the chart defaults alone #2801), and the session keeps the public name.
    • chart_type_to_chart_specs builds from the registry; CHART_TYPES/SENSOR_CHART_TYPES are the registry.
    • Plugins register their own through register_sensor_chart_type, which refuses taken names.
    • The sensor page builds its picker from the registry (the types that apply to the sensor), and starts with the last chosen type where it applies.
  • The fast chart draws the built-in chart types by their public names (and still the legacy ones). For a chart type it does not know, such as one a plugin registered, the asset and sensor pages show the Vega-Lite chart, and disable the fast-chart toggle while it is picked.

  • Fixes a Charge Points chart bug: a "Power flow by type" graph now shows only the charge points power, also when its title starts with a lowercase letter.

  • Tests for both registries, the fields, the endpoints (public, legacy and snake_case names), the pickers, the fast chart's chart types, and chart types registered by a plugin after the app started.

  • Changelog entries in new v1.2.0 and v3.0-41 sections.

Look & Feel

No visible change. The asset and sensor pages' chart pickers offer the same charts as before, under the same labels.

How to test

uv run pytest flexmeasures/data/tests/test_chart_types.py flexmeasures/api/ui/tests flexmeasures/api/v3_0/tests/test_assets_api.py flexmeasures/ui/tests

Before merging

Further Improvements

🤖 Generated with Claude Code

https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf

Flix6x and others added 21 commits November 2, 2026 15:20
…its sessions

The sessions and companion graph rules move into helpers in belief_charts.py, so that a registry of chart types can describe the same layout.
A lowercase "power flow by type" graph is now restricted to the charge points power, as a lowercase "prices" graph was already drawn,
and the builder no longer edits the sensors_to_show it is given.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
The registry in flexmeasures/data/models/charts/chart_types.py is the one place that lists the chart types of an asset:
"default" and "charge-point-sessions".
Each entry has a public, kebab-case name, the assets it applies to, its layout (the graphs it draws, with their sensors) and its Vega-Lite builder.
GenericAsset.chart looks its chart type up there, which answers the todo in its docstring, and still accepts the builder names as legacy names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
… of chart types

GET /api/v3_0/assets/<id>/chart now refuses an unknown chart-type with a 422, and lists the registry's names (default, charge-point-sessions) in its documentation.
The builder names it took so far are still accepted, as legacy values.
Without chart-type, it draws the default chart, as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
The chart picker, graphs.html and the fast chart now use "default" and "charge-point-sessions",
so the asset page no longer relies on the legacy names that the chart endpoint still accepts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
The PR number is not known yet, so the entries link to PR #XXXX.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
…ng sessions out

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
…r organisation

As charge_hub_fresh_db, its name says it may not be used in a module that uses db.
Its site now belongs to the Prosumer organisation, and its Prices graph also names a sensor of another organisation's asset,
so the tests cover the filtering of sensors_to_show per organisation as well.
The charge point asset type is reused if it exists, as its name is unique.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
…ias too

The asset page's Vega-Lite chart sends chart_type, so dropping the alias would silently draw the default chart instead of the Charge Points chart.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
…gistry uses it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
Neither renderer draws such a graph, e.g. a Power flow by type graph without the charge points power,
so the layout no longer holds it either.
The Vega-Lite builder uses the same helper, and keeps leaving such a graph out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
…layout

An asset without sensors_to_show gets suggested graphs, which hold a top-level sensor or sensors;
the layouts now put those in plots, as the registry's docstring promises.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
…er chart tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
…hart type names deprecated

The field used to replace a validate argument with its check against the registry; it now runs both, the registry first.
The OpenAPI enum lists the public names only, so the description now says the legacy names are deprecated, but still accepted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
… is looked up

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
… types

The picker lists the chart types that apply to the asset, with their labels from the registry,
and shows when there is a choice, which is when the asset has a charge point among its children, as before.
That replaces the page's own check of the asset type of each child, and the asset request it made for that.
The picker test moves to a fresh_db module, as it now needs an asset with a charge point.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
…ricts to the charge points power

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
…t registers the built-in ones

register_asset_chart_type refuses a name or legacy name that is already taken,
and adds the chart type to the registry and to the map of legacy names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
…ey are validated

The chart type field copied the registry's names when it was made, at import,
so a chart type that a plugin registers later would be refused with a 422.
Its new validator reads the registry each time, and still lists the registered names as the OpenAPI enum.
The chart API's documentation now says plugins may register more chart types.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
…rt type's fields provisional

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
…I and offered by the asset page, and that taken names are refused

A fixture registers a test chart type after the app was created, as a plugin would, and restores the registry afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
@Flix6x Flix6x added this to the 1.2.0 milestone Nov 2, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
Flix6x and others added 4 commits November 3, 2026 01:16
Asset charts go through the registry of asset chart types, so the asset chart keeps AssetChartTypeField (and its public names in the API docs),
and #2801's validate_asset_chart_type and ASSET_CHART_BUILDERS are dropped.
CHART_TYPES now lists the sensor chart types only.
The test that the API docs name no asset chart types now checks that they list the public names, and mention the legacy names only as deprecated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
…nd say which chart types it draws

The sensor chart types get public, kebab-case names (bar-chart, daily-heatmap, weekly-heatmap),
so the fast chart draws them by those names, while still taking the legacy ones.
fastChartDrawsChartType tells pages which chart types it draws,
so they can leave chart types registered by plugins to Vega-Lite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
The sensor chart types move into a registry next to the asset chart types,
sharing its registration and lookup (ChartTypeRegistry),
under the public names bar-chart, histogram, daily-heatmap and weekly-heatmap.
The names the sensor chart endpoint took so far stay accepted as legacy names.
Plugins add their own with register_sensor_chart_type, which refuses taken names.

The sensor chart endpoint validates chart-type against the registry when the request comes in,
so it accepts chart types registered after the app was created,
and the session keeps the public name of the chart type.
The sensor page lists the chart types that apply to the sensor,
starting with the one last chosen where it applies,
and draws those the fast chart does not know with Vega-Lite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
@Flix6x Flix6x changed the title Give asset chart types public names, in a registry that plugins can add to Give chart types public names, in registries that plugins can add to Nov 3, 2026
Conflicts resolved as follows, keeping #2790's behaviour:
belief_charts.py keeps CHARGE_POINT_CHART_NAMES and charge_point_chart_sensors from #2790, next to the registry's public charge_point_session_sensors and its companion graphs without sensors left out;
GenericAsset.chart_sensors keeps its rules, but takes the public chart type names, which the asset page sends since the registry (the legacy names are mapped to them, any other name still gets all sensors);
graphs.html imports both fastChartDrawsChartType and isChargePointCompanionTitle, and checks the belief tooltip by the public chart type names;
and test_fast_chart.py keeps both sides' tests, handing the Charge Points chart test the chart's names, which the fast chart needs since #2790.

chart-type on chart_data stays out of the API docs, and its description now names the public chart types;
its test now also asks for the chart types by the public names the asset page sends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
Flix6x and others added 2 commits November 6, 2026 19:18
…gelog sections

Conflicts resolved:
- documentation/changelog.rst: the PR's entries move into main's v1.2.0 section.
- documentation/api/change_log.rst: the PR's API section sits on top of main's v3.0-34, which consolidates the former v3.0-35 to v3.0-40; its sentence on the 422 for an unknown chart-type is dropped, as v3.0-34 already ships that.
- flexmeasures/ui/tests/js/test_fast_chart.py: both sides added tests at the same spot; all are kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
v1.1.0 shipped with API version v3.0-34 (#2818), so the next unreleased version is v3.0-35.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf
Signed-off-by: F.N. Claessen <claessen@seita.nl>
@Flix6x

Flix6x commented Nov 6, 2026

Copy link
Copy Markdown
Member Author

Brought this branch up to date with main and renumbered its API change log section, since v1.1.0 shipped with API version v3.0-34 (#2818):

  • 03becfe merges main. Conflicts: the changelog entries move into main's v1.2.0 section; the API section now sits on top of v3.0-34, and its sentence about the 422 for an unknown chart-type is dropped, as v3.0-34 already ships that; in test_fast_chart.py, the tests both sides added are all kept.
  • 7c8ade2 renumbers the API section from v3.0-41 to v3.0-35, the next unreleased version. No other file referred to v3.0-41.

The chart type tests (Python and JS, 155) pass locally.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant