Repository: sunpy/sunpy

Issue:
Add an `angular_radius` convenience property to `Helioprojective`
We keep calculating the solar angular radius in various places (e.g., #5177), when we're invariably working with a `Helioprojective` coordinate.  Let's just add a convenience property to `Helioprojective` itself, since it already has all of the information it needs to calculate the solar angular radius.  This would be a natural way to replace `sunpy.map.maputils.solar_angular_radius()` as well (see #4516)


Discussion:
hey @ayshih, I was looking over this issue and is there a python file with helioprojective beacuse I am not able to find it !
Albert will correct if I am wrong but I believe it is this one: https://github.com/sunpy/sunpy/blob/master/sunpy/coordinates/frames.py#L380 

Resolving patch:
diff --git a/sunpy/coordinates/frames.py b/sunpy/coordinates/frames.py
--- a/sunpy/coordinates/frames.py
+++ b/sunpy/coordinates/frames.py
@@ -479,6 +479,25 @@ class Helioprojective(SunPyBaseCoordinateFrame):
     rsun = QuantityAttribute(default=_RSUN, unit=u.km)
     observer = ObserverCoordinateAttribute(HeliographicStonyhurst)
 
+    @property
+    def angular_radius(self):
+        """
+        Angular radius of the Sun as seen by the observer.
+
+        The ``rsun`` frame attribute is the radius of the Sun in length units.
+        The tangent vector from the observer to the edge of the Sun forms a
+        right-angle triangle with the radius of the Sun as the far side and the
+        Sun-observer distance as the hypotenuse. Thus, the sine of the angular
+        radius of the Sun is ratio of these two distances.
+        """
+        from sunpy.coordinates.sun import _angular_radius  # avoiding a circular import
+
+        if not isinstance(self.observer, HeliographicStonyhurst):
+            if self.observer is None:
+                raise ValueError("The observer must be defined, not `None`.")
+            raise ValueError("The observer must be fully defined by specifying `obstime`.")
+        return _angular_radius(self.rsun, self.observer.radius)
+
     def make_3d(self):
         """
         This method calculates the third coordinate of the Helioprojective


Test patch:
diff --git a/sunpy/coordinates/tests/test_frames.py b/sunpy/coordinates/tests/test_frames.py
--- a/sunpy/coordinates/tests/test_frames.py
+++ b/sunpy/coordinates/tests/test_frames.py
@@ -20,6 +20,7 @@
     HeliographicStonyhurst,
     Helioprojective,
 )
+from sunpy.coordinates.sun import angular_radius
 from sunpy.time import parse_time
 from sunpy.util.exceptions import SunpyUserWarning
 
@@ -433,3 +434,20 @@ def test_hgc_incomplete_observer():
     with pytest.raises(ValueError, match=r'Full 3D coordinate \(including radius\) must be specified'):
         SkyCoord(0*u.deg, 0*u.deg, frame="heliographic_carrington",
                  observer='self', obstime="2011-01-01T00:00:00")
+
+
+def test_angular_radius():
+    coord = Helioprojective(0*u.deg, 0*u.deg, 5*u.km, obstime="2010/01/01T00:00:00", observer="earth")
+    assert_quantity_allclose(coord.angular_radius, angular_radius(coord.obstime))
+
+
+def test_angular_radius_no_observer():
+    coord = Helioprojective(0*u.deg, 0*u.deg, 5*u.km, obstime="2010/01/01T00:00:00", observer=None)
+    with pytest.raises(ValueError, match=r"The observer must be defined, not `None`"):
+        coord.angular_radius
+
+
+def test_angular_radius_no_obstime():
+    coord = Helioprojective(0*u.deg, 0*u.deg, 5*u.km, obstime=None, observer="earth")
+    with pytest.raises(ValueError, match=r"The observer must be fully defined by specifying `obstime`."):
+        coord.angular_radius