/
source_pix.py
216 lines (182 loc) · 9.28 KB
/
source_pix.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
import autofit as af
import autolens as al
from typing import Optional, Tuple, Union
def run_1(
settings_search: af.SettingsSearch,
analysis: Union[al.AnalysisImaging, al.AnalysisInterferometer],
source_lp_result: af.Result,
image_mesh_init: af.Model(al.AbstractImageMesh) = af.Model(al.image_mesh.Overlay),
mesh_init: af.Model(al.AbstractMesh) = af.Model(al.mesh.Delaunay),
image_mesh_init_shape: Tuple[int, int] = (34, 34),
regularization_init: af.Model(al.AbstractRegularization) = af.Model(
al.reg.AdaptiveBrightnessSplit
),
) -> af.Result:
"""
The first SLaM SOURCE PIX PIPELINE, which initializes a lens model which uses a pixelized source for the source
analysis.
The first SOURCE PIX PIPELINE performs a fit using an initial pixelizaiton, which does not require an
adapt-image to perform the fit (e.g. it does not adapt the source's pixelization to the source's unlensed
morphology).
The result of this pipeline is used in the second SOURCE PIX PIPELINE to adapt the source pixelization to the
source's unlensed morphology via an adapt image.
Parameters
----------
analysis
The analysis class which includes the `log_likelihood_function` and can be customized for the SLaM model-fit.
source_lp_result
The results of the SLaM SOURCE LP PIPELINE which ran before this pipeline.
image_mesh_init
The image mesh, which defines how the mesh centres are computed in the image-plane, used by the pixelization
in the first search which initializes the source.
image_mesh_init_shape
The shape (e.g. resolution) of the image-mesh used in the initialization search (`search[1]`). This is only
used if the image-mesh has a `shape` parameter (e.g. `Overlay`).
mesh_init
The mesh, which defines how the source is reconstruction in the source-plane, used by the pixelization
in the first search which initializes the source.
regularization_init
The regularization, which places a smoothness prior on the source reconstruction, used by the pixelization
which fits the source light in the initialization search (`search[1]`).
"""
"""
__Model + Search + Analysis + Model-Fit (Search 1)__
Search 1 of the SOURCE PIX PIPELINE fits a lens model where:
- The lens galaxy light is modeled using light profiles [parameters fixed to result of SOURCE LP PIPELINE].
- The lens galaxy mass is modeled using a total mass distribution [parameters initialized from the results of the
SOURCE LP PIPELINE].
- The source galaxy's light is the input initialization image mesh, mesh and regularization scheme [parameters of
regularization free to vary].
This search improves the lens mass model by modeling the source using a pixelization and computes the adapt
images that are used in search 2.
"""
mass = al.util.chaining.mass_from(
mass=source_lp_result.model.galaxies.lens.mass,
mass_result=source_lp_result.model.galaxies.lens.mass,
unfix_mass_centre=True,
)
image_mesh_init.shape = image_mesh_init_shape
model = af.Collection(
galaxies=af.Collection(
lens=af.Model(
al.Galaxy,
redshift=source_lp_result.instance.galaxies.lens.redshift,
bulge=source_lp_result.instance.galaxies.lens.bulge,
disk=source_lp_result.instance.galaxies.lens.disk,
mass=mass,
shear=source_lp_result.model.galaxies.lens.shear,
),
source=af.Model(
al.Galaxy,
redshift=source_lp_result.instance.galaxies.source.redshift,
pixelization=af.Model(
al.Pixelization,
image_mesh=image_mesh_init,
mesh=mesh_init,
regularization=regularization_init,
),
),
),
clumps=al.util.chaining.clumps_from(result=source_lp_result),
)
search = af.Nautilus(
name="source_pix[1]_light[fixed]_mass[init]_source[pix_init_mag]",
**settings_search.search_dict,
n_live=150,
)
result = search.fit(model=model, analysis=analysis, **settings_search.fit_dict)
return result
def run_2(
settings_search: af.SettingsSearch,
analysis: Union[al.AnalysisImaging, al.AnalysisInterferometer],
source_lp_result: af.Result,
source_pix_result_1: af.Result,
image_mesh: af.Model(al.AbstractImageMesh) = af.Model(al.image_mesh.Hilbert),
mesh: af.Model(al.AbstractMesh) = af.Model(al.mesh.Delaunay),
regularization: af.Model(al.AbstractRegularization) = af.Model(
al.reg.AdaptiveBrightnessSplit
),
image_mesh_pixels_fixed: Optional[int] = 1000,
) -> af.Result:
"""
The second SLaM SOURCE PIX PIPELINE, which fits a fixed lens model which uses a pixelized source for the source
analysis.
The second SOURCE PIX PIPELINE performs a fit using an advanced pixelizaiton which adapt the source's pixelization
to the source's unlensed morphology. This feature requires an adapt-image, which is computed after the
first SOURCE PIX PIPELINE.
Parameters
----------
analysis
The analysis class which includes the `log_likelihood_function` and can be customized for the SLaM model-fit.
source_lp_result
The results of the SLaM SOURCE LP PIPELINE which ran before this pipeline.
image_mesh
The image mesh, which defines how the mesh centres are computed in the image-plane, used by the pixelization
in the final search which improves the source adaption.
mesh
The mesh, which defines how the source is reconstruction in the source-plane, used by the pixelization
in the final search which improves the source adaption.
regularization
The regularization, which places a smoothness prior on the source reconstruction, used by the pixelization
in the final search which improves the source adaption.
image_mesh_pixels_fixed
The fixed number of pixels in the image-mesh, if an image-mesh with an input number of pixels is used
(e.g. `Hilbert`).
"""
"""
__Model + Search + Analysis + Model-Fit (Search 2)__
Search 2 of the SOURCE PIX PIPELINE fits a lens model where:
- The lens galaxy light is modeled using a light profiles [parameters fixed to result of SOURCE LP PIPELINE].
- The lens galaxy mass is modeled using a total mass distribution [parameters fixed to result of search 2].
- The source galaxy's light is the input final mesh and regularization.
This search initializes the pixelization's mesh and regularization.
"""
model = af.Collection(
galaxies=af.Collection(
lens=af.Model(
al.Galaxy,
redshift=source_lp_result.instance.galaxies.lens.redshift,
bulge=source_lp_result.instance.galaxies.lens.bulge,
disk=source_lp_result.instance.galaxies.lens.disk,
mass=source_pix_result_1.instance.galaxies.lens.mass,
shear=source_pix_result_1.instance.galaxies.lens.shear,
),
source=af.Model(
al.Galaxy,
redshift=source_lp_result.instance.galaxies.source.redshift,
pixelization=af.Model(
al.Pixelization,
image_mesh=image_mesh,
mesh=mesh,
regularization=regularization,
),
),
),
clumps=al.util.chaining.clumps_from(result=source_lp_result),
)
if image_mesh_pixels_fixed is not None:
if hasattr(model.galaxies.source.pixelization.image_mesh, "pixels"):
model.galaxies.source.pixelization.image_mesh.pixels = (
image_mesh_pixels_fixed
)
"""
__Search (Search 2)__
This search uses the nested sampling algorithm Dynesty, in contrast to nearly every other search throughout the
autolens workspace which use `Nautilus`.
The reason is quite technical, but in a nutshell it is because the likelihood function sampled in `source_pix[2]`
is often not smooth. This leads to behaviour where the `Nautilus` search gets stuck sampling small regions of
parameter space indefinitely, and does not converge and terminate.
Dynesty has proven more robust to these issues, because it uses a random walk nested sampling algorithm which
is less susceptible to a noisy likelihood function.
The reason this likelihood function is noisy is because it has parameters which change the distribution of source
pixels. For example, the parameters may mean more or less source pixels cluster over the brightest regions of the
image. In all other searches, the source pixelization parameters are fixed, ensuring that the likelihood function
is smooth.
"""
search = af.DynestyStatic(
name="source_pix[2]_light[fixed]_mass[fixed]_source[pix]",
**settings_search.search_dict,
nlive=100,
)
result = search.fit(model=model, analysis=analysis, **settings_search.fit_dict)
return result