|
1 | 1 | import numpy as np |
2 | 2 | from typing import Tuple |
| 3 | +from autogalaxy.convert import multipole_comps_from, multipole_k_m_and_phi_m_from |
3 | 4 |
|
4 | 5 |
|
5 | 6 | from autogalaxy.ellipse.ellipse.ellipse import Ellipse |
@@ -72,3 +73,57 @@ def points_perturbed_from( |
72 | 73 | y = points[:, 0] + radial * np.sin(theta) |
73 | 74 |
|
74 | 75 | return np.stack((y, x), axis=-1) |
| 76 | + |
| 77 | +class EllipseMultipoleRelative(EllipseMultipole): |
| 78 | + def __init__( |
| 79 | + self, |
| 80 | + m=4, |
| 81 | + input_multipole_comps: Tuple[float, float] = (0.0, 0.0), |
| 82 | + major_axis=1., |
| 83 | + ): |
| 84 | + self.input_multipole_comps = input_multipole_comps |
| 85 | + k, phi = multipole_k_m_and_phi_m_from(multipole_comps=input_multipole_comps, m=m) |
| 86 | + k_adjusted = k*major_axis |
| 87 | + |
| 88 | + adjusted_multipole_comps = multipole_comps_from(k_adjusted, phi, m) |
| 89 | + |
| 90 | + super().__init__(m, adjusted_multipole_comps) |
| 91 | + |
| 92 | + self.adjusted_multipole_comps = adjusted_multipole_comps |
| 93 | + self.m = m |
| 94 | + |
| 95 | + def points_perturbed_from( |
| 96 | + self, pixel_scale, points, ellipse: Ellipse, n_i: int = 0 |
| 97 | + ) -> np.ndarray: |
| 98 | + """ |
| 99 | + Returns the (y,x) coordinates of the input points, which are perturbed by the multipole of the ellipse. |
| 100 | +
|
| 101 | + Parameters |
| 102 | + ---------- |
| 103 | + pixel_scale |
| 104 | + The pixel scale of the data that the ellipse is fitted to and interpolated over. |
| 105 | + points |
| 106 | + The (y,x) coordinates of the ellipse that are perturbed by the multipole. |
| 107 | + ellipse |
| 108 | + The ellipse that is perturbed by the multipole, which is used to compute the angles of the ellipse. |
| 109 | +
|
| 110 | + Returns |
| 111 | + ------- |
| 112 | + The (y,x) coordinates of the input points, which are perturbed by the multipole. |
| 113 | + """ |
| 114 | + |
| 115 | + # 1) compute cartesian (polar) angle |
| 116 | + theta = np.arctan2(points[:,0], points[:,1]) # <- true polar angle |
| 117 | + |
| 118 | + # 2) multipole in that same frame |
| 119 | + delta_theta = self.m * (theta - ellipse.angle_radians) |
| 120 | + radial = ( |
| 121 | + self.adjusted_multipole_comps[1] * np.cos(delta_theta) |
| 122 | + + self.adjusted_multipole_comps[0] * np.sin(delta_theta) |
| 123 | + ) |
| 124 | + |
| 125 | + # 3) perturb along the true radial direction |
| 126 | + x = points[:, 1] + radial * np.cos(theta) |
| 127 | + y = points[:, 0] + radial * np.sin(theta) |
| 128 | + |
| 129 | + return np.stack((y, x), axis=-1) |
0 commit comments