Skip to content

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

Closed

Description

@Xunius

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

Activity

  1. Xunius commented on Dec 24, 2019

    @Xunius
    Author

    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 ?

  2. timhoffm commented on Jan 5, 2020

    @timhoffm
    Member

    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().

  3. 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()`[/+] on Jan 5, 2020
  4. added this to the v3.3.0 milestone on Jun 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions