You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Provide a way to make a copy of a model with different parameter values, or be more flexible with parameter shape #16593
GIven a model with scalar or array parameters, I would like to be able to easily make another model which has different parameter values (either scalar or array), while preserving other things (e.g. constraints, polynomial degree, etc). One can try the naive approach of making a copy of the model and then changing the parameters, but this doesn't always work:
This works ok because scalars are broadcastable to arrays. This is not ideal though as one temporarily has a copy of all the arrays in memory, and if the arrays are big it might be annoying.
Array ▶️ array
This does not work if the new array shape is not broadcastable to the old one:
InputParameterError: Value for parameter c0 does not match shape or size
expected by model ((5,), 5) vs ((1,), 1)
Possible solutions
One option would not be to check the dimensions whenever parameters are set, but to instead validate them at the point where the model is called - otherwise it is not possible to change the parameters to have a shape that is not broadcastable to the current one.
Another option would be to have a way to do e.g. poly.copy_with_new_parameters(c0=np.arange(5), ...) or similar, that is, do a copy but replace the parameter value with the ones provided in the method call.
#15750 would have worked for this. replace is the new paradigm for dataclasses (which astropy.models are conceptually, if not in actual code). singledispatch allows for us to make a function in astropy (or better yet a companion utility library), called replace that dispatches like this:
@singledispatchdefreplace(obj: Any, /, **kwargs: Any) ->Any:
raiseNotImplementedError@replace.register# a superset of python's dataclasses.replace!defreplace(obj: DataclassInstance, /, **kwargs: Any) ->DataclassInstance:
fromdataclassesimportreplacereturnreplace(obj, **kwargs)
@replace.register# it works on anything!defreplace(obj: AstropyModel, /, **kwargs: Any) ->AstropyModel:
... whatevermechanismwewantreturnnewobj
With this dispatcher, each sub-package in astropy can register copy-and-modify methods into a single tool.
Stick an example in the docstring Examples and it's easily discoverable.
Ok so after digging into this further, it is possible to get some of these examples to work by setting the parameter value instead of the top-level parameter, so e.g.:
works, and if parameters are set with incompatible shapes an error is raised at model evaluation time, which I think is sensible. I guess the question is then should Model.__setattr__ be more permissive to match what is possible by setting Parameter.value directly?
Activity
nstarman commentedon Jun 19, 2024
#15750 would have worked for this.
replaceis the new paradigm for dataclasses (whichastropy.modelsare conceptually, if not in actual code).singledispatchallows for us to make a function in astropy (or better yet a companion utility library), calledreplacethat dispatches like this:With this dispatcher, each sub-package in
astropycan register copy-and-modify methods into a single tool.Stick an example in the docstring
Examplesand it's easily discoverable.astrofrog commentedon Jul 12, 2024
Ok so after digging into this further, it is possible to get some of these examples to work by setting the parameter value instead of the top-level parameter, so e.g.:
works, and if parameters are set with incompatible shapes an error is raised at model evaluation time, which I think is sensible. I guess the question is then should
Model.__setattr__be more permissive to match what is possible by settingParameter.valuedirectly?astrofrog commentedon Jul 12, 2024
See #16710 for a bug that occurs when doing this though