glue-viz / glue

Linked Data Visualizations Across Multiple Files
http://glueviz.org
Other
744 stars 153 forks source link

Profile fitting plugin interface #287

Closed ChrisBeaumont closed 7 years ago

ChrisBeaumont commented 10 years ago

I'm interested in @keflavich and @astrofrog's thoughts here

I'm working on a spectrum/profile extraction utility in Glue that, among other things, allows users to fit models to profiles. It looks like this currently:

image

I'd like to make it easy for users to plug in their own model fitting code (maybe from astropy, or something homegrown). Here's a possible interface:


class GaussianModel:
    label = "Mixture of Gaussians"
    n_components = ChoiceOption([1, 2, 3], label="Number of Gaussians")
    option_2 = FloatOption(min=0, max=3, label="Option 2")
    option_3 = IntOption(min=0, max=100, label="Option 3")
    fixed_at_zero = BoolOption(label="Fix baseline at 0")

    def fit(x, y, dy, **params):
        ...fit code here...
        predictor = (callable that maps model(x) -> prediction)
        report = "Converted successfully. Mean=1, stdev=3,..."
        return self.fit_result(predictor, report)

Given a class like this, Glue would:

image

I think such a class is simple enough that any python coder could roll their own basic fitting plugin based on an example tutorial. My main questions are:

keflavich commented 10 years ago

This is relatively straightforward, I agree, but still quite a bit of overhead. Long-term, it would be nice if a user could simply define a model function and you'd have a wrapper class to perform introspection on the function to extract parameter names.

The most important options I think you're presently missing are limits on the individual parameters. My preference is to have each parameter have at least 4 user-settable properties: value, upper and lower limit, and "fixed".

I really like having "sliders" to control the various parameters too. That may not be what you're asking though.

I want to have access to the parameters, error on parameters (both to put in tables, in principle) and the full array.

Minor comment on spectrum display: could you make the plot type 'step-filled'? I feel pretty strongly that, because the data points are discrete, it is more honest to show them without interpolation. Also, it makes it easier to display a 'filled' style error bar.

ChrisBeaumont commented 10 years ago

step-filled profiles and option sliders are both good ideas. (What do you mean by filled style error bar?)

Regarding your first point: you could imagine an even simpler interface, like this:

@fit_plugin
def fitter (x, y, dy, n_components=3, baseline_fixed=False):
    pass

That introspects the signature to build a UI. Some drawbacks: 1) I've found I usually want my UI labels to be different (more human/descriptive) than the variable name they correspond to. E.g., how do you specify that baseline_fixed should be presented as Use a fixed baseline? 2) You have to make more guesses about what kind of UI to build. Should n_components be a slider or dropdown? Does it have an upper/lower bound? is it constrained to be one of a few values? What are those values, and what is the default? etc.

One solution is to use the class-based approach above, but make the Option attributes optional and auto-generate them from the fit signature if they aren't present. I prefer that over adding lots of optional kwargs to a @fit_plugin decorator (although you could still have the bare decorator interface to support the example above).

Regarding the comment about constraining the model parameters themselves: I just want to confirm that tweaking this information is something you would want to do interactively, and it is worth spending screen real-estate on? Another approach is to write multiple plugins with different hard-coded sets of constraints. It isn't as flexible, but would be easier to fit onto a widget. But maybe that's too hacky/restrictive.

keflavich commented 10 years ago

Filled style error bars like: this

keflavich commented 10 years ago
That introspects the signature to build a UI. Some drawbacks:
1) I've found I usually want my UI labels to be different (more human/descriptive) than the variable name they correspond to. E.g., how do you specify that baseline_fixed should be presented as Use a fixed baseline?

Good point - this would be great to parse from the docstring! That may well be extremely difficult, though.

2) You have to make more guesses about what kind of UI to build. Should n_components be a slider or dropdown? Does it have an upper/lower bound? is it constrained to be one of a few values? What are those values, and what is the default? etc.

Yes, that's also a real difficulty, and counts as a vote in favor of preferring class-based plugins.

So, I agree with your approach: have the decorator that defaults everything to the least restrictive setting (for example), but have the class interface as a preferred / more flexible one.

keflavich commented 10 years ago
Regarding the comment about constraining the model parameters themselves: I just want to confirm that tweaking this information is something you would want to do interactively, and it is worth spending screen real-estate on? Another approach is to write multiple plugins with different hard-coded sets of constraints. It isn't as flexible, but would be easier to fit onto a widget. But maybe that's too hacky/restrictive.

Yes. And this brings up a new use-case: Say I want to fit a model, subtract it from the data, then fit another model to the residual. That's a perfect case where I'd want to change the restrictions on-the-fly.

The other common use case for restricting fits is if you have, say, a CO spectrum through the Galactic midplane and want to fit 6 gaussians, each restricted to be narrow and limited to a particular velocity range.

Finally, the most important: if you fit one parameter and you like that fit, it's really helpful to fix that parameter but free the others on the fly. This feature is implemented nicely in xspec and was my favorite (and I believe a favorite of many X-ray astronomers).

astrofrog commented 8 years ago

Just as an update on this, @keflavich and I have been working on a more sophisticated spectral viewer in Glue based on pysepeckit: https://github.com/glue-viz/glue-pyspeckit-plugin

astrofrog commented 7 years ago

I think the original intent was this issue was actually implemented as fitter plugins in glue by @ChrisBeaumont - http://glueviz.org/en/stable/gui_guide/spectrum.html#custom-fitting-plugins