1
+ import os
2
+ import logging
3
+ from typing import Optional , Union
4
+
5
+ from autoconf import conf
6
+ from autoconf .dictable import to_dict , output_to_json
7
+
8
+ import autofit as af
9
+ import autoarray as aa
10
+ import autogalaxy as ag
11
+
12
+ from autogalaxy .analysis .analysis .dataset import AnalysisDataset as AgAnalysisDataset
13
+
14
+ from autolens .analysis .analysis .lens import AnalysisLens
15
+ from autolens .analysis .result import ResultDataset
16
+ from autolens .analysis .maker import FitMaker
17
+ from autolens .analysis .preloads import Preloads
18
+ from autolens .analysis .positions import PositionsLHResample
19
+ from autolens .analysis .positions import PositionsLHPenalty
20
+
21
+ from autolens import exc
22
+
23
+ logger = logging .getLogger (__name__ )
24
+
25
+ logger .setLevel (level = "INFO" )
26
+
27
+ class AnalysisDataset (AgAnalysisDataset , AnalysisLens ):
28
+ def __init__ (
29
+ self ,
30
+ dataset ,
31
+ positions_likelihood : Optional [
32
+ Union [PositionsLHResample , PositionsLHPenalty ]
33
+ ] = None ,
34
+ adapt_image_maker : Optional [ag .AdaptImageMaker ] = None ,
35
+ cosmology : ag .cosmo .LensingCosmology = ag .cosmo .Planck15 (),
36
+ settings_inversion : aa .SettingsInversion = None ,
37
+ raise_inversion_positions_likelihood_exception : bool = True ,
38
+ ):
39
+ """
40
+ Fits a lens model to a dataset via a non-linear search.
41
+
42
+ This abstract Analysis class has attributes and methods for all model-fits which fit the model to a dataset
43
+ (e.g. imaging or interferometer data).
44
+
45
+ This class stores the Cosmology used for the analysis and settings that control aspects of the calculation,
46
+ including how pixelizations, inversions and lensing calculations are performed.
47
+
48
+ Parameters
49
+ ----------
50
+ dataset
51
+ The imaging, interferometer or other dataset that the model if fitted too.
52
+ positions_likelihood
53
+ An object which alters the likelihood function to include a term which accounts for whether
54
+ image-pixel coordinates in arc-seconds corresponding to the multiple images of the lensed source galaxy
55
+ trace close to one another in the source-plane.
56
+ adapt_images
57
+ Contains the adapt-images which are used to make a pixelization's mesh and regularization adapt to the
58
+ reconstructed galaxy's morphology.
59
+ cosmology
60
+ The AstroPy Cosmology assumed for this analysis.
61
+ settings_inversion
62
+ Settings controlling how an inversion is fitted during the model-fit, for example which linear algebra
63
+ formalism is used.
64
+ raise_inversion_positions_likelihood_exception
65
+ If an inversion is used without the `positions_likelihood` it is likely a systematic solution will
66
+ be inferred, in which case an Exception is raised before the model-fit begins to inform the user
67
+ of this. This exception is not raised if this input is False, allowing the user to perform the model-fit
68
+ anyway.
69
+ """
70
+
71
+ super ().__init__ (
72
+ dataset = dataset ,
73
+ adapt_image_maker = adapt_image_maker ,
74
+ cosmology = cosmology ,
75
+ settings_inversion = settings_inversion ,
76
+ )
77
+
78
+ AnalysisLens .__init__ (
79
+ self = self ,
80
+ positions_likelihood = positions_likelihood ,
81
+ cosmology = cosmology ,
82
+ )
83
+
84
+ self .preloads = self .preloads_cls ()
85
+
86
+ self .raise_inversion_positions_likelihood_exception = (
87
+ raise_inversion_positions_likelihood_exception
88
+ )
89
+
90
+ if os .environ .get ("PYAUTOFIT_TEST_MODE" ) == "1" :
91
+ self .raise_inversion_positions_likelihood_exception = False
92
+
93
+ def modify_before_fit (self , paths : af .DirectoryPaths , model : af .Collection ):
94
+ """
95
+ This function is called immediately before the non-linear search begins and performs final tasks and checks
96
+ before it begins.
97
+
98
+ This function:
99
+
100
+ - Checks that the adapt-dataset is consistent with previous adapt-datasets if the model-fit is being
101
+ resumed from a previous run.
102
+
103
+ - Checks the model and raises exceptions if certain critieria are not met.
104
+
105
+ Once inherited from it also visualizes objects which do not change throughout the model fit like the dataset.
106
+
107
+ Parameters
108
+ ----------
109
+ paths
110
+ The PyAutoFit paths object which manages all paths, e.g. where the non-linear search outputs are stored,
111
+ visualization and the pickled objects used by the aggregator output by this function.
112
+ model
113
+ The PyAutoFit model object, which includes model components representing the galaxies that are fitted to
114
+ the imaging data.
115
+ """
116
+
117
+ super ().modify_before_fit (paths = paths , model = model )
118
+
119
+ self .raise_exceptions (model = model )
120
+
121
+ def raise_exceptions (self , model ):
122
+ has_pix = model .has_model (cls = (aa .Pixelization ,)) or model .has_instance (
123
+ cls = (aa .Pixelization ,)
124
+ )
125
+
126
+ if has_pix :
127
+ if (
128
+ self .positions_likelihood is None
129
+ and self .raise_inversion_positions_likelihood_exception
130
+ and not conf .instance ["general" ]["test" ][
131
+ "disable_positions_lh_inversion_check"
132
+ ]
133
+ ):
134
+ raise exc .AnalysisException (
135
+ "You have begun a model-fit which reconstructs the source using a pixelization.\n \n "
136
+ "However, you have not input a `positions_likelihood` object.\n \n "
137
+ "It is likely your model-fit will infer an inaccurate solution.\n \n "
138
+ ""
139
+ "Please read the following readthedocs page for a description of why this is, and how to set up"
140
+ "a positions likelihood object:\n \n "
141
+ ""
142
+ "https://pyautolens.readthedocs.io/en/latest/general/demagnified_solutions.html"
143
+ )
144
+
145
+ @property
146
+ def preloads_cls (self ):
147
+ return Preloads
148
+
149
+ @property
150
+ def fit_maker_cls (self ):
151
+ return FitMaker
152
+
153
+ def save_results (self , paths : af .DirectoryPaths , result : ResultDataset ):
154
+ """
155
+ At the end of a model-fit, this routine saves attributes of the `Analysis` object to the `files`
156
+ folder such that they can be loaded after the analysis using PyAutoFit's database and aggregator tools.
157
+
158
+ For this analysis it outputs the following:
159
+
160
+ - The maximum log likelihood tracer of the fit.
161
+
162
+ Parameters
163
+ ----------
164
+ paths
165
+ The PyAutoFit paths object which manages all paths, e.g. where the non-linear search outputs are stored,
166
+ visualization and the pickled objects used by the aggregator output by this function.
167
+ result
168
+ The result of a model fit, including the non-linear search, samples and maximum likelihood tracer.
169
+ """
170
+ try :
171
+ output_to_json (
172
+ obj = result .max_log_likelihood_tracer ,
173
+ file_path = paths ._files_path / "tracer.json" ,
174
+ )
175
+ except AttributeError :
176
+ pass
177
+
178
+ image_mesh_list = []
179
+
180
+ for galaxy in result .instance .galaxies :
181
+ pixelization_list = galaxy .cls_list_from (cls = aa .Pixelization )
182
+
183
+ for pixelization in pixelization_list :
184
+ if pixelization is not None :
185
+ image_mesh_list .append (pixelization .image_mesh )
186
+
187
+ if len (image_mesh_list ) > 0 :
188
+ paths .save_json (
189
+ name = "preload_mesh_grids_of_planes" ,
190
+ object_dict = to_dict (
191
+ result .max_log_likelihood_fit .tracer_to_inversion .image_plane_mesh_grid_pg_list
192
+ ),
193
+ )
0 commit comments