The approach I took there was to hierarchically fit out the axes - fit a 1D model to the first axes, take results from that and use them as the inputs to an independent fit to the second axis.
The main benefit of this approach is that it doesn't require changes to any existing code. So, we keep the dominant use-case of single-dimensional data nice and simple.
This works pretty nicely. However:
We're not letting the fit make use of the full dataset to do a joint fit to all parameters at the same time. We're also not doing the second fit with the correct statistics. In practice this is probably more of a conceptual issue than a practical issue (multi-dimensional fitting has been a bit of a niche use-case so far, as has fitting where one cares about the statistics beyond having something vaguely sensible)
It introduces new elements into our ontology. Not a big deal, just a shame. Model2D already does pretty much everything it needs to to be a subclass of Model (just need things like a parameter estimator, but those exist somewhere in the git history as well). A downside of this is that one can't combine Model2Ds with the standard Model helpers / containers. So, one can't trivially rescale the x axes of a Model2D or expand their y-dimension (e.g. fit a two-ion signal to a pair of gaussians).
Let's let the dust settle on the current implementation and then consider doing this "properly". Something like:
[x] Make Model2D a subclass of model and move it to fits.models.containers. This should be doable in a way that maintains full backward compatibility
[x] Make Fitter work with multi-dimensional x-axis data. There are a few things that will need thought here. For example, we currently only have one value for "x-scale" and "y-scale". We've gotten away with that so far, despite supporting data with multi-dimensional y-axes because y-axis scale factors tend to vary less than x-axis ones (we're often fitting probability functions, whereas for x, it's not uncommon to want to fit MHz v degrees). Probably what we should do is: make the models return scale functions as lists in x and y; make the pre-defined scale functions take x/y dim arguments (default to 1) and raise errors if they get the wrong number of dimensions.
[x] Think more carefully about types for x and y. e.g. our type annotations for y aren't great at the moment - we're not clear about where we're squeezing out singleton dimensions. How should we handle single-axis x data? Should we still have a list for consistency and let the models extract the data from it? Or, should the fitter do that? Probably the former for consistency but this will be a bigger breaking change.
Make validators support windowing with multi-dimensional x-axis data
I don't think this is a huge amount of work, but it will need some thought in various places.
https://github.com/OxIonics/ionics_fits/pull/135 was our first foray into fitting datasets with multi-dimensional x axes.
The approach I took there was to hierarchically fit out the axes - fit a 1D model to the first axes, take results from that and use them as the inputs to an independent fit to the second axis.
The main benefit of this approach is that it doesn't require changes to any existing code. So, we keep the dominant use-case of single-dimensional data nice and simple.
This works pretty nicely. However:
Model2D
already does pretty much everything it needs to to be a subclass ofModel
(just need things like a parameter estimator, but those exist somewhere in the git history as well). A downside of this is that one can't combineModel2D
s with the standardModel
helpers / containers. So, one can't trivially rescale the x axes of aModel2D
or expand their y-dimension (e.g. fit a two-ion signal to a pair of gaussians).Let's let the dust settle on the current implementation and then consider doing this "properly". Something like:
Model2D
a subclass of model and move it tofits.models.containers
. This should be doable in a way that maintains full backward compatibilityFitter
work with multi-dimensional x-axis data. There are a few things that will need thought here. For example, we currently only have one value for "x-scale" and "y-scale". We've gotten away with that so far, despite supporting data with multi-dimensional y-axes because y-axis scale factors tend to vary less than x-axis ones (we're often fitting probability functions, whereas for x, it's not uncommon to want to fit MHz v degrees). Probably what we should do is: make the models return scale functions as lists in x and y; make the pre-defined scale functions take x/y dim arguments (default to 1) and raise errors if they get the wrong number of dimensions.I don't think this is a huge amount of work, but it will need some thought in various places.