Parameter binding in astropy.modeling

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...> ⁝ 
+5
source share
1 answer

The example below is similar to the one in astrology documentation.

Compound model = sum of two one-dimensional Gaussian functions.

Constrain: mean_1 = 2 * mean_0

 import numpy as np import matplotlib.pyplot as plt from astropy.modeling import models, fitting def tie_center(model): mean = 2* model.mean_0 return mean tied_parameters = {'mean_1': tie_center} np.random.seed(42) g1 = models.Gaussian1D(2, 0.4, 0.3) g2 = models.Gaussian1D(2.5, 0.2, 0.2) TwoGaussians = (models.Gaussian1D + models.Gaussian1D).rename('TwoGaussians') x = np.linspace(-1, 1, 200) y = g1(x) + g2(x) + np.random.normal(0., 0.2, x.shape) gg_init = TwoGaussians(amplitude_0=1.4, mean_0=1.2, stddev_0=0.1,\ amplitude_1=1.0,stddev_1=0.2, tied=tied_parameters) fitter = fitting.SLSQPLSQFitter() gg_fit = fitter(gg_init, x, y) plt.figure(figsize=(8,5)) plt.plot(x, y, 'ko') plt.plot(x, gg_fit(x)) plt.xlabel('Position') plt.ylabel('Flux') plt.show() print(gg_fit.mean_0,gg_fit.mean_1) 

Linking parameters to astropy when Compund_model = sum of three 1D Gaussian functions of Constrain: the sum of all three means should always be equal to one.

 def tie_center(model): mean = 1-(model.mean_0+ model.mean_1) return mean tied_parameters = {'mean_2': tie_center} np.random.seed(42) g1 = models.Gaussian1D(2, 0.4, 0.3) g2 = models.Gaussian1D(2.5, 0.2, 0.2) g3 = models.Gaussian1D(1.5, 0.4, 0.1) ThreeGaussians = (models.Gaussian1D + models.Gaussian1D + models.Gaussian1D).rename('ThreeGaussians') x = np.linspace(-1, 1, 200) y = g1(x) + g2(x) + g3(x) + np.random.normal(0., 0.2, x.shape) gg_init = ThreeGaussians(amplitude_0=1.4, mean_0=0.3, stddev_0=0.1, amplitude_1=1.0, mean_1=0.3,stddev_1=0.2, \ amplitude_2=1.5,stddev_2=0.1,tied=tied_parameters) fitter = fitting.SLSQPLSQFitter() gg_fit = fitter(gg_init, x, y) plt.figure(figsize=(8,5)) plt.plot(x, y, 'ko') plt.plot(x, gg_fit(x)) plt.xlabel('Position') plt.ylabel('Flux') plt.show() print(gg_fit.mean_0,gg_fit.mean_1, gg_fit.mean_2) 
0
source

Source: https://habr.com/ru/post/1270599/


All Articles