summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOle Streicher <olebole@debian.org>2026-05-01 11:38:20 +0200
committergit-ubuntu importer <ubuntu-devel-discuss@lists.ubuntu.com>2026-05-01 16:40:55 +0000
commit06a3486b00c0ed58b2416fc13e295d2ddac4f356 (patch)
treed8c126d05267e98044230a34037bcc4e79a742e3
parent68bc2449158c0afe50adc236ea51b73e0dd768d8 (diff)
Imported using git-ubuntu import.
Notes
Notes: * New upstream version 7.1.2 * Rediff patches * Push Standards-Version to 4.7.4, no changes needed
-rw-r--r--.cruft.json4
-rw-r--r--.editorconfig2
-rw-r--r--.github/workflows/cron.yml10
-rw-r--r--CHANGELOG.rst9
-rw-r--r--README.rst4
-rw-r--r--changelog/8571.doc.rst1
-rw-r--r--changelog/8574.doc.rst1
-rw-r--r--changelog/8578.trivial.rst1
-rw-r--r--debian/changelog8
-rw-r--r--debian/control2
-rw-r--r--debian/patches/Ignore-some-warnings-in-tests.patch4
-rw-r--r--examples/showcase/artemis-ii-eclipse.py514
-rw-r--r--examples/showcase/artemis-ii-trajectory.py161
-rw-r--r--pyproject.toml3
-rw-r--r--sunpy/map/mapbase.py5
-rw-r--r--sunpy/map/sources/tests/test_hmi_source.py6
-rw-r--r--sunpy/map/tests/test_mapbase.py35
-rw-r--r--sunpy/tests/figure_hashes_mpl_382_astropy_702_animators_121.json (renamed from sunpy/tests/figure_hashes_mpl_382_ft_261_astropy_702_animators_121.json)0
-rw-r--r--sunpy/tests/figure_hashes_mpl_dev_astropy_dev_animators_dev.json94
-rw-r--r--sunpy/tests/figure_hashes_mpl_dev_ft_261_astropy_dev_animators_dev.json94
-rw-r--r--sunpy/tests/helpers.py3
21 files changed, 847 insertions, 114 deletions
diff --git a/.cruft.json b/.cruft.json
index f81002a..87b196a 100644
--- a/.cruft.json
+++ b/.cruft.json
@@ -1,6 +1,6 @@
{
"template": "https://github.com/sunpy/package-template",
- "commit": "93c8bc491584f214226a039a35d0cbebe305cd31",
+ "commit": "6436220cebd96b3638682023e7149eb78e012fdc",
"checkout": null,
"context": {
"cookiecutter": {
@@ -33,7 +33,7 @@
".github/workflows/sub_package_update.yml"
],
"_template": "https://github.com/sunpy/package-template",
- "_commit": "93c8bc491584f214226a039a35d0cbebe305cd31"
+ "_commit": "6436220cebd96b3638682023e7149eb78e012fdc"
}
},
"directory": null
diff --git a/.editorconfig b/.editorconfig
index a2c6683..aba2aa8 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -12,6 +12,6 @@ trim_trailing_whitespace=true
indent_style=space
indent_size=4
-[*.yml]
+[{*.yml, *.toml}]
indent_style=space
indent_size=2
diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml
index 89b1a1f..339cb8b 100644
--- a/.github/workflows/cron.yml
+++ b/.github/workflows/cron.yml
@@ -9,19 +9,11 @@ on:
types:
- synchronize
- labeled
- # We want this workflow to always run on release branches as well as
- # all tags since we want to be really sure we don't introduce
- # regressions on the release branches, and it's also important to run
- # this on pre-release and release tags.
+ # We want this workflow to always run on release branches.
push:
branches:
- '*.*'
- '!*backport*'
- tags:
- - 'v*'
- - '!*dev*'
- - '!*pre*'
- - '!*post*'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 714818a..cb6dca1 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,3 +1,12 @@
+7.1.2 (2026-04-19)
+==================
+
+Bug Fixes
+---------
+
+- Fixed a bug where SIP distortion information in a Map WCS was ignored. (`#8573 <https://github.com/sunpy/sunpy/pull/8573>`__)
+
+
7.1.1 (2026-03-26)
==================
diff --git a/README.rst b/README.rst
index 28f87ba..1c8d97a 100644
--- a/README.rst
+++ b/README.rst
@@ -1,5 +1,7 @@
+``sunpy``
+=========
+
SunPy core package: Python for Solar Physics
-============================================
|SunPy Logo|
diff --git a/changelog/8571.doc.rst b/changelog/8571.doc.rst
new file mode 100644
index 0000000..5625080
--- /dev/null
+++ b/changelog/8571.doc.rst
@@ -0,0 +1 @@
+Added a gallery example (:ref:`sphx_glr_generated_gallery_showcase_artemis-ii-eclipse.py`) to visualise and analyse solar eclipse observed by Artemis-II.
diff --git a/changelog/8574.doc.rst b/changelog/8574.doc.rst
new file mode 100644
index 0000000..799b31d
--- /dev/null
+++ b/changelog/8574.doc.rst
@@ -0,0 +1 @@
+Added a gallery example (:ref:`sphx_glr_generated_gallery_showcase_artemis-ii-trajectory.py`) to visualize the Artemis II trajectory in two different coordinate frames.
diff --git a/changelog/8578.trivial.rst b/changelog/8578.trivial.rst
new file mode 100644
index 0000000..4e5802f
--- /dev/null
+++ b/changelog/8578.trivial.rst
@@ -0,0 +1 @@
+The hash libraries for figure tests have been renamed to remove the version of ``freetype``.
diff --git a/debian/changelog b/debian/changelog
index 90bc07d..c11617b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+sunpy (7.1.2-1) unstable; urgency=medium
+
+ * New upstream version 7.1.2
+ * Rediff patches
+ * Push Standards-Version to 4.7.4, no changes needed
+
+ -- Ole Streicher <olebole@debian.org> Fri, 01 May 2026 11:38:20 +0200
+
sunpy (7.1.1-1) unstable; urgency=medium
* Ecxclude .pybuild and __pycache__ from MANIFEST.in
diff --git a/debian/control b/debian/control
index 8c04deb..660397b 100644
--- a/debian/control
+++ b/debian/control
@@ -1,5 +1,5 @@
Source: sunpy
-Standards-Version: 4.7.3
+Standards-Version: 4.7.4
Maintainer: Debian Astronomy Team <debian-astro-maintainers@lists.alioth.debian.org>
Uploaders:
Ole Streicher <olebole@debian.org>,
diff --git a/debian/patches/Ignore-some-warnings-in-tests.patch b/debian/patches/Ignore-some-warnings-in-tests.patch
index b701020..2ab2afd 100644
--- a/debian/patches/Ignore-some-warnings-in-tests.patch
+++ b/debian/patches/Ignore-some-warnings-in-tests.patch
@@ -33,10 +33,10 @@ index dda5bdd..494c36a 100644
always::pytest.PytestConfigWarning
# A list of warnings to ignore follows. If you add to this list, you MUST
diff --git a/sunpy/map/tests/test_mapbase.py b/sunpy/map/tests/test_mapbase.py
-index 3222537..5bd30a3 100644
+index 4aba5cc..034af7c 100644
--- a/sunpy/map/tests/test_mapbase.py
+++ b/sunpy/map/tests/test_mapbase.py
-@@ -1790,9 +1790,8 @@ def test_map_arithmetic_multiplication_division(aia171_test_map, value):
+@@ -1825,9 +1825,8 @@ def test_map_arithmetic_multiplication_division(aia171_test_map, value):
check_arithmetic_value_and_units(new_map, value * aia171_test_map.quantity)
new_map = aia171_test_map / value
check_arithmetic_value_and_units(new_map, aia171_test_map.quantity / value)
diff --git a/examples/showcase/artemis-ii-eclipse.py b/examples/showcase/artemis-ii-eclipse.py
new file mode 100644
index 0000000..e0d98e8
--- /dev/null
+++ b/examples/showcase/artemis-ii-eclipse.py
@@ -0,0 +1,514 @@
+"""
+========================
+Artemis-II Solar Eclipse
+========================
+
+This example demonstrates how to process a solar eclipse image taken by the
+Artemis-II crew using a digital camera onboard the spacecraft during their
+Lunar flyby on April 7, 2026. Due to the relative positions of the Artemis II
+spacecraft and the Moon, this eclipse provided nearly 54 minutes of totality,
+far exceeding what is possible on Earth. This example walks through turning
+one of those crew photos, a plain JPEG with EXIF metadata and no pointing
+information, into a `~sunpy.map.Map` with a Helioprojective WCS. Starting from
+raw JPEG images with EXIF metadata, the observation time is extracted. Then,
+the known positions of the Moon, Sun, and planets are retrieved from JPL
+Horizons via `sunpy.coordinates.get_horizons_coord` to build an initial
+Helioprojective WCS using `sunpy.map.header_helper.make_fitswcs_header`.
+The camera roll angle is refined by comparing the predicted and detected pixel
+positions of Saturn, Mars, and Mercury, identified automatically.
+
+Finally, the residual radial barrel distortion is modelled using a single
+`Simple Imaging Polynomial (SIP) <https://fits.gsfc.nasa.gov/registry/sip>`_
+3rd order coefficient derived from the planets positions. With the resulting
+calibrated `sunpy.map.Map` it is straightforward to overplot some space-based
+coronagraph data on top of the eclipse image.
+
+Image credit: NASA/Artemis II crew
+
+"""
+from pathlib import Path
+
+import exifread
+import hvpy
+import matplotlib
+import numpy as np
+import requests
+from hvpy.datasource import DataSource
+from matplotlib import pyplot as plt
+from matplotlib.patches import Circle
+from scipy.signal import medfilt2d
+from skimage import transform
+from skimage.color import rgb2gray
+from skimage.feature import canny, peak_local_max
+from skimage.transform import hough_circle, hough_circle_peaks
+
+import astropy.units as u
+from astropy.coordinates import CartesianRepresentation, SkyCoord, solar_system_ephemeris
+from astropy.time import Time
+from astropy.wcs import WCS
+
+import sunpy.map
+from sunpy.coordinates import Helioprojective, SphericalScreen, get_horizons_coord
+from sunpy.map import Map
+from sunpy.map.header_helper import make_fitswcs_header
+from sunpy.util.config import get_and_create_download_dir
+
+# Accurate planetary ephemeris from JPL Horizons
+solar_system_ephemeris.set('de440s')
+
+###############################################################################
+# Get and Convert the Raw Image
+# =============================
+# The starting point is a single JPEG hosted in the NASA image library. It
+# has no WCS, no pointing solution, or plate scale, we only have the raw
+# image data.
+#
+# We first download and read in the raw image data directly taken by the crew
+# on Artemis-II and convert the RGB jpeg data to a grayscale image.
+
+url = "https://images-assets.nasa.gov/image/art002e009301/art002e009301~orig.jpg"
+filename = url.split("/")[-1]
+with requests.get(url, stream=True) as res:
+ res.raise_for_status()
+ with open(filename, "wb") as f:
+ for chunk in res.iter_content(chunk_size=8192):
+ f.write(chunk)
+
+artemis_image_rbg = np.flipud(matplotlib.image.imread(filename))
+artemis_image = rgb2gray(artemis_image_rbg)
+
+###############################################################################
+# Let's downsample the image to reasonable size for processing and
+# visualization. The original frame is very large, so for this example we
+# downsample by a factor of 6. This can be set to `False` if running locally
+# for full resolution analysis.
+
+downsampled = True
+if downsampled:
+ artemis_image = transform.rescale(artemis_image, 1/6, anti_aliasing=True)
+
+###############################################################################
+# And now let's plot the raw image.
+
+fig, ax = plt.subplots()
+ax.imshow(artemis_image_rbg, origin="lower")
+ax.set_axis_off()
+# Reduce memory usage on RTD build
+del artemis_image_rbg
+
+###############################################################################
+# Extract Metadata
+# ================
+#
+# Let's now extract metadata stored in the JPEG image, in particular the date
+# and time the image was taken. The time stamp of the image is the key
+# information we need, as from this we can query JPL horizons for the positions
+# of Artemis II, the Sun, the Moon and the planets.
+
+with Path(filename).open("rb") as f:
+ tags = exifread.process_file(f)
+
+obsdate, obstime= tags['EXIF DateTimeDigitized'].values.split(" ")
+obsdate = obsdate.replace(":", "-")
+obstime = Time(f"{obsdate}T{obstime}")
+print(obstime)
+
+hours, _ = [int(part) for part in tags['EXIF OffsetTime'].values.split(":")]
+offset = hours*u.hour
+
+# obstime = obstime + offset # It seems like the timezone or offset is set incorrectly
+
+###############################################################################
+# Get Coordinates
+# ===============
+#
+# To get the coordinates of the Artemis II spacecraft, the Sun, the Moon, and
+# the planets at the observation time, we query JPL Horizons.
+# Here we use the NAIF IDs for the bodies for the query.
+
+NAIF_IDS = {
+ "artemis_ii": -1024,
+ "moon": 301,
+ "sun": 10,
+ "mercury": 199,
+ "venus": 299,
+ "earth": 399,
+ "mars": 499,
+ "jupiter": 599,
+ "saturn": 699,
+ "uranus": 799,
+ "neptune": 899
+}
+
+coords = {name: get_horizons_coord(str(id), obstime) for name, id in NAIF_IDS.items()}
+
+###############################################################################
+# Find and Fit Moon's Limb and Center
+# ===================================
+#
+# While we now know where the Moon is on the sky, we still need to know where
+# it is in the image. Fitting the Moon's limb gives us that pixel location, and
+# combined with the Moon's known angular size, we can estimate the plate scale.
+#
+# Here we use canny edge detection and circular Hough filtering to obtain the
+# Moon's limb and center.
+#
+# First pass on a downscaled version is used to get an estimate, which is
+# used to extract the region of interest (ROI) for full resolution pass.
+
+print("starting low res pass")
+scale = 0.5 if downsampled else 0.1
+down_scaled = transform.rescale(artemis_image, scale, anti_aliasing=True)
+
+ # Edge detection
+edges = canny(down_scaled, sigma=2)
+
+ # Radius range in scaled image (diameter ~1/3 of image height)
+h, w = down_scaled.shape
+radii = np.arange(0.25*h, 0.4*h, 10)
+
+ # Hough
+hough_res = hough_circle(edges, radii)
+accums, cx, cy, rad = hough_circle_peaks(hough_res, radii, total_num_peaks=1)
+del hough_res
+
+ # Scale back to original resolution
+moon_x = int(cx[0] / scale)
+moon_y = int(cy[0] / scale)
+moon_r = rad[0] / scale
+roi_ext = int(1.05*moon_r)
+
+slice_y = slice(moon_y-roi_ext, moon_y+roi_ext)
+slice_x = slice(moon_x-roi_ext, moon_x+roi_ext)
+print(f"Low res pass moon_x: {moon_x}, moon_y: {moon_y}, moon_r: {moon_r}")
+
+###############################################################################
+# Full resolution pass within ROI
+# -------------------------------
+#
+# Let's now re-run the limb fitting on the full resolution within the cropped
+# ROI.
+
+roi = artemis_image[slice_y, slice_x]
+
+edges = canny(roi, sigma=2)
+
+hough_radii = np.linspace(edges.shape[0] / 2.5, edges.shape[0] / 2, 30)
+hough_res = hough_circle(edges, hough_radii).astype(np.float32) # reduce peak memory usage
+
+accums, cx, cy, radii = hough_circle_peaks(hough_res, hough_radii, total_num_peaks=1)
+
+print(f"High res pass moon_x: {cx[0] + slice_x.start}, moon_y: {cy[0]+slice_y.start}, moon_r: {radii}")
+
+###############################################################################
+# Plot edge detection and Hough filtering results
+# -----------------------------------------------
+
+fig, ax = plt.subplots(ncols=3, nrows=1, figsize=(9, 3))
+ax[0].imshow(artemis_image[slice_y, slice_x])
+ax[0].set_title("Original")
+ax[1].imshow(edges)
+ax[1].set_title("Canny")
+circ = Circle(
+ np.hstack([cx, cy]), radius=radii[0], facecolor="none", edgecolor="red",
+ linewidth=2, linestyle="dashed", label="Hough fit")
+ax[2].imshow(artemis_image[slice_y, slice_x])
+ax[2].add_patch(circ)
+ax[2].set_title("Original with fit")
+fig.legend()
+
+
+###############################################################################
+# Create metadata
+# ================
+#
+# Build up the metadata required to make a `sunpy.map.Map`
+# Here we calculate the reference pixel, and plate scale.
+
+im_cx = (cx[0] + slice_x.start) * u.pix
+im_cy = (cy[0] + slice_y.start) * u.pix
+im_radius = radii[0] * u.pix
+
+moon = SkyCoord(coords['moon'], observer=coords['artemis_ii'])
+R_moon = 0.2725076 * u.R_earth # IAU mean radius
+dist_moon = SkyCoord(coords['artemis_ii']).separation_3d(moon)
+moon_obs = np.arcsin(R_moon / dist_moon).to("arcsec")
+print(moon_obs)
+
+plate_scale = moon_obs / im_radius
+print(plate_scale)
+
+###############################################################################
+# Make a Map
+# ==========
+#
+# Make a `sunpy.map.Map` using the metadata obtained so far using
+# `sunpy.map.header_helper.make_fitswcs_header`.
+
+frame = Helioprojective(observer=coords['artemis_ii'], obstime=obstime)
+moon_hpc = coords['moon'].transform_to(frame)
+
+header = make_fitswcs_header(
+ artemis_image,
+ moon_hpc,
+ reference_pixel=u.Quantity([im_cx, im_cy]),
+ scale=u.Quantity([plate_scale, plate_scale])
+)
+
+artemis_map = Map(artemis_image, header)
+
+###############################################################################
+# Reusable plot helper
+
+def plot_artemis_map(amap, moon_coord, planets, reset_lim=True, legend=True, figsize=(9,4), **kwargs):
+ fig, ax = plt.subplots(1, 1, subplot_kw={"projection": amap}, figsize=figsize, **kwargs)
+ amap.plot(axes=ax)
+ amap.draw_limb(axes=ax, label='Sun')
+ ax.coords[0].set_format_unit(u.deg)
+ ax.coords[1].set_format_unit(u.deg)
+
+ ax.plot_coord(moon_coord, 'b+', label="Lunar Center")
+ theta = np.linspace(0, 360, 100) * u.deg
+ lunar_limb = np.vstack([moon_hpc.Tx + np.sin(theta) * moon_obs, moon_hpc.Ty + np.cos(theta) * moon_obs])
+ with SphericalScreen(amap.observer_coordinate):
+ ax.plot_coord(SkyCoord(*lunar_limb, frame=amap.coordinate_frame), label="Lunar Limb")
+
+ xlim = ax.get_xlim()
+ ylim = ax.get_ylim()
+ for name, coord in planets.items():
+ ax.plot_coord(coord, 'o', markerfacecolor='none', label=name.title())
+ if reset_lim:
+ ax.set_xlim(xlim)
+ ax.set_ylim(ylim)
+ if legend:
+ ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0)
+ return fig, ax
+
+###############################################################################
+# Plot map and positions of planets to see what should be visible
+
+planets = {name: coord for name, coord in coords.items() if name not in ["sun", "moon", "artemis_ii"]}
+
+fig, ax = plot_artemis_map(artemis_map, moon_hpc, planets, reset_lim=False)
+fig.tight_layout()
+
+###############################################################################
+# Mercury, Mars, Saturn and Neptune are within the field of view, though
+# Neptune is not visible as it is too distant and faint.
+
+planets = {name: coords[name] for name in ["mercury", "mars", "saturn"]}
+
+fig, ax = plot_artemis_map(artemis_map, moon_hpc, planets, reset_lim=False)
+fig.tight_layout()
+
+###############################################################################
+# Find roll angle
+# ===============
+#
+# A clear roll is visible, so the positions of the planets are used to
+# estimate the camera orientation. Use `skimage.feature.peak_local_max` to
+# find the brightest peaks, which should correspond to the planets.
+
+if downsampled:
+ planets_pixels = peak_local_max(artemis_image, threshold_abs=0.9, num_peaks=3, min_distance=30)
+else:
+ artemis_median_img = medfilt2d(artemis_image, kernel_size=5)
+ planets_pixels = peak_local_max(artemis_median_img, threshold_abs=0.9, num_peaks=3, min_distance=30)
+ del artemis_median_img
+
+planets_pix_x = planets_pixels[:,1]
+planets_pix_y = planets_pixels[:,0]
+
+planet_coords = artemis_map.pixel_to_world(planets_pix_x * u.pix, planets_pix_y * u.pix)
+
+###############################################################################
+# Verify we've correctly identified the planets.
+
+fig, ax = plot_artemis_map(artemis_map, moon_hpc, planets)
+with SphericalScreen(coords["artemis_ii"]):
+ ax.plot_coord(planet_coords, 's', markerfacecolor='none')
+
+###############################################################################
+# We need to determine which pixel positions correspond to which planets.
+# From the map above, we can see that, in terms of distance from the Moon,
+# the planets are Saturn, Mars, and Mercury, in that order. Therefore, we
+# sort them by the separation angle from the Moon's center.
+
+# Saturn, Mars, Mercury
+with SphericalScreen(coords["artemis_ii"]):
+ sep = moon_hpc.transform_to(planet_coords.frame).separation(planet_coords)
+planet_index = np.argsort(sep)
+actual_planets_pixel = CartesianRepresentation(planets_pix_x[planet_index], planets_pix_y[planet_index], [0] * 3) * u.pix
+
+moon_pixel = CartesianRepresentation(*artemis_map.wcs.world_to_pixel(moon_hpc), 0)*u.pix
+
+# to match the order of the actual_planets_pixel
+planets_temp = SkyCoord([planets[name] for name in ["saturn", "mars", "mercury"]])
+planets_pixel = CartesianRepresentation(*artemis_map.wcs.world_to_pixel(planets_temp), 0) * u.pix
+
+vec_expected = planets_pixel - moon_pixel
+vec_actual = actual_planets_pixel - moon_pixel
+roll_angles = -np.arccos(vec_expected.dot(vec_actual) / (vec_expected.norm() * vec_actual.norm()))
+
+weights = sep[planet_index].to(u.deg).value
+roll_angles_weighted = np.average(roll_angles, weights=weights)
+print(roll_angles.to('deg'))
+print(roll_angles.mean().to('deg'))
+print(f"Weighted roll: {np.degrees(roll_angles_weighted):.4f} deg")
+
+###############################################################################
+# Use derived roll and make new header and map
+
+header_roll = make_fitswcs_header(
+ artemis_image,
+ moon_hpc,
+ reference_pixel=u.Quantity([im_cx, im_cy]),
+ scale=u.Quantity([plate_scale, plate_scale]),
+ rotation_angle=-roll_angles_weighted.to('deg')
+)
+
+artemis_map_roll = Map(artemis_image, header_roll)
+
+###############################################################################
+# Let's now plot map and positions of Saturn, Mars, and Mercury to check if
+# the WCS is correct.
+#
+# There seems to be some residual distortion that gets worse towards the edges.
+
+fig, ax = plot_artemis_map(artemis_map_roll, moon_hpc, planets)
+
+###############################################################################
+# Correct Optical Distortion
+# ==========================
+#
+# We can see that there is some optical distortion. Let's assume the distortion
+# is due to the lens (e.g., barrel or pincushion), centered in the middle of
+# the image, and derive the correction from the observed versus actual planet
+# positions.
+
+cx, cy = artemis_map_roll.wcs.wcs.crpix
+r_actual, r_predicted = [], []
+for i, name in enumerate(["saturn", "mars", "mercury"]):
+ hpc = planets[name].transform_to(artemis_map_roll.coordinate_frame)
+ px, py = artemis_map_roll.wcs.world_to_pixel(hpc)
+ ax, ay = planets_pix_x[planet_index][i], planets_pix_y[planet_index][i]
+ r_predicted.append(np.sqrt((px - cx)**2 + (py - cy)**2))
+ r_actual.append(np.sqrt((ax - cx)**2 + (ay - cy)**2))
+
+r_predicted = np.array(r_predicted)
+r_actual = np.array(r_actual)
+
+k1_estimates = (r_actual/r_predicted - 1) / r_predicted**2
+weights = r_predicted # weight by distance — Mercury most reliable
+k1 = np.average(k1_estimates, weights=weights)
+print(f"k1 per planet: {k1_estimates}")
+print(f"Weighted k1: {k1:.6e} pix^-2")
+
+# Use only Mars and Mercury — Saturn too close to center and fit error
+k1_estimates_reliable = k1_estimates[1:]
+r_reliable = r_predicted[1:]
+k1 = np.average(k1_estimates_reliable, weights=r_reliable)
+print(f"k1 (Mars+Mercury only): {k1:.6e} pix^-2")
+
+###############################################################################
+# Create a SIP header, WCS and verify the SIP improve positions
+
+header_sip = artemis_map_roll.fits_header.copy()
+header_sip['CTYPE1'] = 'HPLN-TAN-SIP'
+header_sip['CTYPE2'] = 'HPLT-TAN-SIP'
+header_sip['A_ORDER'] = 3
+header_sip['B_ORDER'] = 3
+header_sip['A_3_0'] = -k1
+header_sip['A_1_2'] = -k1
+header_sip['B_0_3'] = -k1
+header_sip['B_2_1'] = -k1
+header_sip['A_DMAX'] = 1.0
+header_sip['B_DMAX'] = 1.0
+wcs_sip = WCS(header_sip)
+
+for i, name in enumerate(["saturn", "mars", "mercury"]):
+ hpc = planets[name].transform_to(artemis_map_roll.coordinate_frame)
+ px_nosip = wcs_sip.wcs_world2pix([[hpc.Tx.to(u.deg).value, hpc.Ty.to(u.deg).value]], 0)[0]
+ px_sip = wcs_sip.all_world2pix([[hpc.Tx.to(u.deg).value, hpc.Ty.to(u.deg).value]], 0)[0]
+ ax, ay = planets_pix_x[planet_index][i], planets_pix_y[planet_index][i]
+ print(f"{name}: residual without SIP=({ax-px_nosip[0]:.1f}, {ay-px_nosip[1]:.1f}) "
+ f"with SIP=({ax-px_sip[0]:.1f}, {ay-px_sip[1]:.1f})")
+
+###############################################################################
+# Final Map
+# =========
+#
+# Create a final version of the map with the SIP headers.
+
+artemis_map_final = Map((artemis_image, header_sip))
+fig, ax = plot_artemis_map(artemis_map_final, moon_hpc, planets)
+ax.set_title(f"Artemis-II Solar Eclipse {obstime}")
+fig.tight_layout()
+
+###############################################################################
+# Overplotting Coronagraph Images
+# ===============================
+# In this section we will fetch images of the near corona from SOHO/LASCO
+# and overplot them on the eclipse map.
+# The Artemis II image shows the faint outer corona around the Moon, as the
+# spacecraft was close to the moon during the flyby, so the apparent angular
+# size is much larger than the Sun's, so it blocks not only the Sun's disk but
+# a substantial region of the inner corona around it.
+#
+# By reprojecting and overplotting the LASCO images, we can overlap them inside
+# the Moon's image, to produce a composite that extends from the inner corona
+# outwards.
+#
+# First step is to fetch the images from Helioviewer.
+
+lasco_c2_file = hvpy.save_file(hvpy.getJP2Image(obstime.datetime,
+ DataSource.LASCO_C2.value),
+ filename=get_and_create_download_dir() + "/LASCO_C2.jp2", overwrite=True)
+lasco_c2_map = Map(lasco_c2_file)
+lasco_c3_file = hvpy.save_file(hvpy.getJP2Image(obstime.datetime,
+ DataSource.LASCO_C3.value),
+ filename=get_and_create_download_dir() + "/LASCO_C3.jp2", overwrite=True)
+lasco_c3_map = Map(lasco_c3_file)
+
+###############################################################################
+# Next we reproject the LASCO map to the same WCS as the Artemis eclipse map.
+
+with SphericalScreen(coords["artemis_ii"]):
+ c3_map_img = lasco_c3_map.reproject_to(artemis_map_final.wcs)
+ c2_map_img = lasco_c2_map.reproject_to(artemis_map_final.wcs)
+
+
+###############################################################################
+# As the final step we will crop the LASCO C3 image to the limb of the Moon
+# and mask regions with no data.
+
+# Calculate coordinates for each pixel in the map.
+all_hpc = sunpy.map.all_coordinates_from_map(c3_map_img)
+
+# Calculate the angular offset from the center of the moon for each pixel.
+moon_cen_offsets = all_hpc.separation(coords['moon'])
+
+# Create a mask which is True for all offsets greater than the
+# observed angular width of the moon.
+c3_map_img.mask = np.logical_or(
+ moon_cen_offsets >= moon_obs,
+ # Also mask out the parts of the image with no data
+ c3_map_img.data < 10,
+)
+# Mask out the parts of the C2 image with no data
+c2_map_img.mask = c2_map_img.data < 10
+
+###############################################################################
+# Now setup a new plot with the same distortion corrected eclipse image and
+# reprojected, masked LASCO data.
+
+fig, ax = plot_artemis_map(artemis_map_final, moon_hpc, planets)
+
+# Overplot both LASCO images, with autoalign off as we already reprojected them.
+c3_map_img.plot(axes=ax, autoalign=False)
+c2_map_img.plot(axes=ax, autoalign=False)
+
+ax.set_title(f"Artemis-II Solar Eclipse {obstime}")
+fig.tight_layout()
+
+# sphinx_gallery_thumbnail_number = -2
diff --git a/examples/showcase/artemis-ii-trajectory.py b/examples/showcase/artemis-ii-trajectory.py
new file mode 100644
index 0000000..dec0907
--- /dev/null
+++ b/examples/showcase/artemis-ii-trajectory.py
@@ -0,0 +1,161 @@
+"""
+=====================
+Artemis II trajectory
+=====================
+
+This example visualizes the trajectory of the Artemis II spacecraft.
+
+Artemis II was NASA's first crewed mission to the Moon since Apollo 17 in 1972,
+flying four astronauts around the Moon on a ~10 day test flight in April 2026.
+The trajectory is visualized in two different coordinate frames. The plots
+also highlight the segment of the trajectory when Artemis II was in eclipse.
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+from matplotlib.dates import DateFormatter
+
+import astropy.units as u
+from astropy.constants import R_earth
+from astropy.coordinates import solar_system_ephemeris
+from astropy.time import Time
+
+from sunpy.coordinates import get_horizons_coord, sun
+from sunpy.time import parse_time
+
+##############################################################################
+# First, define times spanning the Artemis II mission, with higher resolution
+# across eclipse transitions (i.e., the four contacts). The contact times are
+# approximate.
+
+t_start = parse_time("2026-Apr-02 01:58:33")
+t_c1 = parse_time("2026-Apr-07 00:32:46") # start of partial eclipse
+t_c2 = parse_time("2026-Apr-07 00:34:28") # start of total eclipse
+t_c3 = parse_time("2026-Apr-07 01:28:55") # end of total eclipse
+t_c4 = parse_time("2026-Apr-07 01:31:03") # end of partial eclipse
+t_end = parse_time("2026-Apr-10 23:54:22")
+
+time_spans = [(t_start, t_c1 - 10*u.s, 5*u.min),
+ (t_c1 - 30*u.s, t_c2 + 30*u.s, 5*u.s),
+ (t_c2 + 30*u.s, t_c3 - 30*u.s, 5*u.min),
+ (t_c3 - 30*u.s, t_c4 + 30*u.s, 5*u.s),
+ (t_c4 + 30*u.s, t_end, 5*u.min)]
+times = Time(np.concatenate([np.arange(t1.jd, t2.jd, dt.to_value(u.day))
+ for t1, t2, dt in time_spans]), format='jd')
+
+##############################################################################
+# Use JPL Horizons via :func:`~sunpy.coordinates.get_horizons_coord` to
+# retrieve relevant coordinates, and then use the coordinate framework to
+# convert to ecliptic coordinates. There is no convenient coordinate frame
+# for the Earth-Moon system, so convert to a heliocentric frame for now.
+
+# Use a JPL ephemeris because astropy's built-in ephemeris is not accurate enough
+solar_system_ephemeris.set('de440s')
+
+# Get the Artemis II coordinate in Heliocentric Mean Ecliptic
+artemis = get_horizons_coord("Artemis II", times).heliocentricmeanecliptic
+
+# Get other relevant coordinates
+# Specify NAIF IDs for Earth and Moon due to multiple matches for string input
+earth = get_horizons_coord(399, times).heliocentricmeanecliptic
+moon = get_horizons_coord(301, times).heliocentricmeanecliptic
+em_barycenter = get_horizons_coord("Earth-Moon Barycenter", times).heliocentricmeanecliptic
+
+##############################################################################
+# Determine when Artemis II was in eclipse using :func:`sunpy.coordinates.sun.eclipse_amount`.
+# When the eclipse percentage is greater than 0, at least part of the Sun is
+# eclipsed by the Moon. Be aware that this function assumes a uniform lunar
+# radius, but features of the lunar terrain may be comparable to the apparent
+# size of the Sun as seen from Artemis II, so the calculation is only an
+# approximation.
+
+eclipse_percentage = sun.eclipse_amount(artemis)
+eclipsed = np.flatnonzero(eclipse_percentage > 0) # at least partially eclipsed
+
+##############################################################################
+# Plot the eclipse percentage when transitioning in an out of eclipse.
+
+fig, axs = plt.subplots(1, 2, layout="constrained")
+
+axs[0].plot(times.datetime64, eclipse_percentage, '.-')
+axs[0].set_xlim((t_c1 - 1*u.min).datetime64, (t_c2 + 1*u.min).datetime64)
+axs[0].set_title("Entering eclipse")
+
+axs[1].plot(times.datetime64, eclipse_percentage, '.-')
+axs[1].set_xlim((t_c3 - 1*u.min).datetime64, (t_c4 + 1*u.min).datetime64)
+axs[1].set_title("Exiting eclipse")
+
+for ax in axs:
+ ax.grid()
+ ax.xaxis.set_major_formatter(DateFormatter('%m-%d %H:%M'))
+ ax.tick_params('x', rotation=90)
+ ax.set_ylabel("Eclipse percentage")
+
+##############################################################################
+# Shift the coordinates to have the Earth-Moon barycenter as the origin,
+# convert to units of Earth radii, and keep only the X and Y components for
+# later plotting.
+
+artemis_x, artemis_y, _ = ((artemis.cartesian - em_barycenter.cartesian).xyz / R_earth).decompose()
+earth_x, earth_y, _ = ((earth.cartesian - em_barycenter.cartesian).xyz / R_earth).decompose()
+moon_x, moon_y, _ = ((moon.cartesian - em_barycenter.cartesian).xyz / R_earth).decompose()
+
+##############################################################################
+# Plot the Artemis II trajectory in fixed ecliptic X-Y coordinates. The motion
+# of the Earth relative to the Earth-Moon barycenter is not discernible on
+# this plot. The segment of the trajectory when Artemis II was in eclipse is
+# highlighted.
+
+fig, ax = plt.subplots()
+
+ax.plot(earth_x, earth_y, ls='dashed', color='b', label='Earth')
+ax.plot(earth_x[-1], earth_y[-1], '.', color='b')
+
+ax.plot(moon_x, moon_y, ls='dashed', color='g', label='Moon')
+ax.plot(moon_x[-1], moon_y[-1], '.', color='g')
+
+ax.plot(artemis_x, artemis_y, color='k', label='Artemis II')
+ax.plot(artemis_x[-1], artemis_y[-1], '.', color='k')
+ax.plot(artemis_x[eclipsed], artemis_y[eclipsed], color='m', lw=3, label='eclipse')
+
+ax.set_title('Fixed coordinate frame')
+ax.set_xlabel('Ecliptic X (Earth radii)')
+ax.set_ylabel('Ecliptic Y (Earth radii)')
+ax.set_aspect('equal')
+ax.legend(loc='center right')
+
+##############################################################################
+# Transform the X and Y components so that the we are in the frame co-rotating
+# with the Moon's orbital motion.
+
+angle = np.arctan2(moon_y, moon_x)
+c, s = np.cos(-angle), np.sin(-angle)
+
+artemis_xp, artemis_yp = artemis_x * c - artemis_y * s, artemis_x * s + artemis_y * c
+earth_xp, earth_yp = earth_x * c - earth_y * s, earth_x * s + earth_y * c
+moon_xp, moon_yp = moon_x * c - moon_y * s, moon_x * s + moon_y * c
+
+##############################################################################
+# Plot the Artemis II trajectory in coordinates co-rotating with the Moon's
+# orbital motion.
+
+fig, ax = plt.subplots()
+
+ax.plot(earth_xp, earth_yp, ls='dashed', color='b', label='Earth')
+ax.plot(earth_xp[-1], earth_yp[-1], '.', color='b')
+
+ax.plot(moon_xp, moon_yp, ls='dashed', color='g', label='Moon')
+ax.plot(moon_xp[-1], moon_yp[-1], '.', color='g')
+
+ax.plot(artemis_xp, artemis_yp, color='k', label='Artemis II')
+ax.plot(artemis_xp[-1], artemis_yp[-1], '.', color='k')
+ax.plot(artemis_xp[eclipsed], artemis_yp[eclipsed], color='m', lw=3, label='eclipse')
+
+ax.set_title('Coordinate frame co-rotating with the Moon')
+ax.set_xlabel('X (Earth radii)')
+ax.set_ylabel('Y (Earth radii)')
+ax.set_aspect('equal')
+ax.legend(loc='center')
+
+plt.show()
+
+# sphinx_gallery_thumbnail_number = 3
diff --git a/pyproject.toml b/pyproject.toml
index f11038a..17753ce 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -68,7 +68,7 @@ map = [
"reproject>=0.13.0",
"scipy>=1.12.0",
]
-opencv = ["opencv-python>=4.8.0.74"]
+opencv = ["opencv-python>=4.8.0.74,!=4.13.0.*"]
net = [
"beautifulsoup4>=4.13.1",
"drms>=0.7.1",
@@ -147,6 +147,7 @@ docs-gallery = [
"astroquery>=0.4.6",
"jplephem>=2.19",
"pillow",
+ "exifread",
]
dev = ["sunpy[docs,tests]"]
diff --git a/sunpy/map/mapbase.py b/sunpy/map/mapbase.py
index 57dbfae..5fd6880 100644
--- a/sunpy/map/mapbase.py
+++ b/sunpy/map/mapbase.py
@@ -674,6 +674,11 @@ class GenericMap(NDData):
# Set the shape of the data array
w2.array_shape = self.data.shape
+ # Unlike Astropy we only use SIP distortions if it is in the CTYPE.
+ if any(t.endswith("-SIP") for t in self.coordinate_system):
+ sip_wcs = astropy.wcs.WCS(header=self.meta)
+ w2.sip = sip_wcs.sip
+
# Validate the WCS here.
w2.wcs.set()
return w2
diff --git a/sunpy/map/sources/tests/test_hmi_source.py b/sunpy/map/sources/tests/test_hmi_source.py
index cc063de..3fe1eac 100644
--- a/sunpy/map/sources/tests/test_hmi_source.py
+++ b/sunpy/map/sources/tests/test_hmi_source.py
@@ -112,11 +112,15 @@ def test_wcs(hmi_map, hmi_bharp_map, hmi_cea_sharp_map, hmi_sharp_map):
# We use our sample HMI image to test memory mapping because it is large (8 MB data array)
@pytest.mark.remote_data
def test_memmap():
+ from sunpy.data.sample import HMI_LOS_IMAGE
+
+ # Burn in base memory usage associated with Map instantiation
+ _ = Map(HMI_LOS_IMAGE)
+
process = psutil.Process()
initial = process.memory_info()
- from sunpy.data.sample import HMI_LOS_IMAGE
hmi_map = Map(HMI_LOS_IMAGE)
instantiated = process.memory_info()
diff --git a/sunpy/map/tests/test_mapbase.py b/sunpy/map/tests/test_mapbase.py
index 3222537..4aba5cc 100644
--- a/sunpy/map/tests/test_mapbase.py
+++ b/sunpy/map/tests/test_mapbase.py
@@ -107,6 +107,41 @@ def test_wcs_pv():
assert pv_values[6] == (2, 10, 0.1)
+def test_wcs_sip(aia171_test_map):
+ wcs1 = aia171_test_map.wcs
+ header_sip = wcs1.to_header()
+ k1 = -7e-12
+
+ header_sip["CTYPE1"] = header_sip["CTYPE1"] + "-SIP"
+ header_sip["CTYPE2"] = header_sip["CTYPE2"] + "-SIP"
+ header_sip['A_ORDER'] = 3
+ header_sip['B_ORDER'] = 3
+ header_sip['A_3_0'] = -k1
+ header_sip['A_1_2'] = -k1
+ header_sip['B_0_3'] = -k1
+ header_sip['B_2_1'] = -k1
+ header_sip['A_DMAX'] = 1.0
+ header_sip['B_DMAX'] = 1.0
+
+ sip_map = sunpy.map.Map(aia171_test_map.data, header_sip)
+
+ sip_wcs = sip_map.wcs
+ assert sip_wcs.sip is not None
+
+ # The SIP distortion shouldn't affect the ref pixel
+ ref1 = aia171_test_map.wcs.pixel_to_world(*aia171_test_map.reference_pixel)
+ ref2 = sip_map.wcs.pixel_to_world(*aia171_test_map.reference_pixel)
+
+ assert u.allclose(ref1.Tx, ref2.Tx)
+ assert u.allclose(ref1.Ty, ref2.Ty)
+
+ # Pixels away from the ref should be distorted
+ edge1 = aia171_test_map.wcs.pixel_to_world(1020, 1020)
+ edge2 = sip_map.wcs.pixel_to_world(1020, 1020)
+
+ assert not u.allclose(edge1.Tx, edge2.Tx)
+ assert not u.allclose(edge1.Ty, edge2.Ty)
+
def test_wcs_cache(aia171_test_map):
wcs1 = aia171_test_map.wcs
wcs2 = aia171_test_map.wcs
diff --git a/sunpy/tests/figure_hashes_mpl_382_ft_261_astropy_702_animators_121.json b/sunpy/tests/figure_hashes_mpl_382_astropy_702_animators_121.json
index dcafe07..dcafe07 100644
--- a/sunpy/tests/figure_hashes_mpl_382_ft_261_astropy_702_animators_121.json
+++ b/sunpy/tests/figure_hashes_mpl_382_astropy_702_animators_121.json
diff --git a/sunpy/tests/figure_hashes_mpl_dev_astropy_dev_animators_dev.json b/sunpy/tests/figure_hashes_mpl_dev_astropy_dev_animators_dev.json
new file mode 100644
index 0000000..deb2b35
--- /dev/null
+++ b/sunpy/tests/figure_hashes_mpl_dev_astropy_dev_animators_dev.json
@@ -0,0 +1,94 @@
+{
+ "sunpy.image.tests.test_transform.test_clipping": "45ce3c4b8e1f3df166607b40e1c351dfc0cea35b12c369e7837682cd74f1f190",
+ "sunpy.image.tests.test_transform.test_nans": "a2c61b11cbd3c27fb34645d77a43aa8cf54cf4500c77761f1c4acf4bccd2e223",
+ "sunpy.map.tests.test_compositemap.test_autoalign_needed": "3aabd400efda925c76ea9f52e6ff35b2e55b48f5a37d6f7b4b3ca6e0eb670a2c",
+ "sunpy.map.tests.test_compositemap.test_autoalign_not_needed": "ca87b99d3eb6556938db2cdcb29693838b6d23479cd99b84b459cba0ca4f51d4",
+ "sunpy.map.tests.test_compositemap.test_peek_composite_map": "a361ece636c91f1c0d0090415254833d646251b3f90e87717b5c1f437634f926",
+ "sunpy.map.tests.test_compositemap.test_plot_composite_map": "3aabd400efda925c76ea9f52e6ff35b2e55b48f5a37d6f7b4b3ca6e0eb670a2c",
+ "sunpy.map.tests.test_compositemap.test_plot_composite_map_colors": "afabf49fc230d7cce3e8654f93bc8003b10494306a47ac930fd49e379c0de45d",
+ "sunpy.map.tests.test_compositemap.test_plot_composite_map_contours": "bf9625a4ba8e2f46a3b8a4970715b4020b24c7d22199884d299f49b039e061af",
+ "sunpy.map.tests.test_compositemap.test_plot_composite_map_linestyles": "2dec3d990edf53686d10d3ab96eea6f5d963a1a93538210580b00c1a92b0c8ee",
+ "sunpy.map.tests.test_compositemap.test_plot_composite_map_linewidths": "f6936102dafcd52d2103c532b30e89c4c89f0c5de4418956ca3cbcf74a66e10a",
+ "sunpy.map.tests.test_compositemap.test_set_alpha_composite_map": "b9ed2ee1795f6735d0d6d78d32a5b9b711e79dd04e009d32244fc41a76b6154f",
+ "sunpy.map.tests.test_map_factory.test_map_jp2_HMI": "0543a91daf4aba425dbd9856c1cb7ffdca26be1a0bbb60488eeed61441492481",
+ "sunpy.map.tests.test_mapbase.test_derotating_nonpurerotation_pcij[opencv]": "395f5d2f5e0c79f2247cd6189391bb16ba5e27072da167897937218aa2935e1b",
+ "sunpy.map.tests.test_mapbase.test_derotating_nonpurerotation_pcij[scikit-image]": "a5fa27410962242a71334363df0c3d224ee31bb79a2341d20fad56c2fa9e3481",
+ "sunpy.map.tests.test_mapbase.test_derotating_nonpurerotation_pcij[scipy]": "138be10fe0c0c3000c866773e48e15ead9f295c0a576b52a6caac7c7305363bf",
+ "sunpy.map.tests.test_mapbase.test_draw_carrington_map": "ebdc5f4341cbb3f316d9c8defce4433cfdceae9b82b2b91bf00466d4602d6a65",
+ "sunpy.map.tests.test_mapbase.test_draw_contours_with_transform": "b3337a429e63eb67ca3d904188b857d05dc48aaf957e448a520e2386e7dd6d18",
+ "sunpy.map.tests.test_mapbase.test_draw_simple_map": "38b43458e341d0d896ff45c82a882b0ef7810caed178607039a0b1a62bb548f2",
+ "sunpy.map.tests.test_mapbase.test_rotation_rect_pixelated_data": "e4958838204e6b1de24113b61f6aa5c720497cd2c24f37dd6e6aaf8944ce90ec",
+ "sunpy.map.tests.test_mapsequence.test_map_sequence_plot": "e52e75b857e87a38d52f7ee875aa3979c7ba2d90ad423112d15fcfbb19012cd0",
+ "sunpy.map.tests.test_mapsequence.test_map_sequence_plot_clip_interval": "38c09506c305d77afd5ebdacc63f1bc7ce4fd076c96c06d0af661ee9d61a52b4",
+ "sunpy.map.tests.test_mapsequence.test_map_sequence_plot_custom_cmap_norm": "00d5e4e139062b434d5185e0f64fe30b1a81a4da9def3e25cc9aed34f911a788",
+ "sunpy.map.tests.test_mapsequence.test_map_sequence_plot_custom_title": "fc9fe740f640fccc7a5e53c96302b079cab022019f218ecdbe8429f4305cf684",
+ "sunpy.map.tests.test_mapsequence.test_norm_animator": "c9bb3df202c3a93b19cc50876f830184bd0e4d4e26e76747626ecd37b09347e0",
+ "sunpy.map.tests.test_plotting.test_draw_contours_aia": "58ca84de5202f102614f87b939d95c38f440ff18dc33c97df779df92f3999d25",
+ "sunpy.map.tests.test_plotting.test_draw_contours_aia_fill": "4f95b006d8ccf999b1fc263d8aa5831c2a8393b6adb047fe240b1c74043ff968",
+ "sunpy.map.tests.test_plotting.test_draw_contours_different_wcs": "1f1ae893be3fb186c8d29c93cec1d3601e636e719d1df4aaee6333129444b362",
+ "sunpy.map.tests.test_plotting.test_draw_grid_aia171": "f79f03e3f33b84c57e992dc3581f72ff6261a87b23458c98e245802dbfdc6930",
+ "sunpy.map.tests.test_plotting.test_draw_limb_different_observer": "86ff4ef5f3ed259e644a9c535f90883f58b14cf5b10c3f92977ec1ea5365ed38",
+ "sunpy.map.tests.test_plotting.test_draw_limb_heliographic_stonyhurst": "35683606ced97f0b0a9b5d006354f650bf0af9f60cea9698c879bce946a82103",
+ "sunpy.map.tests.test_plotting.test_heliographic_grid_annotations": "a83229e7e0fe3814e88b94620dc2761197d88516779a6ea96d1f1ea199605409",
+ "sunpy.map.tests.test_plotting.test_heliographic_peek": "ba3d3a31457afc0f3d423cbb8fe04137c2003afbebb8f00f4e94c07585527183",
+ "sunpy.map.tests.test_plotting.test_heliographic_quadrangle_top_right": "9db4232f67fb7ba5d371d2d3087d32ca32b65e6383cb6210224ab5d26a41c529",
+ "sunpy.map.tests.test_plotting.test_heliographic_quadrangle_width_height": "0f9ad7b226bb7d50360d4ab81f0cec55278e9137a38c1ad0900c68a9b3f1071b",
+ "sunpy.map.tests.test_plotting.test_map_draw_extent": "7c4f47dfbf2ee801d94fbd40bac5b6459674c97fb7f573f79efe52a38722599b",
+ "sunpy.map.tests.test_plotting.test_peek_aia171": "a6c2de0c613492e3dd77456c70b8f837de07fec7d465b575aa84389d2b2be245",
+ "sunpy.map.tests.test_plotting.test_peek_grid_aia171": "bb15419df628155796b74e1deb7b30e5a9502d78f458b38860f82d0c7d6de8a1",
+ "sunpy.map.tests.test_plotting.test_peek_grid_limb_aia171": "539eb4374521fd31add197d10251ac566fcc8fb76aadc9601de886a721833d96",
+ "sunpy.map.tests.test_plotting.test_peek_grid_spacing_aia171": "6f88c76cd547c678ab86bab4fe296baeed88abfae3c0eadceadd7823715cd92a",
+ "sunpy.map.tests.test_plotting.test_peek_limb_aia171": "82ce40f43a08129df4b83746f95aa06fb4225c8ded0389750de549a65f3d5e7c",
+ "sunpy.map.tests.test_plotting.test_plot_aia171": "e52e75b857e87a38d52f7ee875aa3979c7ba2d90ad423112d15fcfbb19012cd0",
+ "sunpy.map.tests.test_plotting.test_plot_aia171_clip": "4bd57c317dce9c5f1afdfa1f0e94023900351776ee81620e58c37c76a6a856c4",
+ "sunpy.map.tests.test_plotting.test_plot_aia171_superpixel": "f79cb0bb834ebe8f5d96e93aa6c0fd6b93ff98c9ae3ecbe2c04a6b61d12cdc98",
+ "sunpy.map.tests.test_plotting.test_plot_autoalign[True]": "aec00583b197b1a5e3042ee097893828d5b37a233793e1c00bac3e11bf3301ac",
+ "sunpy.map.tests.test_plotting.test_plot_autoalign[image]": "aec00583b197b1a5e3042ee097893828d5b37a233793e1c00bac3e11bf3301ac",
+ "sunpy.map.tests.test_plotting.test_plot_autoalign[mesh]": "5e7d46a37f9b75661e5a676ead38d59f34ac18a297916b28bd0eb6a1e2cc45d6",
+ "sunpy.map.tests.test_plotting.test_plot_autoalign_datalim": "b0e486ab131fda609029a3a64620e860b70a9c542c3d1152558129e04e846f8d",
+ "sunpy.map.tests.test_plotting.test_plot_autoalign_image_incomplete": "91040d74b4b9b9f09a3d486545848792e75fc116097f8324abea4043b8643ccf",
+ "sunpy.map.tests.test_plotting.test_plot_autoalign_pixel_alignment": "fcc53382a574808f06012eab4760b206fd3e5bf38f229883d810870f488e5071",
+ "sunpy.map.tests.test_plotting.test_plot_masked_aia171": "51a1bf0993d6862ab2fe9a2be3a9c0ee0e84509206809a7687dd37831de2847d",
+ "sunpy.map.tests.test_plotting.test_plot_masked_aia171_superpixel": "d44104a9b972398ec0ac9e3a9020afd13e305ec9b5bd5fb5a475ce44f4115c79",
+ "sunpy.map.tests.test_plotting.test_plot_masked_aia171_superpixel_conservative_mask_true": "09711d507167ae70d46aff2e52676d663ff2debc5e97546684c3edf73a958e01",
+ "sunpy.map.tests.test_plotting.test_plot_resample": "52ee22bfcdf30b5009b00e15c983e26b67d94072309adb0a7a8469013aa568a4",
+ "sunpy.map.tests.test_plotting.test_plot_rotated_aia171": "af83310f31294c2d7c4ec188b7433780dab3583cfa94a3777200614323db9dc5",
+ "sunpy.map.tests.test_plotting.test_plot_superpixel": "ae88dfd735eb1131024c7a70ddbeb2b3c63793a272777cfc3732e320f7914cec",
+ "sunpy.map.tests.test_plotting.test_quadrangle_aia17_pix_top_right": "0cb8f6892c5fb5a29b9acce2296fb177350067e7cb0fc01b055ff17cb286130f",
+ "sunpy.map.tests.test_plotting.test_quadrangle_aia17_pix_top_right_different_axes": "4a644bb5491663a50171bd8db4dd92ab37312816443b5dcca4342d3fcee99d68",
+ "sunpy.map.tests.test_plotting.test_quadrangle_aia17_pix_width_height": "feca366403e47e0587524979370ed40b0daaca0da5c08ccda94329b09b9ce49a",
+ "sunpy.map.tests.test_plotting.test_quadrangle_aia17_top_right": "8b7e680de38ca40688a45cf84ba94ff4d76cfd8e6921c0bb643aaf5c63e9200c",
+ "sunpy.map.tests.test_plotting.test_quadrangle_aia17_width_height": "743deb72b95fb78b4e6a6dc7324aefc9e5408ad745b5e3e15d5b1696b9160f6a",
+ "sunpy.map.tests.test_plotting.test_rectangle_aia171_top_right": "2222b190a3b639dd05416495f9695a81801e3d91aa6a8d26aa34c8abc564bd4d",
+ "sunpy.map.tests.test_plotting.test_rectangle_aia171_width_height": "0a1d75764c3ff65c076c0bd12e4ac00d1ad506f07db6ee9a4333cc14c0392f5d",
+ "sunpy.map.tests.test_reproject_to.test_reproject_to_auto_extent[None]": "5df61a75bbde4329543b96dd68ff04db2ae713beb56f680b9ef6f4ab8214bbb6",
+ "sunpy.map.tests.test_reproject_to.test_reproject_to_auto_extent[all]": "17bb642f63337daa3feb431de417a634c39c27f944c18ca0a368d344f63a599f",
+ "sunpy.map.tests.test_reproject_to.test_reproject_to_auto_extent[corners]": "0c9c9e274c28d9d2a420c68413d3080c743a152809f46a4ce500e7c2869f1559",
+ "sunpy.map.tests.test_reproject_to.test_reproject_to_auto_extent[edges]": "474d82eb9aeb1f4a8bf58f28e450bc3d10ae59eff324d10389aaad82a51db2f2",
+ "sunpy.map.tests.test_reproject_to.test_reproject_to_hgs": "0dac9107b33c480c1f0990706958fd5472e79a578548c612231ef483b8abe1a9",
+ "sunpy.map.tests.test_reproject_to.test_reproject_to_hpc_adaptive": "1b2ae1627d891265b22bc8f633512d365bbbc09954ca266a78aeffba4639028b",
+ "sunpy.map.tests.test_reproject_to.test_reproject_to_hpc_exact": "bf8da1c2c158665c0462b9c55db4c38a608805e2d4a39b0f8912dd8cca3f14eb",
+ "sunpy.map.tests.test_reproject_to.test_reproject_to_hpc_interpolation": "3f29022c68615cbfc94294b31e48dd41d1791ac36ca979cfc0fca4c409ab6d54",
+ "sunpy.map.tests.test_reproject_to.test_reproject_to_screen_plus_diffrot[PlanarScreen]": "f7fef6ebf50d64098c82c2cf5c5ad388b62e853df6780adc6b5b4d5c141c44f7",
+ "sunpy.map.tests.test_reproject_to.test_reproject_to_screen_plus_diffrot[SphericalScreen]": "cddf9a465580d22a6c18b554778040ff5290c8057ddbdf7451b158910f0bbc86",
+ "sunpy.timeseries.sources.tests.test_eve.test_esp_peek": "def94de87f94900813558471037ebd1cbb3777ae73f53a7994a9d05034a020b8",
+ "sunpy.timeseries.sources.tests.test_eve.test_eve_peek": "60635fe0496c7acd687d1a130c04be42c2f6644f103ca9d4730e0768daac29f8",
+ "sunpy.timeseries.sources.tests.test_fermi_gbm.test_fermi_gbm_peek": "4b33235b8862a239dfda1e594c96886672399e7c7f400d50f0df5e999355188f",
+ "sunpy.timeseries.sources.tests.test_goes.test_goes_peek": "7f891a842285d94afc492b9d75cdbbc65d9f6fbd3a3a9876138b49ffa10d2e65",
+ "sunpy.timeseries.sources.tests.test_goes.test_goes_ylim": "c278f6e36d63ce8b2a8ea5d9baf875a6624b22e4573c9ae900c8da8c47995427",
+ "sunpy.timeseries.sources.tests.test_lyra.test_lyra_peek": "f54fabd3c8f42977283692cdec9df183f6e318b5d3f8dae3c3b41c14845a4ce9",
+ "sunpy.timeseries.sources.tests.test_noaa.test_noaa_json_ind_peek": "8d553c78b46064d03a2811acd178fa0c6c1cfc425d5a0d1ae1a5395ece19e3e1",
+ "sunpy.timeseries.sources.tests.test_noaa.test_noaa_json_pre_peek": "736979df04bd61ee7eb84c9290590c58cfd7e4c96363df6eed51355abf905a9f",
+ "sunpy.timeseries.sources.tests.test_norh.test_norh_peek": "e2a76010927cdf443f5595cb7c9089bcd6046bbaf2680a1b162c7a6c9ef0d295",
+ "sunpy.timeseries.sources.tests.test_rhessi.test_rhessi_peek": "4d27daf59c58b8d3171cb7419632ea596b8ce1bdff0f37e726cf7677bef54e37",
+ "sunpy.timeseries.tests.test_timeseriesbase.test_column_subset_peek": "c2d7a46442a7e82c436579971c548c91d59f1974b23945054f8fe21e5b9ec8de",
+ "sunpy.timeseries.tests.test_timeseriesbase.test_generic_ts_peek": "59c11df98874ad49bb91b03908f41a5cb96ec235682e81b02f4cf84bbaddf1dc",
+ "sunpy.visualization.animator.tests.test_mapsequenceanimator.test_map_sequence_animator_wcs_simple_plot": "9da6b4c3682b0a996aa4fce296f93915de716a75fca51a38a512c434cbf17646",
+ "sunpy.visualization.colormaps.tests.test_cm.test_cmap_visual": "c68cd97a4592af1092e9801991d945ee45ba66806bb9b9eb03d4b1e7b8661e36",
+ "sunpy.visualization.tests.test_drawing.test_draw_equator_aia171": "475f677ed6c1108e78612c4b9f6dbaea0c6a1211f902fe1d54ce6157c1f42c44",
+ "sunpy.visualization.tests.test_drawing.test_draw_extent": "a755ff30c6199f103165bc3e02ed8a194e4badc949050c417f9d5a4377d2ab22",
+ "sunpy.visualization.tests.test_drawing.test_draw_extent_3d": "4ce066dbbc0b9134dcdb87691888375bbfef3cf56e252917ce89138837412131",
+ "sunpy.visualization.tests.test_drawing.test_draw_prime_meridian_aia171": "ee1ca9019c8873bd631ebea6e791792c6179f8f6436f9fa8bcf7ed4859ba09c3",
+ "sunpy.visualization.tests.test_drawing.test_heliographic_equator_prime_meridian": "22a628bc8e1b644511f2e720d3fbf3252dd3c920c24cf2220ff6c58ec4818f01",
+ "sunpy.visualization.tests.test_visualization.test_show_hpr_impact_angle": "c5963b0e9a17c4a1ed592d99d7f0979073ecaaa5d2eed766d1a2d8ccd9c7a4f5"
+}
diff --git a/sunpy/tests/figure_hashes_mpl_dev_ft_261_astropy_dev_animators_dev.json b/sunpy/tests/figure_hashes_mpl_dev_ft_261_astropy_dev_animators_dev.json
deleted file mode 100644
index 74f2421..0000000
--- a/sunpy/tests/figure_hashes_mpl_dev_ft_261_astropy_dev_animators_dev.json
+++ /dev/null
@@ -1,94 +0,0 @@
-{
- "sunpy.image.tests.test_transform.test_clipping": "3d4d308a9807a7e0f5f71e5a77f04e671c65c8eb13fe3c6c4d3cfc68c2cf0650",
- "sunpy.image.tests.test_transform.test_nans": "776e5a2c12bbbff9f5f9de647052cd2ad1be03b39586b91502c8ebba08e87c1b",
- "sunpy.map.tests.test_compositemap.test_autoalign_needed": "82c6eeadafcabd3e9e525f83ee02ef5d603082d1b7356736041405f52694c792",
- "sunpy.map.tests.test_compositemap.test_autoalign_not_needed": "f1ae5d46dbd1dfbd95e3766f98c31778220663ed4d88cc9627c2522092bab22e",
- "sunpy.map.tests.test_compositemap.test_peek_composite_map": "48ffab3c2e79f083588a665afb008af7d2f2867183ed24dd7988dcf7d5aceabc",
- "sunpy.map.tests.test_compositemap.test_plot_composite_map": "82c6eeadafcabd3e9e525f83ee02ef5d603082d1b7356736041405f52694c792",
- "sunpy.map.tests.test_compositemap.test_plot_composite_map_colors": "a44726ea33a1e39a846fe6b1ec6f063a311f47c2c468e86985cd22c67c87fe77",
- "sunpy.map.tests.test_compositemap.test_plot_composite_map_contours": "12ccc5f578614ebe0b37ba8e9b63e6d3e95b3c595e98705968f2ef8d8c5693ed",
- "sunpy.map.tests.test_compositemap.test_plot_composite_map_linestyles": "5478542c64be610c991b727393aef216dbb6d3da85ec763d484b1a1873455a86",
- "sunpy.map.tests.test_compositemap.test_plot_composite_map_linewidths": "08481651b4fdff6d93567b89eec3647ff6869c9099a4b36a597c8913af1df4e7",
- "sunpy.map.tests.test_compositemap.test_set_alpha_composite_map": "c38147ed9c41ab3a3310e60f321d17bb4e16a8077963c24799b9628b34b6f616",
- "sunpy.map.tests.test_map_factory.test_map_jp2_HMI": "2eef1b68d7352bb299d7bbc2b5d3d8f3aa7c1dfd5e2116c915bb64d742bb4a44",
- "sunpy.map.tests.test_mapbase.test_derotating_nonpurerotation_pcij[opencv]": "72f1dcce4cace519c0e68a514b8b08437c8244685654ece27a06e8c10ae470d7",
- "sunpy.map.tests.test_mapbase.test_derotating_nonpurerotation_pcij[scikit-image]": "faab0f5e28ff6cc93d1a80456e34300d44618acc3d57543ce786a20c8ce25d8b",
- "sunpy.map.tests.test_mapbase.test_derotating_nonpurerotation_pcij[scipy]": "c8e919e5b5c8ed6485e9b1d5e002aa380f30d848c2af2d77cac5d185d1a66442",
- "sunpy.map.tests.test_mapbase.test_draw_carrington_map": "1b03d5f7eef721492e58e9e6420078223acbe54dd6cde5a1a934506ac9d3e39d",
- "sunpy.map.tests.test_mapbase.test_draw_contours_with_transform": "52d9589b67abf11d554b2c88b2e08f46ba719838a724c32675c3ccd7ec0201be",
- "sunpy.map.tests.test_mapbase.test_draw_simple_map": "61b1f3381bbda0da5769c8ab9ce006470794d5175682c040d09e60df43d073b0",
- "sunpy.map.tests.test_mapbase.test_rotation_rect_pixelated_data": "a044791b96520b24a26ac7aca129657f6c20f2ab422ef85b4a5fd070006ad456",
- "sunpy.map.tests.test_mapsequence.test_map_sequence_plot": "683ee918c3f72dfb533d38aaaf40b4f5133fb5a161661b884feaa2b3640b84f8",
- "sunpy.map.tests.test_mapsequence.test_map_sequence_plot_clip_interval": "850904ee981a23f914dcb90ad29eebd78d4cbaf9ba03e9fbd979a739ca708a17",
- "sunpy.map.tests.test_mapsequence.test_map_sequence_plot_custom_cmap_norm": "045b4390351310707e99ccd3f1fd2e01ae9c075b99fb3e4b2131c5ed161d73e6",
- "sunpy.map.tests.test_mapsequence.test_map_sequence_plot_custom_title": "9db000405d46b2985c83f75d54c2f7b1b62e7e046d3d15facd1a5e091356456f",
- "sunpy.map.tests.test_mapsequence.test_norm_animator": "f09dcfc8152526da4e33eda932273775a03276c508009c949e78aa476b15e438",
- "sunpy.map.tests.test_plotting.test_draw_contours_aia": "b852393357ea5072feee3d3748263426a4328a66bdd78bee07b38384c8465740",
- "sunpy.map.tests.test_plotting.test_draw_contours_aia_fill": "c503dd17fc11874452f5e778e283d3e70e1fd47ef95158a4ae68a23564cc241e",
- "sunpy.map.tests.test_plotting.test_draw_contours_different_wcs": "0109fdd15e8e4e95037279813d182706fd39431ab91f29b4e257196dead4cbce",
- "sunpy.map.tests.test_plotting.test_draw_grid_aia171": "36cf119197d832d23294316a9f2aff5138b87d246bdf941886518d1e31b63afe",
- "sunpy.map.tests.test_plotting.test_draw_limb_different_observer": "87c1d52e34efb02b1fb99b2343a28b907a9d262f2c3fbfb711cb16c00c74a929",
- "sunpy.map.tests.test_plotting.test_draw_limb_heliographic_stonyhurst": "ffc7d30b8739d7eace36cee2221a4433534fcc1a55baeda0a587f57bfb52add8",
- "sunpy.map.tests.test_plotting.test_heliographic_grid_annotations": "c7c08b2b6dae1b96c303345b04682060da97a1b304e7f25bcfd40b2154751465",
- "sunpy.map.tests.test_plotting.test_heliographic_peek": "cd1968b8b0b6b5447ce739a3d4728721d59d6f0f26c25ca0d333cb0e05f043ce",
- "sunpy.map.tests.test_plotting.test_heliographic_quadrangle_top_right": "40591e49e6b32ec3a27b6fc50b9e2fdfcaa9665eca70b6a515dfb9dc7c0b1724",
- "sunpy.map.tests.test_plotting.test_heliographic_quadrangle_width_height": "a52dca9100f3f96644e924f283c7ba9bd26db115be3a8e19b91898406d06f9ba",
- "sunpy.map.tests.test_plotting.test_map_draw_extent": "d84c6ad1d119cde881c35130cee1a71f72b1eb26b073f5a6e174c5f1efb4a7dd",
- "sunpy.map.tests.test_plotting.test_peek_aia171": "62c4d51d9a58f05279e5fe2bf665992fd51b7523112893f2febd8449dead0ec4",
- "sunpy.map.tests.test_plotting.test_peek_grid_aia171": "3c93b346888c716ab0f78b84df22cad86502baedaf5ed89c005e1ae84f4a6562",
- "sunpy.map.tests.test_plotting.test_peek_grid_limb_aia171": "e525da86084a63477d65b95389f1a7fa8739c53f3ed900aa8aa0e3e418872a3c",
- "sunpy.map.tests.test_plotting.test_peek_grid_spacing_aia171": "947d5947c020bbeb10022c0f146b68e2a33a5f4ebc6b64d5d773d5818c2b0305",
- "sunpy.map.tests.test_plotting.test_peek_limb_aia171": "42d4c7f61de58e5186c15e0230555df7f4076e3f5d63a405c3e4dc72d245c8f8",
- "sunpy.map.tests.test_plotting.test_plot_aia171": "683ee918c3f72dfb533d38aaaf40b4f5133fb5a161661b884feaa2b3640b84f8",
- "sunpy.map.tests.test_plotting.test_plot_aia171_clip": "0481d2760a1da354e6b001c79accc1aa4c4bb41d3ee86b1740fbc125dd4aa84d",
- "sunpy.map.tests.test_plotting.test_plot_aia171_superpixel": "ea868748df67922cfc5c7b7d3b0f5febe7f524d8e6c7183d9a496ae27009367a",
- "sunpy.map.tests.test_plotting.test_plot_autoalign[True]": "a0f08c7afd382c233584810246153b05585f1d9ffdf16e128be9a768d89e666f",
- "sunpy.map.tests.test_plotting.test_plot_autoalign[image]": "a0f08c7afd382c233584810246153b05585f1d9ffdf16e128be9a768d89e666f",
- "sunpy.map.tests.test_plotting.test_plot_autoalign[mesh]": "c87a041f263fbbc01cfa1c3faa79372e39f13be5f6da5a6bb097e09ad551a95f",
- "sunpy.map.tests.test_plotting.test_plot_autoalign_datalim": "8182d215f6a42968bd89ca057c8500ccfb88af8f9d04e26375c4fd4bb141e50b",
- "sunpy.map.tests.test_plotting.test_plot_autoalign_image_incomplete": "86f7918cece5ca5c95a0f6c7693fa7b33df552cd651a322d54cf68d8ff1d1ed1",
- "sunpy.map.tests.test_plotting.test_plot_autoalign_pixel_alignment": "29c7c1545ca51a248bf25b8f112aeb01ca5f3394bb07fc7655f095bd3281e0b6",
- "sunpy.map.tests.test_plotting.test_plot_masked_aia171": "717db809663aa480530c574111126713bf9a2d68fe54525797e735bdc4eaeab2",
- "sunpy.map.tests.test_plotting.test_plot_masked_aia171_superpixel": "01a00df0e69ddee3f052ac6021a019e7c9bb91707541fffa26069e9d4058be79",
- "sunpy.map.tests.test_plotting.test_plot_masked_aia171_superpixel_conservative_mask_true": "196cff21e41c87813b2af7ce95d9feb9746bf00fc94588886f5bb59887c8e488",
- "sunpy.map.tests.test_plotting.test_plot_resample": "a6398dfebbbd68a649966b3b8aeb382d725e0f09cc20a7ce5187564b537ddc83",
- "sunpy.map.tests.test_plotting.test_plot_rotated_aia171": "8682f8136fc8358078fa9b0c6a135d3c75f29cf98f0f2f3eb7acc78b3fa9abf6",
- "sunpy.map.tests.test_plotting.test_plot_superpixel": "8b08a9fbf50767a1b84e246588ba0e4d4589982931107deaee7429db483e1a3a",
- "sunpy.map.tests.test_plotting.test_quadrangle_aia17_pix_top_right": "14a773dd9da0fb6ce6dda591d095c381d14d1e0eb6c8e571488e251db5c4c832",
- "sunpy.map.tests.test_plotting.test_quadrangle_aia17_pix_top_right_different_axes": "28be219434976780e77459c3f7466a9089ca0b780769b3a88d73d47c88635b62",
- "sunpy.map.tests.test_plotting.test_quadrangle_aia17_pix_width_height": "e5dfd3f94410dcbd57fb15112574918085a7973cdc7e1c5612f695bc7825de6c",
- "sunpy.map.tests.test_plotting.test_quadrangle_aia17_top_right": "74629151615d7ab4b1e38e8713ecdc9643f764679cb103b8bf4c0d95357dd558",
- "sunpy.map.tests.test_plotting.test_quadrangle_aia17_width_height": "1bce6d6646b1079908f5518b2121cf109d56dd27c3955eeba05cb1756552e7b5",
- "sunpy.map.tests.test_plotting.test_rectangle_aia171_top_right": "80faf44417e779f446052b2c79ddb51e57ff999af42b83a3c8bd175766786b35",
- "sunpy.map.tests.test_plotting.test_rectangle_aia171_width_height": "29959cf78b26039994312edfcba1ebc3fa0307d083d782341cb50ba84c62390e",
- "sunpy.map.tests.test_reproject_to.test_reproject_to_auto_extent[None]": "8f7a5cd79fb4070c078b2a242ea2d2a0b06b4070b6bdde6a812f74b88aa13490",
- "sunpy.map.tests.test_reproject_to.test_reproject_to_auto_extent[all]": "7bcea2aef8c7e6ec497a81c7c7b2428cda6c40a7e448b400dba176371d29e8d4",
- "sunpy.map.tests.test_reproject_to.test_reproject_to_auto_extent[corners]": "dbe700a16f237db15ef882c8bf41d4bb80cf5f38d8921e452565c6c94e9e114f",
- "sunpy.map.tests.test_reproject_to.test_reproject_to_auto_extent[edges]": "65ae0b7ae9c62066805c89dd6fa5c62f7203fff821f14608683c6002fe7d6640",
- "sunpy.map.tests.test_reproject_to.test_reproject_to_hgs": "84494999fcf4b128fd17608dd95f7645ffbce4ccf3cb5ac59911d7d62dd2f5e7",
- "sunpy.map.tests.test_reproject_to.test_reproject_to_hpc_adaptive": "d5ba72c05de79fed68a6e362fc54e20bf838451306c32de371a54746acc0a4aa",
- "sunpy.map.tests.test_reproject_to.test_reproject_to_hpc_exact": "8fbbdb74b9c5ff80797aa0ea2b47c75301413863f8f28ab2ee4c56a70e4cf3e8",
- "sunpy.map.tests.test_reproject_to.test_reproject_to_hpc_interpolation": "4d82b7e502e16c52f7ab429c932549187246416517a747221a71667e578d3e11",
- "sunpy.map.tests.test_reproject_to.test_reproject_to_screen_plus_diffrot[PlanarScreen]": "37f5115e233440858a00469494860c9ace31edd2f2676b8ddf2a7ff72c76af04",
- "sunpy.map.tests.test_reproject_to.test_reproject_to_screen_plus_diffrot[SphericalScreen]": "ce8606d5a1fbe55dc174c8352cd29cb33d8c39fce4a70c17226d9b2d3508df1b",
- "sunpy.timeseries.sources.tests.test_eve.test_esp_peek": "bbbd836512e0bad9484442254e2419be04376a7b2874275f8aad0efdcbee601f",
- "sunpy.timeseries.sources.tests.test_eve.test_eve_peek": "2a22f93af44971411800e4fcd0d93d2128fe2b9e6b97e576e8372c2cd12d7d78",
- "sunpy.timeseries.sources.tests.test_fermi_gbm.test_fermi_gbm_peek": "a70fb9370b822a18c3da726854c6b9cdd41c7fc8af2f427c66dbc6267b54b551",
- "sunpy.timeseries.sources.tests.test_goes.test_goes_peek": "7ec64d707735bf5f2556ea99a099520aa417c183bcfdb4fc9272f05a7436a010",
- "sunpy.timeseries.sources.tests.test_goes.test_goes_ylim": "8c0283e086bba71a35fa66fbb1d251dd399470bdc7e5c2f76d5d36c08e8dbe8c",
- "sunpy.timeseries.sources.tests.test_lyra.test_lyra_peek": "464333b759d734edabc597aaed748f40d14178b651b8fd6477ff6b077246d134",
- "sunpy.timeseries.sources.tests.test_noaa.test_noaa_json_ind_peek": "0406c11e80d3e4d148f536f580620bd116485afb8856512b89b7b5c26b2cdfd0",
- "sunpy.timeseries.sources.tests.test_noaa.test_noaa_json_pre_peek": "b2e96da3ee10fd76428c6a8a227383cc1aa8005c37e4f0ca35e7c19d7d42164c",
- "sunpy.timeseries.sources.tests.test_norh.test_norh_peek": "b91a29cb2efee5e75940f31531c0bd49109d5d41358434a54a1a66708ad2cb64",
- "sunpy.timeseries.sources.tests.test_rhessi.test_rhessi_peek": "05ea139e1238ab6d46ec2c3b375c46f342d94ebdc035a32a761d066ce803fd88",
- "sunpy.timeseries.tests.test_timeseriesbase.test_column_subset_peek": "0f59e0373961dd47104d0919b22720d2f755716b9b57fd302c728d147a9f9fb6",
- "sunpy.timeseries.tests.test_timeseriesbase.test_generic_ts_peek": "1cb20c67030167b5d9f5047dd3ab488fd7670692f27f51e90ff27e0abaab0a3e",
- "sunpy.visualization.animator.tests.test_mapsequenceanimator.test_map_sequence_animator_wcs_simple_plot": "f92be06a340c32a757d4f73ca80105ca30e05e65d3c9d95aa03c40baf6589890",
- "sunpy.visualization.colormaps.tests.test_cm.test_cmap_visual": "3ea2a02e0c72c28388835dbd12daaad13be9b06bd78fca821213c425bdbc9c07",
- "sunpy.visualization.tests.test_drawing.test_draw_equator_aia171": "080d2b0047c4d16092be263eb4e3736d3d67428c19d9e5fe8908ff837f8c6afe",
- "sunpy.visualization.tests.test_drawing.test_draw_extent": "5da012355e3740b339be789d0079c103ddad19c822975730448f766fddf8b025",
- "sunpy.visualization.tests.test_drawing.test_draw_extent_3d": "57dc22fbd6909c080fb476a7ccd4916b4c4b56ac02bc7ed2e5e8db1b18e60024",
- "sunpy.visualization.tests.test_drawing.test_draw_prime_meridian_aia171": "8c3600762afc1dbf5cf05e79651bd715767ebaeb615c1b788390df6f9bb27bde",
- "sunpy.visualization.tests.test_drawing.test_heliographic_equator_prime_meridian": "3cb195a44e899ef46de7365bd0a0c580b7ea69662bdc560a1bbb1686c2ad48cf",
- "sunpy.visualization.tests.test_visualization.test_show_hpr_impact_angle": "b6cdb96de7411476a395f41c30877ff48db6f17a2f72a3d05b5d8406144072f3"
-}
diff --git a/sunpy/tests/helpers.py b/sunpy/tests/helpers.py
index e0a8663..db1962c 100644
--- a/sunpy/tests/helpers.py
+++ b/sunpy/tests/helpers.py
@@ -90,10 +90,9 @@ def get_hash_library_name():
import mpl_animators
animators_version = "dev" if (("dev" in mpl_animators.__version__) or ("rc" in mpl_animators.__version__)) else mpl_animators.__version__.replace('.', '')
- ft2_version = f"{mpl.ft2font.__freetype_version__.replace('.', '')}"
mpl_version = "dev" if (("dev" in mpl.__version__) or ("rc" in mpl.__version__)) else mpl.__version__.replace('.', '')
astropy_version = "dev" if (("dev" in astropy.__version__) or ("rc" in astropy.__version__)) else astropy.__version__.replace('.', '')
- return f"figure_hashes_mpl_{mpl_version}_ft_{ft2_version}_astropy_{astropy_version}_animators_{animators_version}.json"
+ return f"figure_hashes_mpl_{mpl_version}_astropy_{astropy_version}_animators_{animators_version}.json"
def figure_test(test_function):