← Back to team overview

python-quantities-developers team mailing list archive

Re: some ideas on compound units and canceling

 

Lets make it a habit to post in-line or below the previous exchange, it
makes it easier to follow the conversation...

On Sun, Jan 4, 2009 at 6:24 AM, John Salvatier <jsalvati@xxxxxxxxxxxxxxxx>wrote:

> On Sun, Jan 4, 2009 at 3:06 AM, John Salvatier <jsalvati@xxxxxxxxxxxxxxxx>wrote:
>
>> I have been thinking a bit about how we should handle units that the user
>> wants to be compound (like m**2/m**3, which currently reduces to 1/m) and
>> units of the same "type" (like J and BTU).
>
>
I wrote up a blueprint yesterday for a CompoundUnit convenience function,
implemented it and pushed it to launchpad last night. The use is simple:

area_per_unitvolume = CompountUnit('m**2/m**3')

It automatically determines the reference quantity from the definition
string, and it also automatically encloses them in brackets. Thats all it
does, its just a convenience class, really.


> I think ideally, the quantity 10.0 * J/BTU (it currently stays as J/BTU)
>> should come out as dimensionless under most circumstances, but there should
>> be some way to force it to stay as a compound unit.
>>
>> Here is one way we could deal with this:
>>
>> Units which have exactly the same base type (like J and BTU) should cancel
>> normally, but any quantity/dimension can be told to be "static" which makes
>> it not cancel unless forced to do so. The .static property would be used
>> when creating a compound unit. I envision something like this:
>>
>> kPa * L / J     ->     kPa * L / J
>>
>> but
>>
>> J/BTU     ->      (dimensionless)
>>
>> but
>>
>> J.static/BTU.static     ->      J/BTU
>>
>> but
>>
>> (J.static/BTU.static).simplified     ->      (dimensionless)
>>
>> Creating compound units would be done like: compoundUnit = CompoundUnit (
>> (km**2).static/(m**3).static)
>>
>

I want to keep the interface for Quantities simple and compelling. I dont
understand how static would work, it looks like a whole new ndarray subclass
with different rules for combining dimensionalities. I dont like the
approach though, its not intuitive.


> We might also think about automatically simplifying any unit group that
>> comes out dimensionless (kPa * m**3/J      ->      (dimensionless) but
>> kPa * m**3/ ( J/m)      ->      kPa * m**3/ ( J/m) ) . However, I suspect
>> this might be too confusing.
>>
>
I think consistency is very important. Automatically simplifying only in
cases where the result would be dimensionless is too arbitrary.

Some other ideas:
>> 1) Instead of using the .static property, we could have extra units like
>> BTU_ and J_ etc. that would behave statically (not reduce unless forced) and
>> use most of the above
>
>
I used to have such animals in Quantities, and opted to remove them to make
the the package less confusing to the user, and to the maintainer. The
implementation is much simpler now, I would rather not add a second
definition that behaves differently.

2) Instead of the above, we could parse a string so that creating a would
>> work like this: compoundUnit = CompoundUnit ("km**2/m**3")
>
>
You should keep your branch up to date :)


> 3) Or we could simply use the existing framework; have the user name a unit
>> and give it a reference quantity: compoundUnit = UnitQuantity ("km**2/m**3",
>> km**2/m**3).  We could add an argument that tells the quantity it is a
>> compound unit so that uses parentheses when it writes it out. I suspect this
>> may end up being the simplest solution.
>
>
I agree. The current implementation is sort of a combination of 2) and 3).


> 4) We could also change around quantities so that units are not reduced at
>> all except when they are printed out (so m/m gets stored as m/m but is
>> reduced when printed out). This would allow us to simply print out compound
>> units as they are actually stored. However, I suspect this would be very
>> awkward.
>>
>
I don't see what would be gained with this approach. I would rather not go
this way, though.


> Tell me what ideas you think are good or bad.
>
>
I appreciate all ideas, as long as they are contributed in good faith. Its a
difficult issue, figuring out what a package should do in such
circumstances.

My opinion has changed over the last four months, and now I think that a
successful package for dealing with physical quantities needs to be
intuitive, capable, consistent, and simple. To me that means that it should
simply give the user what they asked for, this avoids all kinds of
ambiguities. The simplified representation is easily accessible to the user,
so lets not worry about doing so automatically.

Two more potential models (I think I went a little overboard thinking about
> this):
>
> 1) Have a function that takes the different parts of a compound unit as
> separate positional arguments and then puts them together into a compound
> unit: compoundUnit = CompoundUnit( km**2  ,   m**-3) would print out as "
> (km**2/m**3) "
>

This is similar to 2) and 3), I think.

>
> 2) have a special unit called "compound" which would be placed on the far
> left hand side of a unit quantity and would have a flag that would prevent
> units multiplied with it from reducing. So to create a compound unit, one
> would write:  compoundUnit = UnitQuantity( compound * m**2 / m**3 ). The
> drawbacks to this model is that it is sort of a novel mechanism, so it may
> confuse people and that the syntax is very specific, the "compound" must be
> placed at the very left of the reference quantity and cannot have any
> parentheses in it.


I think what is in place is the most intuitive from both the users and the
developers perspective, and its easy to maintain. I think an important part
of getting serious consideration from the numpy or scipy folks is having a
simple design that anyone with an hour or two of spare time can grok (I'm
planning on discussing this at length in the documentation).

Finally, I'm not paid to work on this project so I want to keep it easy and
pleasurable to maintain.

Darren

References