Skip to content

Allow more complex unit transformation rules #282

@MichaelClerx

Description

@MichaelClerx

This issue has two goals:

  • Currently we assume all unit conversion can be handled by a multiplicative factor cf, we should somehow let that restriction go
  • Pint provides a system where you can create transformations, it'd be good if we could provide support for that, e.g. by letting the user specify a lambda in terms of sympy functions?
#!/usr/bin/env python
import pint

r = pint.UnitRegistry()

r.define('uA=ampere * 1e-6')
r.define('pA=ampere * 1e-12')
r.define('uF=farad * 1e-6')
r.define('pF=farad * 1e-12')
r.define('cm2=centimetre ** 2')
r.define('uA_per_cm2=uA / cm2')
r.define('uF_per_cm2=uF / cm2')
r.define('A_per_F=ampere / farad')

Cm = r.Quantity(12, r.pF)
Cs = r.Quantity(1.1, r.uF_per_cm2)

# Rules
c = pint.Context()
c.add_transformation(r.A_per_F, r.uA_per_cm2, lambda ureg, rhs: rhs * Cs)
c.add_transformation(r.uA_per_cm2, r.A_per_F, lambda ureg, rhs: rhs / Cs)
c.add_transformation(r.uA, r.uA_per_cm2, lambda ureg, rhs: rhs * Cs / Cm)
c.add_transformation(r.uA_per_cm2, r.uA, lambda ureg, rhs: rhs * Cm / Cs)
r.enable_contexts(c)

# Test
x = r.Quantity(1, r.pA)
print(x.to(r.A_per_F))

The above is an example of pint transformations.

There's some subtle gotchas:

# Gotchas
r.disable_contexts()
c = pint.Context()
c.add_transformation(r.A_per_F, r.uA_per_cm2, lambda ureg, rhs: rhs * Cs)
c.add_transformation(r.uA_per_cm2, r.A_per_F, lambda ureg, rhs: rhs / Cs)
f = Cs / Cm
c.add_transformation(r.uA, r.uA_per_cm2, lambda ureg, rhs: rhs * f)
f = Cm / Cs
c.add_transformation(r.uA_per_cm2, r.uA, lambda ureg, rhs: rhs * f)
r.enable_contexts(c)

# Test
x = r.Quantity(1, r.pA)
print(x.to(r.A_per_F))

this will break, because the lambda doesn't store a copy of f, it just grabs an f from the local scope whenever it's used, so both functions actually use the same f. So some tricks needed there (e.g. define a callable class).

But the main thing to figure out is whether we can come up with some cellmlmanip API that can be re-used by FC (Web Lab) and chaste codegen, for specifying rules with lambdas (python lambdas? sympy expressions?) so that conversion of currents is easier

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions