Skip to content

Add an __array__ method to NDData - #266

Merged
eteq merged 3 commits into
astropy:masterfrom
mdboom:nddata_array_conversion
Jun 12, 2012
Merged

eteq merged 3 commits into
astropy:masterfrom
mdboom:nddata_array_conversion

Conversation

@mdboom

@mdboom mdboom commented Jun 8, 2012

Copy link
Copy Markdown
Contributor

This makes them easier to plot in matplotlib, such as:

In [1]: from astropy.nddata import nddata

In [2]: x = nddata.NDData([[0, 1, 2], [4, 5, 6], [7, 8, 9]], mask=[[False, True, True], [True, True, False], [True, True, True]])                                                                      

In [3]: from matplotlib import pyplot as plt                                                                                                                                                           

In [4]: plt.imshow(x, interpolation='nearest')                                                                                                                                                         
Out[4]: <matplotlib.image.AxesImage at 0x4911950>

In [5]: plt.show()

Note, this creates zero dependency on matplotlib.

Inspired by the mailing list thread "NDData plot proposal"

…d by the mailing list thread "NDData plot proposal"
@embray

embray commented Jun 8, 2012

Copy link
Copy Markdown
Member

+1 I think this fulfills any near-term desire for easy plotting.
For that matter, I'm kind of surprised NDData didn't already have an __array__, but I haven't been following it very closely.

@eteq

eteq commented Jun 8, 2012

Copy link
Copy Markdown
Member

+1 from me as well. Even if there ends up being a plot method, this is still useful.

@kbarbary

kbarbary commented Jun 8, 2012

Copy link
Copy Markdown
Member

My one concern with this is that it makes NDData look like an array when it is really much more than that. If not told otherwise, it would be tempting for users to end up doing, e.g.,

d = NDData( ... )
...
d[:, 2]

to access the underlying data of an NDData object, rather than using d.data[:, 2]. The two would give different results depending on the mask attribute.

I'm not that familiar with the use of masked arrays, but if a masked array is what you want all the time anyway, here's a possible alternative: change NDData. Rather than having separate data and mask attributes, only have data, which would be a masked array if there is a mask, and a normal ndarray if there is not a mask. (There could still be a mask attribute that points to the mask in the data attribute for convenience.) Then, instead of doing plt.imshow(x, interpolation='nearest') in the example above, one could do plt.imshow(x.data, interpolation='nearest') with the same result, and we would avoid having two similar but different ways to access the data attribute.

Just a thought. Would this cause problems for the use of NDData in other situations? (i.e., not knowing if data is an ndarray or a masked array?)

@eteq

eteq commented Jun 8, 2012

Copy link
Copy Markdown
Member

@kbarbary - we definitely don't want data to be a masked array, because numpy masked arrays have significant performance penalties. Also, they are more limited in what "mask" means than what we intend (in the future) for NDData.

And to clarify, d[:,2] will not give an array out. Definiting __array__ does not automatically make the object into an ndarray - it just tells how to translate the object into an array if the array function is used. So the behavior you're talking about would instead require:

d = NDData( ... )
...
darr = np.array(d)
darr[:, 2]

Which is explicit and makes it clear what's going on. @mdboom suggested this as a solution to the plotting commands, because matplotlib functions like plot convert to arrays if the input is not an array internally, so this makes plot(nddataobj) possible, but without nddataobj being an array.

@eteq

eteq commented Jun 8, 2012

Copy link
Copy Markdown
Member

This does raise a point about this leading to some user confusion, though. @mdboom, can you update this PR to add a little bit to the nddata documentation that gives an example of this, and tries to clarify this point so other users don't make the (very reasonable) assumption @kbarbary did?

@kbarbary

kbarbary commented Jun 8, 2012

Copy link
Copy Markdown
Member

@eteq Thanks for the clarification. I withdraw my comments :)

@mdboom

mdboom commented Jun 8, 2012

Copy link
Copy Markdown
Contributor Author

I agree it's reasonable to elaborate in a comment (or docstring). Will do.

@eteq

eteq commented Jun 8, 2012

Copy link
Copy Markdown
Member

Ok, great - once you've done that, as far as I'm concerned this can be merged.

@astrofrog

Copy link
Copy Markdown
Member

I'm don't have access to my computer right now, but does this actually make sense for anything else than 1 and 2d datasets? If not, should it just be implemented in Spectrum and Image instead?

@mdboom

mdboom commented Jun 11, 2012

Copy link
Copy Markdown
Contributor Author

For plotting images, lines or scatters with matplotlib, yes it only makes sense for 1 and 2d datasets. 3d is less useful -- looking at mayavi2 as an example, there aren't really any functions that take a 3d array as a volume.

In general, though, I think __array__ may be useful (for things other than matplotlib) on any array, and it's certainly simple to do so.

@astrofrog

Copy link
Copy Markdown
Member

Ok - in that case I agree it is useful!

@eteq

eteq commented Jun 11, 2012

Copy link
Copy Markdown
Member

@mdboom - I just generated the docstring on this now, and unfortunately, __array__ does not get documented because it has a leading underscore. Perhaps move part/all of it to the main documentation for the NDData object? It would also be good to include some of it in the docs/nddata somewhere, although I can do that after this is merged, if you'd prefer.

@mdboom

mdboom commented Jun 12, 2012

Copy link
Copy Markdown
Contributor Author

I've moved the __array__ docstring to the class-level docstring as a note.

@eteq

eteq commented Jun 12, 2012

Copy link
Copy Markdown
Member

Alright, looks good - I'll go ahead and merge this, and I'll add a little bit to the docs/nddata.

eteq added a commit that referenced this pull request Jun 12, 2012
@eteq
eteq merged commit 302cb30 into astropy:master Jun 12, 2012
@eteq eteq mentioned this pull request Jun 13, 2012
keflavich pushed a commit to keflavich/astropy that referenced this pull request Oct 9, 2013
@mdboom
mdboom deleted the nddata_array_conversion branch May 21, 2014 23:56
astrofrog pushed a commit to astrofrog/astropy that referenced this pull request Jun 12, 2019
Updating bundled numpydoc version to v0.6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants