Skip to content

Conversation

@eteq
Copy link
Member

@eteq eteq commented Feb 19, 2013

(Note that this is based on #793, so only the last commit is unique to this PR)

This makes the change of converting Distance objects in coordinates to subclass from Quantity. They already use the same internal naming scheme (_value and _unit), so no substansive changes are needed. As @astrofrog mentions in #793, though, this does mean Distance picks up the methods from Quantity.

An alternative approach (which wouldn't actually be that much more work) would be to drop the Distance class completely, and just require a Quantity that is a length. I'm mildly against this, because the current API is slightly more convenient - d.kpc is easier than d.to('kpc').value. Also, with a Distance class, we can have the initializer that allows providing a z, and hopefully in the near future, distmod (and similar acessors). With a raw Quantity that's not possible.

This was referenced Feb 19, 2013
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be checking that the quantity's unit is in fact a length? (i.e. is_equivalent(u.m)?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, definitely, good point! Will send up a fix for this shortly.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, no it's in there already, just further down - see line 101.

I'll add a test for it, though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh -- great!

@eteq
Copy link
Member Author

eteq commented Feb 22, 2013

Given that #793 was merged by not addressing what's here, I suppose we should revisit @astrofrog's comments: he brought up a concern that this adds functionality to Distance in the form of the various Quantity methods.

I think this is not a problem. The point of having a Distance class is that it provides a few convinience properties that simplify using a distance in the context of a coordinate. That is, it has accessors like pc and Mpc that give the value in those units, as this is a common thing someone might want. I could see the argument that these are redundant with q.to(u.pc).value and the like, but if someone really feels strongly about it, I would prefer to drop the special accessors and make it more like Quantity, rather than leaving Distance sparate.

Once this is resolved, I also plan to add support for distance modulii in a similar way to how z is currently handled - this is something I've already found myself wanting, and it's pretty easy to implement. (This, like the current z, would not go away even if we removed the pc et al. accessors, because it's not a simple to scaling).

@eteq
Copy link
Member Author

eteq commented Feb 22, 2013

Oh, and @mdboom @adrn - do you have any opinions on @astrofrog's concerns here?

@adrn
Copy link
Member

adrn commented Feb 23, 2013

I'd say drop the special accessors...

@eteq
Copy link
Member Author

eteq commented Feb 26, 2013

Another thought occurred to me in the on-list discussion of __astropy_XX__ methods - that might be a better solution here. That is, we could leave Distance as it is, but implement __astropy_quantity__, so that Quantity(somedist) gives out a Quantity object.

@adrn
Copy link
Member

adrn commented Feb 27, 2013

Just throwing out another crazy idea here...and this really is crazy, but here it goes.

We could also standardize single-unit Quantity objects to allow dot notation accessors for any equivalent units. So:

>>> q = 15.6135*u.m
>>> q.micron
<Quantity 15613500.0 micron> (or just the value?)
>>> q = 11.4512*u.s
>>> q.year
<Quantity 3.62874381364e-07 yr>

This would require some restructuring or namespace hacking...

@mdboom
Copy link
Contributor

mdboom commented Feb 27, 2013

It is a crazy idea, but I actually like it. I'd want to think about how best to implement it. I wouldn't want to just slap a __getattr__ on there, because that doesn't work well with IPython autocompletion. So we'd have to generate the options in advance, but listing all equivalent units can be a little slow. Some sort of caching might be in order -- but that could be problematic if the user extends the set of units later on. Will have to think on it, but I really like the idea in principle.

@embray
Copy link
Member

embray commented Feb 27, 2013

I've been feeling like Units really need a closer tie to the physical units that they represent (even for compound units). Then it would be much faster to generate a list of equivalencies because there would just be a registry of all 'length' units and such. That said, that may be easy enough for things like length, time, and mass. But I could see it getting hairy pretty quickly--it's a pre-baked idea.

@eteq
Copy link
Member Author

eteq commented Feb 27, 2013

I also like @adrn's "crazy" idea. Then we could put the extra things like Distance.z and Distance.distmod in a Quantity subclass and they would be fully consistent with everything else.

@mdboom - perhaps the thing is to generate the cache in Quantity.__dir__(), but support Quantity.__getattr__ even if the cache hasn't been built - then you can do e.g. q.m cheaply even if the cache hasn't been built, but you only have to build it when you try to do IPython tab-completion (and a delay there is more OK because it's interactive, anyway). It might also be nice to have a way to pre-compute the cache for an object like Distance where we know it's always a length.

Another question, though: would q.m give a Quantity object, or the value of that Quantity in meters? The former is @adrn's example, but the latter is how Distance and Angle currently work. That's a subtle distinction from the current API...

@mdboom
Copy link
Contributor

mdboom commented Feb 28, 2013

I'm just thinking this through, but I think I prefer these new "magical" properties to return the value of the quantity in the requested unit. In that sense, I think of q.m to be a peer to q.value in a sense (it's another way of getting a value out, and in many ways is safer than value alone because the desired unit is explicit). If the user really wants another Quantity object, they can always use Quantity.to().

Thinking through this further, I was concerned about the lack of equivalency support in this interface. But I think there are some obvious places where we would want it to be "automatic", and in other cases, the user will just have to use to() directly. For example, if we ever wanted to include a Wavelength class for handling spectral stuff, that might have a built-in equivalency and allow one to convert between nm and Hz etc., but the Distance class would not. Does all that make sense?

If there's agreement that this would be nice, I can go ahead and work up a PR for @adrn's idea.

@astrofrog
Copy link
Member

👍 to these properties returning values

@adrn
Copy link
Member

adrn commented Feb 28, 2013

I like it! I thought about this a bit and I agree with @mdboom on returning values.

@eteq
Copy link
Member Author

eteq commented Feb 28, 2013

👍 to @mdboom's idea from me.

Lets leave this PR open until that is implemented then, and I can rebase this once that's done to remove the "special" accessors that will become redundant.

Regarding equivalencies, it's been on my to-do list to add an option to Quantity to give it a list of equivalencies it stores and uses when you try to do Quantity.to - so once that's in, this accessor could have equivalencies, too.

@mdboom
Copy link
Contributor

mdboom commented Feb 28, 2013

@eteq: #837, which adds conversions as attributes on Quantity objects, also (by necessity) added what you proposed: storing an equivalency list with the quantity. In this case, it's set using the Quantity constructor, but I could imagine Quantity subclasses, such as Wavelength setting it to something useful by default.

@eteq
Copy link
Member Author

eteq commented Feb 28, 2013

Ah, great, guess I'll remove it from my todo list, then!

mdboom added a commit to mdboom/astropy that referenced this pull request Apr 22, 2013
Quantity that allow the user to easily convert to other units.

This involved add a more complex UnitRegistry class, that also keeps
a dictionary of all registered units sorted by their physical
type.

From this new registry, a `compose` can also limit the set of units
that it needs to search through for a match, making it faster, so
this PR has the added bonus of being a performance improvement.
@mdboom
Copy link
Contributor

mdboom commented Jul 26, 2013

Now that #929 is done, unfortunately this probably will no longer works. Once #1006 (which makes Angle a subclass of Quantity) that should light the way to doing the same for Distance. (This is probably all obvious to those involved, just notating it for posterity).

@eteq
Copy link
Member Author

eteq commented Aug 2, 2013

@mdboom and/or @astrofrog - I'm trying to pick out the parts of #1006 that need to be "translated" here - it looks to me like the methods that need to be overridden are __quantity_view__, __quantity_instance__, and __array_wrap__, and __new__, is that right? (and maybe arithmetic operations)

@mdboom
Copy link
Contributor

mdboom commented Aug 2, 2013

@eteq: Yes. You may not need to do array_wrap if you don't need to add any extra attributes. The Angle class does it so it can limit the angles to the bounds, and then set the new values and bounds. If Distance doesn't have any members beyond what Quantity has, it might not be necessary.

@eteq
Copy link
Member Author

eteq commented Sep 20, 2013

I'm going to just close this and open a new one, because it's completely different.

@eteq eteq closed this Sep 20, 2013
@eteq eteq mentioned this pull request Sep 20, 2013
@eteq eteq deleted the distance-to-quantity branch May 3, 2015 17:18
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