UnitfulLsqFit

This is not registered, in part because I think there are features in LsqFit.jl that I haven’t implemented an interface to yet, and in part because I wanted to know if anyone else wants this before I polish it further than I need for my personal use.

UnitfulLsqFit

Has this ever happened to you? You’re doing some physics in Julia, and enjoying the fact that you don’t have to keep track of your own units with Unitful.jl. You plot your velocities against your times (simple, thanks to UnitfulRecipes.jl) and notice a pattern that you wish to explore numerically. So you fire up LsqFit.jl and ask it to fit a curve. Chaos ensues:

ERROR: MethodError...

oh great, now I have to convert my pretty unitful vectors to float ditto

julia> t_stripped = t / u"s" # this should do it. Or is there a reason I should be using `ustrip`? Panik...

Okay, now I have my fit, but what do these parameters mean? I better convert back to those units I removed before. This should be possible to automate…

Well it happened to me. Here’s my latest addition to the Unitful toolbox: UnitfulLsqFit.jl! It extends the curve_fit function from LsqFit.jl to accept, and treat correctly (I think), Unitful quantities. It’s the one piece that was missing for me to go fully unitful on everything.

fit = curve_fit(model, t, v, p_0) # kalm

See a slightly more in-depth example in the docs.

Docs

https://gustaphe.github.io/UnitfulLsqFit.jl/dev/

Repo

9 Likes

I wonder if it might make sense to have a lightweight “AbstractUnitful” package that only defines the abstract types related to units and functions like ustrip. That way, packages could add unit compatibility without adding the full Unitful to their deps.

So basically the same successful approach as with Recipes, Adapt and ChainRulesCore. Units are a very fundamental concept, after all.

4 Likes
1 Like

I don’t think that pull request in the current form does what Oliver suggested. It just moves most of Unitful to UnitfulBase

2 Likes

It seems to me that it still makes sense to have all seven SI base units in Unitful.jl, since most other units in common use are derived from them.

I would totally use a unit-aware LsqFit! It would not only be super convenient for daily work, but also wonderful for teaching: when calculating things manually, students are expected to keep track of units to present a meaningful result at the end, so why expect less of a program?

A related idea: it would be great if curve_fit() could also accept a vector of Measurements. As it is now, you have to provide a vector of X values, a vector of Y values, and optionally a vector of some kind of uncertainties on the Y values (most commonly std of replicate Y values); but it would be so convenient if you could give it a vector of Y ± Z of type Measurement. As things are now, if you want to, say, plot data points with error bars and also do curve fitting, you have to keep around the original vectors of Y values and their uncertainties in addition to the vector of Measurement, even though they are the same data, because LsqFit doesn’t understand Measurement types.

Finally, it seems like curve_fit() could work seamlessly with both units and uncertainties, since you can already do this and get a result that makes sense:

julia> using Unitful
julia> using Measurements
julia> x = [ i * u"m" ± j * u"cm" for (i, j) in zip(1:10, 1:10) ]
10-element Vector{Quantity{Measurement{Float64}, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}}}:
 1.0 ± 0.01 m
 2.0 ± 0.02 m
 3.0 ± 0.03 m
 4.0 ± 0.04 m
 5.0 ± 0.05 m
 6.0 ± 0.06 m
 7.0 ± 0.07 m
 8.0 ± 0.08 m
 9.0 ± 0.09 m
 10.0 ± 0.1 m