Repository: sunpy/sunpy

Issue:
Header helper is bugged when creating a PCij matrix from a rotation angle for rectangular pixels
As [noted on the mailing list](https://groups.google.com/d/msgid/sunpy/0352a093-e23d-4681-8113-e560bd2be92an%40googlegroups.com), the calculation in the header helper of a PCij matrix from a rotation angle is incorrect when working with rectangular pixels (`CDELT1` not equal to `CDELT2`) because `lam` is the inverse of what it should be:
https://github.com/sunpy/sunpy/blob/1fa82dd5e39282ab392ae1b8ac4ad3c66b6d65da/sunpy/map/header_helper.py#L156

The analogous bug was fixed in `GenericMap` in #5766, but was missed in the header helper.

Discussion:

Patch:
diff --git a/changelog/6597.bugfix.rst b/changelog/6597.bugfix.rst
new file mode 100644
index 000000000..17fb0e881
--- /dev/null
+++ b/changelog/6597.bugfix.rst
@@ -0,0 +1,1 @@
+Fixed the incorrect calculation in :func:`~sunpy.map.header_helper.make_fitswcs_header` of the rotation matrix from a rotation angle when the pixels are non-square.
diff --git a/sunpy/map/header_helper.py b/sunpy/map/header_helper.py
index f899b83eb..65faa7908 100644
--- a/sunpy/map/header_helper.py
+++ b/sunpy/map/header_helper.py
@@ -169,7 +169,7 @@ def _set_rotation_params(meta_wcs, rotation_angle, rotation_matrix):
         rotation_angle = 0 * u.deg
 
     if rotation_angle is not None:
-        lam = meta_wcs['cdelt1'] / meta_wcs['cdelt2']
+        lam = meta_wcs['cdelt2'] / meta_wcs['cdelt1']
         p = np.deg2rad(rotation_angle)
 
         rotation_matrix = np.array([[np.cos(p), -1 * lam * np.sin(p)],


Test patch:
diff --git a/sunpy/map/tests/test_header_helper.py b/sunpy/map/tests/test_header_helper.py
index fefd01816..1a3d5efe5 100644
--- a/sunpy/map/tests/test_header_helper.py
+++ b/sunpy/map/tests/test_header_helper.py
@@ -66,7 +66,14 @@ def test_metakeywords():
     assert isinstance(meta, dict)
 
 
-def test_deafult_rotation(map_data, hpc_coord):
+def test_scale_conversion(map_data, hpc_coord):
+    # The header will have cunit1/2 of arcsec
+    header = make_fitswcs_header(map_data, hpc_coord, scale=[1, 2] * u.arcmin / u.pix)
+    assert header['cdelt1'] == 60
+    assert header['cdelt2'] == 120
+
+
+def test_default_rotation(map_data, hpc_coord):
     header = make_fitswcs_header(map_data, hpc_coord)
     wcs = WCS(header)
     np.testing.assert_allclose(wcs.wcs.pc, [[1, 0], [0, 1]], atol=1e-5)
@@ -79,6 +86,13 @@ def test_rotation_angle(map_data, hpc_coord):
     np.testing.assert_allclose(wcs.wcs.pc, [[0, -1], [1, 0]], atol=1e-5)
 
 
+def test_rotation_angle_rectangular_pixels(map_data, hpc_coord):
+    header = make_fitswcs_header(map_data, hpc_coord, scale=[2, 5] * u.arcsec / u.pix,
+                                 rotation_angle=45*u.deg)
+    wcs = WCS(header)
+    np.testing.assert_allclose(wcs.wcs.pc, np.sqrt(0.5) * np.array([[1, -2.5], [0.4, 1]]), atol=1e-5)
+
+
 def test_rotation_matrix(map_data, hpc_coord):
     header = make_fitswcs_header(map_data, hpc_coord,
                                  rotation_matrix=np.array([[1, 0], [0, 1]]))