scipy2013-quantities



scipy2013-quantities

1 1


scipy2013-quantities

A comprehensive look at representing physical quantities in Python (talk at SciPy 2013)

On Github tbekolay / scipy2013-quantities

A comprehensive look at representing physical quantities in Python

Trevor Bekolay University of Waterloo bekolay.org/scipy2013-quantities

Hi, I'm Trevor Bekolay You can follow along with this talk at this URL I want to talk to you about quantities Introduced in python-neo It was good Why aren't they more common?

35.0 m/s

78.2928 mph

What is a physical quantity? Magnitude + units = quantity These two quantities are the same How can you treat them the same in your code?

tbekolay/pyconca2012

Famous Mars Climate Orbiter example Crashed into the surface of Mars because of force units (pounds vs Newtons) * Tracking units is important!

Packages

There are lots of packages out there Most common feedback I received: "Did you get x package?"

Packages

I couldn't get all of them working But we still have 12 Why 12? Different use cases?

Why?!

  • Making a quantities package is easy
  • Making a good quantities package is hard

Implementation

Container

class Quantity(object):
    def __init__(self, magnitude, unit):
        ...

Subclass

class Quantity(numpy.ndarray):
    def __new__(cls, ...):
        ...
To clarify about implementation, this is what I mean If you want pure speed and dimensional analysis check out numericalunits * Or check it out anyway, it's neat

Wrapping functions

from scipy.optimize import fsolve

CA0 = 1 * u.mol / u.L
CA = 0.01 * u.mol / u.L
k = 1.0 / u.s

def func(t):
    return CA - CA0 * np.exp(-k * t)

tguess = 4 * u.s
print fsolve(func, tguess)
from scipy.optimize import fsolve as _fsolve

def fsolve(func, t0):
    # units on initial guess, normalized
    tU = t0 / float(t0)
    def wrapped_func(t):
        return float(func(t * tU))

    sol, = _fsolve(wrapped_func, t0)
    return sol * tU

Thanks John! (jkitchin.github.io/blog)

xkcd on standards There are lots of use cases This comic is maybe why there are so many packages * Let's avoid making our own for now
Nameastropy.unitsdimensions.pydimpyipython-physicsmagnitudenumericalunitspintpiquantquantitiesscimathSP.PhysicalQuantitiesunumImplementation LOC First release Most recent release PyPI Container 3448 2013-01 2013-05 astropy Container 403 2010-07 2010-07 Container 1900 2008-08 2008-08 Container 640 2011-10 2013-03 Container 483 2010-05 2010-05 magnitude Unique! 270 2012-07 2013-06 numericalunits Container 2914 2012-07 2013-05 pint Subclass 5888 2008-05 2008-05 piquant Subclass 7030 2009-10 2011-09 quantities Subclass 4488 2009-03 2013-03 scimath Container 486 2005-12 2012-10 Container 778 2000 2010-06 unum
First, let's get to know these libraries Take some of these things with a grain of salt, but sometimes good to know

What should I use?

tbekolay/quantities-comparison

What should I use, given my use case I've quantified/codified this in this repository (and this talk) Please add your own use cases Maybe there will always be a best choice (fingers crossed)

My use case

  • Time-series data
  • Not mixing units often
  • Transparent, except errors
My needs are pretty minimal I mainly am manipulating time-series data * I just want to be able to write code such that it works whether my time-scale is seconds, milliseconds, whatever

My criteria

NumPy compatibility Simple syntax Low overhead So, these are my criteria We'll go into more detail soon

Syntax

Creating a quantity

Multiply magnitude by unit
length = 5.0 * q.meter
Quantity constructor with unit argument (string or unit)
length = q.Quantity(5.0, units='meter')
length = q.Quantity(5.0, units=q.meter)
Nameastropy.unitsdimensions.pydimpyipython-physicsmagnitudenumericalunitspintpiquantquantitiesscimathSP.PhysicalQuantitiesunummake print multiply 5.0 m constructor Q(5.0, 'm') multiply 5.0 m constructor 5 m constructor 5.0000 m multiply 10.1663291883 multiply 5.0 meter multiply 5.0 m multiply 5.0 m constructor 5.0 constructor 5.0 m multiply 5.0 [m]

Compatibility

NumPy magnitudes

length = np.ones((3, 3)) * q.meter

length = q.Quantity(np.ones((3, 3)),
                    units='meter')
length = q.Quantity(np.ones((3, 3)),
                    units=q.units.meter)
Nameastropy.unitsdimensions.pydimpyipython-physicsmagnitudenumericalunitspintpiquantquantitiesscimathSP.PhysicalQuantitiesunumprint shape [ 5. 10.] m Q([5.0, 10.0], 'm') [ 5. 10.] meter (2,) [5.0, 10.0] [ 5. 10.] m (2,) [ 5. 10.] (2,) [5.0, 10.0] m [5.0, 10.0] [m]

Python operators

  • Unary (e.g., -length)
  • Binary (e.g., length * other_length)
    • length and other_length have same units
    • length and other_length have compatible units
    • length and other_length have different units
Nameastropy.unitsdimensions.pydimpyipython-physicsmagnitudenumericalunitspintpiquantquantitiesscimathSP.PhysicalQuantitiesunumabs neg pos

Nameastropy.unitsdimensions.pydimpyipython-physicsmagnitudenumericalunitspintpiquantquantitiesscimathSP.PhysicalQuantitiesunumadd div eq floordiv ge gt le lt mod mul ne pow sub truediv
Binary operators, same units

Nameastropy.unitsdimensions.pydimpyipython-physicsmagnitudenumericalunitspintpiquantquantitiesscimathSP.PhysicalQuantitiesunumadd div eq floordiv ge gt le lt mod mul ne pow sub truediv
Binary operators, compatible units

Nameastropy.unitsdimensions.pydimpyipython-physicsmagnitudenumericalunitspintpiquantquantitiesscimathSP.PhysicalQuantitiesunumadd div eq floordiv ge gt le lt mod mul ne pow sub truediv
Binary operators, different units

Speed

astropy.unitsdimensions.pydimpyipython-physicsmagnitudenumericalunitsSP.PhysicalQuantitiespintpiquantquantitiesscimathunum-1200.980.991.000.990.980.990.990.990.990.990.990.9920.001.5320.002.371.370.912.4220.001.0012.622.721.562.912.24-1.003.021.890.923.143.501.012.191.2220.00makeopsufunc

What should I use now?

  • For me, quantities

tbekolay/quantities-comparison

Ideas

Funnel development to one package
  • Should be easy to wrap a function
Make a fully wrapped version of NumPy
  • import numpy_quantities as np
Implement units support in NumPy

bekolay.org/scipy2013-quantitiestbekolay@gmail.com

So what should you use? For my use case, quantities works Plus I have to use it But I'm more convinced now that it's a good idea