Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

mplot3d: add_collection3d issues #17755

Copy link
Copy link
Closed
@thangleiter

Description

@thangleiter
Issue body actions

Bug report

Bug summary

  1. When plotting a parametrized line in 3D using LineCollection, a ValueError is thrown when Axes3D.add_collection_3d upconverts 2D Collections with the zs parameter.
    In the MWE below, this is because this line in _paths_to_3d_segments tries to broadcast a 2D array (number of line segments on the first axis and segment start & end on the second) to a 1D array (number of line segments):
    zs = np.broadcast_to(zs, len(paths))

    Commenting out this line will make the example work.
  2. Additionally, add_collection3d does not return the collection like add_collection does (it does not return anything). Hence, you cannot pass the collection object to, e.g., a colorbar call:
    elif type(col) is mcoll.PatchCollection:
    art3d.patch_collection_2d_to_3d(col, zs=zs, zdir=zdir)
    col.set_sort_zpos(zsortval)
    super().add_collection(col)
    def scatter(self, xs, ys, zs=0, zdir='z', s=20, c=None, depthshade=True,

    Simply returning the return value of the call to super().add_collection does the trick for me here:
collection = super().add_collection(col)
return collection

Code for reproduction

A minimal working example (including the reason why I use LineCollection instead of plot, namely a multicolored line) stitched together from two official examples (1, 2) is:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection

theta = np.linspace(-4 * np.pi, 4 * np.pi, 100)
z = np.linspace(-2, 2, 100)
r = z**2 + 1
x = r * np.sin(theta)
y = r * np.cos(theta)

points = np.array([x, y, z]).T.reshape(-1, 1, 3)
segments = np.concatenate([points[:-1], points[1:]], axis=1)

fig = plt.figure()
ax = fig.gca(projection='3d')

norm = plt.Normalize(0, 2*np.pi)
# 2D LineCollection from x & y values
lc = LineCollection(segments[:, :, :2], cmap='twilight', norm=norm)
lc.set_array(np.mod(theta, 2*np.pi))
# Add 2D collection at z values to ax
line = ax.add_collection3d(lc, zs=segments[:, :, 2])  # line is None

# fig.colorbar(line, ax=ax)  # Would fail because add_collection3d does not return the collection

ax.set_xlim(-5, 5)
ax.set_ylim(-4, 6)
ax.set_zlim(-2, 2)
plt.show()

Actual outcome

Traceback (most recent call last):

  File "<ipython-input-1-d8492282873b>", line 23, in <module>
    line = ax.add_collection3d(lc, zs=segments[:, :, 2])

  File "c:\users\hangleiter\appdata\local\continuum\anaconda3\envs\py38\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py", line 2178, in add_collection3d
    art3d.line_collection_2d_to_3d(col, zs=zs, zdir=zdir)

  File "c:\users\hangleiter\appdata\local\continuum\anaconda3\envs\py38\lib\site-packages\mpl_toolkits\mplot3d\art3d.py", line 332, in line_collection_2d_to_3d
    segments3d = _paths_to_3d_segments(col.get_paths(), zs, zdir)

  File "c:\users\hangleiter\appdata\local\continuum\anaconda3\envs\py38\lib\site-packages\mpl_toolkits\mplot3d\art3d.py", line 234, in _paths_to_3d_segments
    zs = np.broadcast_to(zs, len(paths))

  File "<__array_function__ internals>", line 5, in broadcast_to

  File "C:\Users\hangleiter\AppData\Local\Continuum\anaconda3\envs\py38\lib\site-packages\numpy\lib\stride_tricks.py", line 182, in broadcast_to
    return _broadcast_to(array, shape, subok=subok, readonly=True)

  File "C:\Users\hangleiter\AppData\Local\Continuum\anaconda3\envs\py38\lib\site-packages\numpy\lib\stride_tricks.py", line 125, in _broadcast_to
    it = np.nditer(

ValueError: input operand has more dimensions than allowed by the axis remapping

Expected outcome
This is the result if both of the above fixes are applied:
grafik

Matplotlib version

  • Operating system: Windows
  • Matplotlib version: 3.2.2
  • Matplotlib backend (print(matplotlib.get_backend())): module://ipykernel.pylab.backend_inline
  • Python version: 3.8.3
  • Numpy version: 1.18.5

Matplotlib is installed via conda:defaults.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.