holoviz / holoviews

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

Saving scrubber to html broken (result is slider instead) #2885

Closed xushaozhi closed 5 years ago

xushaozhi commented 6 years ago

When i run the following code in Spyder: import numpy as np import holoviews as hv hv.extension('bokeh') np.random.seed(42) coords = [(i, np.random.random()) for i in range(20)] hv.Scatter(coords)

The output is :"Out[45]: :Scatter [x] (y)",nothing else is shown。。 I wonder if Holoviews can run properly in Spyder(IDE) , but in jupyter notebook is OK. Plesase help me, thanks.

jbednar commented 6 years ago

According to https://github.com/spyder-ide/spyder/issues/1821 , Bokeh plots (and therefore presumably HoloViews plots) should work fine in Spyder once Spyder supports Jupyter notebooks. It looks like there is a Jupyter notebook plugin for Spyder at https://github.com/spyder-ide/spyder-notebook , but I haven't tried it myself. Maybe that will work?

jbednar commented 6 years ago

Holoviews and Bokeh works well in my Spyder-notebook plugin (same as Jupyter notebooks). Most of my time,I don't use Spyder-notebook plugin, only use the origin Spyder workspace.

In the origin Spyder workspace,Bokeh works well with a new pop-up Html window in my browser. But when I run Holoviews code(hv.extension('bokeh')),there is nothing shown,no pop-up new Html window like Bokeh, which makes me confused.

So, my real question is ,"Holoviews can only work in Jupyter notebooks IDE?" and "how to run Holoviews in origin Spyder workspace, not Jupyter notebooks, with Html format like Bokeh?"

Ah, I see. How are you displaying your Bokeh plot? You can get a handle to the Bokeh plot for any HoloViews object as described in http://holoviews.org/user_guide/Plots_and_Renderers.html and display that the same way; its just an extra step. I.e. for some object obj, I think you can do r=hv.renderer('bokeh') then b = r.get_plot(obj).state for some viewable object obj; b should then be a Bokeh plot that you can display however you were displaying it before.

This step happens automatically in a Jupyter notebook, but if you aren't running in that context, you have to do something like it explicitly.

ghost commented 6 years ago

I have a related question. I am working with a timeseries of precipitation data on a grid of locations. It is in the form of an xarray Dataset with three dimensions (time, lat, lon).

I have not used Holoviews before but I am becoming motivated to learn it because I would very much like to be able to explore these data interactively using a "scrubber" (DVD-style controls, as I understand it) type visualization, just like the example shown at the bottom of the post here.

(I would also like to be able to save the scrubber visualization to a standalone html file that can be shared with others who will then be able to view the data interactively in their own browsers, etc.)

I use Spyder, in particular its IPython console, for most everything I do-- not notebooks. I am wondering if it will be possible to create, view, and save the scrubber visualization without using a notebook?

From what you’ve said here, it seems like I should be able to do this. But I haven’t yet been successful.

Background info (Bokeh test case): From the IPython console I can in fact successfully use Bokeh to create an interactive plot, open it in a browser, and save it to an html file. I used this simple example (not my precipitation data): import numpy as np from bokeh.plotting import figure, output_file, show N = 4000 x = np.random.random(size=N) * 100 y = np.random.random(size=N) * 100 radii = np.random.random(size=N) * 1.5 colors = ["#%02x%02x%02x" %(int(r),int(g),150) for r,g in zip(50+2*x, 30+2*y)] TOOLS="hover,crosshair,pan,wheel_zoom,zoom_in,zoom_out,box_zoom,undo,redo,reset,tap,save,box_select,poly_select,lasso_select," p = figure(tools=TOOLS) p.scatter(x, y, radius=radii, fill_color=colors, fill_alpha=0.6, line_color=None) output_file("Test.html", title="example") show(p) # open a browser Back to Holoviews now. For my precipitation data in an xarray Dataset called ds, I put together some lines of code that I thought would work. My starting point was the code I saw at the link included above, but note, that was written for a notebook. So I tried to translate the lines of magic commands ‘output’ and ‘opts’ in to non-notebook code. Here is what I came up with: import holoviews as hv hv.extension('bokeh') hv.output(holomap='scrubber') hv_ds = hv.Dataset(ds) holomap = hv_ds.to(hv.Image, ['lon', 'lat']) hv.opts("Image style(cmap='viridis') plot[colorbar=True]",holomap) hv.opts("Image [width=1000,height=1000]",holomap) r=hv.renderer('bokeh') b = r.get_plot(holomap).state bkshow(b) # open in browser

Note that the last three lines of code are what you just suggested.

The result: the browser was opened and the first frame of the precipitation data was presented in it, with size, colorbar, and colormap just as requested … BUT no scrubber (DVD-like) controls appeared, nor did any kind of widget that would enable me to view anything other than the first image.

Suggestions? I seems like I am either close to getting it right, and just need a little help with my syntax, or possibly something about the scrubber functionality does not work, from an IPython console instead of a notebook.

jlstevens commented 6 years ago

BUT no scrubber (DVD-like) controls appeared, nor did any kind of widget that would enable me to view anything other than the first image.

That might be because you are using bokeh's bkshow on the plots .state - this won't include the javascript needed by holoviews to show the widgets.

It might be a little more painful to use (because it won't open a browser window for you) but I would recommend saving the holoviews object to an html file using hv.options. Instead of the lines at the end of your snippet above (from r onwards) try hv.output(holomap, filename='holomap.html') instead and viewing the resulting file.

ghost commented 6 years ago

Thanks for the suggestion. I tried it. It gives me a slider type widget, and the widget works. So that’s a step forward-- I’m getting the javascript functionality now. (And as far as opening it in a browser it's no problem-- I just use python's webbrowser.open('file.html') on the line immediately after the one that saves to file.html.)

However, ... I can’t seem to get a scrubber-- just the slider type widget. Don't understand why. Need more help or suggestions please.

[ Fwiw, I find I get the same result, i.e. slider not scrubber, whether I save it to html using hv.output or using the bokeh renderer i.e. r = hv.renderer('bokeh') and then r.save(hv_obj,'filename'). ]

I found some older posts discussing changes to whether the slider or the scrubber are the default, based on whether there is more than one key dimension in the dataset. Could that be related?

Here is info about the xarray dataset:

Dimensions: (lat: 18, lon: 19, tZ: 744) Coordinates: \* lat (lat) float64 42.0 42.04 42.07 42.11 42.14 ... \* tZ (tZ) datetime64[ns] 2011-03-01 ... \* lon (lon) float64 -71.6 -71.55 -71.5 -71.45 ... Data variables: QPE Precip at BMA grid [mm] (tZ, lat, lon) float64 ... And here is the code: `hv.extension('bokeh')` `hv_ds = hv.Dataset(ds)` `scenes = hv_ds.to(hv.Image, ['lon', 'lat'])` `hv.opts("Image style(cmap='viridis') plot[colorbar=True]",scenes)` `hv.opts("Image [width=500,height=500]",scenes)` `hv.output(scenes,holomap='scrubber',filename='qpe')` `webbrowser.open('qpe.html')` p.s. Where is the best documentation of the syntax for hv.opts() and hv.output() located? For example, I am finding that width=500, height=500 does not give a square on the screen and want to learn more about my options for controlling the size and aspect ratio of the images.
jbednar commented 6 years ago

I think we need better docs for hv.opts and hv.output, but what I know of is on http://holoviews.org/user_guide/Customizing_Plots.html .

Controlling size and aspect for the Bokeh backend is not at all straightforward; see https://github.com/bokeh/bokeh/issues/5186 , https://github.com/ioam/holoviews/pull/2171 , https://github.com/ioam/holoviews/issues/1953, and https://github.com/bokeh/bokeh/pull/6784 . Bokeh is currently experimenting with a different layout engine that would make this all much easier to control, but it may be some weeks still before it's ready to ship (at which point Bokeh will finally reach 1.0 status!).

ghost commented 6 years ago

Ok thanks for that info (about documentation, and aspect ratios in bokeh plots).

I guess nobody can suggest why I'm getting the slider instead of the scrubber.

At this point I'm a little unsure of whether the problem is related to me doing things in an ipython console (instead of a notebook)-- as opposed to me simply not understanding yet how the holoviews commands work. Will keep trying things out. Suggestions very welcome.

jlstevens commented 6 years ago

It will probably need some investigation as hv.output(scenes,holomap='scrubber',filename='qpe') does explicitly say 'scrubber'....

ghost commented 6 years ago

Thank you @jlstevens for identifying this as a bug so it gets tested-- and also for putting it on the milestones list. I suggest it be renamed to something like "Can only get slider, not scrubber, in ipython console (not jupyter notebook)". I would have done this myself but I'm not sure I have the permissions...

ghost commented 6 years ago

Quick update on this now.

Recall, my end goal: Save an interactive scrubber visualization to an html file (viewable in a browser, easily shared with colleagues).

I had been thinking that the trouble was due to me using an ipython console instead of a jupyter notebook. But now I'm not so sure of that.

As a test I used a jupyter notebook to create the scrubber visualization. All went well. The final statement that successfully presented the interactive scrubber to me inside the notebook was

%%output holomap='scrubber' %%opts Image style(cmap='viridis') plot[colorbar=True] %%opts Image [width=500, height=400] hv_ds.to(hv.Image, ['Lon', 'Lat'])

So: What is the syntax (from right there within the same jupyter notebook) to save the interactive visualization to an html file (instead of viewing it within the notebook)?

If you can point me to an example, and/or the section of the documentation, addressing this it would be very helpful.

I tried hv.output(hv_ds.to(hv.Image, ['Lon', 'Lat']),filename='qpe',holomap='scrubber') and it created a file qpe.html. But when I view that in a browser, I get the slider widget not the scrubber. That's the same problem as I was having earlier-- and attributed to using an ipython console instead of a jupyter notebook. But now I'm in jupyter...

Thanks in advance.

ghost commented 6 years ago

I also tried this hv.renderer('bokeh').save(hv_ds.to(hv.Image,['Lon','Lat']),'test') but no success.

ghost commented 6 years ago

Could be related to #2933 ?

ghost commented 6 years ago

@jlstevens and/or @jbednar I'd say the title of this issue should be updated to something like "Saving scrubber to html broken (result is slider instead)" because it isn't really tied to IPython nor Spyder. Let me know if it would be better for me to just open a new issue. Thank you.

philippjfr commented 6 years ago

@DanCodigaMWRA Could you try this:

ds = hv.Dataset((range(10), range(10), range(10), np.random.rand(10, 10, 10)), ['x', 'y', 'z'], 'value')
hmap = ds.to(hv.Image, ['x', 'y'])
hv.renderer('bokeh').save(hmap, 'test', fmt='scrubber')
ghost commented 6 years ago

Great @philippjfr , that is just the syntax I was needing. It works. And note, just for completeness, I tested that it works (1) in both (a) IPython, from within Spyder, and (b) a Jupyter notebook, and (2) for both (a) the random-data test case you gave me and (b) my own dataset. Thanks so much. (Am especially glad it works inside Spyder's IPython, as I don't commonly use Jupyter.)

jlstevens commented 6 years ago

@philippjfr Wouldn't you expect the example above to work?

hv.output(hv_ds.to(hv.Image, ['Lon', 'Lat']),filename='qpe',holomap='scrubber')

Maybe the holomap argument isn't being applied correctly to the renderer when saving with hv.output...

philippjfr commented 6 years ago

@philippjfr Wouldn't you expect the example above to work?

I would, but then I have no idea how hv.output works. Both APIs are to obscure imo and I'd strongly argue for a hv.save function.

jlstevens commented 6 years ago

Ok, I'll look into what is going on in hv.output.

The goal of hv.output is to have a pure Python equivalent to the output magic. It certainly doesn't claim to be the best API for saving things to disk. For this reason, so I have no objection to a hv.save (where the implementation would live in hv.util).

github-actions[bot] commented 1 month ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.