I'm trying to use Model.tied (or Parameter.tied ) in astropy.modelling but can't seem to figure out how this works. For example, suppose I wanted to create a composite model with two parameters: flux_0 and flux_1 . However, I want flux_0 to flux_0 used during installation: flux_1 should always be set to 1 - flux_0 . (In the end, I need to extend this functionality to flux_0 + flux_1 + ... + flux_n = 1 )
I define the model class and the "called" for the tied attribute as follows:
>>> from astropy.modeling import Fittable1DModel, Parameter >>> >>> class MyModel(Fittable1DModel): ... flux = Parameter() ... @staticmethod ... def evaluate(x, flux): ... return flux ... >>> def tie_fluxes(model): ... flux_1 = 1 - model.flux_0 ... return flux_1 ... >>> TwoModel = MyModel + MyModel >>> >>> TwoModel <class '__main__.CompoundModel0'> Name: CompoundModel0 Inputs: ('x',) Outputs: ('y',) Fittable parameters: ('flux_0', 'flux_1') Expression: [0] + [1] Components: [0]: <class '__main__.MyModel'> Name: MyModel Inputs: ('x',) Outputs: ('y',) Fittable parameters: ('flux',) [1]: <class '__main__.MyModel'> Name: MyModel Inputs: ('x',) Outputs: ('y',) Fittable parameters: ('flux',)
Then I check the tied attribute. I understand that this should be a dictionary (see Footnote), but it is not:
>>> TwoModel.tied <property object at 0x109523958> >>> >>> TwoModel.tied['flux_1'] = tie_fluxes Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'property' object does not support item assignment
If I try to install it as a dictionary, it will not update the corresponding Parameter :
>>> TwoModel.tied = {'flux_1': tie_fluxes} >>> >>> TwoModel.flux_1.tied False
But when I try to create an object immediately with a bat instead of a composite model class (this is not what I want to do at the end), the tied attribute of the object is a dictionary. Unfortunately, installing this dictionary still does not produce the desired effect:
>>> TwoSetModel = MyModel(0.2) + MyModel(0.3) >>> >>> TwoSetModel <CompoundModel1(flux_0=0.2, flux_1=0.3)> >>> >>> TwoSetModel.tied {'flux_1': False, 'flux_0': False} >>> >>> TwoSetModel.tied['flux_1'] = tie_fluxes >>> >>> TwoSetModel <CompoundModel1(flux_0=0.2, flux_1=0.3)> >>> >>> TwoSetModel.flux_1.tied <function tie_fluxes at 0x102987730>
So, in this example, the tied attribute contains the correct function, but the value parameter is not updated accordingly.
What am I doing wrong here? Am I completely misunderstanding the tied attribute?
(I am using Python 3.5.2 with Astropy 1.3.3 in the examples above)
Footnote:
Running help(TwoModel) , I get the following information:
⁝ | tied : dict, optional | Dictionary ``{parameter_name: callable}`` of parameters which are | linked to some other parameter. The dictionary values are callables | providing the linking relationship. | | Alternatively the `~astropy.modeling.Parameter.tied` property of a | parameter may be used to set the ``tied`` constraint on individual | parameters. ⁝ | Examples | -------- | >>> from astropy.modeling import models | >>> def tie_center(model): | ... mean = 50 * model.stddev | ... return mean | >>> tied_parameters = {'mean': tie_center} | | Specify that ``'mean'`` is a tied parameter in one of two ways: | | >>> g1 = models.Gaussian1D(amplitude=10, mean=5, stddev=.3, | ... tied=tied_parameters) | | or | | >>> g1 = models.Gaussian1D(amplitude=10, mean=5, stddev=.3) | >>> g1.mean.tied | False | >>> g1.mean.tied = tie_center | >>> g1.mean.tied | <function tie_center at 0x...> ⁝