holoviz / geoviews

Simple, concise geographical visualization in Python
http://geoviews.org
BSD 3-Clause "New" or "Revised" License
578 stars 75 forks source link

coordinate labels in a bokeh backend #98

Closed suvarchal closed 6 years ago

suvarchal commented 6 years ago

The latitude longitude labels in a geoviews Image have a weird formatting issue. 1) Labels are formatted scientific. 2) It is just not about label formatting, the values are multiplied by 10^5.

The last plot in bokeh examples page is a good demonstration of this issue. http://geo.holoviews.org/Working_with_Bokeh.html

one could also reproduce with a xarray sample data

import xarray as xr
import holoviews as hv
import geoviews as gv
T_data   = xr.tutorial.load_dataset('air_temperature')
gT_data = gv.Dataset(T_data.isel(time=0))
gv.Image(gT_data,kdims=['lon','lat'])

if one plots the same data using holoviews using hv.Image(gT_data) the latitude labels/longitude labels are right but then overlaying coastlines is not available. Hence, I think there might be an easy fix for someone who knows geoviews/holoviews in depth.

some of the consequences i face are 1) Utility of hover tool is limited as the coordinate information displayed is useless. 2) It also stops a user from making interactive plots using a stream. although there is a fix by dividing coordinates by 100000. An example of 1,2 here 3) it also makes overlaying a Point or a Path unnatural, one has to pass latitude , longitude values multipled by 10^5.

suvarchal commented 6 years ago

I tried if i could fix the issue by using bokeh.models.formatters and holoviews hooks but didnt manage to make it work.

philippjfr commented 6 years ago

Labels are formatted scientific.

The axes are now formatted with latitudes/longitudes in master.

It is just not about label formatting, the values are multiplied by 10^5.

I'm not sure what you mean, to display things with bokeh coordinates are projected to web mercator which is defined in eastings/northings, i.e. meters. If you want to display Points or Paths use gv.Points and gv.Path and declare the coordinate reference system (crs) of the data, GeoViews will automatically project your data to Mercator.

suvarchal commented 6 years ago

oh I see, I was misled by what the values are then.

any hints on how to convert those displayed latitude , longitude labels to values in degrees?, or is it limited by the webmercator projection?

philippjfr commented 6 years ago

Just to clarify are you talking about hover positions or axes? Axes now display longitude and latitudes on master, which will be in the upcoming release. Hover values are not currently supported but could be and it would be worth filing an issue specifically about that.

suvarchal commented 6 years ago

I meant both, i assumed both were related somehow. I checked with current master, got the same axis labels as before, will try again and update. Thanks.

suvarchal commented 6 years ago

whoops another issue from master, on running previous working code

import xarray as xr
import holoviews as hv
import geoviews as gv
hv.notebook_extension('bokeh')
T_data=xr.tutorial.load_dataset('air_temperature')
gT_data=gv.Dataset(T_data.isel(time=0))
gv.Image(gT_data,kdims=['lon','lat'])

leads to a TypeError

~/miniconda2/envs/python35/lib/python3.5/site-packages/IPython/core/formatters.py in __call__(self, obj)
    339                 pass
    340             else:
--> 341                 return printer(obj)
    342             # Finally look for special method names
    343             method = get_real_method(obj, self.print_method)

~/miniconda2/envs/python35/lib/python3.5/site-packages/holoviews/ipython/display_hooks.py in pprint_display(obj)
    257     if not ip.display_formatter.formatters['text/plain'].pprint:
    258         return None
--> 259     return display(obj, raw=True)
    260 
    261 

~/miniconda2/envs/python35/lib/python3.5/site-packages/holoviews/ipython/display_hooks.py in display(obj, raw, **kwargs)
    237     elif isinstance(obj, (CompositeOverlay, ViewableElement)):
    238         with option_state(obj):
--> 239             html = element_display(obj)
    240     elif isinstance(obj, (Layout, NdLayout, AdjointLayout)):
    241         with option_state(obj):

~/miniconda2/envs/python35/lib/python3.5/site-packages/holoviews/ipython/display_hooks.py in wrapped(element)
    129         try:
    130             html = fn(element,
--> 131                       max_frames=OutputSettings.options['max_frames'])
    132 
    133             # Only want to add to the archive for one display hook...

~/miniconda2/envs/python35/lib/python3.5/site-packages/holoviews/ipython/display_hooks.py in element_display(element, max_frames)
    176     if renderer.fig == 'pdf':
    177         renderer = renderer.instance(fig='png')
--> 178     return renderer.html(element, fmt=renderer.fig)
    179 
    180 

~/miniconda2/envs/python35/lib/python3.5/site-packages/holoviews/plotting/renderer.py in html(self, obj, fmt, css, comm, **kwargs)
    253         code to initialize a Comm, if the plot supplies one.
    254         """
--> 255         plot, fmt =  self._validate(obj, fmt)
    256         figdata, _ = self(plot, fmt, **kwargs)
    257         if css is None: css = self.css

~/miniconda2/envs/python35/lib/python3.5/site-packages/holoviews/plotting/renderer.py in _validate(self, obj, fmt)
    189         if isinstance(obj, tuple(self.widgets.values())):
    190             return obj, 'html'
--> 191         plot = self.get_plot(obj, renderer=self)
    192 
    193         fig_formats = self.mode_formats['fig'][self.mode]

~/miniconda2/envs/python35/lib/python3.5/site-packages/holoviews/plotting/bokeh/renderer.py in get_plot(self_or_cls, obj, doc, renderer)
    129         combining the bokeh model with another plot.
    130         """
--> 131         plot = super(BokehRenderer, self_or_cls).get_plot(obj, renderer)
    132         if self_or_cls.mode == 'server' and doc is None:
    133             doc = curdoc()

~/miniconda2/envs/python35/lib/python3.5/site-packages/holoviews/plotting/renderer.py in get_plot(self_or_cls, obj, renderer)
    176             plot = self_or_cls.plotting_class(obj)(obj, renderer=renderer,
    177                                                    **plot_opts)
--> 178             plot.update(0)
    179         else:
    180             plot = obj

~/miniconda2/envs/python35/lib/python3.5/site-packages/holoviews/plotting/plot.py in update(self, key)
    483     def update(self, key):
    484         if len(self) == 1 and key == 0 and not self.drawn:
--> 485             return self.initialize_plot()
    486         item = self.__getitem__(key)
    487         self.traverse(lambda x: setattr(x, '_updated', True))

~/miniconda2/envs/python35/lib/python3.5/site-packages/holoviews/plotting/bokeh/element.py in initialize_plot(self, ranges, plot, plots, source)
    789         self.handles['plot'] = plot
    790 
--> 791         self._init_glyphs(plot, element, ranges, source)
    792         if not self.overlaid:
    793             self._update_plot(key, plot, style_element)

~/miniconda2/envs/python35/lib/python3.5/site-packages/holoviews/plotting/bokeh/element.py in _init_glyphs(self, plot, element, ranges, source)
    740             data, mapping = self.get_batched_data(element, ranges)
    741         else:
--> 742             data, mapping = self.get_data(element, ranges)
    743             current_id = element._plot_id
    744         if source is None:

TypeError: get_data() missing 1 required positional argument: 'style'

should i create a new issue?

philippjfr commented 6 years ago

No, you just need latest HoloViews master or a dev release as well.

suvarchal commented 6 years ago

oh great it works! after latest holoviews master and bokeh 0.12.10 image

will create a new issue for hover Thanks