Skip to content
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

Dealing with nested lists of quantities #7341

Open
keflavich opened this issue Mar 30, 2018 · 6 comments
Open

Dealing with nested lists of quantities #7341

keflavich opened this issue Mar 30, 2018 · 6 comments

Comments

@keflavich
Copy link
Contributor

I often end up with individual quantities that I want to stitch together into arrays. For example:

longitudes = [1,2,3]*u.deg
lonmin,lonmax = longitudes.min(), longitudes.max()
# reconstituting these into an array works:
lonminmax = u.Quantity([lonmin, lonmax])

However, if I have nested lists, we get ValueError: setting an array element with a sequence. shows up

longitudes = [1,2,3]*u.deg
latitudes = [-1,0,1]*u.deg
lonmin,lonmax = longitudes.min(), longitudes.max()
latmin,latmax = latitudes.min(), latitudes.max()
# reconstituting these into an array does not work:
extrema = u.Quantity([[lonmin,lonmax],[latmin,latmax]])

Is there a better approach than just looping over each individual value? I don't like the approach of:

extrema = u.Quantity([[lonmin.to(u.deg).value, lonmax.to(u.deg).value],
                                   [latmin.to(u.deg).value, latmax.to(u.deg).value]], u.deg)

because it's tedious and inflexible.

@pllim
Copy link
Member

pllim commented Mar 30, 2018

This works but it is not super elegant either.

>>> u.Quantity(list(map(u.Quantity, [[lonmin,lonmax],[latmin,latmax]])))
<Quantity [[ 1.,  3.],
           [-1.,  1.]] deg>

@mhvk
Copy link
Contributor

mhvk commented Apr 1, 2018

It might work to rework the whole is-this-a-list-of-Quantity check currently in the initializer and instead replace a failure in the np.array call with something like:

# make an object array full of Quantity.
extrema = np.array([[lonmin,lonmax],[latmin,latmax]], dtype=object)
# Get them all to the same unit, makes object array of floats.
conv = np.frompyfunc(lambda x: x.to(u.deg).value, 1, 1)
# u.Quantity implicity converts to float; reassign unit.
u.Quantity(conv(extrema), u.deg)
# <Quantity [[ 1., 3.],
#            [-1., 1.]] deg>

@mhvk
Copy link
Contributor

mhvk commented Apr 12, 2021

Looking over old issues: this one should now be solved, if one uses np.block: continuing from the example on top,

In [17]: longitudes = [1,2,3]*u.deg
    ...: lonmin,lonmax = longitudes.min(), longitudes.max()
    ...: 

In [18]: np.block([lonmin, lonmax])
Out[18]: <Quantity [1., 3.] deg>

So, closing!

@mhvk mhvk closed this as completed Apr 12, 2021
@keflavich
Copy link
Contributor Author

The original syntax is still not supported, though, right? Can the quantity initializer not use block internally instead of leaving it to the user to figure out? (I've never heard of np.block before today)

@mhvk
Copy link
Contributor

mhvk commented Apr 12, 2021

Yes, perhaps instead of our custom code that goes through the list it could just call np.block. Let me re-open the issue...

@mhvk mhvk reopened this Apr 12, 2021
@mhvk
Copy link
Contributor

mhvk commented Apr 12, 2021

p.s. np.block was added in numpy 1.13 - it is quite neat, as it allows stacking of all types of shapes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants