|
1 | | -import numpy as np |
2 | | -from typing import Optional, Tuple |
3 | | - |
4 | 1 | import autofit as af |
5 | 2 | import autolens as al |
6 | 3 |
|
7 | | - |
8 | | -def mge_model_from( |
9 | | - mask_radius: float, |
10 | | - total_gaussians: int = 30, |
11 | | - gaussian_per_basis: int = 1, |
12 | | - centre_prior_is_uniform: bool = True, |
13 | | - centre: Tuple[float, float] = (0.0, 0.0), |
14 | | - centre_fixed: Optional[Tuple[float, float]] = None, |
15 | | - use_spherical: bool = False, |
16 | | -) -> af.Collection: |
17 | | - """ |
18 | | - Construct a Multi-Gaussian Expansion (MGE) for the lens or source galaxy light |
19 | | -
|
20 | | - This model is designed as a "start here" configuration for lens modeling: |
21 | | -
|
22 | | - - The lens and source light are represented by a Basis object composed of many |
23 | | - Gaussian light profiles with fixed logarithmically spaced widths (`sigma`). |
24 | | - - All Gaussians within each basis share common centres and ellipticity |
25 | | - components, reducing degeneracy while retaining flexibility. |
26 | | -
|
27 | | - - Users can combine with a lens mass model of their choiuce. |
28 | | -
|
29 | | - The resulting model provides a good balance of speed, flexibility, and accuracy |
30 | | - for fitting most galaxy-scale strong lenses. |
31 | | -
|
32 | | - This code is mostly to make the API simple for new users, hiding the technical |
33 | | - details of setting up an MGE. More advanced users may wish to customize the |
34 | | - model further. |
35 | | -
|
36 | | - Parameters |
37 | | - ---------- |
38 | | - mask_radius |
39 | | - The outer radius (in arcseconds) of the circular mask applied to the data. |
40 | | - This determines the maximum Gaussian width (`sigma`) used in the lens MGE. |
41 | | - lens_total_gaussians |
42 | | - Total number of Gaussian light profiles used in the lens MGE basis. |
43 | | - source_total_gaussians |
44 | | - Total number of Gaussian light profiles used in the source MGE basis. |
45 | | - lens_gaussian_per_basis |
46 | | - Number of separate Gaussian bases to include for the lens light profile. |
47 | | - Each basis has `lens_total_gaussians` components. |
48 | | - source_gaussian_per_basis |
49 | | - Number of separate Gaussian bases to include for the source light profile. |
50 | | - Each basis has `source_total_gaussians` components. |
51 | | -
|
52 | | - Returns |
53 | | - ------- |
54 | | - model : af.Collection |
55 | | - An `autofit.Collection` containing: |
56 | | - - A lens galaxy at redshift 0.5, with: |
57 | | - * bulge light profile: MGE basis of Gaussians |
58 | | - * mass profile: Isothermal ellipsoid |
59 | | - * external shear |
60 | | - - A source galaxy at redshift 1.0, with: |
61 | | - * bulge light profile: MGE basis of Gaussians |
62 | | -
|
63 | | - Notes |
64 | | - ----- |
65 | | - - Lens light Gaussians have widths (sigma) logarithmically spaced between 0.01" |
66 | | - and the mask radius. |
67 | | - - Source light Gaussians have widths logarithmically spaced between 0.01" and 1.0". |
68 | | - - Gaussian centres are free parameters but tied across all components in each |
69 | | - basis to reduce dimensionality. |
70 | | - - This function is a convenience utility: it hides the technical setup of MGE |
71 | | - composition and provides a ready-to-use lens model for quick experimentation. |
72 | | - """ |
73 | | - |
74 | | - # The sigma values of the Gaussians will be fixed to values spanning 0.01 to the mask radius, 3.0". |
75 | | - log10_sigma_list = np.linspace(-4, np.log10(mask_radius), total_gaussians) |
76 | | - |
77 | | - # By defining the centre here, it creates two free parameters that are assigned below to all Gaussians. |
78 | | - |
79 | | - if centre_fixed is not None: |
80 | | - centre_0 = centre[0] |
81 | | - centre_1 = centre[1] |
82 | | - elif centre_prior_is_uniform: |
83 | | - centre_0 = af.UniformPrior( |
84 | | - lower_limit=centre[0] - 0.1, upper_limit=centre[0] + 0.1 |
85 | | - ) |
86 | | - centre_1 = af.UniformPrior( |
87 | | - lower_limit=centre[1] - 0.1, upper_limit=centre[1] + 0.1 |
88 | | - ) |
89 | | - else: |
90 | | - centre_0 = af.GaussianPrior(mean=centre[0], sigma=0.3) |
91 | | - centre_1 = af.GaussianPrior(mean=centre[1], sigma=0.3) |
92 | | - |
93 | | - if use_spherical: |
94 | | - model_cls = al.lp_linear.GaussianSph |
95 | | - else: |
96 | | - model_cls = al.lp_linear.Gaussian |
97 | | - |
98 | | - bulge_gaussian_list = [] |
99 | | - |
100 | | - for j in range(gaussian_per_basis): |
101 | | - # A list of Gaussian model components whose parameters are customized belows. |
102 | | - |
103 | | - gaussian_list = af.Collection( |
104 | | - af.Model(model_cls) for _ in range(total_gaussians) |
105 | | - ) |
106 | | - |
107 | | - # Iterate over every Gaussian and customize its parameters. |
108 | | - |
109 | | - for i, gaussian in enumerate(gaussian_list): |
110 | | - gaussian.centre.centre_0 = centre_0 # All Gaussians have same y centre. |
111 | | - gaussian.centre.centre_1 = centre_1 # All Gaussians have same x centre. |
112 | | - if not use_spherical: |
113 | | - gaussian.ell_comps = gaussian_list[ |
114 | | - 0 |
115 | | - ].ell_comps # All Gaussians have same elliptical components. |
116 | | - gaussian.sigma = ( |
117 | | - 10 ** log10_sigma_list[i] |
118 | | - ) # All Gaussian sigmas are fixed to values above. |
119 | | - |
120 | | - bulge_gaussian_list += gaussian_list |
121 | | - |
122 | | - # The Basis object groups many light profiles together into a single model component. |
123 | | - |
124 | | - return af.Model( |
125 | | - al.lp_basis.Basis, |
126 | | - profile_list=bulge_gaussian_list, |
127 | | - ) |
| 4 | +from autogalaxy.analysis.model_util import mge_model_from |
128 | 5 |
|
129 | 6 |
|
130 | 7 | def simulator_start_here_model_from( |
|
0 commit comments