Skip to content

Better argument checking of subplot definition in add_subplot() #16016

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Xunius opened this issue Dec 24, 2019 · 2 comments · Fixed by #16527
Closed

Better argument checking of subplot definition in add_subplot() #16016

Xunius opened this issue Dec 24, 2019 · 2 comments · Fixed by #16527

Comments

@Xunius
Copy link

Xunius commented Dec 24, 2019

Bug report

Bug summary
This *** ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() error is raised when executing the bubble() function in cbook/__init__.py file.

Code for reproduction
Unfortunately I'm unable to provide an easy working example to reproduce the issue. I don't know how I ended up in this bubble() function, the line I wrote that triggered the error is:

cax=figure.add_axes([x, y, w, h])

When I tried composing a minimal example it worked fine.

Actual outcome

Below is the traceback:

Traceback (most recent call last):
  File "/home/guangzhi/anaconda3/envs/cdat2b/lib/python2.7/pdb.py", line 1314, in main
    pdb._runscript(mainpyfile)
  File "/home/guangzhi/anaconda3/envs/cdat2b/lib/python2.7/pdb.py", line 1233, in _runscript
    self.run(statement)
  File "/home/guangzhi/anaconda3/envs/cdat2b/lib/python2.7/bdb.py", line 400, in run
    exec cmd in globals, locals
  File "<string>", line 1, in <module>
  File "straighten_analysis_layers.py", line 7, in <module>
    '''
  File "/home/guangzhi/anaconda3/envs/cdat2b/lib/python2.7/site-packages/matplotlib/figure.py", line 1152, in add_axes
    self.sca(a)
  File "/home/guangzhi/anaconda3/envs/cdat2b/lib/python2.7/site-packages/matplotlib/figure.py", line 1848, in sca
    self._axstack.bubble(a)
  File "/home/guangzhi/anaconda3/envs/cdat2b/lib/python2.7/site-packages/matplotlib/figure.py", line 121, in bubble
    return Stack.bubble(self, self._entry_from_axes(a))
  File "/home/guangzhi/anaconda3/envs/cdat2b/lib/python2.7/site-packages/matplotlib/cbook/__init__.py", line 1239, in bubble
    if o not in self._elements:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Uncaught exception. Entering post mortem debugging

I tried examining the if o not in self._elements: line it stopped at:

(Pdb) print o
((((0.125, -0.09000000000000002, 0.20514705882352943, 0.1),), ()), (25, <matplotlib.axes._axes.Axes object at 0x7efbc85c0310>))
(Pdb) print self._elements
[(((8, 3, 1), ()), (1, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbcaad6cd0>)),
 (((8, 3, 4), ()), (2, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc8d79490>)),
 (((8, 3, 7), ()), (3, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc8cf7c10>)),
 (((8, 3, 10), ()), (4, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc8c766d0>)),
 (((8, 3, 13), ()), (5, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc8c50990>)),
 (((8, 3, 16), ()), (6, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc8be4c10>)),
 (((8, 3, 19), ()), (7, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc8b6c6d0>)),
 (((8, 3, 22), ()), (8, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc8aec190>)),
 (((8, 3, 2), ()), (9, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc8c3e890>)),
(((8, 3, 5), ()), (10, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc8cd1e50>)),
 (((8, 3, 8), ()), (11, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc8a7fb50>)),
 (((8, 3, 11), ()), (12, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc8a05610>)),
 (((8, 3, 14), ()), (13, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc89820d0>)), 
(((8, 3, 17), ()), (14, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc88f4b50>)),
 (((8, 3, 20), ()), (15, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc887b610>)),
 (((8, 3, 23), ()), (16, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc87f90d0>)),
 (((8, 3, 3), ()), (17, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc873f3d0>)),
 (((8, 3, 6), ()), (18, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc86f56d0>)),
 (((8, 3, 9), ()), (19, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc8673150>)),
 (((8, 3, 12), ()), (20, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc873ff90>)), 
(((8, 3, 15), ()), (21, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc88d6bd0>)),
 (((8, 3, 18), ()), (22, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc89c32d0>)), 
(((8, 3, 21), ()), (23, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc8ce7d90>))
, (((8, 3, 24), ()), (24, <matplotlib.axes._subplots.AxesSubplot object at 0x7efbc87560d0>)), 
((((0.125, -0.09000000000000002, 0.20514705882352943, 0.1),), ()), (25, <matplotlib.axes._axes.Axes object at 0x7efbc85c0310>))]
(Pdb) self._elements[-1] == o
True
(Pdb) self._elements[-2] == o
*** ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
(Pdb) print

(Pdb) 

(Pdb) o in set(self._elements)
True
(Pdb) np.any([np.all(i==o) for i in self._elements])
*** ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

So it failed to do the equality comparison between o and elements in self._elements. As shown in the console output, np.any([np.all(i==o) for i in self._elements]) doesn't work.

I managed to get around this by using:

if o not in set(self._elements):

Similarly for the same line in remove() in the same cbook/__init__.py file.

And also for the line

if thiso == o:

is changed to

if set([thiso]) == set([o]):

Not entirely sure this is the correct way though.

Matplotlib version

  • Operating system: Linux Mint 19.1
  • Matplotlib version: 2.2.3 py27hb69df0a_0
  • Matplotlib backend (print(matplotlib.get_backend())): Qt5Agg
  • Python version: 2.7.17
  • Other libraries: probably not relevant.

Matplotlib installed via conda install matplotlib

@Xunius
Copy link
Author

Xunius commented Dec 24, 2019

Update myself:
I managed to find the trigger:

figure=plt.figure()
nrow=np.ceil(8).astype('int')
ax=figure.add_subplot(nrow, 2, 1)
ax2=figure.add_axes([0.1, 0.2, 0.3, 0.4])

So the key part is nrow which is of type numpy.int64. Casting it to int solves this error.

So is it related to #880 ?

@timhoffm
Copy link
Member

timhoffm commented Jan 5, 2020

This is partly related to #880.

The deeper problem is a not clean parameter handling, for example add_subplot('8', 2.2, 1) is valid. IMHO strings and floats should not be accepted. Not quite sure about np.int64, but I tend to not support them either, because we would have to special-case that to explicitly enable integer-typed numpy scalars. In the rare case the numpy scalars are present, I think it's bearable to cast to int by the user. Of course, this should have a better error message and already error out in add_subplot().

@timhoffm timhoffm changed the title "The truth value of an array with more than one element is ambiguous" error in bubble() function Better argument checking of subplot definition in add_subplot() Jan 5, 2020
@QuLogic QuLogic added this to the v3.3.0 milestone Jun 16, 2020
MichaelGrupp added a commit to MichaelGrupp/matplotlib that referenced this issue Jul 17, 2020
These examples produce a deprecation warning with mpl>3.3.0
Following PR matplotlib#16016, use int instead of strings.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants