@@ -156,7 +156,7 @@ def wofz(z, xp=np):
156156 @aa .grid_dec .transform
157157 def deflections_2d_via_mge_from (
158158 self , grid : aa .type .Grid2DLike , xp = np , * , sigma_log_list , three_D : bool ,
159- sigmas_factor : float = 1.0 , func_terms : int = 28 , ** kwargs ,
159+ ellipticity_convention : str , func_terms : int = 28 , ** kwargs ,
160160 ):
161161 """
162162 Calculates the deflection angle of an arbitrary elliptical convergence / 3d density
@@ -183,6 +183,9 @@ def deflections_2d_via_mge_from(
183183 q = xp .asarray (self .axis_ratio (xp ), dtype = xp .float64 )
184184
185185 # Change ellipticity convention to (q**2*x**2 + y**2) (most profiles are in (x**2 + y**2/q**2))
186+ sigmas_factor = self .sigmas_factor_from (input_convention = ellipticity_convention ,
187+ target_convention = 'minor' ,
188+ xp = xp )
186189 sigmas = sigmas_factor * sigma_log_array
187190
188191 deflection_angles = (
@@ -292,7 +295,7 @@ def zeta_from(self, grid: aa.type.Grid2DLike, sigma_log_list, xp=np):
292295 @aa .grid_dec .transform
293296 def convergence_2d_via_mge_from (
294297 self , grid : aa .type .Grid2DLike , xp = np , * ,
295- sigma_log_list , three_D : bool , sigmas_factor : float = 1.0 , func_terms : int = 28 , ** kwargs ,
298+ sigma_log_list , three_D : bool , ellipticity_convention : str , func_terms : int = 28 , ** kwargs ,
296299 ):
297300 """
298301 Calculate the projected convergence at a given set of arc-second gridded coordinates.
@@ -306,6 +309,11 @@ def convergence_2d_via_mge_from(
306309
307310 eccentric_radii = self .mass_profile .eccentric_radii_grid_from (grid = grid , xp = xp , ** kwargs )
308311
312+
313+ sigmas_factor = self .sigmas_factor_from (input_convention = ellipticity_convention ,
314+ target_convention = 'circularised' ,
315+ xp = xp )
316+
309317 return self ._convergence_2d_via_mge_from (grid_radii = eccentric_radii , xp = xp , sigma_log_list = sigma_log_list ,
310318 three_D = three_D , sigmas_factor = sigmas_factor , func_terms = func_terms
311319 )
@@ -328,7 +336,7 @@ def _convergence_2d_via_mge_from(self, grid_radii, xp=np, *, sigma_log_list, thr
328336 sigma_log_list = sigma_log_array , func_terms = func_terms , three_D = three_D , xp = xp )
329337
330338 # Change ellipticity convention to (q*x**2 + y**2/q) (most profiles are in (x**2 + y**2/q**2))
331- sigmas = xp . sqrt ( self . mass_profile . axis_ratio ( xp )) * xp .asarray (sigmas )[:, None ] / sigmas_factor
339+ sigmas = sigmas_factor * xp .asarray (sigmas )[:, None ]
332340 amps = xp .asarray (amps )[:, None ]
333341
334342 grid_radii = grid_radii [None , ...]
@@ -348,3 +356,100 @@ def convergence_func_gaussian(self, grid_radii, sigma, intensity, xp=np):
348356 return xp .multiply (
349357 intensity , xp .exp (- 0.5 * xp .square (xp .divide (grid_radii .array , sigma )))
350358 )
359+
360+ def sigmas_factor_from (self , input_convention : str , target_convention : str , xp = np ):
361+ """
362+ Returns the multiplicative factor required to convert a scale parameter (e.g. sigma)
363+ defined under one ellipticity convention to another.
364+
365+ The three supported ellipticity conventions are:
366+
367+ Major-axis convention
368+ ---------------------
369+ The elliptical radius is defined such that the scale parameter lies along
370+ the major axis:
371+
372+ R^2 = x^2 + y^2 / q^2
373+
374+ where q = b/a is the projected minor-to-major axis ratio (q <= 1).
375+ In this convention, the scale parameter corresponds directly to the
376+ semi-major axis length.
377+
378+ Circularised convention
379+ ------------------------
380+ The elliptical radius is defined such that the ellipse has the same area
381+ as a circle of radius R:
382+
383+ R^2 = q x^2 + y^2 / q
384+
385+ In this case:
386+
387+ a = R / sqrt(q)
388+ b = R sqrt(q)
389+
390+ and the enclosed area πab = πR^2 is independent of q.
391+ The scale parameter corresponds to the circularised radius.
392+
393+ Minor-axis convention
394+ ----------------------
395+ The elliptical radius is defined such that the scale parameter lies along
396+ the minor axis:
397+
398+ R^2 = q^2 x^2 + y^2
399+
400+ Here, the scale parameter corresponds directly to the semi-minor axis length.
401+
402+ ------------------------------------------------------------------------------
403+
404+ Parameters
405+ ----------
406+ input_convention : str
407+ The current definition of the scale parameter.
408+ Must be one of: 'major', 'circularised', or 'minor'.
409+
410+ target_convention : str
411+ The desired definition of the scale parameter.
412+ Must be one of: 'major', 'circularised', or 'minor'.
413+
414+ Returns
415+ -------
416+ float or array-like
417+ Multiplicative factor required to convert the scale parameter
418+ between ellipticity conventions.
419+ """
420+ if target_convention == 'major' :
421+ if input_convention == 'major' :
422+ return 1.0
423+ elif input_convention == 'circularised' :
424+ return xp .divide (1.0 , xp .sqrt (self .mass_profile .axis_ratio (xp )))
425+ elif input_convention == 'minor' :
426+ return xp .divide (1.0 , self .mass_profile .axis_ratio (xp ))
427+ else :
428+ raise TypeError (
429+ "sigmas_factor_from takes either 'major', 'circularised' or 'minor' as an input ellipticity convention" )
430+
431+ elif target_convention == 'circularised' :
432+ if input_convention == "major" :
433+ return xp .sqrt (self .mass_profile .axis_ratio (xp ))
434+ elif input_convention == "circularised" :
435+ return 1.0
436+ elif input_convention == "minor" :
437+ return xp .divide (1.0 , xp .sqrt (self .mass_profile .axis_ratio (xp )))
438+ else :
439+ raise TypeError (
440+ "sigmas_factor_from takes either 'major', 'circularised' or 'minor' as an input ellipticity convention" )
441+
442+ elif target_convention == 'minor' :
443+ if input_convention == "major" :
444+ return self .mass_profile .axis_ratio (xp )
445+ elif input_convention == "circularised" :
446+ return xp .sqrt (self .mass_profile .axis_ratio (xp ))
447+ elif input_convention == "minor" :
448+ return 1.0
449+ else :
450+ raise TypeError (
451+ "sigmas_factor_from takes either 'major', 'circularised' or 'minor' as an input ellipticity convention" )
452+
453+ else :
454+ raise TypeError (
455+ "sigmas_factor_from takes either 'major', 'circularised' or 'minor' as a target ellipticity convention" )
0 commit comments