Skip to content

Add SOFAUnits, a utilitary lib for unit conversion#622

Merged
hugtalbot merged 15 commits into
sofa-framework:masterfrom
bakpaul:26_07_add_unit_converter
Jul 9, 2026
Merged

Add SOFAUnits, a utilitary lib for unit conversion#622
hugtalbot merged 15 commits into
sofa-framework:masterfrom
bakpaul:26_07_add_unit_converter

Conversation

@bakpaul

@bakpaul bakpaul commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

It has been a looooong time issue for the community : how to deal with units in SOFA. "If I use mm instead of m, what appends ton my Young modulus ?" : heard too many times.

This is a simple utilitary lib that provide a class where you can define the system of parameter that you use, given a set of "primary" units (length, mass and time).

Then, when you need to specify a value that has a certain unit, you just specify the unit you want and the conversion is done automatically for you. For instance :

    SceneUnit = SOFAParameters(s, mm, g) #I know my scene is in mm and in g
    ...
    root.gravity=[0, SceneUnit.convert(-9.81, N/kg), 0]
    ...
    liver.addObject('DiagonalMass', name="Mass", massDensity=SceneUnit.convert(1.0,g/(cm**3)))
    ...
    liver.addObject('TetrahedralCorotationalFEMForceField', youngModulus=SceneUnit.convert(3,kPa),  template="Vec3d", name="FEM", method="large", poissonRatio="0.3",computeGlobalMatrix="0")

And you can also use the 'call' overload

    SceneUnit = SOFAParameters(s, mm, g) #I know my scene is in mm and in g
    ...
    root.gravity=[0, SceneUnit(-9.81, N/kg), 0]
    ...

The usual units for mechanics are given (see units.py). It is really easy to add more, even for "primary" units, e.g. if we want to deal with electricity at one point

A = PrimaryUnit("A")   #ampere

### Derived units
V = kg*m**2*/(s**3*A)  # Volt
C = s*A                # Coulomb
F = C/V                # Farad


## Scaled primary units
mV = ScaledUnit(V, 1e-3)
....

👨 Human made ! The tests have been generated by AI, the rest I did it myself for fun.

@bakpaul bakpaul changed the title Add SOFAUnits, a utilitary lib for unit convertion Add SOFAUnits, a utilitary lib for unit conversion Jul 1, 2026
@damienmarchal

damienmarchal commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Hi @bakpaul,

Thank for the PR and the envy to tackle the issue;
I have a first question, can you elaborate about the why doing our own unit system given there exists already other project doing exactly that ?

Now, taking the assumption that the existing system don't do the job, some specific comment.
The name 'SOFAParameters' suggest that this object has a more general scope that just handling units. According the implementation I don't thing this is the case (i.e it is handling a set of units). To make that explicit I suggest to use a different name, dropping the SOFA prefix and "parameters" which is a programmer's concept. I think that UnitSystem would be a good name as it convey both the idea it stores multiples units... and only that.

The un-conventionnal naming scheme used for "SceneUnit" to hold an instance catched my eye. This makes it looking like a class, and the override of make it call look like a constructor. But a constructor is expected to return an instance of a class, so a SceneUnits not the raw data. This make the API quite confusing in its intent and actions.
If found clearer:

unit_system = UnitSystem(m, kg, N)  # replace SofaParameter()
# and 
unity_system(expr) 

On the PR example, It is not clear the difference between convert and the call of the overload... while the code path look really different. As the function are not documented can you provide more examples and documentation to se can understand the intent.

@hugtalbot hugtalbot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few suggestions to improve the existing example

Comment thread examples/SofaUnitsExample.py Outdated
Comment thread examples/SofaUnitsExample.py Outdated
Comment thread examples/SofaUnitsExample.py Outdated
Comment thread examples/SofaUnitsExample.py Outdated
Comment thread examples/SofaUnitsExample.py Outdated
Co-authored-by: Hugo <hugo.talbot@sofa-framework.org>
@bakpaul

bakpaul commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

@damienmarchal

To answer your first concern, firstly I did it as a first intent as a fun project to tackle during a train trip without really looking around. Then I looked and yes some already exist and are really extensive on their features. I guess the reason nothing has been proposed to this day for the community from us using those libs also come from the fact that they might not be the best suited for our simple case here, the learning curves are just not adapted. So I designed a tool that doesn't do more than what we want. Everything is though around creating your unit system and then convert any units to it. Not any units into any units dealing with affine transformation, imperial system and so on... It is simple, fits our needs, and only depends on math and numpy (only for supporting numpy array, not as a core concept of the lib), and I prefer it like that rather than having yet another dependency.

For your next comment I kind of agree with it. But I added SOFA as prefix just because here we really only expect the user to define mechanical parameters (length, time and mass). So I would call it "MechanicalUnitSystem" and maybe for the base class "UnitSystem".

About convert, I did more modification since this message. Convert really does the conversion for one scalar. The call supports arrays ans uses convert inside of it for each data in the array. So using the convert method is not really the good way to use it.

Comment thread examples/SofaUnitsExample.py Outdated
Co-authored-by: Hugo <hugo.talbot@sofa-framework.org>
@hugtalbot hugtalbot merged commit bf752a5 into sofa-framework:master Jul 9, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants