-
Notifications
You must be signed in to change notification settings - Fork 794
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use object specific counter instead of a global counter for unnamed parameter & view names #3416
Comments
Hi @lukasmasuch, thanks for the report. Unfortunately it's not quite as straightforward as moving the counters from class-level to instance-level. The purpose of these is to make sure that subcharts and params have unique names across concatenation. For example: chart1.to_dict()
chart2.to_dict()
(chart1 | chart2).to_dict() In the result of To avoid a global counter, we might need to refactor to delay assigning these names until the conversion to a dictionary. |
@jonmmease Thanks for the quick response :)
This sounds like a reasonable solution. Our temporary solution in Streamlit will probably be some hacky replacements in the vega-lite spec, but it would be much better if it were eventually solved with a counter that is applied only in the |
It's the same issue with data referencing, that one was stabilized by using the hash value of the dataset. We might be able to do this by introducing a hash method on the chart specification, and use that somehow when referencing views and params. Thanks for raising! |
## Describe your changes Altair uses global counters to name unnamed parameter & view/subchart names (see this issue [here](vega/altair#3416)). This leads to different vega-lite chart specs across reruns for the same charts since the auto-named parameters will change the counter on every new chart creation. Some of our features like forward message cache & the upcoming chart selections will require a stable identity for the chart element. Therefore, we are applying a (temporary) slightly hacky solution to replace these generated names with names that are stable across reruns. The relevant naming patterns are: `view_<number>` and `param_<number>`. Eventually, we can replace this hack if it gets addressed in Altair (see issue [here](vega/altair#3416)) I performance-tested the `_stabilize_vega_json_spec` method with a bigger concatenated chart spec by running it 10k times. The total runtime was ~0.3s, about ~0.03 milliseconds per execution. There are a couple of ways to make this a lot more performant, but I think it would be fine to put that into a follow-up PR after the selections release. ## Testing Plan - Added unit tests. --- **Contribution License Agreement** By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.
I agree, it would be cleaner and useful for web apps if there is no global counter. We have the same issue in dash-vega-components (although less severe as there is no "rerun" of the whole app) and maybe there are other use cases which would benefit from this too. I'm worried that delaying the parameter naming breaks user code. In the documentation, and many examples on other sites, use the pattern of accessing parameter names in expressions via the bind_range = alt.binding_range(min=100, max=300, name='Slider value: ')
param_width = alt.param(bind=bind_range)
# Examples of how to write both js and python expressions
param_color_js_expr = alt.param(expr=f"{param_width.name} < 200 ? 'red' : 'black'") So I think names already need to be available when a parameter is instantiated. We could port the fix of @lukasmasuch in streamlit/streamlit#8628. Doing this on the JSON string feels hacky but I also can't come up with something better, see https://github.com/streamlit/streamlit/pull/8628/files#diff-611496cd0d1726cf41aed099fd6723e35d40833db11afbafef9be914fc425f26R270 for reasoning on why working on the dict does not work. Same goes for chart objects. Basically, parameters can just be referenced in too many places and even in strings as shown above and hence the replacement needs to happen on strings anyway. It could be a new argument to
For Streamlit, not much would change compared to the current fix apart from that it's something officially supported and maintained in Altair, but the upside would be that it's also available for other libraries. Thoughts? |
Thanks @binste, I like the solution of adding an optional argument to |
Streamlit has to introduce custom code that utilise internal altair functions. This might be one of reasons that #3554 is popping up as an issue. I say, might, because this specific issue might not be related. |
## Describe your changes Altair uses global counters to name unnamed parameter & view/subchart names (see this issue [here](vega/altair#3416)). This leads to different vega-lite chart specs across reruns for the same charts since the auto-named parameters will change the counter on every new chart creation. Some of our features like forward message cache & the upcoming chart selections will require a stable identity for the chart element. Therefore, we are applying a (temporary) slightly hacky solution to replace these generated names with names that are stable across reruns. The relevant naming patterns are: `view_<number>` and `param_<number>`. Eventually, we can replace this hack if it gets addressed in Altair (see issue [here](vega/altair#3416)) I performance-tested the `_stabilize_vega_json_spec` method with a bigger concatenated chart spec by running it 10k times. The total runtime was ~0.3s, about ~0.03 milliseconds per execution. There are a couple of ways to make this a lot more performant, but I think it would be fine to put that into a follow-up PR after the selections release. ## Testing Plan - Added unit tests. --- **Contribution License Agreement** By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.
We found a different source for that particular bug, which was fixed in #3637 (@mattijn you can ignore this, just making sure it is recorded here) |
What is your suggestion?
Unnamed parameters and sub-charts are automatically named by using a global counter:
Parameter:
altair/altair/vegalite/v5/api.py
Lines 196 to 201 in f345cd9
Subcharts/Views:
altair/altair/vegalite/v5/api.py
Lines 2885 to 2890 in f345cd9
This will lead to different specs for the same charts in a multi-threaded/multi-user environment (e.g., Streamlit). In Streamlit, we rely on the spec to be stable to calculate a deterministic element identity across app reruns. Having this global counter makes the usage of Altair complicated. It would be awesome if the global counter would be replaced with a counter that's specific to the chart object -> which would make the chart spec stable independent of the global state.
Have you considered any alternative solutions?
No response
The text was updated successfully, but these errors were encountered: