vega / altair

Declarative statistical visualization library for Python
https://altair-viz.github.io/
BSD 3-Clause "New" or "Revised" License
9.26k stars 793 forks source link

Heatmaps are non interactive #2712

Closed josephernest closed 1 year ago

josephernest commented 1 year ago

Is it normal that Altair heatmaps are non interactive, even when specifying .interactive():

import altair as alt, numpy as np, pandas as pd
x, y = np.meshgrid(range(-5, 5), range(-5, 5))
z = x ** 2 + y ** 2
source = pd.DataFrame({'x': x.ravel(), 'y': y.ravel(), 'z': z.ravel()})
alt.Chart(source).mark_rect().encode(x='x:O', y='y:O', color='z:Q').interactive().save('test2.html')

?

Is there a way to enable interactivity : moving, zooming, etc. in the browser?

joelostblom commented 1 year ago

Interactivity does not work with ordinal scales unfortunately (tracked in https://github.com/vega/vega-lite/issues/4369). If you change them to quantitative it will work, but it might not have the appearance you want

josephernest commented 1 year ago

Thanks @joelostblom. Would you have an example code, based on my sample code in my post, showing it in quantitative mode?

joelostblom commented 1 year ago

Yes, you change the encoding to x='x:Q', y='y:Q'

josephernest commented 1 year ago

Thanks @joelostblom.

Before this change:

image

After x='x:Q', y='y:Q', it becomes movable/zoomable indeed, but the appearance is not good indeed, as you suggested:

image

Is there a way to have both interactive + normal rendering?

jakevdp commented 1 year ago

I think you're looking for binned quantitative encodings:

alt.Chart(source).mark_rect().encode(
  x=alt.X('x:Q', bin=True),
  y=alt.Y('y:Q', bin=True),
  color='z:Q'
).interactive()
josephernest commented 1 year ago

Perfect indeed @jakevdp! Would you have a link to the right documentation page? So I'll learn how to do this and similar modifications. Thanks again :)

PS: would you know if it's possible to do a "rectangle selection" on such a heatmap, to do a Region Of Interest (ROI) selection?

betaigeuze commented 1 year ago

PS: would you know if it's possible to do a "rectangle selection" on such a heatmap, to do a Region Of Interest (ROI) selection?

You can add a rectangular selection with

sel = alt.selection_interval()

So to extend @jakevdp 's example:

sel = alt.selection_interval()

alt.Chart(source).mark_rect().encode(
  x=alt.X('x:Q', bin=True),
  y=alt.Y('y:Q', bin=True),
  color='z:Q'
).add_selection(sel)

However, if you do it like this, you're dropping the .interactive(). Afaik, you can only assign one function to a mouse click: Either create a selection window or move the plot.

Would you have a link to the right documentation page?

You can read more about this kind of selections here