arbor-sim/arbor

Improve interface of property wrappers like `membrane_capacitance`.

Opened this issue · 7 comments

There's some stubs like arbor.membrane_capacitance that aren't very Python friendly, to retrieve the value it seems I have to parse their string representations:

>>> x = arbor.membrane_capacitance(1 * units.F / units.m2)
>>> x + 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'arbor._arbor.membrane_capacitance' and 'int'
>>> x * 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'arbor._arbor.membrane_capacitance' and 'int'
>>> int(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'arbor._arbor.membrane_capacitance'
>>> float(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: float() argument must be a string or a real number, not 'arbor._arbor.membrane_capacitance'
>>> dir(x)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> x < 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'arbor._arbor.membrane_capacitance' and 'int'
>>> x >= 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>=' not supported between instances of 'arbor._arbor.membrane_capacitance' and 'int'
>>> float(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: float() argument must be a string or a real number, not 'arbor._arbor.membrane_capacitance'
>>> float(str(x))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: could not convert string to float: 'Cm=1'
>>> float(str(x)[3:])
1.0

There's also arbor.axial_resistivity and probably others. These are returned from decor.paintings() and make it pretty opaque to inspection.

Hi @Helveg,

I'd agree with the API as written here:

x = 42 * U.m2
# Should give an error; numbers are not quantities
y = x + 1 
# Error, wrong unit
y = x + 1 * U.Ohm
# That works, though
y = x + 1 * U.cm2

If you want the magnitude of a quantity, use

x = 42 * U.m2
# as currently set
x_m = x.value
# safer: force your expected unit
x_m = x.value_as(U.cm2)

x.value and x.value_as solve this, but they're not listed in dir(x) (and so likely also not easily found in other places?), which should list all regularly available members of an object. I'd guess there's an issue with the quantity class's bindings if it has no visible members.

I just checked, at least for v0.10.0 it seems like expected:

In [8]: q = 4 * U.ns

In [9]: dir(q)
Out[9]:
['__add__',
 '__class__',
 '__delattr__',
[...]
 '__subclasshook__',
 '__truediv__',
 'units',
 'value',
 'value_as']

Ok!

Wait, did you check the return value of an arbor function like arbor.membrane_capacitance(1 * units.F / units.m2) the way I did in the original report?

Aha, no I didn't, led astray by the title mentioning 'stubs'. Yes, that interface leaves something to be desired,
you can't even extract the value.

yea my massive text blurb of my interpreter adventures isn't the greatest bug report either ;) sorry :)