FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

ScalarMappable should copy its input and allow non-arrays · Issue #18841 · matplotlib/matplotlib · GitHub

Repository navigation

ScalarMappable should copy its input and allow non-arrays #18841

Description

Problem

Recently I wanted to draw some colormapped vlines. As LineCollection inherits from ScalarMappable, one can indeed write e.g.

from pylab import *
xs = vals = np.arange(10)
plt.vlines(xs, 0, 1, array=vals)
plt.show()

and get

Unfortunately,

  1. The array kwarg only accepts ndarrays, and not e.g. nested lists: plt.vlines(np.arange(10), 0, 1, array=[*range(10)]) crashes (at draw time, which is even worse) with "AttributeError: 'list' object has no attribute 'ndim'". This is unlike most other Axes/pyplot APIs (e.g. imshow), which happily accept lists (nested/2D lists, for imshow).
  2. The array kwarg is not copied, so later changes to it get reflected back into the artist (i.e. doing vals[5] = 45 after the call to vlines still affects the line colors). Again, this is unlike other Axes/pyplot APIs (e.g. imshow), which insulate the artist from later changes to the input.

Proposed Solution

Make a copy of the input and cast it to arrays. (Well, modulo unit handling...)

Additional context and prior art

Behave like imshow.

Activity

  1. aitikgupta commented on Nov 2, 2020

    Contributor

    I'd love to take this up! :)
    Initial scanning leads to the following points:

    • In case of imshow, _ImageBase class inherits from ScalarMappable, but overrides its set_array function as:
      def set_array(self, A):
      """
      Retained for backwards compatibility - use set_data instead.
      Parameters
      ----------
      A : array-like
      """
      # This also needs to be here to override the inherited
      # cm.ScalarMappable.set_array method so it is not invoked by mistake.
      self.set_data(A)
    • imshow doesn't raise this error as its set_data (called from set_array) copies the original array and checks for numpy casts:
      self._A = cbook.safe_masked_invalid(A, copy=True)
      if (self._A.dtype != np.uint8 and
      not np.can_cast(self._A.dtype, float, "same_kind")):
      raise TypeError("Image data of dtype {} cannot be converted to "
      "float".format(self._A.dtype))
    • In case of vlines, ScalarMappable is inherited again, but there's no overriding its set_array function, which evidently just accepts ndarray:
      def set_array(self, A):
      """
      Set the image array from numpy array *A*.
      Parameters
      ----------
      A : ndarray
      """
      self._A = A
      self._update_dict['array'] = True
  2. aitikgupta commented on Nov 2, 2020

    Contributor

    To solve this, I added set_array to Collection class, overriding it again. It will need some reviews, I'll issue a PR for the same.

  3. added this to the v3.5.0 milestone on May 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL