99
1010class ExternalShear (MassProfile ):
1111 def __init__ (self , gamma_1 : float = 0.0 , gamma_2 : float = 0.0 ):
12- """
13- An `ExternalShear` term, to model the line-of-sight contribution of other galaxies / satellites.
12+ r"""
13+ Constant external shear term used in strong-lens mass models.
14+
15+ ``ExternalShear`` represents the line-of-sight contribution to the lensing potential from mass that is
16+ not part of the primary lens — typically nearby group/cluster members, large-scale structure, or
17+ unmodelled satellites. Because this contribution is approximately uniform across the small angular
18+ extent of a strong-lens system, it is parameterised as a constant shear with two components,
19+ :math:`\gamma_1` and :math:`\gamma_2`, in the same convention as
20+ ``LensCalc.shear_yx_2d_via_hessian_from`` and ``ShearYX2DIrregular``:
21+
22+ - :math:`\gamma_1` produces stretching along the x/y axes
23+ - :math:`\gamma_2` produces stretching along the diagonals
24+
25+ The associated shear *magnitude* and *position angle* (degrees, anticlockwise from the +x axis) are:
1426
15- The shear angle is defined in the direction of stretching of the image. Therefore, if an object located \
16- outside the lens is responsible for the shear, it will be offset 90 degrees from the value of angle.
27+ .. math::
28+
29+ |\gamma| = \sqrt{\gamma_1^2 + \gamma_2^2}, \qquad
30+ \phi = \tfrac{1}{2} \, \mathrm{arctan2}(\gamma_2, \gamma_1).
31+
32+ Note that the shear *position angle* lies in the direction of image stretching. An external mass
33+ located in the *direction of compression* therefore appears at an angle offset by 90 degrees from
34+ :math:`\phi`.
1735
1836 Parameters
1937 ----------
20- gamma
38+ gamma_1
39+ The :math:`\gamma_1` shear component.
40+ gamma_2
41+ The :math:`\gamma_2` shear component.
2142 """
2243
2344 super ().__init__ (centre = (0.0 , 0.0 ), ell_comps = (0.0 , 0.0 ))
2445 self .gamma_1 = gamma_1
2546 self .gamma_2 = gamma_2
2647
2748 def magnitude (self , xp = np ):
49+ r"""Returns the shear magnitude :math:`|\gamma| = \sqrt{\gamma_1^2 + \gamma_2^2}`."""
2850 return convert .shear_magnitude_from (
2951 gamma_1 = self .gamma_1 , gamma_2 = self .gamma_2 , xp = xp
3052 )
3153
3254 def angle (self , xp = np ):
55+ r"""Returns the shear position angle :math:`\phi = \tfrac{1}{2}\,\mathrm{arctan2}(\gamma_2, \gamma_1)`
56+ in degrees, in the [0, 180) convention used elsewhere in the package."""
3357 return convert .shear_angle_from (
3458 gamma_1 = self .gamma_1 , gamma_2 = self .gamma_2 , xp = xp
3559 )
@@ -42,13 +66,25 @@ def average_convergence_of_1_radius(self):
4266
4367 @aa .decorators .to_array
4468 def convergence_2d_from (self , grid : aa .type .Grid2DLike , xp = np , ** kwargs ):
69+ """A pure shear term has zero convergence at every grid point."""
4570 return xp .zeros (shape = grid .shape [0 ])
4671
4772 @aa .decorators .to_array
4873 def potential_2d_from (self , grid : aa .type .Grid2DLike , xp = np , ** kwargs ):
74+ r"""
75+ Returns the lensing potential of the constant external shear, given by:
76+
77+ .. math::
78+
79+ \psi(\theta) = -\tfrac{1}{2} |\gamma| \, r^2 \, \cos\!\big(2\,(\varphi - \phi_\gamma)\big)
80+
81+ where :math:`r, \varphi` are the polar coordinates of ``grid`` and :math:`\phi_\gamma` is the shear
82+ position angle (offset by ``-90 deg`` to remain consistent with the deflection-angle convention used
83+ elsewhere in PyAutoLens).
84+ """
4985 shear_angle = (
5086 self .angle (xp ) - 90
51- ) ##to be onsistent with autolens deflection angle calculation
87+ ) # offset by -90 deg to match the deflection- angle convention used elsewhere
5288 phig = xp .deg2rad (shear_angle )
5389 shear_amp = self .magnitude (xp = xp )
5490 phicoord = xp .arctan2 (grid .array [:, 0 ], grid .array [:, 1 ])
@@ -59,14 +95,28 @@ def potential_2d_from(self, grid: aa.type.Grid2DLike, xp=np, **kwargs):
5995 @aa .decorators .to_vector_yx
6096 @aa .decorators .transform (rotate_back = True )
6197 def deflections_yx_2d_from (self , grid : aa .type .Grid2DLike , xp = np , ** kwargs ):
62- """
63- Calculate the deflection angles at a given set of arc-second gridded coordinates.
98+ r"""
99+ Returns the deflection angles of the constant external shear at each ``(y, x)`` arc-second
100+ coordinate.
101+
102+ In the profile's rotated reference frame (where the shear position angle is aligned with the x-axis)
103+ the deflection reduces to:
104+
105+ .. math::
106+
107+ \alpha_y(y, x) = -|\gamma| \, y, \qquad \alpha_x(y, x) = +|\gamma| \, x.
108+
109+ The ``@transform(rotate_back=True)`` decorator rotates the input grid into this aligned frame and
110+ rotates the resulting deflection vectors back into the original frame. Because the shear is a spin-2
111+ field, the *position angle* :math:`\phi` of the shear is encoded in the rotation of the grid and not
112+ as an extra factor in the deflection formula above.
64113
65114 Parameters
66115 ----------
67116 grid
68117 The grid of (y,x) arc-second coordinates the deflection angles are computed on.
69-
118+ xp
119+ The array module (``numpy`` or ``jax.numpy``).
70120 """
71121 deflection_y = - xp .multiply (self .magnitude (xp = xp ), grid .array [:, 0 ])
72122 deflection_x = xp .multiply (self .magnitude (xp = xp ), grid .array [:, 1 ])
0 commit comments