2121from autolens import exc
2222
2323
24- class AbstractPositionsLH :
24+ class PositionsLH :
2525 def __init__ (
2626 self ,
27+ positions : aa .Grid2DIrregular ,
2728 threshold : float ,
28- positions : Optional [ aa . Grid2DIrregular ] = None ,
29+ log_likelihood_penalty_factor : float = 1e8 ,
2930 plane_redshift : Optional [float ] = None ,
3031 ):
3132 """
@@ -37,9 +38,17 @@ def __init__(
3738 on the basis that this indicates an unphysical or inaccurate mass model. If they trace within the
3839 threshold the penalty term is not applied.
3940
41+ For the `PositionsLH` object, if the multiple image coordinates do not trace within the source-plane
42+ threshold of one another a penalty to the likelihood is applied:
43+
44+ `log_Likelihood_penalty_base - log_likelihood_penalty_factor * (max_source_plane_separation - threshold)`
45+
46+ The penalty term reduces as the source-plane coordinates trace closer to one another, meaning that the
47+ initial stages of the non-linear search can sample mass models that reduce the threshold.
48+
4049 For example, for one penalty term, if the multiple image coordinates are defined
4150 via `positions=aa.Grid2DIrregular([(1.0, 0.0), (-1.0, 0.0)]` and they do not trace within `threshold=0.3` of
42- one another, the mass model will be rejected and a new model sampled .
51+ one another, the mass model will receive a large likelihood penalty .
4352
4453 The default behaviour assumes a single lens plane and single source plane, meaning the input `positions`
4554 are the image-plane coordinates of one source galaxy at a specifc redshift.
@@ -55,11 +64,13 @@ def __init__(
5564 threshold
5665 If the maximum separation of any two source plane coordinates is above the threshold the penalty term
5766 is applied.
67+ log_likelihood_penalty_factor
68+ A factor which multiplies how far source pixels do not trace within the threshold of one another, with a
69+ larger factor producing a larger penalty making the non-linear parameter space gradient steeper.
5870 plane_redshift
5971 The plane redshift of the lensed source multiple images, which is only required if position threshold
6072 for a double source plane lens system is being used where the specific plane is required.
6173 """
62-
6374 self .positions = positions
6475 self .threshold = threshold
6576 self .plane_redshift = plane_redshift
@@ -71,10 +82,7 @@ def __init__(
7182 "Please input more positions into the Positions."
7283 )
7384
74- def log_likelihood_function_positions_overwrite (
75- self , instance : af .ModelInstance , analysis : AnalysisDataset
76- ) -> Optional [float ]:
77- raise NotImplementedError
85+ self .log_likelihood_penalty_factor = log_likelihood_penalty_factor
7886
7987 def output_positions_info (self , output_path : str , tracer : Tracer ):
8088 """
@@ -94,7 +102,7 @@ def output_positions_info(self, output_path: str, tracer: Tracer):
94102 -------
95103
96104 """
97- with open_ (path .join (output_path , "positions.info" ), "w +" ) as f :
105+ with open_ (path .join (output_path , "positions.info" ), "a +" ) as f :
98106
99107 positions_fit = SourceMaxSeparation (
100108 data = self .positions , noise_map = None , tracer = tracer , plane_redshift = self .plane_redshift
@@ -104,7 +112,11 @@ def output_positions_info(self, output_path: str, tracer: Tracer):
104112 coordinate = (0.0 , 0.0 )
105113 )
106114
107- f .write (f"Plane Redshift: { self .plane_redshift } \n " )
115+ if self .plane_redshift is None :
116+ f .write (f"Plane Index: -1 \n " )
117+ else :
118+ f .write (f"Plane Redshift: { self .plane_redshift } \n " )
119+
108120 f .write (f"Positions: \n { self .positions } \n \n " )
109121 f .write (f"Radial Distance from (0.0, 0.0): \n { distances } \n \n " )
110122 f .write (f"Threshold = { self .threshold } \n " )
@@ -113,116 +125,6 @@ def output_positions_info(self, output_path: str, tracer: Tracer):
113125 )
114126 f .write ("" )
115127
116-
117- class PositionsLHResample (AbstractPositionsLH ):
118- """
119- The `PositionsLH` objects add a penalty term to the likelihood of the **PyAutoLens** `log_likelihood_function`
120- defined in the `Analysis` classes.
121-
122- The penalty term inspects the distance that the locations of the multiple images of the lensed source galaxy
123- trace within one another in the source-plane and penalizes solutions where they trace far from one another,
124- on the basis that this indicates an unphysical or inaccurate mass model. If they trace within the
125- threshold the penalty term is not applied.
126-
127- For the `PositionsLHResample` object, if the multiple image coordinates do not trace within the source-plane
128- threshold of one another the mass model is rejected and a new model is sampled.
129-
130- The penalty term rejects any model where the source-plane coordinates do not trace within the threshold, meaning
131- that the initial stages of the non-linear search may need to sample many mass models randomly in order to sample
132- an initial set that that trace within the threshold.
133-
134- Parameters
135- ----------
136- positions
137- The arcsecond coordinates of the lensed source multiple images which are used to compute the likelihood
138- penalty.
139- threshold
140- If the maximum separation of any two source plane coordinates is above the threshold the penalty term
141- is applied.
142- """
143-
144- def log_likelihood_function_positions_overwrite (
145- self , instance : af .ModelInstance , analysis : AnalysisDataset
146- ) -> Optional [float ]:
147- """
148- This is called in the `log_likelihood_function` of certain `Analysis` classes to add the penalty term of
149- this class, which rejects and resamples mass models which do not trace within the threshold of one another
150- in the source-plane.
151-
152- Parameters
153- ----------
154- instance
155- The instance of the lens model that is being fitted for this iteration of the non-linear search.
156- analysis
157- The analysis class from which the log likliehood function is called.
158- """
159- tracer = analysis .tracer_via_instance_from (instance = instance )
160-
161- if not tracer .has (cls = ag .mp .MassProfile ) or len (tracer .planes ) == 1 :
162- return
163-
164- positions_fit = SourceMaxSeparation (
165- data = self .positions ,
166- noise_map = None ,
167- tracer = tracer ,
168- plane_redshift = self .plane_redshift ,
169- )
170-
171- if not positions_fit .max_separation_within_threshold (self .threshold ):
172- if os .environ .get ("PYAUTOFIT_TEST_MODE" ) == "1" :
173- return
174-
175- raise exc .RayTracingException
176-
177-
178- class PositionsLHPenalty (AbstractPositionsLH ):
179- def __init__ (
180- self ,
181- threshold : float ,
182- log_likelihood_penalty_factor : float = 1e8 ,
183- positions : Optional [aa .Grid2DIrregular ] = None ,
184- plane_redshift : Optional [float ] = None ,
185- ):
186- """
187- The `PositionsLH` objects add a penalty term to the likelihood of the **PyAutoLens** `log_likelihood_function`
188- defined in the `Analysis` classes.
189-
190- The penalty term inspects the distance that the locations of the multiple images of the lensed source galaxy
191- trace within one another in the source-plane and penalizes solutions where they trace far from one another,
192- on the basis that this indicates an unphysical or inaccurate mass model. If they trace within the
193- threshold the penalty term is not applied.
194-
195- For the `PositionsLHPenalty` object, if the multiple image coordinates do not trace within the source-plane
196- threshold of one another a penalty to the likelihood is applied:
197-
198- `log_Likelihood_penalty_base - log_likelihood_penalty_factor * (max_source_plane_separation - threshold)`
199-
200- The penalty term reduces as the source-plane coordinates trace closer to one another, meaning that the
201- initial stages of the non-linear search can sample mass models that reduce the threshold.
202-
203- Parameters
204- ----------
205- positions
206- The arcsecond coordinates of the lensed source multiple images which are used to compute the likelihood
207- penalty.
208- threshold
209- If the maximum separation of any two source plane coordinates is above the threshold the penalty term
210- is applied.
211- log_likelihood_penalty_factor
212- A factor which multiplies how far source pixels do not trace within the threshold of one another, with a
213- larger factor producing a larger penalty making the non-linear parameter space gradient steeper.
214- plane_redshift
215- The plane redshift of the lensed source multiple images, which is only required if position threshold
216- for a double source plane lens system is being used where the specific plane is required.
217- """
218- super ().__init__ (
219- positions = positions ,
220- threshold = threshold ,
221- plane_redshift = plane_redshift
222- )
223-
224- self .log_likelihood_penalty_factor = log_likelihood_penalty_factor
225-
226128 def log_likelihood_penalty_base_from (
227129 self , dataset : Union [aa .Imaging , aa .Interferometer ]
228130 ) -> float :
0 commit comments