Jammy2211 / PyAutoLens

PyAutoLens: Open Source Strong Gravitational Lensing
https://pyautolens.readthedocs.io/
MIT License
159 stars 32 forks source link

Shared Parameters of Combined Light / Mass Profiles #13

Closed Jammy2211 closed 6 years ago

Jammy2211 commented 6 years ago

Lets say we are modeling a lens galaxy's light profile using a double Sersic profile:

sersic1 = EllipticalSersic(...) sersic2 = EllipticalSersic(...) light_profile = CombinedLightProfile(sersic1, sersic2)

If the two light profiles are completely independent, this means each is controlled by 7 nonlinear parameters, giving us a total of 14 non-linear parameters.

In many modeling situations, it is unclear if the two Sersic's should share the same geometry. For example, we might want the second Sersic to share the same centre as the first sersic. This must be reflected in the priors we give sersic2, as it no longer draws its values of the centre from a prior but simply acquires the values from sersic1. The same could happen for the rotation angle and ellipticity. Thus, we need the code to be able to know if the centers of two light profiles are shared, that there are now just 12 non-linear parameters.

This could feasibly happen when there are 3 Light profiles (e.g. a Sersic + Sersic + Sersic) and we need flexibility in choosing if sersic3 and sersic2 are aligned with sersic1, or not.

This also occurs for mass profiles. For example, we may have a dark matter halo given by an EllipticalNFWProfile, and may want to align it with the centre or rotation angle of our CombinedLightProfile (somehow picking which component we align it with). Thus, for any mass profile, we need the option too tie its geometry to given component of a CombinedLightProfile.

Mass profiles also have some level of shared parameters. For example, a SersicMassProfile has a mass to light ratio. If a CombinedMassProfile is formed of two SersicMassProfiles, the question arises whether they share the same mass_to_light ratio, or use indepedent values.

rhayes777 commented 6 years ago

So currently we create three prior collections:

shared_lens_light_priors = PriorCollection(UniformPrior('centre_x'), UniformPrior('centre_y'))
lens_light_sersic_1_priors = PriorCollections(...)
lens_light_sersic_2_priors = PriorCollections(...)

In this formalism we need a unit hypercube vector corresponding to each individual collection. That is converted into a dictionary of arguments by the collection:

sersic_1_arguments = lens_light_sersic_1_priors.arguments_for_vector(vector1)
sersic_2_arguments = lens_light_sersic_2_priors.arguments_for_vector(vector2)
shared_lens_arguments = shared_lens_light_priors.arguments_for_vector(vector3)

The individual sersic arguments are updated using the shared arguments:

sersic_1_arguments.update(shared_lens_arguments)
sersic_2_arguments.update(shared_lens_arguments)

And finally the sersic profiles are instantiated using the combined arguments:

sersic_1 = EllipticalSersic(**sersic_1_arguments)
sersic_2 = EllipticalSersic(**sersic_2_arguments)

This has some aspect of manually mapping unit vectors to classes. We may want to encode the associated classes and their structure into the PriorCollection some how.

Jammy2211 commented 6 years ago

I'm going to close this, as we seem to have moved the CombinedProfile classes to the Galaxy class, and are discussing this aspect of the ClassMap w.r.t that now.