Skip to content
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

Add HoloViews' subcoordinate_y #1160

Closed
droumis opened this issue Oct 2, 2023 · 6 comments · Fixed by #1379
Closed

Add HoloViews' subcoordinate_y #1160

droumis opened this issue Oct 2, 2023 · 6 comments · Fixed by #1379

Comments

@droumis
Copy link
Member

droumis commented Oct 2, 2023

subcoordinate_y was recently added to HoloViews to plot on subcordinates. This should now be incorporated into hvPlot when working with xarray.

The API could be something as simple as: da.hvplot(subcoordinate_y=True).

This would produce something like:
image

The minimum data are:

  • 1D time array (common to all channel sources)
  • 2D stack (time x channel source) of 1D amplitude arrays
  • 1D array of channel source labels

There should also be the option for adjusting subcoordinate_scale (as in HoloViews).

Whether or not the minimap should be included with the simple default API call is something that needs to be discussed and considered further.

@maximlt
Copy link
Member

maximlt commented Dec 10, 2023

@droumis I can see the project board that this is planned for Q4 of this year. Is this a hard deadline?

But my main question would be: is this feature not too niche to be exposed in hvPlot? Increasing hvPlot's API comes with a cost, it makes it more difficult for users to navigate through its many parameters. I'm not -1 on this, but I'd like to make sure this is discussed.


Whether or not the minimap should be included with the simple default API call is something that needs to be discussed and considered further.

Yes I wouldn't tie the "minimap" (or however we call it in the end) with subcoordinate_y. We should open a separate issue to discuss how we'd generally like to expose the minimap in hvPlot.


If it's eventually implemented, I guess we could also support a DataFrame with a datetime index, using the column names as the source labels.

@maximlt maximlt added this to the 0.10.0 milestone Dec 10, 2023
@philippjfr
Copy link
Member

But my main question would be: is this feature not too niche to be exposed in hvPlot? Increasing hvPlot's API comes with a cost, it makes it more difficult for users to navigate through its many parameters. I'm not -1 on this, but I'd like to make sure this is discussed.

Personally, I feel like this is more of an issue on how our doc(strings) are organized than a general issue. subplot_y can be quite a nice and general feature and if it isn't general enough to generate e.g. a joy plot then that should be improved at the HoloViews level.

@droumis
Copy link
Member Author

droumis commented Dec 11, 2023

@maximlt , I'm in the process of updating the project board (this week); Q4 is not a hard deadline for this task, I'm going to push it to later since we are also still working on tasks that would directly impact this implementation.

I agree with @philippjfr that a ridgeplot (aka joyplot) is a common enough type of plot to justify the inclusion burden for hvPlot. With subcoordinate_y this is possible using Curve, but Area is more commonly used for a ridgeplot and it looks like it needs the element order to be reversed by default. I'll file an issue with HoloViews.

Code
import numpy as np
import holoviews as hv; hv.extension('bokeh')
from scipy.stats import gaussian_kde

categories = ['A', 'B', 'C', 'D', 'E']
data = {cat: np.random.normal(loc=i-2, scale=1.0, size=100) for i, cat in enumerate(categories)}
x = np.linspace(-5, 5, 100)

curves = []
areas = []
for i, (cat, values) in enumerate(data.items()):
    pdf = gaussian_kde(values)(x)
    
    curve = hv.Curve((x, pdf), label=cat).opts(
        subcoordinate_y=True, 
        subcoordinate_scale=1.5,
    )
    curves.append(curve)
    
    area = hv.Area((x, pdf), label=cat).opts(
        subcoordinate_y=True, 
        subcoordinate_scale=1.5,
    )
    areas.append(area)

ridge_plot_curves = hv.Overlay(curves).opts(
    width=900,
    height=400,
)

ridge_plot_areas = hv.Overlay(areas).opts(
    width=900,
    height=400,
)

# ridge_plot_areas.opts(show_legend=False)
ridge_plot_curves.opts(show_legend=False)
image image

@philippjfr
Copy link
Member

While we're at it, HoloViews should also support grabbing the label for each subcoordinate from the NdOverlay key. So it becomes as simple as this:

import numpy as np
import hvplot.pandas
from scipy.stats import gaussian_kde

categories = ['A', 'B', 'C', 'D', 'E']
data = {cat: np.random.normal(loc=i-2, scale=1.0, size=100) for i, cat in enumerate(categories)}
pd.DataFrame(data).hvplot.kde(y=categories, subcoordinate_y=True, subcoordinate_scale=1.5)

Right now you have to manually insert the labels explicitly:

import numpy as np
import hvplot.pandas
from scipy.stats import gaussian_kde

categories = ['A', 'B', 'C', 'D', 'E']
data = {cat: np.random.normal(loc=i-2, scale=1.0, size=100) for i, cat in enumerate(categories)}

labels = iter(categories)
overlay = pd.DataFrame(data).hvplot.kde(y=categories).map(lambda el: el.relabel(next(labels)), specs='Distribution')
overlay.opts('Distribution', subcoordinate_y=True, subcoordinate_scale=1.5)

bokeh_plot - 2023-12-11T180002 399

@droumis
Copy link
Member Author

droumis commented Jul 16, 2024

Discussion in meeting: Preferred API is probably 'ridge' kind, so like hvplot(kind='ridge')

@droumis
Copy link
Member Author

droumis commented Jul 16, 2024

(Bokeh#8128) discussion about naming ridge instead of joy

@droumis droumis moved this from Todo to Done in CZI R5 neuro Dec 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants