Skip to content

Problems with basing CartesianPoints on plain 3xN Quantity arrays #1850

Closed

Description

@mhvk

While looking at the test cases for Coordinates to find out why changes to Quantity I made caused problems (#1848), I noticed this in test_distance.py:

    #always preserve the CartesianPoint's units
    c5 = 3 * u.pc + c
    assert c5.unit == c.unit

which is really odd physically: what coordinate should the 3 pc be added to?

This brought home something I worried about while looking for the problems: by using a 3,N array, how can CartesianPoints protect against unphysical mixing of x, y, and z? Or ensure that methods such as np.mean work only work along relevant axes?

Easiest may be to behave more closely to the SphericalCoordinatesBase and just have x, y, and z Quantity arrays internally, but if they are combined in a single array, my suggestion would be to use a record array as the basis instead (with dtype=[('x', 'f8'), ('y', 'f8'), ('z', 'f8')]). In either case, one needs to override methods for the relevant functions.

Activity

  1. embray commented on Dec 2, 2013

    @embray
    Member

    On the question of np.mean, one can already use the axis= argument to specify which axis to take the mean along. Or if you just want the mean of one coordinate you can take the mean of a slice. But I agree it's not a bad idea to use a record array. Not sure how that works with Quantities but it should be okay in principle...

  2. mhvk commented on Dec 2, 2013

    @mhvk
    ContributorAuthor

    @embray - indeed, the current implementation does not prevent one from doing the right thing (though one has to keep remembering the order in the array), but ideally it should prevent one from doing something as unphysical as the test case... Fortunately, it does seem Quantity is quite happy with record arrays (though perhaps subclassing from Table is not completely crazy either; that way spherical coordinates could have the same structure (three columns as well, but with different units).

  3. eteq commented on Dec 12, 2013

    @eteq
    Member

    @mhvk - there are three reasons for this that I remember off the top of my head:

    1. Storing it this may means that no conversion is necessary to do the large number of matrix operations required for coordinate transformations. My tests indicated that this was a major performance gain over breaking into separate x, y, z arrays and re-forming them every time, at least for some array sizes.
    2. This preserves the normal numpy array-broadcasting behavior: if c in the above example is a 3x1 array, it's the same as offsetting the origin by that vector. With a record array form, you'll always have to completely re-build the array instead of letting numpy optimize this.
    3. It's easier to implement and maintain because then all the normal numpy and Quantity beahvior just transfers over. Although I do recognize your point is that sometimes this is a bad thing if the behavior seems not as applicable. To me consistency makes things like this easier to understand, and therefor has a slight advantage over it being "exactly right". But that's all pretty vague, so there's definitely room for debate and/or change.

    One other thing: it may be that this should be part of the upcoming new coordinate API/APE (it's been a bit delayed because I decided I should do an APE on the topic at the same time). CartesianPoints will probably be something of a prototype for other similar classes there, so perhaps that context will help clear some of this up.

  4. mhvk commented on Dec 12, 2013

    @mhvk
    ContributorAuthor

    @eteq - Indeed, for performance reasons you're almost certainly right that separate arrays is a bad idea. recarray is much less bad, since one can quickly change it to a normal array just by doing the appropriate view. But your other points are good too, and probably it is indeed best to think of this more in the larger context. In this respect, one possible plus for the recarray is that it may be substantially easier to share code with SpericalCoordinates (which might have an 'r','phi','theta' recarray inside).

  5. eteq commented on Dec 12, 2013

    @eteq
    Member

    @mhvk - this is a good idea that definitely bears more thought... I'll have to do some performance tests to see how much (if any) of a penalty `recarr.view(dtype=float).reshape(...)`` has. Will definitely want to think more about it for the upcoming API!

  6. astrofrog commented on May 9, 2014

    @astrofrog
    Member

    @mhvk @eteq - is this still relevant post-APE5?

  7. added this to the Future milestone on May 9, 2014
  8. mhvk commented on May 9, 2014

    @mhvk
    ContributorAuthor

    @mhvk @eteq - is this still relevant post-APE5?

    No, it isn't; feel free to close (am offline now; sending a reply e-mail just so this doesn't get forgotten).

  9. eteq commented on May 9, 2014

    @eteq
    Member

    Agreed, so I'll close this just so we don't forget to do so after merging APE5.

  10. removed this from the Future milestone on May 9, 2014
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

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions