-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Fix unit support with plot
and pint
#4803
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
Conversation
👍 Just an aside, I've been working on |
I am poking the same section of code in #4787 to pull out the index if it exists. |
This is nice idea, but it would almost certainly break existing code using To my surprise, this actually does work for pandas Index and Series objects:
But there are other duck array types that can't handle this operation, even though they implement
h5py datasets are another example, off the top of my head. To be fair, this tradeoff might be worthwhile. In many cases, plotting duck arrays already fails, and this may not be a feature that matplotlib ever intended to support. But it's certainly worth considering the broader question of what classes of duck array types matplotlib intends to support as input to plotting functions. In many cases, calling After all that discussion, it occurs to me that a better approach here would be simply to explicitly look for types that have been registered with matplotlib's unit system rather than to whitelist all objects with a |
Well |
4cb45dc
to
20cb005
Compare
I've updated this to have more thorough checks. The bonus here is that it seems to eliminate any changes to the examples, though I won't completely trust that until Travis finishes... |
''' | ||
Converts a sequence of less than 1 dimension, to an array of 1 | ||
dimension; leaves everything else untouched. | ||
''' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about instead using something like the following?
def asarray_units_okay(x):
if type(x) in units.registry:
return x
else:
return np.asarray(x)
def atleast_1d_units_okay(x);
x = asarray_units_okay(x)
if x.ndim == 0:
x = x[np.newaxis]
return x
I am nervous about preemptively checking all allowed operations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This breaks anything using units that relies upon having atleast_1d
called; this includes the "simple" unit framework in the examples.
Otherwise, the decomposition seems fine.
@tacaswell Any chance we can sneak this in for 1.5? |
Yes, but this is going to conflict with the logic added in https://github.com/matplotlib/matplotlib/pull/4829/files#diff-a7f4f21aa80e975d813bc436acb68d8cL280 I am sure how the discussion with @shoyer ended, it looks like the comment should have been folded as addressed, but is pinned to the documentation? |
I like the preemptive checking better as I think it plays better with some of the label/index related checking else where. Relying on the unit registry also adds a bit more order dependence then is strictly necessary as in most cases the conversion to float for plotting is deferred to draw time where as the proposed alternative method would possibly strip some of the data earlier. @jrevans might have useful thoughts on this as well. |
@dopplershift This needs a rebase now |
There's a rebase on my branch fix-plot-units, but since this PR adds no tests, it's hard to say if the rebase still fixes the original issue. I would recommend adding a test case. |
20cb005
to
7e1f13e
Compare
Rebase done. I agree about the tests, but my problem is that I couldn't readily come up with a good test that didn't involve depending/ingesting |
I can confirm that the "test" I posted at the top works with the rebased branch. I'll take a quick look at a stubbed out "pint" that works for testing. |
7e1f13e
to
ab03007
Compare
Alright, simple test added (and now I know |
remember to white-list the new test file |
@tacaswell huh? |
This is the list of tests that are run by default https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/__init__.py#L1416 (and this is what travis runs) |
fd4f962
to
f2d1e8a
Compare
I don't understand the failures (or at least how they can only fail sometimes):
|
That helpful exception means that there is an import error in |
f2d1e8a
to
03e4cc1
Compare
Thanks, turns out I didn't understand about importing mock. |
This is catching the problems with pint-like libraries who wrap numpy arrays.
Even if the argument to atleast_1d is array-compatible and has sufficient dimensions, it is still converted from its original type to a numpy array. This is overly aggressive for our purposes (especially unit support), so replace the direct call with a helper function that only calls atleast_1d if it's actually necessary.
03e4cc1
to
9b65233
Compare
FIX: unit support with `plot` and `pint`
pint
is a unit support library that wraps (almost) anything with mathematical-aware unit operations. Since it tries to quack like a numpy array, but is not actually an ndarray subclass, this creates problems when thrown into functions likeatleast_1d
.atleast_1d
converts all arguments, regardless of whether they are properly dimensioned, into numpy arrays (or subclasses).Currently,
pint
can't even trigger matplotlib's unit infrastructure, as evidenced by:This example triggers no print statements on master. With these changes, unit support works (I think) properly with
pint
.