Skip to content

Support vector data cubes in xarray #737

Open
holoviz/hvplot
#1405
@ahuang11

Description

@ahuang11

from https://earthmover.io/blog/vector-datacube-pt1

# !pip install xvec gcsfs huggingface_hub

import geopandas as gpd
import pandas as pd
import hvplot.pandas

import xarray as xr

uri = "gs://gcp-public-data-arco-era5/ar/1959-2022-full_37-6h-0p25deg-chunk-1.zarr-v2"
era5_ds_sub = (
    # Open the dataset
    xr.open_zarr(uri, chunks={"time": 48}, consolidated=True)
    # Select the near-surface level
    .isel(level=0, drop=True)
    # subset in time
    .sel(time=slice("2017-01", "2018-01"))
    # reduce to two arrays
    [["2m_temperature", "u_component_of_wind"]]
)
era5_ds_sub


cities_df = pd.read_json(
    "hf://datasets/jamescalam/world-cities-geo/train.jsonl", lines=True
)
cities_eur = cities_df.loc[cities_df["continent"] == "Europe"]
cities_eur = gpd.GeoDataFrame(
    cities_eur,
    geometry=gpd.points_from_xy(cities_eur.longitude, cities_eur.latitude),
    crs="EPSG:4326",
).drop(["latitude", "longitude", "x", "y", "z"], axis=1)
import xvec

era5_europe_cities = era5_ds_sub.xvec.extract_points(
    cities_eur.geometry, x_coords="longitude", y_coords="latitude"
).drop_vars("index")
era5_europe_cities.hvplot()

traceback currently:

{
	"name": "TypeError",
	"message": "'<' not supported between instances of 'Point' and 'Point'",
	"stack": "---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
File ~/miniconda3/envs/hvplot/lib/python3.10/site-packages/IPython/core/formatters.py:974, in MimeBundleFormatter.__call__(self, obj, include, exclude)
    971     method = get_real_method(obj, self.print_method)
    973     if method is not None:
--> 974         return method(include=include, exclude=exclude)
    975     return None
    976 else:

File ~/repos/holoviews/holoviews/core/dimension.py:1275, in Dimensioned._repr_mimebundle_(self, include, exclude)
   1268 def _repr_mimebundle_(self, include=None, exclude=None):
   1269     \"\"\"
   1270     Resolves the class hierarchy for the class rendering the
   1271     object using any display hooks registered on Store.display
   1272     hooks.  The output of all registered display_hooks is then
   1273     combined and returned.
   1274     \"\"\"
-> 1275     return Store.render(self)

File ~/repos/holoviews/holoviews/core/options.py:1423, in Store.render(cls, obj)
   1421 data, metadata = {}, {}
   1422 for hook in hooks:
-> 1423     ret = hook(obj)
   1424     if ret is None:
   1425         continue

File ~/repos/holoviews/holoviews/ipython/display_hooks.py:287, in pprint_display(obj)
    285 if not ip.display_formatter.formatters['text/plain'].pprint:
    286     return None
--> 287 return display(obj, raw_output=True)

File ~/repos/holoviews/holoviews/ipython/display_hooks.py:255, in display(obj, raw_output, **kwargs)
    253 elif isinstance(obj, (CompositeOverlay, ViewableElement)):
    254     with option_state(obj):
--> 255         output = element_display(obj)
    256 elif isinstance(obj, (Layout, NdLayout, AdjointLayout)):
    257     with option_state(obj):

File ~/repos/holoviews/holoviews/ipython/display_hooks.py:149, in display_hook.<locals>.wrapped(element)
    147 try:
    148     max_frames = OutputSettings.options['max_frames']
--> 149     mimebundle = fn(element, max_frames=max_frames)
    150     if mimebundle is None:
    151         return {}, {}

File ~/repos/holoviews/holoviews/ipython/display_hooks.py:195, in element_display(element, max_frames)
    192 if type(element) not in Store.registry[backend]:
    193     return None
--> 195 return render(element)

File ~/repos/holoviews/holoviews/ipython/display_hooks.py:76, in render(obj, **kwargs)
     73 if renderer.fig == 'pdf':
     74     renderer = renderer.instance(fig='png')
---> 76 return renderer.components(obj, **kwargs)

File ~/repos/holoviews/holoviews/plotting/renderer.py:396, in Renderer.components(self, obj, fmt, comm, **kwargs)
    394 embed = (not (dynamic or streams or self.widget_mode == 'live') or config.embed)
    395 if embed or config.comms == 'default':
--> 396     return self._render_panel(plot, embed, comm)
    397 return self._render_ipywidget(plot)

File ~/repos/holoviews/holoviews/plotting/renderer.py:403, in Renderer._render_panel(self, plot, embed, comm)
    401 doc = Document()
    402 with config.set(embed=embed):
--> 403     model = plot.layout._render_model(doc, comm)
    404 if embed:
    405     return render_model(model, comm)

File ~/miniconda3/envs/hvplot/lib/python3.10/site-packages/panel/viewable.py:736, in Viewable._render_model(self, doc, comm)
    734 if comm is None:
    735     comm = state._comm_manager.get_server_comm()
--> 736 model = self.get_root(doc, comm)
    738 if self._design and self._design.theme.bokeh_theme:
    739     doc.theme = self._design.theme.bokeh_theme

File ~/miniconda3/envs/hvplot/lib/python3.10/site-packages/panel/layout/base.py:320, in Panel.get_root(self, doc, comm, preprocess)
    316 def get_root(
    317     self, doc: Optional[Document] = None, comm: Optional[Comm] = None,
    318     preprocess: bool = True
    319 ) -> Model:
--> 320     root = super().get_root(doc, comm, preprocess)
    321     # ALERT: Find a better way to handle this
    322     if hasattr(root, 'styles') and 'overflow-x' in root.styles:

File ~/miniconda3/envs/hvplot/lib/python3.10/site-packages/panel/viewable.py:667, in Renderable.get_root(self, doc, comm, preprocess)
    665 wrapper = self._design._wrapper(self)
    666 if wrapper is self:
--> 667     root = self._get_model(doc, comm=comm)
    668     if preprocess:
    669         self._preprocess(root)

File ~/miniconda3/envs/hvplot/lib/python3.10/site-packages/panel/layout/base.py:186, in Panel._get_model(self, doc, root, parent, comm)
    184 root = root or model
    185 self._models[root.ref['id']] = (model, parent)
--> 186 objects, _ = self._get_objects(model, [], doc, root, comm)
    187 props = self._get_properties(doc)
    188 props[self._property_mapping['objects']] = objects

File ~/miniconda3/envs/hvplot/lib/python3.10/site-packages/panel/layout/base.py:168, in Panel._get_objects(self, model, old_objects, doc, root, comm)
    166 else:
    167     try:
--> 168         child = pane._get_model(doc, root, model, comm)
    169     except RerenderError as e:
    170         if e.layout is not None and e.layout is not self:

File ~/miniconda3/envs/hvplot/lib/python3.10/site-packages/panel/pane/holoviews.py:429, in HoloViews._get_model(self, doc, root, parent, comm)
    427     plot = self.object
    428 else:
--> 429     plot = self._render(doc, comm, root)
    431 plot.pane = self
    432 backend = plot.renderer.backend

File ~/miniconda3/envs/hvplot/lib/python3.10/site-packages/panel/pane/holoviews.py:525, in HoloViews._render(self, doc, comm, root)
    522     if comm:
    523         kwargs['comm'] = comm
--> 525 return renderer.get_plot(self.object, **kwargs)

File ~/repos/holoviews/holoviews/plotting/bokeh/renderer.py:68, in BokehRenderer.get_plot(self_or_cls, obj, doc, renderer, **kwargs)
     61 @bothmethod
     62 def get_plot(self_or_cls, obj, doc=None, renderer=None, **kwargs):
     63     \"\"\"
     64     Given a HoloViews Viewable return a corresponding plot instance.
     65     Allows supplying a document attach the plot to, useful when
     66     combining the bokeh model with another plot.
     67     \"\"\"
---> 68     plot = super().get_plot(obj, doc, renderer, **kwargs)
     69     if plot.document is None:
     70         plot.document = Document() if self_or_cls.notebook_context else curdoc()

File ~/repos/holoviews/holoviews/plotting/renderer.py:234, in Renderer.get_plot(self_or_cls, obj, doc, renderer, comm, **kwargs)
    232 if isinstance(obj, AdjointLayout):
    233     obj = Layout(obj)
--> 234 plot = self_or_cls.plotting_class(obj)(obj, renderer=renderer,
    235                                        **plot_opts)
    236 defaults = [kd.default for kd in plot.dimensions]
    237 init_key = tuple(v if d is None else d for v, d in
    238                  zip(plot.keys[0], defaults))

File ~/miniconda3/envs/hvplot/lib/python3.10/site-packages/geoviews/plotting/bokeh/plot.py:181, in GeoOverlayPlot.__init__(self, element, **params)
    180 def __init__(self, element, **params):
--> 181     super().__init__(element, **params)
    182     self.geographic = any(element.traverse(is_geographic, [_Element]))
    183     if self.geographic:

File ~/miniconda3/envs/hvplot/lib/python3.10/site-packages/geoviews/plotting/bokeh/plot.py:57, in GeoPlot.__init__(self, element, **params)
     56 def __init__(self, element, **params):
---> 57     super().__init__(element, **params)
     58     self.geographic = is_geographic(self.hmap.last)
     59     if self.geographic and not isinstance(self.projection, (PlateCarree, Mercator)):

File ~/repos/holoviews/holoviews/plotting/bokeh/element.py:2995, in OverlayPlot.__init__(self, overlay, **kwargs)
   2993 def __init__(self, overlay, **kwargs):
   2994     self._multi_y_propagation = self.lookup_options(overlay, 'plot').options.get('multi_y', False)
-> 2995     super().__init__(overlay, **kwargs)
   2996     self.callbacks, self.source_streams = self._construct_callbacks()
   2997     self._multi_y_propagation = False

File ~/repos/holoviews/holoviews/plotting/plot.py:1763, in GenericOverlayPlot.__init__(self, overlay, ranges, batched, keys, group_counter, **params)
   1759             self.param.warning(f'{type(s).__name__} stream parameters'
   1760                                f' {list(intersection)} not yet supported with multi_y=True')
   1762 # Apply data collapse
-> 1763 self.hmap = self._apply_compositor(self.hmap, ranges, self.keys)
   1764 self.map_lengths = Counter()
   1765 self.group_counter = Counter() if group_counter is None else group_counter

File ~/repos/holoviews/holoviews/plotting/plot.py:1792, in GenericOverlayPlot._apply_compositor(self, holomap, ranges, keys, dimensions)
   1790 else:
   1791     mapwise_ranges = self.compute_ranges(holomap, None, None)
-> 1792     frame_ranges = dict([(key, self.compute_ranges(holomap, key, mapwise_ranges))
   1793                                 for key in holomap.data.keys()])
   1794 ranges = frame_ranges.values()
   1796 with disable_pipeline():

File ~/repos/holoviews/holoviews/plotting/plot.py:1792, in <listcomp>(.0)
   1790 else:
   1791     mapwise_ranges = self.compute_ranges(holomap, None, None)
-> 1792     frame_ranges = dict([(key, self.compute_ranges(holomap, key, mapwise_ranges))
   1793                                 for key in holomap.data.keys()])
   1794 ranges = frame_ranges.values()
   1796 with disable_pipeline():

File ~/repos/holoviews/holoviews/plotting/plot.py:615, in DimensionedPlot.compute_ranges(self, obj, key, ranges)
    611     # Only compute ranges if not axiswise on a composite plot
    612     # or not framewise on a Overlay or ElementPlot
    613     if (not (axiswise and not isinstance(obj, HoloMap)) or
    614         (not framewise and isinstance(obj, HoloMap))):
--> 615         self._compute_group_range(group, elements, ranges, framewise,
    616                                   axiswise, robust, self.top_level,
    617                                   prev_frame)
    618 self.ranges.update(ranges)
    619 return ranges

File ~/repos/holoviews/holoviews/plotting/plot.py:725, in DimensionedPlot._compute_group_range(cls, group, elements, ranges, framewise, axiswise, robust, top_level, prev_frame)
    723     data_range = ds.range(el_dim, dimension_range=False)
    724 else:
--> 725     data_range = el.range(el_dim, dimension_range=False)
    727 data_ranges[(el, el_dim)] = data_range
    728 if dtype is not None and dtype.kind in 'uif' and robust:

File ~/repos/holoviews/holoviews/core/data/__init__.py:196, in PipelineMeta.pipelined.<locals>.pipelined_fn(*args, **kwargs)
    193     inst._in_method = True
    195 try:
--> 196     result = method_fn(*args, **kwargs)
    197     if PipelineMeta.disable:
    198         return result

File ~/repos/holoviews/holoviews/core/data/__init__.py:508, in Dataset.range(self, dim, data_range, dimension_range)
    506     return dim.range
    507 elif dim in self.dimensions() and data_range and bool(self):
--> 508     lower, upper = self.interface.range(self, dim)
    509 else:
    510     lower, upper = (np.nan, np.nan)

File ~/repos/holoviews/holoviews/core/data/pandas.py:201, in PandasInterface.range(cls, dataset, dimension)
    199     column = column.sort(inplace=False)
    200 else:
--> 201     column = column.sort_values()
    202 try:
    203     column = column[~column.isin([None, pd.NA])]

File ~/miniconda3/envs/hvplot/lib/python3.10/site-packages/pandas/core/indexes/base.py:5848, in Index.sort_values(self, return_indexer, ascending, na_position, key)
   5845 # GH 35584. Sort missing values according to na_position kwarg
   5846 # ignore na_position for MultiIndex
   5847 if not isinstance(self, ABCMultiIndex):
-> 5848     _as = nargsort(
   5849         items=self, ascending=ascending, na_position=na_position, key=key
   5850     )
   5851 else:
   5852     idx = cast(Index, ensure_key_mapped(self, key))

File ~/miniconda3/envs/hvplot/lib/python3.10/site-packages/pandas/core/sorting.py:483, in nargsort(items, kind, ascending, na_position, key, mask)
    481     non_nans = non_nans[::-1]
    482     non_nan_idx = non_nan_idx[::-1]
--> 483 indexer = non_nan_idx[non_nans.argsort(kind=kind)]
    484 if not ascending:
    485     indexer = indexer[::-1]

TypeError: '<' not supported between instances of 'Point' and 'Point'"
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions