Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to construct kernels and convolve with data #10

Open
RastislavTuranyi opened this issue Jan 9, 2025 · 6 comments · May be fixed by #39
Open

Add ability to construct kernels and convolve with data #10

RastislavTuranyi opened this issue Jan 9, 2025 · 6 comments · May be fixed by #39
Labels
enhancement New feature or request

Comments

@RastislavTuranyi
Copy link
Collaborator

The input and output of models are specified using the InstrumentModel.input and InstrumentModel.output class variables, but for now these are only integers signifying the number of input/output values. This should be made more specific, since e.g. models can model both E only and q only, both of which would have only one input argument. I believe the previous consensus on improving this was to use a tuple of strings instead.

@RastislavTuranyi RastislavTuranyi added the enhancement New feature or request label Jan 9, 2025
@ajjackson
Copy link
Collaborator

Would it also make sense to include the information in output that the model is returning, e.g., a Gaussian standard deviation or a Lorentzian FWHM?

@RastislavTuranyi
Copy link
Collaborator Author

RastislavTuranyi commented Jan 9, 2025

Yes, this is the point! In fact, now that you mention it, if we use a named tuple instead of a tuple, we should be able to convey not only what is being returned, e.g. sigma, but also the information about the function, i.e. Gaussian.

However, it might also be nice to go all the way and connect this bottommost layer of resolution functions to the next layer up, which calculates the function. If the output is a class in itself, it could serve both as simple information and as a way to do next step of calculations:

>>> tosca = Instrument.from_default('TOSCA')
>>> model = tosca.get_resolution_function('AbINS')
>>> model.output
Gaussian(parameters=['sigma'])
>>> width = model(200)
>>> gaussian = model.output(width)

but how well that works would probably depend on the topmost layer and how it could be connected to that.

Lastly, a maybe not-so-good idea that just occurred to me is that instead of using output the InstrumentModel.__call__ could maybe directly return a Gaussian object (or array thereof). That would probably be difficult to deal with when working with large numpy arrays, though.

@ajjackson
Copy link
Collaborator

ajjackson commented Jan 9, 2025

Probably better to have the output ("resolution profile", perhaps?) contain an array of values than to create an array of these objects.

I think we need to brainstorm a range of cases, including arbitrary tabulated profiles (where they are not well-described by a common distribution function).

Indeed, it could be nice if the base class promises to always provide the option of a tabulated output; then this is a useful fallback if the upstream code doesn't know what a Lorentzian is, say.

@RastislavTuranyi
Copy link
Collaborator Author

Plan for this - scrap InstrumentModel.output and InstrumentModel.input will be a tuple of strings

Change InstrumentModel interface so that the following functions have to be implemented:

InstrumentModel
    def get_characteristics([Q,w]) -> dict[str, [Q,w]]: ...

    def get_kernel([Q,w], mesh) -> [Q, w, mesh]: ...

    def convolve([Q, w], intensities, mesh): ...

    def __call__([Q, w], intensities, mesh):
        return self.convolve(...)

get_characteristics provides as much useful parameters for the kernel as possible, as a dictionary to provide some metadata, but does not make any promises. May not be defined for some models.

get_gernel generates all the kernels for all points on the mesh. May not be defined depending on a model.

convolve does a convolution of the model with the user data. Must be defined.

@ajjackson
Copy link
Collaborator

ajjackson commented Jan 30, 2025

Meeting flipchart scribbles covering some examples of this:

Image

Maybe the key example to highlight is that while the default implementation of convolve() would call self.get_kernel(), a sufficiently advanced model might actually choose to implement convolve() and then have get_kernel() call self.convolve() on a delta function. Examples would be a model that relies on Monte-Carlo sampling, or on recursive filters.

While the flipchart shows cases of get_sigma() raising NotImplemented, we actually agreed that it would be better for get_characteristics to return an empty dictionary in cases where no useful information is available.

@RastislavTuranyi RastislavTuranyi changed the title Improve scheme for specifying input and output of models Add ability to construct kernels and convolve with data Jan 30, 2025
@RastislavTuranyi
Copy link
Collaborator Author

RastislavTuranyi commented Feb 4, 2025

While I was looking into #24, a question arose: should we accept both an array and a float for the independent variable array(s)?

In the present implementation, the __call__ is type-hinted as accepting an array only, but I believe all the existing models also work when a float is passed in, though such behaviour is not enforced, making it possible for e.g. new models not to do the same. Therefore, should we:

  • enforce the fact that both a float or an array can be provided in the API?
  • allow each model to define whether it accepts only arrays or both arrays and floats?
  • keep the API that all models formally only accept arrays, and if a model happens to work with a float, that's a bonus?
  • enforce the array-only API and actively discourage/forbid floats?
  • something else?

@RastislavTuranyi RastislavTuranyi linked a pull request Feb 17, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants