Repository: sunpy/sunpy

Issue:
Mapbase should convert crln_obs to hgln_obs if it is found in the header
This specifically applies to HMI data which uses crln/t_obs rather than hgln/t


Discussion:
Hey, can you help me solve this?
Hi @Akram9 

To get started, it would be worth having a quick read of the paper on [Solar Coordinates](https://www.aanda.org/component/article?access=bibcode&bibcode=&bibcode=2006A%2526A...449..791TFUL) just for a little background.

The Carrington coordinate system (in the header as crln and crlt) is the same as the stonyhurst system (in the header as hgln and hglt) except that the longitude (ln) is offset by a time dependant angle. So what needs to happen is that in mapbase in the [`heliographic_longitude`](https://github.com/sunpy/sunpy/blob/master/sunpy/map/mapbase.py#L609) property if the `hgln_obs` key is not present but the `crln_obs` key is the `crln_obs` should be converted to `hgln_obs` by getting the offset from the [`get_sun_L0`](https://github.com/sunpy/sunpy/blob/master/sunpy/coordinates/ephemeris.py#L107) function given the time from the map.
Thanks, I'll check into these.
@Cadair : So if I understand it right,  what you are saying is to change the first `if` condition checking the presence of `hgln_obs`, and if `crln_obs` is found, convert it to `hgln_obs`, right?
What I mean is that after [this](https://github.com/sunpy/sunpy/blob/master/sunpy/map/mapbase.py#L613) if statement there should be one that checks for `crln_obs`.
So it needs to be something like:
`if heliographic_longitude is None:
     carrington_longitude = self.meta.get('crln_obs', None)
     if carrington_longitude is None:`

And then the change `crln_obs` to `hgln_obs` by getting the offset out of the last `if` block.
Is this good?
* I am not able to get the tabs in the code block
`if heliographic_longitude is None:`
`<tab> carrington_longitude = self.meta.get('crln_obs', None)`
`<tab> if carrington_longitude is None:`

So even the warning code block will change to incorporate the absence of both, right?
Hey, I was going through the issue. I did the following change. Is it okay?

`if heliographic_longitude is None:
            if self.meta.get('crln_obs', None) in not None:
                heliographic_longitude = self.meta.get('crln_obs', None) - get_sun_L0()`

[https://github.com/sunpy/sunpy/blob/master/sunpy/map/mapbase.py#L609](here)
Only one of you can patch this :stuck_out_tongue: 

You are clearly both understanding it. Check one then check the other, return the Stonyhurst one, raise the warning if you can't get either.

@dodoextinct your example is nearly complete but `get_sun_L0` needs to take the time from the map (I think it's the `.date` property). Also I can't remember off the top of my head if it's `+` or a `-`.
Well, personally I'd like @dodoextinct's way to what I was thinking.
> Only one of you can patch this 
> 
> You are clearly both understanding it. Check one then check the other, return the Stonyhurst one, raise the warning if you can't get either.
> 
> @dodoextinct your example is nearly complete but `get_sun_L0` needs to take the time from the map (I think it's the `.date` property). Also I can't remember off the top of my head if it's `+` or a `-`.

I have updated the code like this.
```
if heliographic_longitude is None:
    if self.meta.get('crln_obs', None) is not None:
        heliographic_longitude = self.meta.get('crln_obs', None) - get_sun_L0(self.date)
            
    else:
        #this parts gets executed when crln_obs is also not present in the header.
        if self._default_heliographic_longitude is None:
            warnings.warn_explicit(
                        "Missing metadata for heliographic longitude: "
                        "assuming longitude of 0 degrees",
                        Warning, __file__,
                        inspect.currentframe().f_back.f_lineno)
            self._default_heliographic_longitude = 0
            heliographic_longitude = self._default_heliographic_longitude
```

Also, Stonyhurst longitude and Carrington longitude are related by the equation,

Carrington longitude = Stonyhurst longitude + Carrington longitude of the central meridian
as seen from Earth

Therefore, Stonyhurst longitude = Carrington longitude - Carrington longitude of the central meridian
as seen from Earth.

Ref:
[http://www.mssl.ucl.ac.uk/grid/iau/extra/local_copy/coordinates.pdf](url)
:+1: looks good, open a PR!

(Also I edited your comment to use ` ``` ` for a block of code :smile: )

Resolving patch:
diff --git a/sunpy/map/mapbase.py b/sunpy/map/mapbase.py
--- a/sunpy/map/mapbase.py
+++ b/sunpy/map/mapbase.py
@@ -611,14 +611,16 @@ def heliographic_longitude(self):
         heliographic_longitude = self.meta.get('hgln_obs', None)
 
         if heliographic_longitude is None:
-            if self._default_heliographic_longitude is None:
-                warnings.warn_explicit(
-                    "Missing metadata for heliographic longitude: "
-                    "assuming longitude of 0 degrees",
-                    Warning, __file__,
-                    inspect.currentframe().f_back.f_lineno)
-                self._default_heliographic_longitude = 0
-            heliographic_longitude = self._default_heliographic_longitude
+            if self.meta.get('crln_obs', None) is not None:
+                heliographic_longitude = self.meta['crln_obs'] * u.deg - get_sun_L0(self.date)
+            else:
+                if self._default_heliographic_longitude is None:
+                    warnings.warn_explicit("Missing metadata for heliographic longitude: "
+                                           "assuming longitude of 0 degrees",
+                                           Warning, __file__,
+                                           inspect.currentframe().f_back.f_lineno)
+                    self._default_heliographic_longitude = 0
+                heliographic_longitude = self._default_heliographic_longitude
 
         if isinstance(heliographic_longitude, str):
             heliographic_longitude = float(heliographic_longitude)


Test patch:
diff --git a/sunpy/map/tests/test_mapbase.py b/sunpy/map/tests/test_mapbase.py
--- a/sunpy/map/tests/test_mapbase.py
+++ b/sunpy/map/tests/test_mapbase.py
@@ -27,6 +27,9 @@
 
 testpath = sunpy.data.test.rootdir
 
+@pytest.fixture
+def hmi_test_map():
+    return sunpy.map.Map(os.path.join(testpath, "resampled_hmi.fits"))
 
 @pytest.fixture
 def aia171_test_map():
@@ -194,7 +197,9 @@ def test_coordinate_frame(aia171_test_map):
     assert frame.observer.lon == aia171_test_map.observer_coordinate.frame.lon
     assert frame.observer.radius == aia171_test_map.observer_coordinate.frame.radius
     assert frame.obstime == aia171_test_map.date
-
+    
+def test_heliographic_longitude_crln(hmi_test_map):
+    assert hmi_test_map.heliographic_longitude == hmi_test_map.carrington_longitude - sunpy.coordinates.get_sun_L0(hmi_test_map.date)
 
 # ==============================================================================
 # Test Rotation WCS conversion