holoviz / holoviews

With Holoviews, your data visualizes itself.
https://holoviews.org
BSD 3-Clause "New" or "Revised" License
2.68k stars 398 forks source link

Non compatibility between categorical plots and annotations plots #4181

Open Jacob-Barhak opened 4 years ago

Jacob-Barhak commented 4 years ago

There is incompatibility between annotation plots such as Arrow and Categorical Axis plots such as Bars. The example below shows some of the artifacts that can be created. The example attempts to create a series of plots showing what happened in each year in bars and then add an arrow with descriptive text. However, when the arrow is added the resulting plot losses information.

This is created with : Windows 10 Python 2.7.16 |Anaconda, Inc.| (default, Mar 14 2019, 15:42:17) [MSC v.1500 64 bit (AMD64)] on win32 Bokeh: 1.4.0 Holoviews: 1.12.7

import holoviews
from holoviews import opts

holoviews.extension('bokeh')

def SaveFile(FileName, PlotObject, Format):
    'Save file using holoviews mechanism'
    holoviews.save(PlotObject, FileName, fmt=Format)

Data = {}

Data['Year'] =                [2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, ]
Data['Cohorts'] =             [  22,   34,   40,   47,   47,   91,   91,  123,  123, ]

Innovations =  {}
Innovations[2012] = 'The Reference Model created'
Innovations[2013] = 'MIST, HPC, Cloud Computing'
Innovations[2014] = 'Evolutionary Computation for Population Generation'
Innovations[2015] = 'Object Oriented Population Generation'
Innovations[2016] = 'Assumption Engine, Cooperative Ensemble Model'
Innovations[2017] = 'ClinicalTrials.Gov Interface'
Innovations[2018] = 'Interactive Visualization of Knowledge Gap'
Innovations[2019] = 'Improved Interactive Visualization'
Innovations[2020] = 'Include Human Interpretation'

AllDimesions = Data.keys()

VerticalDimension = 'Cohorts'
HorizontalLimits = (2010,2030)
VerticalLimits = (0,max(Data[VerticalDimension]))

for (YearIndex,Year) in enumerate(Data['Year']):
    UpToYearData = dict( [ (Key, Value[:YearIndex+1])  for (Key,Value)  in Data.items()])

    Details = holoviews.Bars(UpToYearData, kdims=['Year'], vdims=[VerticalDimension]).opts (xlim = HorizontalLimits, ylim = VerticalLimits, toolbar=None, default_tools=[], width=500, height=500)
    SaveFile('Bars'+VerticalDimension+str(Year), Details, None)
    Arrow = holoviews.Arrow(Year,UpToYearData[VerticalDimension][YearIndex], Innovations[Year], 'v').redim(x='Year',y=VerticalDimension).opts (xlim = HorizontalLimits, ylim = VerticalLimits, toolbar=None, default_tools=[], width=500, height=500)
    MergedPlot = (Arrow*Details).opts (xlim = HorizontalLimits, ylim = VerticalLimits, toolbar=None, default_tools=[], width=500, height=500)
    SaveFile(VerticalDimension+str(Year), MergedPlot, None)

There are multiple files generated. Here is how the 2018 files look like. Here is only the bars plot: image

Here is what happens when an arrow is added: image

As can be seen the bars are ignored and only one bar remains despite all plots having similar options.

Jacob-Barhak commented 4 years ago

This code example actually breaks in development version:

python 3.7,3 Holoviews: 1.13.0a21.post10+gdf1a5803 bokeh: 1.4.0 panel: 0.7.0a13.post10+gb790593

The error message is:

Traceback (most recent call last):
  File "TestBug7.py", line 41, in <module>
    SaveFile(VerticalDimension+str(Year), MergedPlot, None)
  File "TestBug7.py", line 9, in SaveFile
    holoviews.save(PlotObject, FileName, fmt=Format)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\holoviews\util\__init__.py", line 762, in save
    return renderer_obj.save(obj, filename, fmt=fmt, resources=resources)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\holoviews\plotting\renderer.py", line 530, in save
    plot.layout.save(basename, embed=True, resources=resources)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\panel\viewable.py", line 559, in save
    embed_json, json_prefix, save_path, load_path)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\panel\io\save.py", line 92, in save
    model = panel.get_root(doc, comm)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\panel\viewable.py", line 517, in get_root
    root = self._get_model(doc, comm=comm)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\panel\layout.py", line 136, in _get_model
    objects = self._get_objects(model, [], doc, root, comm)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\panel\layout.py", line 126, in _get_objects
    child = pane._get_model(doc, root, model, comm)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\panel\pane\holoviews.py", line 222, in _get_model
    plot = self._render(doc, comm, root)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\panel\pane\holoviews.py", line 280, in _render
    return renderer.get_plot(self.object, **kwargs)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\holoviews\plotting\bokeh\renderer.py", line 72, in get_plot
    plot = super(BokehRenderer, self_or_cls).get_plot(obj, doc, renderer, **kwargs)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\holoviews\plotting\renderer.py", line 222, in get_plot
    plot.update(init_key)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\holoviews\plotting\plot.py", line 851, in update
    return self.initialize_plot()
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\holoviews\plotting\bokeh\element.py", line 2099, in initialize_plot
    plot = self._init_plot(key, element, ranges=ranges, plots=plots)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\holoviews\plotting\bokeh\element.py", line 435, in _init_plot
    axis_types, labels, plot_ranges = self._axes_props(plots, subplots, element, ranges)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\holoviews\plotting\bokeh\element.py", line 348, in _axes_props
    l, b, r, t = self.get_extents(range_el, ranges)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\holoviews\plotting\plot.py", line 1692, in get_extents
    x0, x1 = util.dimension_range(x0, x1, (hx0, hx1), (sx0, sx1), xpad, self.logx)
  File "C:\Users\Work\Anaconda2\envs\py3dev\lib\site-packages\holoviews\core\util.py", line 1007, in dimension_range
    if isfinite(soft_range[0]) and soft_range[0] <= lower:
TypeError: '<=' not supported between instances of 'numpy.ndarray' and 'numpy.str_'

This is regression in development, yet hopefully this situation is temporary.