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 Radial Heatmap #2139

Closed
mansenfranzen opened this issue Nov 19, 2017 · 9 comments
Closed

Add Radial Heatmap #2139

mansenfranzen opened this issue Nov 19, 2017 · 9 comments
Milestone

Comments

@mansenfranzen
Copy link
Contributor

Proposal

Radial heatmaps are great for visualizing periodicity. I would like to help adding radial heatmaps to holoviews.

I've implemented radial heatmaps in bokeh, as you can see here:
radialheatmap

The link to the notebook including the code can be found here.

First steps

I started to take a closer look on how to implement a radial heatmap in holoviews having a working bokeh example. Here are some considerations:

  • Data wise, radial heatmaps are very much like a normal, rectular heatmap. Both have 2 key dimensions and one or more value dimension whereas the first value dimension is used for color. Hence, the Heatmap Element class is the perfect data container.
  • Plotting wise, the corresponding HeatmapPlot provides the basic functionality. The get_data method needs to be adjusted to compute radius, radients and so on (which is no big deal having a working example)

Issues

However, I've ran into 2 concrete problems:

  1. Since radial and rectular heatmaps are very similar, they could be represented within the same class (e.g. HeatmapPlot). To select either a radial or rectular heatmap, a parameter could be used like in grouped or stacked bar plots. However, the underlying glyphs for radial (annular_wedge) and rectular (rect) heatmaps differ. By design, a plot class may only have one single key for _plot_methods, right? Therefore, my current guess is to create a new plotting class (and hence a new element class).

  2. The radial heatmap requires axis labels to be positioned manually since radial axis to not exist. Because of that, I need to add text glyphs to the annular_wedge glyphs. Furthermore, I would like to add some visual marker to increase readability of the chart, like those bold white lines in the following plot which results in 3 different glyphs (annular_wedge, text and multi_line). How can I integrate different glyphs in the same plot? Overlay?:

radialheatmap2

Thanks for your advice.

@mansenfranzen mansenfranzen changed the title Add radial heatmap plot Add Radial Heatmap Diagram Nov 19, 2017
@mansenfranzen mansenfranzen changed the title Add Radial Heatmap Diagram Add Radial Heatmap Nov 19, 2017
@philippjfr
Copy link
Member

philippjfr commented Nov 19, 2017

@mansenfranzen Thanks for the detailed breakdown, I'd love to have radial heatmaps in holoviews. It's great you started looking into plotting implementations already without any reference documentation to guide you. We used to have the concept of PlotSelector classes which could swap out the plotting class depending on some condition. I'm going to investigate how well that would work in this case and get back to you but I'm pretty sure that's the right way forward, so we'll do whatever makes it work.

Alternatively you could also just override the _init_glyph method (inherited from ElementPlot) on the HeatMapPlot and conditionally use the appropriate glyph type, ignoring what's defined _plot_methods.

@mansenfranzen
Copy link
Contributor Author

@philippjfr Thanks for the hints. Using PlotSelector sounds like a good idea and may not require to overwrite _init_glyph (which seems like an undesireable exception to the prefered class hierarchy, right?).

In addition, I've just stumbled across CompositeElementPlot while looking at the BoxWhiskerPlot implementation. It provides the ability to plot multiple, different glyphs within the same plot class. Basically, that's exactly what I need to plot annular_wedges, text and multi_line for the radial heatmap, or is there any drawback to this?

@philippjfr
Copy link
Member

No that is probably what you should use. That said the API used by it could probably be improved still since there are some things are non-obvious. I'll quickly outline how to write such a plot class and if you still want to dive in you can give feedback on improving the API later.

  1. Declare a set of _style_groups as a dictionary mapping between the glyphs you want to draw and the label by which a user will refer to them when setting options, e.g. {'vbar': 'box', 'segment': 'whisker', ...}

  2. Define the style_opts as a list of valid bokeh properties prefixed with the style group aliases you defined in step 1, e.g. ['box_fill_color', 'box_fill_alpha', ..., 'whisker_line_color', ...]

  3. Implement a get_data method that returns a dictionary of ColumnDataSource (CDS) data and mappings declaring how the columns in the data source map onto the CDS columns. Unlike a regular element these data and mapping should be a nested containing the information for each glyph you want to draw. The keys of the data and mapping should be the names of the glyph appended with an underscore and a number, e.g. data = {'vbar_1': {'x': [...], 'bottom': [...], 'top': [...]}, 'segment_1': {'x0': [...], 'x1': [...], 'y0': [...]}, ...} and mapping = {'vbar_1': {'x': 'x', 'bottom': 'bottom', 'top': 'top'}, 'segment_1': {'x0': 'x0', 'x1': 'x1', 'y0': 'y0', 'y1': 'y1'}, ...}

Let me know if you run into problems, you can always ask me questions directly on Gitter.

@philippjfr
Copy link
Member

Thanks for the hints. Using PlotSelector sounds like a good idea and may not require to overwrite _init_glyph (which seems like an undesireable exception to the prefered class hierarchy, right?).

Either would be okay, the default _init_glyph is not always desirable, the main worry is mixing the code of the radial and non-radial HeatMaps in a messy way but depending on the amount of code involved that may also be acceptable.

@mansenfranzen
Copy link
Contributor Author

mansenfranzen commented Nov 20, 2017

Thanks, this will guide me for now using CompositeElementPlot. Employing _style_groups and _style_opts in addition to custom methods to place text labels and segment markers seem to be good reasons to create an extra RadialHeatMapPlot class instead of mixing radial and rectular heatmaps within the HeatMapPlot class.

@philippjfr
Copy link
Member

As a quick aside, I don't know your preferred workflow but I usually prototype new plots in a notebook (e.g. see https://anaconda.org/philippjfr/bars/notebook) and then move it into the code. I think writing a separate RadialHeatMapPlot makes sense, you can simply override the default HeatMapPlot for now using hv.Store.register({HeatMap: RadialHeatMapPlot}, 'bokeh') and then I'd be happy to solve the issue of switching between plotting classes (probably by adding a plot option).

@philippjfr
Copy link
Member

Writing the Chord plot (#2138) I ran into several limitations/bugs in the CompositeElementPlot implementation, which will probably bite you too. I'll try to get a PR merged addressing these limitations and will keep you updated on that.

@mansenfranzen
Copy link
Contributor Author

Ok thanks. I'm going to implement the radial heatmap during this weekend using the existing CompositeElementPlot class or do you suggest I should rather wait until you'll have merged the PR?

@philippjfr
Copy link
Member

I fixed some of the more important issues in #2140, so you should be able to implement it now.

@philippjfr philippjfr added this to the v1.10 milestone Dec 4, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants