Skip to content

Better deal with Numpy array subclasses in methods other than plot and scatter #5896

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
astrofrog opened this issue Jan 21, 2016 · 10 comments
Closed

Comments

@astrofrog
Copy link
Contributor

The plot and scatter methods now deal nicely with Numpy array sub-classes, such as Astropy quantities (which have attached units):

In [1]: from astropy import units as u

In [2]: import matplotlib.pyplot as plt

In [3]: fig = plt.figure()

In [4]: ax = fig.add_subplot(1,1,1)

In [5]: x = [1,2] * u.m

In [6]: y = [3,4] * u.m

In [7]: ax.plot(x,y)
Out[7]: [<matplotlib.lines.Line2D at 0x107f00048>]

In [8]: ax.scatter(x, y)
Out[8]: <matplotlib.collections.PathCollection at 0x107f00ba8>

However, other methods such as axhline and axvline do not:

In [9]: z = 4 * u.m

In [10]: ax.axhline(z)
---------------------------------------------------------------------------
UnitsError                                Traceback (most recent call last)
<ipython-input-10-39d10b51e434> in <module>()
----> 1 ax.axhline(z)

/Users/tom/miniconda3/envs/production35/lib/python3.5/site-packages/matplotlib/axes/_axes.py in axhline(self, y, xmin, xmax, **kwargs)
    744         self._process_unit_info(ydata=y, kwargs=kwargs)
    745         yy = self.convert_yunits(y)
--> 746         scaley = (yy < ymin) or (yy > ymax)
    747 
    748         trans = self.get_yaxis_transform(which='grid')

/Users/tom/miniconda3/envs/production35/lib/python3.5/site-packages/astropy/units/quantity.py in __array_prepare__(self, obj, context)
    344                                      "argument is not a quantity (unless the "
    345                                      "latter is all zero/infinity/nan)"
--> 346                                      .format(function.__name__))
    347             except TypeError:
    348                 # _can_have_arbitrary_unit failed: arg could not be compared

UnitsError: Can only apply 'less' function to dimensionless quantities when other argument is not a quantity (unless the latter is all zero/infinity/nan)

It would be nice to try and make these methods also support Numpy array sub-classes.

@mdboom mdboom added this to the next bug fix release (2.0.1) milestone Jan 25, 2016
@mdboom
Copy link
Member

mdboom commented Jan 25, 2016

I agree it will be nice. This particular case will be tricky -- the view limit object is created before and without any knowledge of the input data datatype...

@bjodah
Copy link
Contributor

bjodah commented Jan 19, 2017

Perhaps not directly related but this issue was the closest I could find:

I'd like axvline to accept numpy array as first argument, along these lines:

In [2]: import numpy as np
In [3]: x = np.linspace(-10, 10); y = np.sin(x)
In [4]: plt.plot(x, y); plt.axvline(x); plt.show()
...
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

now I have to resort to:

In [6]: for _x in x:
   ...:     plt.axvline(_x)
   ...:     

when x is very long I set alpha to e.g. 0.1 (x is not equidistant in that case of course).
Unfortunately this is really slow in matplotlib (when x is a few thousand elements running times
are counted in minutes). Are there any opportunities to make this faster? (or maybe I am approaching this the wrong way?)

@tacaswell
Copy link
Member

@bjodah
Copy link
Contributor

bjodah commented Jan 19, 2017

@tacaswell well kind of, but using ymin/ymax: (-inf, inf) does not work:

>>> import matplotlib.pyplot as plt; import numpy as np;
>>> x = np.linspace(-5, 5); y = np.sin(x); plt.vlines(x, float('-inf'), float('inf')); plt.plot(x, y); plt.show()

(plot shows no vertical lines)

then I need to compute ymin, ymax from the maximum/minimum values of all series which will be plotted later, or use a priori information:

>>> x = np.linspace(-5, 5); y = np.sin(x); plt.vlines(x, -1, 1); plt.plot(x, y); plt.show()

(edit: axvline guarantees to draw the lines across the axes, vlines affects ylim which is not what I want for this particular case).

@tacaswell
Copy link
Member

Use it in conjunction with a blended transform: http://matplotlib.org/users/transforms_tutorial.html#blended-transformations and go from 0 to 1 in axes space.

@bjodah
Copy link
Contributor

bjodah commented Jan 19, 2017

@tacaswell thank you, very neat! For future visitors from e.g. google:

import numpy as np; import matplotlib.pyplot as plt;
import matplotlib.transforms as tf
x = np.linspace(-5, 5); y = np.sin(x); ax = plt.subplot(1, 1, 1);
trans = tf.blended_transform_factory(ax.transData, ax.transAxes)
ax.vlines(x, 0, 1, transform=trans); ax.plot(x, y); plt.show()

... and performance is much better!

@tacaswell
Copy link
Member

that is probably worth an example in the docs. I have seen this question come across multiple times in multiple places.

@QuLogic QuLogic modified the milestones: 2.0.1 (next bug fix release), 2.0.2 (next bug fix release) May 3, 2017
@tacaswell tacaswell modified the milestones: 2.1.1 (next bug fix release), 2.2 (next feature release) Oct 9, 2017
@dstansby
Copy link
Member

axhline/axvline with AstroPy quantities works with astropy/astropy#7037, and I suspect lots of other stuff will start working if that pull request is accepted too.

@github-actions
Copy link

This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

@github-actions github-actions bot added the status: inactive Marked by the “Stale” Github Action label Mar 21, 2023
@ksunden
Copy link
Member

ksunden commented Mar 21, 2023

Closing as the original issue was fixed downstream. There are plenty of areas where units support could be improved in similar ways (and the data prototype work plays into that), but this particular report is no longer a problem, I think

@ksunden ksunden closed this as completed Mar 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants