holoviz / holoviz/hvplot

`TypeError: ufunc 'isfinite'` when using `hvplot.networkx.draw` with `geo=True`

Open
#1,736 0 comments 0 reactions 0 assignees View on GitHub
TRIAGE
Dominant language
Python
Stars
1.4k
Forks
124
Avg merge
1d 18h
Merged PRs (30d)
1

Description

#### ALL software version info

Software Version Info

```plaintext
hvplot: 0.12.2
geoviews: 1.15.1
holoviews: 1.22.1
networkx: 3.6.1
bokeh: 3.9.0
python: 3.12.13
```

#### Description of expected behavior and the observed behavior
Using `hvplot.networkx.draw` with `geo=True, crs="EPSG:4326"` raises a `TypeError` from GeoViews' extent calculation, even with a trivial 2-node graph.

#### Complete, minimal, self-contained example code that reproduces the issue

```python
import networkx as nx
import hvplot.networkx as hvnx

G = nx.Graph()
G.add_node('A', pos=(9.75, 4.05))
G.add_node('B', pos=(9.80, 4.10))
G.add_edge('A', 'B')

pos = nx.get_node_attributes(G, 'pos')
hvnx.draw(G, pos, geo=True, crs="EPSG:4326", tiles='CartoLight', with_labels=True)
```

#### Stack traceback and/or browser JavaScript console output

```plaintext
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
File ~/.local/lib/python3.12/site-packages/holoviews/plotting/bokeh/element.py:752, in ElementPlot._axis_props(self, plots, subplots, element, ranges, pos, dim, range_tags_extras, extra_range_name)
751 try:
--> 752 l, b, r, t = self.get_extents(range_el, ranges, dimension=dim)
753 except TypeError:
754 # Backward compatibility for e.g. GeoViews=<1.10.1 since dimension
755 # is a newly added keyword argument in HoloViews 1.17

File ~/.local/lib/python3.12/site-packages/geoviews/plotting/plot.py:64, in ProjectionPlot.get_extents(self, element, ranges, range_type, **kwargs)
63 return (x0, y0, x1, y1)
---> 64 extents = super().get_extents(element, ranges, range_type)
65 if not getattr(element, 'crs', None) or not self.geographic:

File ~/.local/lib/python3.12/site-packages/holoviews/plotting/plot.py:2034, in GenericOverlayPlot.get_extents(self, overlay, ranges, range_type, dimension, **kwargs)
2033 def get_extents(self, overlay, ranges, range_type='combined', dimension=None, **kwargs):
-> 2034 subplot_extents = self._get_subplot_extents(overlay, ranges, range_type, dimension)
2035 zrange = isinstance(self.projection, str) and self.projection == '3d'

File ~/.local/lib/python3.12/site-packages/holoviews/plotting/plot.py:2029, in GenericOverlayPlot._get_subplot_extents(self, overlay, ranges, range_type, dimension)
2028 for rt in extents:
-> 2029 extent = subplot.get_extents(layer, sp_ranges, range_type=rt)
2030 extents[rt].append(extent)

File ~/.local/lib/python3.12/site-packages/geoviews/plotting/plot.py:67, in ProjectionPlot.get_extents(self, element, ranges, range_type, **kwargs)
66 return extents
---> 67 elif any(e is None or not np.isfinite(e) for e in extents):
68 extents = None

File ~/.local/lib/python3.12/site-packages/geoviews/plotting/plot.py:67, in (.0)
66 return extents
---> 67 elif any(e is None or not np.isfinite(e) for e in extents):
68 extents = None

TypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

During handling of the above exception, another exception occurred:

TypeError Traceback (most recent call last)

File ~/.local/lib/python3.12/site-packages/holoviews/util/__init__.py:892, in render(obj, backend, **kwargs)
890 if len(plot) > 1:
891 return plot.anim(fps=renderer_obj.fps)
--> 892 return renderer_obj.get_plot_state(obj)

File ~/.local/lib/python3.12/site-packages/holoviews/plotting/renderer.py:273, in Renderer.get_plot_state(self_or_cls, obj, renderer, **kwargs)
269 """Given a HoloViews Viewable return a corresponding plot state.
270
271 """
272 if not isinstance(obj, Plot):
--> 273 obj = self_or_cls.get_plot(obj=obj, renderer=renderer, **kwargs)
274 return obj.state

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

File ~/.local/lib/python3.12/site-packages/holoviews/plotting/renderer.py:239, in Renderer.get_plot(self_or_cls, obj, doc, renderer, comm, **kwargs)
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, strict=None))
--> 239 plot.update(init_key)
240 else:
241 plot = obj

File ~/.local/lib/python3.12/site-packages/holoviews/plotting/plot.py:958, in DimensionedPlot.update(self, key)
956 def update(self, key):
957 if len(self) == 1 and key in (0, self.keys[0]) and not self.drawn:
--> 958 return self.initialize_plot()
959 item = self.__getitem__(key)
960 self.traverse(lambda x: setattr(x, '_updated', True))

File ~/.local/lib/python3.12/site-packages/geoviews/plotting/bokeh/plot.py:121, in GeoPlot.initialize_plot(self, ranges, plot, plots, source)
119 def initialize_plot(self, ranges=None, plot=None, plots=None, source=None):
120 opts = {} if isinstance(self, HvOverlayPlot) else {'source': source}
--> 121 fig = super().initialize_plot(ranges, plot, plots, **opts)
122 style_element = self.current_frame.last if self.batched else self.current_frame
123 el_ranges = match_spec(style_element, self.current_ranges) if self.current_ranges else {}

File ~/.local/lib/python3.12/site-packages/holoviews/plotting/bokeh/element.py:3460, in OverlayPlot.initialize_plot(self, ranges, plot, plots)
3458 self.tabs = self.tabs or any(isinstance(sp, TablePlot) for sp in self.subplots.values())
3459 if plot is None and not self.tabs and not self.batched:
-> 3460 plot = self._init_plot(key, element, ranges=ranges, plots=plots)
3461 self._populate_axis_handles(plot)
3462 self.handles['plot'] = plot

File ~/.local/lib/python3.12/site-packages/holoviews/plotting/bokeh/element.py:933, in ElementPlot._init_plot(self, key, element, plots, ranges)
930 subplots = list(self.subplots.values()) if self.subplots else []
932 axis_specs = {'x': {}, 'y': {}}
--> 933 axis_specs['x']['x'] = (*self._axis_props(plots, subplots, element, ranges, pos=0), self.xaxis, {})
934 if self.multi_y and subplots:
935 if not BOKEH_GE_3_2_0:

File ~/.local/lib/python3.12/site-packages/holoviews/plotting/bokeh/element.py:756, in ElementPlot._axis_props(self, plots, subplots, element, ranges, pos, dim, range_tags_extras, extra_range_name)
752 l, b, r, t = self.get_extents(range_el, ranges, dimension=dim)
753 except TypeError:
754 # Backward compatibility for e.g. GeoViews=<1.10.1 since dimension
755 # is a newly added keyword argument in HoloViews 1.17
--> 756 l, b, r, t = self.get_extents(range_el, ranges)
757 if self.invert_axes:
758 l, b, r, t = b, l, t, r

File ~/.local/lib/python3.12/site-packages/geoviews/plotting/plot.py:64, in ProjectionPlot.get_extents(self, element, ranges, range_type, **kwargs)
62 (x0, x1), (y0, y1) = proj.x_limits, proj.y_limits
63 return (x0, y0, x1, y1)
---> 64 extents = super().get_extents(element, ranges, range_type)
65 if not getattr(element, 'crs', None) or not self.geographic:
66 return extents

File ~/.local/lib/python3.12/site-packages/holoviews/plotting/plot.py:2034, in GenericOverlayPlot.get_extents(self, overlay, ranges, range_type, dimension, **kwargs)
2033 def get_extents(self, overlay, ranges, range_type='combined', dimension=None, **kwargs):
-> 2034 subplot_extents = self._get_subplot_extents(overlay, ranges, range_type, dimension)
2035 zrange = isinstance(self.projection, str) and self.projection == '3d'
2036 extents = {k: util.max_extents(rs, zrange) for k, rs in subplot_extents.items()}

File ~/.local/lib/python3.12/site-packages/holoviews/plotting/plot.py:2029, in GenericOverlayPlot._get_subplot_extents(self, overlay, ranges, range_type, dimension)
2027 sp_ranges = util.match_spec(layer, ranges) if ranges else {}
2028 for rt in extents:
-> 2029 extent = subplot.get_extents(layer, sp_ranges, range_type=rt)
2030 extents[rt].append(extent)
2031 return extents

File ~/.local/lib/python3.12/site-packages/geoviews/plotting/plot.py:67, in ProjectionPlot.get_extents(self, element, ranges, range_type, **kwargs)
65 if not getattr(element, 'crs', None) or not self.geographic:
66 return extents
---> 67 elif any(e is None or not np.isfinite(e) for e in extents):
68 extents = None
69 else:

File ~/.local/lib/python3.12/site-packages/geoviews/plotting/plot.py:67, in (.0)
65 if not getattr(element, 'crs', None) or not self.geographic:
66 return extents
---> 67 elif any(e is None or not np.isfinite(e) for e in extents):
68 extents = None
69 else:

TypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
```

Contributor guide

Open the contributing guide

Research direction

Run the minimal Python example with the versions listed, then trace hvplot.networkx.draw through the GeoViews ProjectionPlot.get_extents call shown in the traceback. Investigate the extent values reaching np.isfinite; done means the geo=True graph renders with EPSG:4326 and no TypeError, including this two-node case.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data-visualization
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.