File: adding_earth.py

package info (click to toggle)
sunpy 7.0.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 12,592 kB
  • sloc: python: 41,765; ansic: 1,710; makefile: 39
file content (80 lines) | stat: -rw-r--r-- 3,229 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
"""
===========================
Adding an Earth scale image
===========================

This example shows how to plot a map with an image of the Earth added for scale.
"""
import matplotlib.pyplot as plt
from matplotlib.image import AxesImage
from PIL import Image

import astropy.units as u
from astropy.constants import R_earth
from astropy.coordinates import SkyCoord
from astropy.wcs import WCS

import sunpy.map
from sunpy.coordinates.utils import solar_angle_equivalency
from sunpy.data import EARTH_IMAGE
from sunpy.data.sample import AIA_193_CUTOUT01_IMAGE

###############################################################################
# We start with a sample AIA image.

cutout_map = sunpy.map.Map(AIA_193_CUTOUT01_IMAGE)

###############################################################################
# We use a (low-resolution) image of Earth that we provide with `sunpy`. You
# can use a different image as desired, and it should have a transparent
# background. We also crop the image tightly so that we can assume that the
# image width/height are equal to the Earth diameter. Finally, we flip the
# image vertically so that it is oriented correctly when plotted with the pixel
# origin in the lower-left corner, which is the convention for maps.

earth = Image.open(EARTH_IMAGE)
earth = earth.crop(earth.getbbox())
earth = earth.transpose(Image.FLIP_TOP_BOTTOM)

##############################################################################
# The first step in plotting the Earth is to convert the Earth's diameter in km
# to arcsec on the plane-of-sky for the time of the observation.  We use the
# observer coordinate from the map. For more information about the
# transformation, see :func:`~sunpy.coordinates.utils.solar_angle_equivalency`.

earth_diameter = 2 * R_earth.to(u.arcsec, equivalencies=solar_angle_equivalency(cutout_map.observer_coordinate))
print(f"Earth diameter = {earth_diameter:.2f}")

##############################################################################
# We then create a WCS header so that the Earth will be plotted correctly
# on any underlying map projection. We center the Earth on a specific point in
# the map.

earth_x = 1000 * u.arcsec
earth_y = -200 * u.arcsec
earth_center = SkyCoord(earth_x, earth_y, frame=cutout_map.coordinate_frame)
earth_wcs = sunpy.map.make_fitswcs_header(
    (earth.height, earth.width), earth_center,
    scale=earth_diameter / ([earth.width, earth.height] * u.pix)
)

##############################################################################
# Now we plot the AIA image and superimpose the Earth for scale. We manually
# create and add the image artist so that the Earth will not be considered
# when autoscaling plot limits. We also add a text label above the Earth.

fig = plt.figure()
ax = fig.add_subplot(projection=cutout_map)
cutout_map.plot(clip_interval=(1, 99.9)*u.percent)

earth_artist = AxesImage(ax, transform=ax.get_transform(WCS(earth_wcs)))
earth_artist.set_data(earth)
ax.add_artist(earth_artist)

ax.text(
    earth_x.to_value('deg'), (earth_y + earth_diameter).to_value('deg'),
    'Earth to scale', color='white', fontsize=12, horizontalalignment='center',
    transform=ax.get_transform('world')
)

plt.show()