Repository: sunpy/sunpy

Issue:
Reproduce the "Where is STEREO?" plot in SunPy
### Describe the feature

The STEREO webpage has a handy figure showing where STEREO and other spacecraft are: https://stereo-ssc.nascom.nasa.gov/where.shtml . Given the existing examples in the SunPy gallery it seems that this should be reproducible using SunPy.

### Proposed solution

The solution would use a mix of existing examples that use the ability to get locations of spacecraft and planets.

Discussion:
Jett-Code: Can someone help me with these failed tests?

exitflynn: hi @Jett-Code, i'm a contributor as well but i think i can help you a bit about the tests: 
- Some PR's require a `changelog` entry, some don't (in the latter case you can ignore the changelog failing test but fwiw i think this PR should require one). You can see [this section](https://docs.sunpy.org/en/latest/dev_guide/contents/newcomers.html#setting-up-a-development-environment) of the Newcomer's Guide, in particular [this](https://docs.astropy.org/en/latest/development/workflow/development_workflow.html#add-changelog) part of the astropy workflow docs.
- The `codecov` test is about writing tests for any new code that you've added. Since the PR is only about an example entry and no changes in sunpy functionality have been made i suppose you can ignore this.
- You can fix the `pre-commit` test by either installing and setting up the pre-commit hook with git or by commenting `pre-commit.ci autofix` and have the bot fix it for you

i hope this isn't bad practice, please correct me if im wrong!
Jett-Code: Thank you so much @exitflynn 
Jett-Code: pre-commit.ci autofix
Jett-Code: 

> hi @Jett-Code, i'm a contributor as well but i think i can help you a bit about the tests:
> 
> * Some PR's require a `changelog` entry, some don't (in the latter case you can ignore the changelog failing test but fwiw i think this PR should require one). You can see [this section](https://docs.sunpy.org/en/latest/dev_guide/contents/newcomers.html#setting-up-a-development-environment) of the Newcomer's Guide, in particular [this](https://docs.astropy.org/en/latest/development/workflow/development_workflow.html#add-changelog) part of the astropy workflow docs.
> * The `codecov` test is about writing tests for any new code that you've added. Since the PR is only about an example entry and no changes in sunpy functionality have been made i suppose you can ignore this.
> * You can fix the `pre-commit` test by either installing and setting up the pre-commit hook with git or by commenting `pre-commit.ci autofix` and have the bot fix it for you
> 
> i hope this isn't bad practice, please correct me if I'm wrong!

As specified in the link I've to create a file in docs/changes/<sub-package> but there is no dir with the name changes in docs

Jett-Code: pre-commit.ci autofix

exitflynn: glad i could be of help! 
there are some similarities in astropy and sunpy workflow but some differences too and this is one of the latter cases. you can see previous changelogs and add yours in the [ `changelog/`](https://github.com/sunpy/sunpy/tree/main/changelog) folder.
Jett-Code: pre-commit.ci autofix
Jett-Code: > glad i could be of help! there are some similarities in astropy and sunpy workflow but some differences too and this is one of the latter cases. you can see previous changelogs and add yours in the [ `changelog/`](https://github.com/sunpy/sunpy/tree/main/changelog) folder.

Gotcha, thanks!
Jett-Code: Thanks for letting me know about the changes.
Done with all the changes.
Please tell me if I'm leaving something.

Jett-Code: pre-commit.ci autofix

Patch:
diff --git a/README.rst b/README.rst
index 018b3beac..36dc62656 100644
--- a/README.rst
+++ b/README.rst
@@ -9,7 +9,7 @@
 .. |DOI| image:: https://zenodo.org/badge/2165383.svg
    :target: https://zenodo.org/badge/latestdoi/2165383
 .. |matrix| image:: https://img.shields.io/matrix/sunpy:openastronomy.org.svg?colorB=%23FE7900&label=Chat&logo=matrix&server_fqdn=openastronomy.modular.im
-   :target: https://openastronomy.element.io/#/room/#sunpy:openastronomy.org
+   :target: https://app.element.io/#/room/#sunpy:openastronomy.org
 .. |codecov| image:: https://codecov.io/gh/sunpy/sunpy/branch/main/graph/badge.svg
    :target: https://codecov.io/gh/sunpy/sunpy
 .. |Binder| image:: https://mybinder.org/badge_logo.svg
@@ -80,4 +80,4 @@ Code of Conduct
 
 When you are interacting with the SunPy community you are asked to follow our `Code of Conduct <https://sunpy.org/coc>`__.
 
-.. _SunPy Chat: https://openastronomy.element.io/#/room/#sunpy:openastronomy.org
+.. _SunPy Chat: https://app.element.io/#/room/#sunpy:openastronomy.org
diff --git a/changelog/6648.bugfix.rst b/changelog/6648.bugfix.rst
new file mode 100644
index 000000000..0a0b7a6eb
--- /dev/null
+++ b/changelog/6648.bugfix.rst
@@ -0,0 +1,1 @@
+Fixed a bug that prevented specifying a `~astropy.coordinates.BaseCoordinateFrame` (as opposed to a `~astropy.coordinates.SkyCoord`) to :meth:`sunpy.map.GenericMap.draw_quadrangle`.
diff --git a/changelog/6743.deprecation.rst b/changelog/6743.deprecation.rst
new file mode 100644
index 000000000..07b60a9a8
--- /dev/null
+++ b/changelog/6743.deprecation.rst
@@ -0,0 +1,2 @@
+Using `~sunpy.map.header_helper.meta_keywords` is deprecated.
+Please see :ref:`Meta Keywords Table` for the list of metadata keywords used by `~sunpy.map.Map`.
diff --git a/changelog/6744.doc.rst b/changelog/6744.doc.rst
new file mode 100644
index 000000000..cc5246018
--- /dev/null
+++ b/changelog/6744.doc.rst
@@ -0,0 +1,1 @@
+Added an example (:ref:`sphx_glr_generated_gallery_time_series_goes_xrs_nrt_data.py`) to download GOES NRT data and load it into `~sunpy.timeseries.TimeSeries`.
diff --git a/changelog/6757.doc.rst b/changelog/6757.doc.rst
new file mode 100644
index 000000000..5a9964add
--- /dev/null
+++ b/changelog/6757.doc.rst
@@ -0,0 +1,1 @@
+Added an example gallery (:ref:`sphx_glr_generated_gallery_acquiring_data_querying_and_loading_SHARP_data.py`) for querying SHARP data and loading it into a `~sunpy.map.Map`.
diff --git a/changelog/6771.doc.rst b/changelog/6771.doc.rst
new file mode 100644
index 000000000..a2a7a9b30
--- /dev/null
+++ b/changelog/6771.doc.rst
@@ -0,0 +1,1 @@
+Added an example (:ref:`sphx_glr_generated_gallery_units_and_coordinates_ParkerSolarProbe_trajectory.py`) to plot the trajectory of Parker Solar Probe.
diff --git a/docs/conf.py b/docs/conf.py
index 5e68e9d20..c28980c96 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -204,24 +204,19 @@ intersphinx_mapping = {
 }
 
 # -- Options for hoverxref -----------------------------------------------------
-# adapted from sphinx-hoverxref conf.py
 if os.environ.get("READTHEDOCS"):
-    # Building on Read the Docs
     hoverxref_api_host = "https://readthedocs.org"
 
     if os.environ.get("PROXIED_API_ENDPOINT"):
         # Use the proxied API endpoint
-        # - A RTD thing to avoid a CSRF block when docs are using a
-        #   custom domain
+        # A RTD thing to avoid a CSRF block when docs are using a custom domain
         hoverxref_api_host = "/_"
 
 hoverxref_tooltip_maxwidth = 600  # RTD main window is 696px
 hoverxref_auto_ref = True
 hoverxref_mathjax = True
-
 # hoverxref has to be applied to these
 hoverxref_domains = ["py"]
-#hoverxref_roles = ["confval", "term"]
 
 hoverxref_role_types = {
     # roles with py domain
@@ -234,13 +229,13 @@ hoverxref_role_types = {
     "meth": "tooltip",
     "mod": "tooltip",
     "obj": "tooltip",
-    #
     # roles with std domain
     "confval": "tooltip",
     "hoverxref": "tooltip",
     "ref": "tooltip",
     "term": "tooltip",
 }
+hoverxref_intersphinx = ["numpy", "astropy", "python"]
 
 # -- Options for HTML output ---------------------------------------------------
 # The theme to use for HTML and HTML Help pages.  See the documentation for
diff --git a/docs/dev_guide/contents/example_gallery.rst b/docs/dev_guide/contents/example_gallery.rst
index cd7f847af..7843a5dd0 100644
--- a/docs/dev_guide/contents/example_gallery.rst
+++ b/docs/dev_guide/contents/example_gallery.rst
@@ -4,11 +4,9 @@
 Example Gallery
 ***************
 
-The purpose of the page is to describe the contribution guidelines for the `sunpy Example Gallery <https://docs.sunpy.org/en/stable/generated/gallery/index.html>`_.
+The purpose of the page is to describe the contribution guidelines for the `sunpy Example Gallery <https://docs.sunpy.org/en/stable/generated/gallery/index.html>`__.
 
-All potential contributors to the sunpy Example Gallery should read and abide by the following guidelines.
-
-.. note:: We have an example template located at ``examples/example_template/example_template.py``.
+All potential contributors to the ``sunpy`` example gallery should read and abide by the following guidelines.
 
 Contribution Guidelines
 =======================
@@ -18,13 +16,13 @@ Contribution Guidelines
 
 * Each example should begin with a paragraph that gives a brief overview of the entire example, including relevant astronomy concepts, and motivates the described functionality.
 
-* The examples must be compatible with the versions supported by the last major release of the sunpy core package (i.e., Python >= 3.7).
+* The examples must be compatible with the versions supported by the last major release of the ``sunpy`` core package.
 
-* All the examples must be fully PEP8 compliant, we recommend using one of the many PEP8 linters that are available (autopep8, flake8 as some examples).
+* All the examples must be fully PEP8 compliant, the ``pre-commit`` hook should be used to ensure this.
 
-* Wherever possible, the examples should include linked references with links pointing to the appropriate `DOI <https://zenodo.org/record/2551710>`_ or `ADS <https://ui.adsabs.harvard.edu/>`_ entry.
+* Wherever possible, the examples should include linked references with links pointing to the appropriate `DOI <https://zenodo.org/record/2551710>`__ or `ADS <https://ui.adsabs.harvard.edu/>`__ entry.
 
-* The example should include links to relevant documentation pages.
+* The example should include links (URL or `sphinx intersphinx <https://coderefinery.github.io/sphinx-lesson/intersphinx/>`__) to relevant documentation pages.
 
 * Each example should, where possible, include at least one image, map, or plot to use as the icon in the example gallery.
 
@@ -43,6 +41,9 @@ Contribution Guidelines
 
   * If an axes instance is created, it should be explicitly passed as a keyword argument wherever possible (e.g. in `~sunpy.map.GenericMap.plot` or `~sunpy.map.GenericMap.draw_grid`).
 
-  * After each figure is created, call ``plt.show()``. While not explicitly needed for the gallery to render, this ensures that, when run as a script, the gallery will display each figure sequentially.
+  * At the end of the example,  call ``plt.show()``.
+    While not explicitly needed for the gallery to render, this ensures that when run as a script, the plots will appear.
 
   * If you need to use ``astropy.visualization.{quantity_support, time_support}``, import these functions at the top of the example, and call them directly before the first plot that needs them.
+
+.. note:: We have an example template located at :file:`sunpy/examples/example_template/example_template.py`.
diff --git a/docs/dev_guide/contents/newcomers.rst b/docs/dev_guide/contents/newcomers.rst
index af737e96a..254c6ca59 100644
--- a/docs/dev_guide/contents/newcomers.rst
+++ b/docs/dev_guide/contents/newcomers.rst
@@ -10,7 +10,7 @@ The people who help develop or contribute to SunPy are varied in ability and exp
 
 If you have any questions, comments, or just want to say hello, we have an active `chat room`_, a `mailing list`_ and a `community forum`_.
 
-.. _chat room: https://openastronomy.element.io/#/room/#sunpy:openastronomy.org
+.. _chat room: https://app.element.io/#/room/#sunpy:openastronomy.org
 .. _mailing list: https://groups.google.com/forum/#!forum/sunpy
 .. _community forum: https://community.openastronomy.org/c/sunpy/5
 
@@ -186,7 +186,7 @@ If you get stuck or want help, just `ask here`_!
 .. _GitHub: https://github.com/
 .. _fork: https://guides.github.com/activities/forking/
 .. _sunpy repository: https://github.com/sunpy/sunpy
-.. _ask here: https://openastronomy.element.io/#/room/#sunpy:openastronomy.org
+.. _ask here: https://app.element.io/#/room/#sunpy:openastronomy.org
 
 Checking the code you have written
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/docs/index.rst b/docs/index.rst
index 203d98fe8..b45dd2f4e 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -56,7 +56,7 @@ Further Info
 * Read the :ref:`Developers guide <dev_guide>` to start contributing to the SunPy project.
 
 
-.. _chat room: https://openastronomy.element.io/#/room/#sunpy:openastronomy.org
+.. _chat room: https://app.element.io/#/room/#sunpy:openastronomy.org
 .. _GitHub issue tracker: https://github.com/sunpy/sunpy/issues
 .. _discourse: https://community.openastronomy.org/c/sunpy/5
 
diff --git a/docs/intro/maps.rst b/docs/intro/maps.rst
index e54c5f560..5c0c7d44a 100644
--- a/docs/intro/maps.rst
+++ b/docs/intro/maps.rst
@@ -505,6 +505,8 @@ This includes a :func:`~sunpy.map.header_helper.meta_keywords` function that wil
      ...
 
 The utility function :func:`~sunpy.map.header_helper.make_fitswcs_header` will return a header with the appropriate FITS keywords once the Map data array and an `astropy.coordinates.SkyCoord` or `sunpy.coordinates.frames` is provided.
+All the metadata keywords that a Map will parse along with their description are listed in the :ref:`Meta Keywords Table` at the end of this page.
+
 The `astropy.coordinates.SkyCoord` is defined by the user and contains information on the reference frame, reference coordinate, and observer location.
 This function returns a `sunpy.util.MetaDict`.
 The `astropy.coordinates.SkyCoord` or `sunpy.coordinates.frames` must contain an observation time.
@@ -649,3 +651,90 @@ From these header MetaDict's that are generated, we can now create a custom map:
 .. code-block:: python
 
     >>> my_map = sunpy.map.Map(data, header)
+
+.. _Meta Keywords Table:
+
+.. list-table:: Meta Keywords
+   :widths: 7 30
+   :header-rows: 1
+
+   * - Keyword
+     - Description
+   * - cunit1
+     - Units of the coordinate increments along naxis1 e.g. arcsec (required)
+   * - cunit2
+     - Units of the coordinate increments along naxis2 e.g. arcsec (required)
+   * - crval1
+     - Coordinate value at reference point on naxis1 (required)
+   * - crval2
+     - Coordinate value at reference point on naxis2 (required)
+   * - cdelt1
+     - Spatial scale of pixels for naxis1, i.e. coordinate increment at reference point
+   * - cdelt2
+     - Spatial scale of pixels for naxis2, i.e. coordinate increment at reference point
+   * - crpix1
+     - Pixel coordinate at reference point naxis1
+   * - crpix2
+     - Pixel coordinate at reference point naxis2
+   * - ctype1
+     - Coordinate type projection along naxis1 of data e.g. HPLT-TAN
+   * - ctype2
+     - Coordinate type projection along naxis2 of data e.g. HPLN-TAN
+   * - hgln_obs
+     - Heliographic longitude of observation
+   * - hglt_obs
+     - Heliographic latitude of observation
+   * - dsun_obs
+     - distance to Sun from observation in metres
+   * - rsun_obs
+     - radius of Sun in meters from observation
+   * - dateobs
+     - date of observation e.g. 2013-10-28 00:00
+   * - date_obs
+     - date of observation e.g. 2013-10-28 00:00
+   * - rsun_ref
+     - reference radius of Sun in meters
+   * - solar_r
+     - radius of Sun in meters from observation
+   * - radius
+     - radius of Sun in meters from observation
+   * - crln_obs
+     - Carrington longitude of observation
+   * - crlt_obs
+     - Heliographic latitude of observation
+   * - solar_b0
+     - Solar B0 angle
+   * - detector
+     - name of detector e.g. AIA
+   * - exptime
+     - exposure time of observation, in seconds e.g 2
+   * - instrume
+     - name of instrument
+   * - wavelnth
+     - wavelength of observation
+   * - waveunit
+     - unit for which observation is taken e.g. angstom
+   * - obsrvtry
+     - name of observatory of observation
+   * - telescop
+     - name of telescope of observation
+   * - lvl_num
+     - FITS processing level
+   * - crota2
+     - Rotation of the horizontal and vertical axes in degrees
+   * - PC1_1
+     - Matrix element PCi_j describing the rotation required to align solar North with the top of the image.
+   * - PC1_2
+     - Matrix element PCi_j describing the rotation required to align solar North with the top of the image.
+   * - PC2_1
+     - Matrix element PCi_j describing the rotation required to align solar North with the top of the image.
+   * - PC2_2
+     - Matrix element PCi_j describing the rotation required to align solar North with the top of the image.
+   * - CD1_1
+     - Matrix element CDi_j describing the rotation required to align solar North with the top of the image.
+   * - CD1_2
+     - Matrix element CDi_j describing the rotation required to align solar North with the top of the image.
+   * - CD2_1
+     - Matrix element CDi_j describing the rotation required to align solar North with the top of the image.
+   * - CD2_2
+     - Matrix element CDi_j describing the rotation required to align solar North with the top of the image.
diff --git a/examples/acquiring_data/querying_and_loading_SHARP_data.py b/examples/acquiring_data/querying_and_loading_SHARP_data.py
new file mode 100644
index 000000000..ea6c33ac9
--- /dev/null
+++ b/examples/acquiring_data/querying_and_loading_SHARP_data.py
@@ -0,0 +1,48 @@
+"""
+===============================
+Querying and loading SHARP data
+===============================
+
+In this example we will demonstrate how to acquire `Spaceweather HMI Active Region Patch (SHARP) <http://jsoc.stanford.edu/doc/data/hmi/sharp/sharp.htm>`__ data and load it into a `sunpy.map.Map`.
+"""
+import os
+
+import matplotlib.pyplot as plt
+
+import astropy.units as u
+
+import sunpy.map
+from sunpy.net import Fido
+from sunpy.net import attrs as a
+
+###################################################################
+# To search for SHARP data, we will need to query the `JSOC <http://jsoc.stanford.edu/>`__.
+# We will use `Fido <sunpy.net.fido_factory.UnifiedDownloaderFactory>`
+# and make use of the search attributes in `sunpy.net.jsoc` that allow us to query the JSOC.
+#
+# Exporting data from the JSOC requires registering your email first.
+# Please replace this with your email address once you have registered.
+# See `this page <http://jsoc.stanford.edu/ajax/register_email.html>`__ for more details.
+jsoc_email = os.environ["JSOC_EMAIL"]
+
+result = Fido.search(a.Time("2011-03-09 23:20:00", "2011-03-09 23:30:00"),
+                     a.Sample(1*u.hour),
+                     a.jsoc.Series("hmi.sharp_cea_720s"),
+                     a.jsoc.PrimeKey("HARPNUM", 401),
+                     a.jsoc.Notify(jsoc_email),
+                     a.jsoc.Segment("Bp"))
+print(result)
+
+###################################################################
+# Next, we can download the file.
+
+file = Fido.fetch(result)
+
+###################################################################
+# Now that we have the file, we can construct a `~sunpy.map.Map` and plot it.
+
+sharp_map = sunpy.map.Map(file)
+plt.figure()
+sharp_map.plot(vmin=-1500, vmax=1500)
+
+plt.show()
diff --git a/examples/differential_rotation/differentially_rotated_coordinate.py b/examples/differential_rotation/differentially_rotated_coordinate.py
index e42c0dc86..0fa8137da 100644
--- a/examples/differential_rotation/differentially_rotated_coordinate.py
+++ b/examples/differential_rotation/differentially_rotated_coordinate.py
@@ -34,7 +34,7 @@ point = SkyCoord(187*u.arcsec, 283*u.arcsec, frame=aiamap.coordinate_frame)
 # times.  Let's define a daily cadence for +/- five days.
 
 durations = np.concatenate([range(-5, 0), range(1, 6)]) * u.day
-diffrot_point = RotatedSunFrame(base=point, duration=durations)
+diffrot_point = SkyCoord(RotatedSunFrame(base=point, duration=durations))
 
 ##############################################################################
 # To see what this coordinate looks like in "real" helioprojective
diff --git a/examples/time_series/goes_xrs_nrt_data.py b/examples/time_series/goes_xrs_nrt_data.py
new file mode 100644
index 000000000..d42168c01
--- /dev/null
+++ b/examples/time_series/goes_xrs_nrt_data.py
@@ -0,0 +1,72 @@
+"""
+=======================================================
+Creating a TimeSeries from GOES-XRS near real time data
+=======================================================
+
+This example will demonstrate how to download and load GOES XRS Near Real Time (NRT) data into a `sunpy.timeseries.TimeSeries`.
+"""
+
+import matplotlib.pyplot as plt
+import pandas as pd
+
+from astropy import units as u
+
+from sunpy import timeseries as ts
+from sunpy.time import parse_time
+
+###############################################################################
+# We will start by getting reading the GOES-XRS JSON file using `pandas.read_json`.
+# This allows us to download the file and load it straight into a `pandas.DataFrame`.
+# This file updates every minute and contains only the last 7 days worth of data.
+
+goes_json_data = pd.read_json("https://services.swpc.noaa.gov/json/goes/primary/xrays-7-day.json")
+
+###############################################################################
+# XRS collects data in two energy channels, "0.05-0.4nm" and "0.1-0.8nm".
+# We separate these "short" and "long" wavelength readings into two arrays.
+
+# This will get us the short wavelength data.
+goes_short = goes_json_data[goes_json_data["energy"] == "0.05-0.4nm"]
+# This will get us the long wavelength data.
+goes_long = goes_json_data[goes_json_data["energy"] == "0.1-0.8nm"]
+
+###############################################################################
+# `sunpy.timeseries.TimeSeries` requires a datetime index which we can get
+# directly and transform into `astropy.time.Time`.
+
+time_array = parse_time(goes_short["time_tag"])
+
+###############################################################################
+# `sunpy.timeseries.TimeSeries` requires that there are units for data variables.
+# To do this, we will create a dictionary that will map the names of the two columns,
+# "xrsa" and "xrsb" (the channel names for GOES XRS), to their corresponding
+# physical flux units, ``u.W/u.m**2``.
+
+units = dict([("xrsa", u.W/u.m**2), ("xrsb", u.W/u.m**2)])
+
+###############################################################################
+# We need to create a metadata dictionary for the data.
+# Typically, `sunpy.timeseries.TimeSeries` reads the metadata directly from the file.
+# However, here we need to define our own metadata and we will keep it fairly simple.
+
+meta = dict({"instrument": "GOES X-ray sensor", "measurements": "primary", "type": "quicklook"})
+
+###############################################################################
+#  The final pre-step is create a new `pandas.DataFrame` which we can pass to
+# `sunpy.timeseries.TimeSeries` as the data input.
+
+goes_data = pd.DataFrame({"xrsa": goes_short["flux"].values, "xrsb": goes_long["flux"].values}, index=time_array.datetime)
+
+###############################################################################
+# Now we will create a `sunpy.timeseries.TimeSeries` by passing in the data,
+# the metadata and the units.
+
+goes_ts = ts.TimeSeries(goes_data, meta, units, source="xrs")
+
+###############################################################################
+# Finally, we can plot the timeseries.
+
+plt.figure()
+goes_ts.plot()
+
+plt.show()
diff --git a/examples/units_and_coordinates/ParkerSolarProbe_trajectory.py b/examples/units_and_coordinates/ParkerSolarProbe_trajectory.py
new file mode 100644
index 000000000..b96759246
--- /dev/null
+++ b/examples/units_and_coordinates/ParkerSolarProbe_trajectory.py
@@ -0,0 +1,77 @@
+"""
+===================================================
+Obtaining a spacecraft trajectory from JPL Horizons
+===================================================
+
+This example shows how to obtain the trajectory of a spacecraft from JPL Horizons
+and plot it relative to other bodies in the solar system.
+
+JPL `Horizons <https://ssd.jpl.nasa.gov/horizons/>`__ can return the locations of
+planets and minor bodies (e.g., asteroids) in the solar system, and it can also
+return the location of a variety of major spacecraft.
+
+You will need `astroquery <https://astroquery.readthedocs.io/>`__ installed.
+"""
+
+import matplotlib.pyplot as plt
+
+import astropy.units as u
+
+from sunpy.coordinates import get_body_heliographic_stonyhurst, get_horizons_coord
+from sunpy.time import parse_time
+
+##############################################################################
+# We use :func:`~sunpy.coordinates.get_horizons_coord` to query JPL Horizons
+# for the trajectory of Parker Solar Probe (PSP).  Let's request 50 days on
+# either side of PSP's 14th closest approach to the Sun.
+
+perihelion_14 = parse_time('2022-12-11 13:16')
+psp = get_horizons_coord('Parker Solar Probe',
+                         {'start': perihelion_14 - 50 * u.day,
+                          'stop': perihelion_14 + 50 * u.day,
+                          'step': '180m'})
+
+##############################################################################
+# We also obtain the location of Earth at PSP perihelion.  We could query
+# JPL Horizons again, but :func:`~sunpy.coordinates.get_body_heliographic_stonyhurst` returns
+# a comparably accurate location using the Astropy ephemeris.
+
+earth = get_body_heliographic_stonyhurst('Earth', perihelion_14)
+
+##############################################################################
+# For the purposes of plotting on a Matplotlib polar plot, we create a short
+# convenience function to extract the necessary values in the appropriate units.
+
+
+def coord_to_polar(coord):
+    return coord.lon.to_value('rad'), coord.radius.to_value('AU')
+
+##############################################################################
+# Finally, we plot the trajectory on a polar plot.  Be aware that the
+# orientation of the Stonyhurst heliographic coordinate system rotates
+# over time such that the Earth is always at zero longitude.
+# Accordingly, when we directly plot the trajectory, it does not appear
+# as a simple ellipse because each trajectory point has a different
+# observation time and thus a different orientation of the coordinate
+# system.  To see the elliptical orbit, the trajectory can be
+# transformed to the coordinate frame of Earth at the single time of
+# PSP perihelion (``earth``), so that the trajectory is represented in
+# a non-rotating coordinate frame.
+
+
+fig = plt.figure()
+ax = fig.add_subplot(projection='polar')
+ax.plot(0, 0, 'o', label='Sun', color='orange')
+ax.plot(*coord_to_polar(earth), 'o', label='Earth', color='blue')
+ax.plot(*coord_to_polar(psp),
+        label='PSP (as seen from Earth)', color='purple')
+ax.plot(*coord_to_polar(psp.transform_to(earth)),
+        label='PSP (non-rotating frame)', color='purple', linestyle='dashed')
+ax.set_title('Stonyhurst heliographic coordinates')
+ax.legend(loc='upper center')
+
+plt.show()
+
+##############################################################################
+# There are other tools that enable a similar style of figure.
+# `solarmach <https://github.com/jgieseler/solarmach#usage>`__ is one such example.
diff --git a/sunpy/map/header_helper.py b/sunpy/map/header_helper.py
index 65faa7908..f1c9073da 100644
--- a/sunpy/map/header_helper.py
+++ b/sunpy/map/header_helper.py
@@ -7,10 +7,12 @@ from astropy.coordinates import SkyCoord
 from sunpy import log
 from sunpy.coordinates import frames, sun
 from sunpy.util import MetaDict
+from sunpy.util.decorators import deprecated
 
 __all__ = ['meta_keywords', 'make_fitswcs_header', 'get_observer_meta', 'make_heliographic_header']
 
 
+@deprecated(since="5.0", message="Unused and will be removed in 6.0")
 def meta_keywords():
     """
     Returns the metadata keywords that are used when creating a `sunpy.map.GenericMap`.
@@ -19,12 +21,12 @@ def meta_keywords():
     --------
     Returns a dictionary of all meta keywords that are used in a `sunpy.map.GenericMap` header:
         >>> import sunpy.map
-        >>> sunpy.map.meta_keywords()
+        >>> sunpy.map.meta_keywords() # doctest: +SKIP
         {'cunit1': 'Units of the coordinate increments along naxis1 e.g. arcsec **required',
          'cunit2': 'Units of the coordinate increments along naxis2 e.g. arcsec **required',
          ...
     """
-    return _map_meta_keywords
+    return _map_meta_keywords.copy()
 
 
 @u.quantity_input(equivalencies=u.spectral())
diff --git a/sunpy/map/mapbase.py b/sunpy/map/mapbase.py
index 2772e6b4d..50f18681c 100644
--- a/sunpy/map/mapbase.py
+++ b/sunpy/map/mapbase.py
@@ -2262,7 +2262,7 @@ class GenericMap(NDData):
             width = Longitude(top_right.spherical.lon - bottom_left.spherical.lon)
             height = top_right.spherical.lat - bottom_left.spherical.lat
             anchor = self._get_lon_lat(bottom_left)
-            transform = axes.get_transform(bottom_left.frame.replicate_without_data())
+            transform = axes.get_transform(bottom_left.replicate_without_data())
 
         kwergs = {
             "transform": transform,


Test patch:
diff --git a/sunpy/map/tests/test_header_helper.py b/sunpy/map/tests/test_header_helper.py
index 1a3d5efe5..47643a8f1 100644
--- a/sunpy/map/tests/test_header_helper.py
+++ b/sunpy/map/tests/test_header_helper.py
@@ -9,6 +9,7 @@ import sunpy.map
 from sunpy.coordinates import frames, sun
 from sunpy.map import make_fitswcs_header
 from sunpy.map.header_helper import make_heliographic_header
+from sunpy.util.exceptions import SunpyDeprecationWarning
 from sunpy.util.metadata import MetaDict
 
 
@@ -62,8 +63,9 @@ def hpc_coord_notime():
 
 
 def test_metakeywords():
-    meta = sunpy.map.meta_keywords()
-    assert isinstance(meta, dict)
+    with pytest.warns(SunpyDeprecationWarning):
+        meta = sunpy.map.meta_keywords()
+        assert isinstance(meta, dict)
 
 
 def test_scale_conversion(map_data, hpc_coord):
diff --git a/sunpy/map/tests/test_plotting.py b/sunpy/map/tests/test_plotting.py
index 9090888dd..c79dc1dd8 100644
--- a/sunpy/map/tests/test_plotting.py
+++ b/sunpy/map/tests/test_plotting.py
@@ -126,7 +126,7 @@ def test_quadrangle_aia17_width_height(aia171_test_map):
         50 * u.deg, -10 * u.deg, frame=HeliographicStonyhurst, obstime=aia171_test_map.date)
     w = 30 * u.deg
     h = 90 * u.deg
-    aia171_test_map.draw_quadrangle(bottom_left=bottom_left, width=w, height=h)
+    aia171_test_map.draw_quadrangle(bottom_left=bottom_left.frame, width=w, height=h)
 
 
 @figure_test
diff --git a/sunpy/net/hek/tests/test_hek.py b/sunpy/net/hek/tests/test_hek.py
index 82bc93f57..5f17c03df 100644
--- a/sunpy/net/hek/tests/test_hek.py
+++ b/sunpy/net/hek/tests/test_hek.py
@@ -179,7 +179,7 @@ def test_mixed_results_get():
                            attrs.hek.FRM.Name == 'SPoCA')
     assert isinstance(result, hek.hek.HEKTable)
     assert len(result) == 89
-    assert result[0]["SOL_standard"] == 'SOL2013-01-31T20:13:31L219C160'
+    assert result[0]["SOL_standard"] == 'SOL2013-01-31T20:13:31L267C094'
 
 
 @pytest.mark.remote_data