Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions autogalaxy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
point_sources as ps,
mass as mp,
light_and_mass_profiles as lmp,
light_linear_and_mass_profiles as lmp_linear,
scaling_relations as sr,
)
from .profiles.light.abstract import LightProfile
Expand Down
215 changes: 121 additions & 94 deletions autogalaxy/analysis/chaining_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from autogalaxy.profiles.light import standard as lp
from autogalaxy.profiles.light import linear as lp_linear
from autogalaxy.profiles import light_and_mass_profiles as lmp
from autogalaxy.profiles import light_linear_and_mass_profiles as lmp_linear


def mass_from(mass, mass_result, unfix_mass_centre: bool = False) -> af.Model:
Expand Down Expand Up @@ -234,144 +235,149 @@ def clumps_from(
return clumps


def mass_light_dark_lmp_from(
light_result: Result, name : str, light_is_model : bool = False
):
def basis_no_linear_from(light_result: Result, name: str) -> af.Model:
"""
Returns a light and mass profile from a standard light profile (e.g. a Sersic) in the LIGHT PIPELINE result, for
the LIGHT DARK MASS PIPELINE.
Returns a basis containing standard light profiles from a basis (e.g. an MGE) in the LIGHT PIPELINE result,
for the TOTAL MASS PIPELINE.

For example, if the light pipeline fits a Sersic profile, this function will return a Sersic profile for the LIGHT
DARK MASS PIPELINE.
For example, if the light pipeline fits a basis of linear Gaussians, this function will return a basis of standard
Gaussians where each Gaussian has been converted to standard light profile.

This is used to fix the lens light subtraction in the TOTAL MASS PIPELINE, as opposed to continue using
linear light profiles which solve for the intensities for each iteration of the pipeline.

These profiles will have been converted from standard light profiles / linear light profiles to light and mass
profiles, where their light profile parameters (e.g. their `centre`, `ell_comps`) are used to set up the parameters
of the light and mass profile.

If a linear light profile is passed in, the function will return a light and mass profile where its `intensity` is
fixed to the solved for value of the maximum log likelihood linear fit.

The light and mass profiles can also be switched to variants which have a radial gradient in their mass-to-light
conversion, by setting the `include_mass_to_light_gradient` parameter to `True`.


Parameters
----------
light_result
The result of the light pipeline, which determines the light and mass profiles used in the LIGHT DARK
MASS PIPELINE.
name
The name of the light profile in the light pipeline's galaxy model that the model is being created for
light_is_model
If `True`, the light profile is passed as a model component, else it is a fixed instance.
(e.g. `bulge`).

Returns
-------
The light and mass profile for a standard light profile whose priors are initialized from a previous result.
The light and mass profile for a basis (e.g. an MGE) whose priors are initialized from a previous result.
"""

lp_instance = getattr(light_result.instance.galaxies.lens, name)
lp_model = getattr(light_result.model.galaxies.lens, name)

lp_to_lmp_dict = {
lp.Sersic : lmp.Sersic
}
lp_linear_to_lmp_dict = {
lp_linear.Sersic : lmp.Sersic
}

try:
lp_instance = getattr(
light_result.max_log_likelihood_fit.model_obj_linear_light_profiles_to_light_profiles.galaxies[
0
],
name,
)
except AttributeError:
return None

is_linear = False

lmp_model = lp_to_lmp_dict[type(lp_instance)]

except KeyError:

is_linear = True
lmp_model = lp_linear_to_lmp_dict[type(lp_instance)]
if lp_instance is None:
return None

lmp_model = af.Model(lmp_model)
profile_list = lp_instance.profile_list

if light_is_model:
lmp_model.take_attributes(source=lp_model)
else:
lmp_model.take_attributes(source=lp_instance)
lp_model_list = []

if is_linear:
for i, light_profile in enumerate(profile_list):
lp_model = af.Model(lp.Gaussian)

fit = light_result.max_log_likelihood_fit
lp_solved = getattr(fit.model_obj_linear_light_profiles_to_light_profiles.galaxies[0], name)
lp_model.centre = light_profile.centre
lp_model.ell_comps = light_profile.ell_comps
lp_model.intensity = light_profile.intensity
lp_model.sigma = light_profile.sigma

lmp_model.intensity = lp_solved.intensity
lp_model_list += [lp_model]

return lmp_model
return af.Model(Basis, profile_list=lp_model_list)


def basis_no_linear_from(light_result: Result, name : str) -> af.Model:
def mass_light_dark_lmp_from(
light_result: Result,
name: str,
linear_lp_to_standard: bool = False,
light_is_model: bool = False,
):
"""
Returns a basis containing standard light profiles from a basis (e.g. an MGE) in the LIGHT PIPELINE result,
for the TOTAL MASS PIPELINE.

For example, if the light pipeline fits a basis of linear Gaussians, this function will return a basis of standard
Gaussians where each Gaussian has been converted to standard light profile.

This is used to fix the lens light subtraction in the TOTAL MASS PIPELINE, as opposed to continue using
linear light profiles which solve for the intensities for each iteration of the pipeline.
Returns a light and mass profile from a standard light profile (e.g. a Sersic) in the LIGHT PIPELINE result, for
the LIGHT DARK MASS PIPELINE.

These profiles will have been converted from standard light profiles / linear light profiles to light and mass
profiles, where their light profile parameters (e.g. their `centre`, `ell_comps`) are used to set up the parameters
of the light and mass profile.
For example, if the light pipeline fits a Sersic profile, this function will return a Sersic profile for the LIGHT
DARK MASS PIPELINE.

If a linear light profile is passed in, the function will return a light and mass profile where its `intensity` is
fixed to the solved for value of the maximum log likelihood linear fit.
For the light profile, it will by default use a linear light and mass profile, which therefore continues to solve
for the intensity of the linear light profile via linear algebra. This means that during the fit the `intensity`
used to compute deflection angles is not the same as the `intensity` parameter solved for in the linear light
profile. If the input `linear_lp_to_standard` is `True`, the function will instead use a standard light profile.

The light and mass profiles can also be switched to variants which have a radial gradient in their mass-to-light
conversion, by setting the `include_mass_to_light_gradient` parameter to `True`.


Parameters
----------
light_result
The result of the light pipeline, which determines the light and mass profiles used in the LIGHT DARK
MASS PIPELINE.
name
The name of the light profile in the light pipeline's galaxy model that the model is being created for
(e.g. `bulge`).
light_is_model
If `True`, the light profile is passed as a model component, else it is a fixed instance.

Returns
-------
The light and mass profile for a basis (e.g. an MGE) whose priors are initialized from a previous result.
The light and mass profile for a standard light profile whose priors are initialized from a previous result.
"""

lp_instance = getattr(light_result.instance.galaxies.lens, name)
lp_model = getattr(light_result.model.galaxies.lens, name)

try:
lp_instance = getattr(light_result.max_log_likelihood_fit.model_obj_linear_light_profiles_to_light_profiles.galaxies[0], name)
except AttributeError:
return None
is_linear = False

if lp_instance is None:
return None
lp_to_lmp_dict = {lp.Sersic: lmp.Sersic}

profile_list = lp_instance.profile_list
lmp_model = lp_to_lmp_dict[type(lp_instance)]

lp_model_list = []
except KeyError:
if not linear_lp_to_standard:
lp_linear_to_lmp_dict = {lp_linear.Sersic: lmp_linear.Sersic}
else:
lp_linear_to_lmp_dict = {lp_linear.Sersic: lmp.Sersic}

for i, light_profile in enumerate(profile_list):
is_linear = True
lmp_model = lp_linear_to_lmp_dict[type(lp_instance)]

if light_profile.intensity > 0.0:
lmp_model = af.Model(lmp_model)

lp_model = af.Model(lp.Gaussian)
if light_is_model:
lmp_model.take_attributes(source=lp_model)
else:
lmp_model.take_attributes(source=lp_instance)

lp_model.centre = light_profile.centre
lp_model.ell_comps = light_profile.ell_comps
lp_model.intensity = light_profile.intensity
lp_model.sigma = light_profile.sigma
if is_linear:
fit = light_result.max_log_likelihood_fit
lp_solved = getattr(
fit.model_obj_linear_light_profiles_to_light_profiles.galaxies[0], name
)

lp_model_list += [lp_model]
lmp_model.intensity = lp_solved.intensity

return af.Model(
Basis,
profile_list=lp_model_list
)
return lmp_model


def mass_light_dark_basis_from(
light_result: Result, name : str,
light_result: Result,
name: str,
linear_lp_to_standard: bool = False,
) -> af.Model:
"""
Returns a basis containing light and mass profiles from a basis (e.g. an MGE) in the LIGHT PIPELINE result, for the
Expand All @@ -384,8 +390,10 @@ def mass_light_dark_basis_from(
profiles, where their light profile parameters (e.g. their `centre`, `ell_comps`) are used to set up the parameters
of the light and mass profile.

If a linear light profile is passed in, the function will return a light and mass profile where its `intensity` is
fixed to the solved for value of the maximum log likelihood linear fit.
For the light profile, it will by default use a linear light and mass profile, which therefore continues to solve
for the intensity of the linear light profile via linear algebra. This means that during the fit the `intensity`
used to compute deflection angles is not the same as the `intensity` parameter solved for in the linear light
profile. If the input `linear_lp_to_standard` is `True`, the function will instead use a standard light profile.

The light and mass profiles can also be switched to variants which have a radial gradient in their mass-to-light
conversion, by setting the `include_mass_to_light_gradient` parameter to `True`.
Expand All @@ -404,34 +412,40 @@ def mass_light_dark_basis_from(
The light and mass profile for a basis (e.g. an MGE) whose priors are initialized from a previous result.
"""

lp_instance = getattr(light_result.max_log_likelihood_fit.model_obj_linear_light_profiles_to_light_profiles.galaxies[0], name)
lp_instance = getattr(
light_result.max_log_likelihood_fit.model_obj_linear_light_profiles_to_light_profiles.galaxies[
0
],
name,
)

profile_list = lp_instance.profile_list

lmp_model_list = []

for i, light_profile in enumerate(profile_list):

if light_profile.intensity > 0.0:

if not linear_lp_to_standard:
lmp_model = af.Model(lmp_linear.Gaussian)
else:
lmp_model = af.Model(lmp.Gaussian)

lmp_model.centre = light_profile.centre
lmp_model.ell_comps = light_profile.ell_comps
lmp_model.intensity = light_profile.intensity
lmp_model.sigma = light_profile.sigma
lmp_model.centre = light_profile.centre
lmp_model.ell_comps = light_profile.ell_comps
lmp_model.intensity = light_profile.intensity
lmp_model.sigma = light_profile.sigma

lmp_model_list += [lmp_model]
lmp_model_list += [lmp_model]

lmp_model.mass_to_light_ratio = lmp_model_list[0].mass_to_light_ratio
lmp_model.mass_to_light_ratio = lmp_model_list[0].mass_to_light_ratio

return af.Model(Basis, profile_list=lmp_model_list)

return af.Model(
Basis,
profile_list=lmp_model_list
)

def mass_light_dark_from(
light_result: Result, name : str, light_is_model : bool = False
light_result: Result,
name: str,
linear_lp_to_standard: bool = False,
light_is_model: bool = False,
) -> Optional[af.Model]:
"""
Returns light and mass profiles from the LIGHT PIPELINE result, for the LIGHT DARK MASS PIPELINE.
Expand All @@ -443,9 +457,14 @@ def mass_light_dark_from(
profiles, where their light profile parameters (e.g. their `centre`, `ell_comps`) are used to set up the parameters
of the light and mass profile.

If a linear light profile is passed in, the function will return a light and mass profile where its `intensity` is
If a linear light profile is passed in, the function will return a mass profile where its `intensity` is
fixed to the solved for value of the maximum log likelihood linear fit.

For the light profile, it will by default use a linear light and mass profile, which therefore continues to solve
for the intensity of the linear light profile via linear algebra. This means that during the fit the `intensity`
used to compute deflection angles is not the same as the `intensity` parameter solved for in the linear light
profile. If the input `linear_lp_to_standard` is `True`, the function will instead use a standard light profile.

This function supports the input of a basis (e.g. an MGE), converting every individual standard light or
linear light profile in the basis to a light and mass profile.

Expand All @@ -461,6 +480,9 @@ def mass_light_dark_from(
name
The name of the light profile in the light pipeline's galaxy model that the model is being created for
(e.g. `bulge`).
linear_lp_to_standard
If `True`, the light profile is passed as a standard component, else it is a linear component. The
mass always uses the `interity` parameter of the linear light profile solved for in the previous pipeline.
light_is_model
If `True`, the light profile is passed as a model component, else it is a fixed instance. For a basis
(e.g. an MGE) this feature is not used due to the large number of profiles in the basis.
Expand All @@ -476,5 +498,10 @@ def mass_light_dark_from(
return None

if not isinstance(lp_instance, Basis):
return mass_light_dark_lmp_from(light_result=light_result, name=name, light_is_model=light_is_model)
return mass_light_dark_lmp_from(
light_result=light_result,
name=name,
linear_lp_to_standard=linear_lp_to_standard,
light_is_model=light_is_model,
)
return mass_light_dark_basis_from(light_result=light_result, name=name)
Loading