[AstroPy] Bug in units decompose()?

Michael Droettboom mdroe at stsci.edu
Tue Jul 1 16:41:01 EDT 2014


On 07/01/2014 04:14 PM, John Quinn wrote:

> Thanks for the responses.
>
> I think I can use to()  to convert to other units and that will do 
> what I want.

If you just want to convert a value to another unit, |to| is what you 
want. |decompose| and |compose| are really more about introspecting the 
structure of units and finding alternate representations.

>
> I was confused after reading the documentation at:
> http://docs.astropy.org/en/stable/units/decomposing_and_composing.html#reducing-a-unit-to-its-irreducible-parts
> and found that:
> > u.J.compose()
> [Unit("J"), Unit("1e+07 erg"), Unit("4.58743e+17 Ry"), 
> Unit("6.24151e+18 eV")]
>
> > u.Ry.decompose(bases=[u.m, u.N])
> 2.17987e-18 m N
>
> > u.eV.decompose(bases=[u.m, u.N])
> 1.60218e-19 m N
>
> but:
>
> > u.erg.decompose(bases=[u.m, u.N])
> gives an error.

erg is not defined in terms of N since it comes from the cgs system. It 
is |cm2 g / s2|. If you want to recompose that back into N, you should 
use |compose|:

|u.erg.compose(units=[u.m, u.N])
[Unit("1e-07 m N")]
|

>
> Similarly, converting to J sometimes works and sometimes doesn't,

Can you elaborate on this? If something is nondeterministic I'd consider 
that a bug.

> and I was very surprised that decomposing
> something in J to J gave an error.

We could probably special case this for decompose just to avoid confusion.

I know this |decompose| vs. |compose| difference is confusing for others 
as well, and your suggestions about how to improve the docs and/or 
naming of things to make it more obvious are welcome. I think we still 
want to have both available, and I don't see an argument for changing 
the behavior (excepting the |X.decompose(bases=[X])| case). |decompose| 
is asking "how is this unit defined from its lower-level parts?", 
whereas |compose| is asking "given all of the units you know about, how 
can this unit be refactored into them?" So |decompose| is useful for 
introspecting the definition of a unit and |compose| is useful for 
searching for alternative representations. And it should be obvious that 
|compose| is a lot more computationally expensive.  Neither are really 
necessary for pure unit conversion, where `to` is your friend.

Mike

>
> Regards,
>
> John
>
>
>
>
>
> On 1 Jul 2014, at 18:43, Erik Bray <embray at stsci.edu 
> <mailto:embray at stsci.edu>> wrote:
>
>> If I understand correctly this is because u.J is already defined in 
>> terms of
>> kilograms, meters, and seconds (actually Newtons and meters).  You could
>> redefine J as a new unit, and then redefine those other units 
>> relative to the new J.
>>
>> But I'm not entirely clear exactly what the intent is here.  I do 
>> agree the
>> error is a little confusing. But not as much if you know that Joule 
>> is already a
>> compound unit, and it's trying to recursively decompose the units 
>> that comprise
>> it in terms of Joules, hence the confusion.
>>
>> Erik
>>
>> On 07/01/2014 11:18 AM, John Quinn wrote:
>>> Hello,
>>>
>>> I am currently evaluating iPython Notebook as a replacement for 
>>> MATHCAD in our
>>> teaching laboratories
>>> and am particularly interested in using the units and constants 
>>> packages of
>>> astropy.
>>>
>>> I have encountered an apparent bug using the units decompose 
>>> function and have
>>> reduced it to the
>>> following example:
>>>
>>>> from astropy import units as u
>>>> u.J.decompose(bases=[u.J])
>>>
>>> which produces the errors given below.
>>>
>>> Similarly, I cannot decompose a unit consisting of 1 u.N * u.m into 
>>> u.J, but
>>> strangely u.Ry.decompose(bases=[u.J]) works fine.
>>>
>>> Am I missing something obvious or is this a bug?
>>>
>>> I am using astropy 0.3.2 with python 3.4.1 on Mac OS X  (anaconda). 
>>> I see the
>>> same on the Linux and Windows
>>> versions and with Python 2.7.7.
>>>
>>> Thanks,
>>>
>>> John
>>>
>>> ---------------------------------------------------------------------------
>>> UnitsError                                 Traceback (most recent 
>>> call last)
>>> <ipython-input-54-3aa084c7cc08>  in<module>()
>>> ----> 1  u.J.decompose(bases=[u.J])
>>>
>>> /Users/quinn/anaconda/envs/py34/lib/python3.4/site-packages/astropy/units/core.py 
>>>  indecompose(self, bases)
>>>    1837
>>>    1838      def  decompose(self,  bases=set()):
>>> -> 1839          return  self._represents.decompose(bases=bases)
>>>    1840      decompose.__doc__=  UnitBase.decompose.__doc__
>>>    1841
>>>
>>> /Users/quinn/anaconda/envs/py34/lib/python3.4/site-packages/astropy/units/core.py 
>>>  indecompose(self, bases)
>>>    1999
>>>    2000          x = CompositeUnit(self.scale, self.bases, 
>>> self.powers, decompose=True,
>>> -> 2001                            decompose_bases=bases)
>>>    2002          if  len(bases)  ==  0:
>>>    2003              self._decomposed_cache=  x
>>>
>>> /Users/quinn/anaconda/envs/py34/lib/python3.4/site-packages/astropy/units/core.py 
>>>  in__init__(self, scale, bases, powers, decompose, decompose_bases, 
>>> _error_check)
>>>    1897          self._powers=  powers
>>>    1898          self._decomposed_cache=  None
>>> -> 1899          self._expand_and_gather(decompose=decompose, 
>>>  bases=decompose_bases)
>>>    1900
>>>    1901      def  __repr__(self):
>>>
>>> /Users/quinn/anaconda/envs/py34/lib/python3.4/site-packages/astropy/units/core.py 
>>>  in_expand_and_gather(self, decompose, bases)
>>>    1959          for  b,  pin  zip(self.bases,  self.powers):
>>>    1960              if  decomposeand  bnot  in  bases:
>>> -> 1961                  b  =  b.decompose(bases=bases)
>>>    1962
>>>    1963              if  isinstance(b,  CompositeUnit):
>>>
>>> /Users/quinn/anaconda/envs/py34/lib/python3.4/site-packages/astropy/units/core.py 
>>>  indecompose(self, bases)
>>>    1837
>>>    1838      def  decompose(self,  bases=set()):
>>> -> 1839          return  self._represents.decompose(bases=bases)
>>>    1840      decompose.__doc__=  UnitBase.decompose.__doc__
>>>    1841
>>>
>>> /Users/quinn/anaconda/envs/py34/lib/python3.4/site-packages/astropy/units/core.py 
>>>  indecompose(self, bases)
>>>    1999
>>>    2000          x = CompositeUnit(self.scale, self.bases, 
>>> self.powers, decompose=True,
>>> -> 2001                            decompose_bases=bases)
>>>    2002          if  len(bases)  ==  0:
>>>    2003              self._decomposed_cache=  x
>>>
>>> /Users/quinn/anaconda/envs/py34/lib/python3.4/site-packages/astropy/units/core.py 
>>>  in__init__(self, scale, bases, powers, decompose, decompose_bases, 
>>> _error_check)
>>>    1897          self._powers=  powers
>>>    1898          self._decomposed_cache=  None
>>> -> 1899          self._expand_and_gather(decompose=decompose, 
>>>  bases=decompose_bases)
>>>    1900
>>>    1901      def  __repr__(self):
>>>
>>> /Users/quinn/anaconda/envs/py34/lib/python3.4/site-packages/astropy/units/core.py 
>>>  in_expand_and_gather(self, decompose, bases)
>>>    1959          for  b,  pin  zip(self.bases,  self.powers):
>>>    1960              if  decomposeand  bnot  in  bases:
>>> -> 1961                  b  =  b.decompose(bases=bases)
>>>    1962
>>>    1963              if  isinstance(b,  CompositeUnit):
>>>
>>> /Users/quinn/anaconda/envs/py34/lib/python3.4/site-packages/astropy/units/core.py 
>>>  indecompose(self, bases)
>>>    1573              raise UnitsError(
>>>    1574                  "Unit {0} can not be decomposed into the 
>>> requested"
>>> -> 1575                  "bases".format(self))
>>>    1576
>>>    1577          return  self
>>>
>>> UnitsError: Unit kg can not be decomposed into the requested bases
>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> AstroPy mailing list
>>> AstroPy at scipy.org <mailto:AstroPy at scipy.org>
>>> http://mail.scipy.org/mailman/listinfo/astropy
>>>
>>
>> _______________________________________________
>> AstroPy mailing list
>> AstroPy at scipy.org <mailto:AstroPy at scipy.org>
>> http://mail.scipy.org/mailman/listinfo/astropy
>
> Dr. John Quinn
> School of Physics
> Science Center North
> University College Dublin
> Belfield, Dublin 4
> Ireland
>
> T: +353-1-7162278
> F: +353-1-2837275
> john.quinn at ucd.ie <mailto:john.quinn at ucd.ie>
>
>
>
>
>
> _______________________________________________
> AstroPy mailing list
> AstroPy at scipy.org
> http://mail.scipy.org/mailman/listinfo/astropy

-- 
Michael Droettboom
Science Software Branch
Space Telescope Science Institute

http://www.droettboom.com

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/astropy/attachments/20140701/228c31e4/attachment.html>


More information about the AstroPy mailing list