Plot SUVI L2 Coronal Hole Boundaries

Purpose:

Use Python to plot the SUVI L2 coronal hole boundary (chbnd) product in various coordinate systems.

Overview

In this example, we will be plotting the coronal hole boundaries (chbnd_loc) from the coronal hole boundary product. The boundaries are determined by outlining the coronal hole classifications from the SUVI Thematic Map algorithm.

We will plot chbnd_loc for each of the following coordinate systems:
  • Heliographic Stonyhurst (longitude, latitude)

  • Heliographic Carrington (longitude, latitude)

  • Pixel (x pixels, y pixels)

  • Helioprojective Cartesian (x arcsec, y arcsec)

  • Heliocentric Cartesian (x AU, y AU, z AU)

  • Heliocentric Radial (solar radii, degrees, z solar radii)

Note for this product: The extent is only available in the Heliographic Stonyhurst coordinate system.

Imports

First, we will import the necessary libraries:

__authors__ = "elucas, ajarvis"

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
from datetime import datetime, timedelta
import netCDF4 as nc
from astropy.coordinates import SkyCoord
import sunpy
import sunpy.map
import astropy.units as u
from sunpy.coordinates import frames
from sunpy.net import Fido, attrs as a
from astropy.io import fits

Helper Functions

We need to define a few helper functions for use throughout plotting:

# Fetch the SUVI SunPy map to use as a base for plotting.
def create_suvi_sunpymap(date, goes=16, wavelength=131, rng=2):
    ds0 = (date - timedelta(minutes=rng)).strftime("%Y/%m/%d %H:%M:%S")
    ds1 = (date + timedelta(minutes=rng)).strftime("%Y/%m/%d %H:%M:%S")
    q = Fido.search(a.Time(ds0, ds1), a.Instrument.suvi, a.Wavelength(wavelength*u.angstrom))
    tmp_files = Fido.fetch(q)
    # Select only files for level 2 composites from G16
    for tmp_file in tmp_files:
        if (f'g{goes}' in tmp_file) and ('l2' in tmp_file):
            data, header = fits.getdata(tmp_file, ext=1), fits.getheader(tmp_file, ext=1)
            suvi_map = sunpy.map.Map(data, header)
            return suvi_map, data, header
    print('No SUVI map available')
    return None
# Convert time given in the .nc file to datetime.
def convert_time(time_nc):
    date_2000 = datetime(2000, 1, 1, 12, 0)
    date = date_2000 + timedelta(seconds=time_nc)
    return date
# Define legend for this product.
def legend_handles(coord=''):
    markers = ['o']
    fillstyle = ['full']
    labels = ['chbnd_loc']
    if coord == 'hg':
        markers += ['_']
        fillstyle += ['full']
        labels += ['chbnd_extent']
    f = lambda m, fill: plt.plot([], [], marker=m, color='k', ls='-', fillstyle=fill)[0]
    handles = [f(markers[i], fillstyle[i]) for i in range(len(markers))]
    return handles, labels

Retrieving the SUVI SunPy Map

Let’s use some of the helper functions above to retrieve a SUVI image.
We’ll grab an image of the sun in the 195Å wavelength for datetime 2024-09-12 23:28.
date = datetime(2024, 9, 12, 23, 28)
goes = 16
wavelength = 195
suvi_chbnd_path = f'../../data/suvi/dr_suvi-l2-chbnd_g16_s20240912T232800Z_e20240912T233200Z_v1-0-6.nc'
chbnd_nc = nc.Dataset(suvi_chbnd_path)

Let’s look at the variables contained in the coronal hole boundary files.

for k in chbnd_nc.variables.keys():
    print(k)
time
degraded_status
num_chbnd
chbnd_area
chbnd_extent_hg
chbnd_loc_pix
chbnd_loc_hg
chbnd_loc_car
chbnd_loc_hpc
chbnd_loc_hcc
chbnd_loc_hcr

For our examples, we will be looking at the chbnd_loc variable. We can see the general structure by inspecting this variable in any coordinate system, for example, in Heliographic Stonyhurst.

print(chbnd_nc['chbnd_loc_hg'])
<class 'netCDF4._netCDF4.Variable'>
float32 chbnd_loc_hg(time, feature_number, vertex, location)
    long_name: Coronal hole boundary in Stonyhurst/heliographic coordinates (lon, lat)
    comments: Values provided for on-disk flares only.
    units: degrees, degrees
    _FillValue: -9999.0
unlimited dimensions: time, feature_number, vertex
current shape = (1, 4, 16, 2)
filling on
The structure in this example is (1, 4, 16, 2):
1 : The first dimension of the structure is the time dimension, which will always have 1 value for this product.
4 : The second dimension is the number of separate coronal holes within this image.
16: The third dimension is each vertex of the coronal hole boundary polygon. We are limited to 16 vertices for legacy operational reasons.
2 : The fourth dimension is the coordinate pair (3 for HCC and HCR) of each vertex, with units as described above.

We need to extract the time (found in the ‘time’ variable), and convert to python datetime in order to fetch a corresponding SUVI SunPy map at the closest time possible.

# Get file time
chbnd_time = convert_time(chbnd_nc['time'][:][0])
# Access SUVI SunPy map for that time and defined wavelength
suvi_map, suvi_data, suvi_header = create_suvi_sunpymap(chbnd_time, goes=goes, wavelength=wavelength)
/usr/share/miniconda/envs/goesr-spwx-examples/lib/python3.12/site-packages/sunpy/net/vso/vso.py:222: SunpyUserWarning: VSO-D400 Bad Request - Invalid wavelength, wavetype of filter specification
  warn_user(resp["error"])

Files Downloaded:   0%|          | 0/16 [00:00<?, ?file/s]





OR_SUVI-L1b-Fe195_G16_s20242562328391_e20242562328401_c20242562329104.fits.gz:   0%|          | 0.00/2.18M [00:00<?, ?B/s]




OR_SUVI-L1b-Fe195_G16_s20242562327391_e20242562327391_c20242562328101.fits.gz:   0%|          | 0.00/2.17M [00:00<?, ?B/s]

OR_SUVI-L1b-Fe195_G16_s20242562326191_e20242562326201_c20242562326504.fits.gz:   0%|          | 0.00/2.18M [00:00<?, ?B/s]



OR_SUVI-L1b-Fe195_G16_s20242562327291_e20242562327301_c20242562328008.fits.gz:   0%|          | 0.00/2.18M [00:00<?, ?B/s]


OR_SUVI-L1b-Fe195_G16_s20242562326291_e20242562326291_c20242562327003.fits.gz:   0%|          | 0.00/2.15M [00:00<?, ?B/s]





OR_SUVI-L1b-Fe195_G16_s20242562328391_e20242562328401_c20242562329104.fits.gz:   0%|          | 1.02k/2.18M [00:10<5:56:57, 102B/s]




OR_SUVI-L1b-Fe195_G16_s20242562327391_e20242562327391_c20242562328101.fits.gz:   0%|          | 1.02k/2.17M [00:10<5:56:26, 101B/s]

OR_SUVI-L1b-Fe195_G16_s20242562326191_e20242562326201_c20242562326504.fits.gz:   0%|          | 1.02k/2.18M [00:10<5:57:24, 102B/s]





OR_SUVI-L1b-Fe195_G16_s20242562328391_e20242562328401_c20242562329104.fits.gz:  14%|█▍        | 306k/2.18M [00:10<00:43, 42.7kB/s]




OR_SUVI-L1b-Fe195_G16_s20242562327391_e20242562327391_c20242562328101.fits.gz:   7%|▋         | 153k/2.17M [00:10<01:35, 21.2kB/s]


OR_SUVI-L1b-Fe195_G16_s20242562326291_e20242562326291_c20242562327003.fits.gz:   0%|          | 1.02k/2.15M [00:10<5:50:01, 102B/s]

OR_SUVI-L1b-Fe195_G16_s20242562326191_e20242562326201_c20242562326504.fits.gz:  19%|█▉        | 425k/2.18M [00:10<00:29, 59.4kB/s]


OR_SUVI-L1b-Fe195_G16_s20242562326291_e20242562326291_c20242562327003.fits.gz:  13%|█▎        | 289k/2.15M [00:10<00:45, 40.5kB/s]

OR_SUVI-L1b-Fe195_G16_s20242562326191_e20242562326201_c20242562326504.fits.gz:  79%|███████▊  | 1.72M/2.18M [00:10<00:01, 311kB/s]


OR_SUVI-L1b-Fe195_G16_s20242562326291_e20242562326291_c20242562327003.fits.gz:  65%|██████▌   | 1.40M/2.15M [00:10<00:02, 259kB/s]





OR_SUVI-L1b-Fe195_G16_s20242562328391_e20242562328401_c20242562329104.fits.gz:  40%|████      | 874k/2.18M [00:17<00:20, 63.3kB/s]




OR_SUVI-L1b-Fe195_G16_s20242562327391_e20242562327391_c20242562328101.fits.gz:  20%|██        | 433k/2.17M [00:17<00:55, 31.4kB/s]





OR_SUVI-L1b-Fe195_G16_s20242562328391_e20242562328401_c20242562329104.fits.gz:  54%|█████▎    | 1.17M/2.18M [00:17<00:10, 96.2kB/s]




OR_SUVI-L1b-Fe195_G16_s20242562327391_e20242562327391_c20242562328101.fits.gz:  23%|██▎       | 490k/2.17M [00:17<00:44, 37.5kB/s]





OR_SUVI-L1b-Fe195_G16_s20242562328391_e20242562328401_c20242562329104.fits.gz:  84%|████████▍ | 1.84M/2.18M [00:17<00:01, 202kB/s]




OR_SUVI-L1b-Fe195_G16_s20242562327391_e20242562327391_c20242562328101.fits.gz:  40%|████      | 875k/2.17M [00:17<00:13, 98.7kB/s]






Files Downloaded:   6%|▋         | 1/16 [00:27<06:51, 27.43s/file]



OR_SUVI-L1b-Fe195_G16_s20242562327291_e20242562327301_c20242562328008.fits.gz:   0%|          | 1.00/2.18M [00:17<10737:03:01, 17.7s/B]




OR_SUVI-L1b-Fe195_G16_s20242562327391_e20242562327391_c20242562328101.fits.gz:  56%|█████▌    | 1.21M/2.17M [00:17<00:05, 172kB/s]


Files Downloaded:  12%|█▎        | 2/16 [00:27<02:39, 11.36s/file]



OR_SUVI-L1b-Fe195_G16_s20242562327291_e20242562327301_c20242562328008.fits.gz:   9%|▉         | 193k/2.18M [00:17<02:09, 15.4kB/s]




OR_SUVI-L1b-Fe195_G16_s20242562327391_e20242562327391_c20242562328101.fits.gz:  98%|█████████▊| 2.12M/2.17M [00:17<00:00, 446kB/s]








OR_SUVI-L1b-Fe195_G16_s20242562327291_e20242562327301_c20242562328008.fits.gz:  39%|███▉      | 860k/2.18M [00:17<00:14, 90.5kB/s]



OR_SUVI-L1b-Fe195_G16_s20242562327291_e20242562327301_c20242562328008.fits.gz:  86%|████████▌ | 1.88M/2.18M [00:18<00:01, 250kB/s]




Files Downloaded:  25%|██▌       | 4/16 [00:27<00:51,  4.31s/file]



Files Downloaded:  31%|███▏      | 5/16 [00:28<00:36,  3.32s/file]





OR_SUVI-L1b-Fe195_G16_s20242562329291_e20242562329301_c20242562330002.fits.gz:   0%|          | 0.00/2.19M [00:00<?, ?B/s]

OR_SUVI-L1b-Fe195_G16_s20242562329392_e20242562329392_c20242562330100.fits.gz:   0%|          | 0.00/2.17M [00:00<?, ?B/s]




dr_suvi-l2-ci195_g16_s20240912T232800Z_e20240912T233200Z_v1-0-2.fits:   0%|          | 0.00/1.90M [00:00<?, ?B/s]



OR_SUVI-L1b-Fe195_G18_s20242562326217_e20242562326227_c20242562326454.fits.gz:   0%|          | 0.00/2.20M [00:00<?, ?B/s]


OR_SUVI-L1b-Fe195_G18_s20242562327117_e20242562327127_c20242562327359.fits.gz:   0%|          | 0.00/2.20M [00:00<?, ?B/s]





OR_SUVI-L1b-Fe195_G16_s20242562329291_e20242562329301_c20242562330002.fits.gz:   0%|          | 1.02k/2.19M [00:09<5:44:32, 106B/s]





OR_SUVI-L1b-Fe195_G16_s20242562329291_e20242562329301_c20242562330002.fits.gz:  18%|█▊        | 401k/2.19M [00:09<00:30, 58.1kB/s]

OR_SUVI-L1b-Fe195_G16_s20242562329392_e20242562329392_c20242562330100.fits.gz:   0%|          | 4.00/2.17M [00:09<1470:49:50, 2.44s/B]





OR_SUVI-L1b-Fe195_G16_s20242562329291_e20242562329301_c20242562330002.fits.gz:  67%|██████▋   | 1.47M/2.19M [00:09<00:02, 273kB/s]

OR_SUVI-L1b-Fe195_G16_s20242562329392_e20242562329392_c20242562330100.fits.gz:   5%|▍         | 105k/2.17M [00:09<02:17, 15.0kB/s]





OR_SUVI-L1b-Fe195_G16_s20242562329291_e20242562329301_c20242562330002.fits.gz:  93%|█████████▎| 2.04M/2.19M [00:10<00:00, 424kB/s]






Files Downloaded:  38%|███▊      | 6/16 [00:43<01:07,  6.76s/file]

OR_SUVI-L1b-Fe195_G16_s20242562329392_e20242562329392_c20242562330100.fits.gz:  37%|███▋      | 802k/2.17M [00:09<00:08, 155kB/s]

OR_SUVI-L1b-Fe195_G16_s20242562329392_e20242562329392_c20242562330100.fits.gz:  68%|██████▊   | 1.48M/2.17M [00:10<00:02, 339kB/s]

OR_SUVI-L1b-Fe195_G16_s20242562329392_e20242562329392_c20242562330100.fits.gz:  98%|█████████▊| 2.13M/2.17M [00:10<00:00, 568kB/s]


Files Downloaded:  44%|████▍     | 7/16 [00:43<00:43,  4.80s/file]


OR_SUVI-L1b-Fe195_G18_s20242562327117_e20242562327127_c20242562327359.fits.gz:   0%|          | 1.02k/2.20M [00:10<5:58:50, 102B/s]


OR_SUVI-L1b-Fe195_G18_s20242562327117_e20242562327127_c20242562327359.fits.gz:  22%|██▏       | 481k/2.20M [00:10<00:25, 67.6kB/s]


OR_SUVI-L1b-Fe195_G18_s20242562327117_e20242562327127_c20242562327359.fits.gz:  79%|███████▉  | 1.74M/2.20M [00:10<00:01, 314kB/s]



Files Downloaded:  50%|█████     | 8/16 [00:48<00:38,  4.79s/file]





OR_SUVI-L1b-Fe195_G18_s20242562327217_e20242562327217_c20242562327446.fits.gz:   0%|          | 0.00/2.14M [00:00<?, ?B/s]




dr_suvi-l2-ci195_g16_s20240912T232800Z_e20240912T233200Z_v1-0-2.fits:   0%|          | 1.02k/1.90M [00:19<10:16:26, 51.3B/s]




dr_suvi-l2-ci195_g16_s20240912T232800Z_e20240912T233200Z_v1-0-2.fits:  16%|█▌        | 296k/1.90M [00:20<01:16, 21.0kB/s]



OR_SUVI-L1b-Fe195_G18_s20242562326217_e20242562326227_c20242562326454.fits.gz:   0%|          | 1.02k/2.20M [00:20<11:58:45, 51.1B/s]




dr_suvi-l2-ci195_g16_s20240912T232800Z_e20240912T233200Z_v1-0-2.fits:  75%|███████▌  | 1.43M/1.90M [00:20<00:03, 134kB/s]



OR_SUVI-L1b-Fe195_G18_s20242562326217_e20242562326227_c20242562326454.fits.gz:  15%|█▌        | 336k/2.20M [00:20<01:18, 23.8kB/s]





Files Downloaded:  56%|█████▋    | 9/16 [00:53<00:34,  4.96s/file]

OR_SUVI-L1b-Fe195_G18_s20242562328017_e20242562328027_c20242562328256.fits.gz:   0%|          | 0.00/2.20M [00:00<?, ?B/s]



OR_SUVI-L1b-Fe195_G18_s20242562326217_e20242562326227_c20242562326454.fits.gz:  59%|█████▉    | 1.31M/2.20M [00:20<00:07, 120kB/s]


OR_SUVI-L1b-Fe195_G18_s20242562328117_e20242562328117_c20242562328353.fits.gz:   0%|          | 0.00/2.12M [00:00<?, ?B/s]





OR_SUVI-L1b-Fe195_G18_s20242562327217_e20242562327217_c20242562327446.fits.gz:   0%|          | 1.02k/2.14M [00:09<5:36:29, 106B/s]





OR_SUVI-L1b-Fe195_G18_s20242562327217_e20242562327217_c20242562327446.fits.gz:   9%|▉         | 193k/2.14M [00:09<01:09, 28.0kB/s]





OR_SUVI-L1b-Fe195_G18_s20242562327217_e20242562327217_c20242562327446.fits.gz:  56%|█████▌    | 1.19M/2.14M [00:09<00:04, 231kB/s]

OR_SUVI-L1b-Fe195_G18_s20242562328017_e20242562328027_c20242562328256.fits.gz:   0%|          | 1.02k/2.20M [00:09<5:39:51, 108B/s]




OR_SUVI-L1b-Fe195_G18_s20242562329117_e20242562329127_c20242562329341.fits.gz:   0%|          | 0.00/2.20M [00:00<?, ?B/s]





OR_SUVI-L1b-Fe195_G18_s20242562327217_e20242562327217_c20242562327446.fits.gz:  99%|█████████▉| 2.12M/2.14M [00:10<00:00, 484kB/s]






Files Downloaded:  62%|██████▎   | 10/16 [01:03<00:38,  6.36s/file]

OR_SUVI-L1b-Fe195_G18_s20242562328017_e20242562328027_c20242562328256.fits.gz:  15%|█▍        | 328k/2.20M [00:09<00:38, 48.6kB/s]



OR_SUVI-L1b-Fe195_G18_s20242562326217_e20242562326227_c20242562326454.fits.gz:  88%|████████▊ | 1.94M/2.20M [00:29<00:02, 89.4kB/s]





OR_SUVI-L1b-Fe195_G18_s20242562328017_e20242562328027_c20242562328256.fits.gz:  79%|███████▉  | 1.74M/2.20M [00:09<00:01, 339kB/s]


Files Downloaded:  75%|███████▌  | 12/16 [01:03<00:13,  3.46s/file]


OR_SUVI-L1b-Fe195_G18_s20242562328117_e20242562328117_c20242562328353.fits.gz:   0%|          | 1.02k/2.12M [00:09<5:41:56, 103B/s]


OR_SUVI-L1b-Fe195_G18_s20242562328117_e20242562328117_c20242562328353.fits.gz:  33%|███▎      | 704k/2.12M [00:10<00:14, 99.9kB/s]


OR_SUVI-L1b-Fe195_G18_s20242562328117_e20242562328117_c20242562328353.fits.gz:  99%|█████████▊| 2.09M/2.12M [00:10<00:00, 373kB/s]



Files Downloaded:  81%|████████▏ | 13/16 [01:08<00:11,  3.87s/file]




OR_SUVI-L1b-Fe195_G18_s20242562329117_e20242562329127_c20242562329341.fits.gz:   0%|          | 1.02k/2.20M [00:29<17:44:08, 34.4B/s]




OR_SUVI-L1b-Fe195_G18_s20242562329117_e20242562329127_c20242562329341.fits.gz:  18%|█▊        | 400k/2.20M [00:29<01:34, 19.1kB/s]





OR_SUVI-L1b-Fe195_G18_s20242562329217_e20242562329217_c20242562329449.fits.gz:   0%|          | 0.00/2.22M [00:00<?, ?B/s]




OR_SUVI-L1b-Fe195_G18_s20242562329117_e20242562329127_c20242562329341.fits.gz:  88%|████████▊ | 1.93M/2.20M [00:29<00:02, 123kB/s]





Files Downloaded:  88%|████████▊ | 14/16 [01:33<00:18,  9.30s/file]



dr_suvi-l2-ci195_g18_s20240912T232800Z_e20240912T233200Z_v1-0-2.fits:   0%|          | 0.00/1.89M [00:00<?, ?B/s]



dr_suvi-l2-ci195_g18_s20240912T232800Z_e20240912T233200Z_v1-0-2.fits:   0%|          | 8.78k/1.89M [00:00<00:26, 71.3kB/s]



dr_suvi-l2-ci195_g18_s20240912T232800Z_e20240912T233200Z_v1-0-2.fits:  64%|██████▍   | 1.21M/1.89M [00:00<00:00, 6.36MB/s]




Files Downloaded:  94%|█████████▍| 15/16 [01:33<00:06,  6.92s/file]





OR_SUVI-L1b-Fe195_G18_s20242562329217_e20242562329217_c20242562329449.fits.gz:   0%|          | 1.02k/2.22M [00:10<6:01:34, 102B/s]





OR_SUVI-L1b-Fe195_G18_s20242562329217_e20242562329217_c20242562329449.fits.gz:   8%|▊         | 169k/2.22M [00:10<01:26, 23.7kB/s]





OR_SUVI-L1b-Fe195_G18_s20242562329217_e20242562329217_c20242562329449.fits.gz:  30%|██▉       | 662k/2.22M [00:10<00:13, 120kB/s]





OR_SUVI-L1b-Fe195_G18_s20242562329217_e20242562329217_c20242562329449.fits.gz:  44%|████▍     | 973k/2.22M [00:19<00:21, 56.8kB/s]





OR_SUVI-L1b-Fe195_G18_s20242562329217_e20242562329217_c20242562329449.fits.gz:  76%|███████▌  | 1.69M/2.22M [00:19<00:03, 134kB/s]






Files Downloaded: 100%|██████████| 16/16 [01:53<00:00, 10.36s/file]
Files Downloaded: 100%|██████████| 16/16 [01:53<00:00,  7.07s/file]

Plotting the Coronal Holes

Now that the SUVI SunPy map has been retrieved, we can overplot the coordinates from the .nc file onto that image.

Note: Heliographic Stonyhurst and Heliographic Carrington are only defined on-disk, so any features (or pieces of features) that extend off-disk will not be plotted.

Heliographic Stonyhurst Coordinates

# Plot the composite image
fig_hgs = plt.figure(figsize=(10, 10))
fig_hgs.tight_layout(h_pad=-50)
fig_hgs.suptitle(f'Heliographic Stonyhurst Coordinates, GOES-{goes}')
ax_hgs = fig_hgs.add_subplot(projection=suvi_map)
suvi_map.plot(axes=ax_hgs, clip_interval=(0.1, 99.9) * u.percent)

# Ignore INFO message about 'Missing metadata for solar radius: assuming the standard radius of the photosphere.'
# RSUN_REF will be included in future data products.

chbnd_hg = chbnd_nc['chbnd_loc_hg'][:].data[0]

colors = cm.Reds_r(np.linspace(0.3, 0.6, len(chbnd_hg)))

for hole, c in zip(chbnd_hg, colors):
    hole = [*hole, hole[0]]
    hole = np.array(hole, dtype=float)
    hole = np.where(hole == -9999., np.nan, hole)
    chbnd_hgs_sc = SkyCoord([(float(v[0]), float(v[1])) * u.degree for v in hole], obstime=date,
                            observer=suvi_map.observer_coordinate, frame=frames.HeliographicStonyhurst)

    # Transform skycoord object to the suvi sunpy map's coordinate frame
    chbnd_hgs_sc.transform_to(suvi_map.coordinate_frame)

    # Plot flare
    ax_hgs.plot_coord(chbnd_hgs_sc, color=c, marker='o', markersize=2)

chbnd_extent = chbnd_nc['chbnd_extent_hg'][:].data[0]

for hole, c in zip(chbnd_extent, colors):
    hole = np.array(hole, dtype=float)
    hole = np.where(hole == -9999., np.nan, hole)
    if np.isnan(hole).all():
        continue

    # coordinates are in N(0) lat, S(1) lat, E(2) lon, W(3) lon
    # (lon, lat) because skycoord is in (lon, lat)
    bl_coord = [hole[2], hole[1]]
    tr_coord = [hole[3], hole[0]]

    bottom_left = SkyCoord(bl_coord[0] * u.degree, bl_coord[1] * u.degree, obstime=date,
                           observer=suvi_map.observer_coordinate, frame=frames.HeliographicStonyhurst)
    top_right = SkyCoord(tr_coord[0] * u.degree, tr_coord[1] * u.degree, obstime=date,
                         observer=suvi_map.observer_coordinate, frame=frames.HeliographicStonyhurst)

    suvi_map.draw_quadrangle(bottom_left, top_right=top_right, axes=ax_hgs,
                             edgecolor=c, linewidth=1)

# Add legend for features
handles, labels = legend_handles(coord='hg')
plt.legend(handles, labels, loc=1, framealpha=1)

plt.show()
Heliographic Stonyhurst Coordinates, GOES-16, SUVI $195 \; \mathrm{\mathring{A}}$ 2024-09-12 23:28:39
INFO: Missing metadata for solar radius: assuming the standard radius of the photosphere. [sunpy.map.mapbase]
2024-12-01 16:11:29 - sunpy - INFO: Missing metadata for solar radius: assuming the standard radius of the photosphere.
INFO: Missing metadata for solar radius: assuming the standard radius of the photosphere. [sunpy.map.mapbase]
2024-12-01 16:11:39 - sunpy - INFO: Missing metadata for solar radius: assuming the standard radius of the photosphere.

Heliographic Carrington Coordinates

# Plot the SUVI SunPy composite image
fig_car = plt.figure(figsize=(10, 10))
fig_car.tight_layout(h_pad=-50)
fig_car.suptitle(f'Heliographic Carrington Coordinates, GOES-{goes}')
ax_car = fig_car.add_subplot(projection=suvi_map)
suvi_map.plot(axes=ax_car, clip_interval=(0.1, 99.9) * u.percent)

# Extract coronal hole boundary array from netCDF
chbnd_car = chbnd_nc['chbnd_loc_car'][:].data[0]
colors = cm.YlOrBr_r(np.linspace(0.3, 0.6, len(chbnd_car)))

for hole, c in zip(chbnd_car, colors):
    hole[hole == -9999.] = np.nan
    # Close boundary polygon
    hole = [*hole, hole[0]]

    chbnd_car_sc = SkyCoord([(float(v[0]), float(v[1])) * u.degree for v in hole], obstime=date,
                            observer=suvi_map.observer_coordinate, frame=frames.HeliographicCarrington)
    # Transform SkyCoord object to the SUVI SunPy map's coordinate frame
    chbnd_car_sc = chbnd_car_sc.transform_to(suvi_map.coordinate_frame)

    # Plot boundary
    ax_car.plot_coord(chbnd_car_sc, color=c, marker='o', markersize=2)

# Add legend for features
handles, labels = legend_handles()
plt.legend(handles, labels, loc=1, framealpha=1)

plt.show()
Heliographic Carrington Coordinates, GOES-16, SUVI $195 \; \mathrm{\mathring{A}}$ 2024-09-12 23:28:39

Pixel Coordinates

# Plot the SUVI SunPy composite image
fig_px = plt.figure(figsize=(10, 10))
fig_px.tight_layout()
ax_px = fig_px.add_subplot(projection=suvi_map)
suvi_map.plot(axes=ax_px, clip_interval=(0.1, 99.9) * u.percent)
fig_px.suptitle(f'Pixel Coordinates, GOES-{goes}')

# Extract coronal hole boundary array from netCDF
chbnd_pix = chbnd_nc['chbnd_loc_pix'][:].data[0]
colors = cm.Greens_r(np.linspace(0.3, 0.6, len(chbnd_pix)))

for hole, c in zip(chbnd_pix, colors):
    hole[hole == -9999.] = np.nan
    # Close boundary polygon
    hole = [*hole, hole[0]]

    chbnd_pix_x = [h[0] for h in hole]
    chbnd_pix_y = [h[1] for h in hole]

    # Plot boundary
    ax_px.plot_coord(chbnd_pix_x, chbnd_pix_y, color=c, marker='o', markersize=2)

# Add legend for features
handles, labels = legend_handles()
plt.legend(handles, labels, loc=1, framealpha=1)

plt.show()
Pixel Coordinates, GOES-16, SUVI $195 \; \mathrm{\mathring{A}}$ 2024-09-12 23:28:39

Helioprojective Cartesian Coordinates

# Plot the composite image
fig_hpc = plt.figure(figsize=(10, 10))
fig_hpc.tight_layout(h_pad=-50)
fig_hpc.suptitle(f'Helioprojective Cartesian Coordinates, GOES-{goes}')
ax_hpc = fig_hpc.add_subplot(projection=suvi_map)
suvi_map.plot(axes=ax_hpc, clip_interval=(0.1, 99.9) * u.percent)

chbnd_hpc = chbnd_nc['chbnd_loc_hpc'][:].data[0]

colors = cm.Blues_r(np.linspace(0., 0.3, len(chbnd_hpc)))

for hole, c in zip(chbnd_hpc, colors):
    hole = [*hole, hole[0]]
    hole = np.array(hole, dtype=float)
    hole = np.where(hole == -9999., np.nan, hole)
    chbnd_hpc_sc = SkyCoord([(float(v[0]), float(v[1])) * u.arcsec for v in hole], obstime=date,
                            observer=suvi_map.observer_coordinate, frame=frames.Helioprojective)
    # Transform skycoord object to the suvi sunpy map's coordinate frame
    chbnd_hpc_sc.transform_to(suvi_map.coordinate_frame)

    # Plot flare
    ax_hpc.plot_coord(chbnd_hpc_sc, color=c, marker='o', markersize=2)

# Add legend for features
handles, labels = legend_handles()
plt.legend(handles, labels, loc=1, framealpha=1)

plt.show()
Helioprojective Cartesian Coordinates, GOES-16, SUVI $195 \; \mathrm{\mathring{A}}$ 2024-09-12 23:28:39

Helioprojective Cartesian Coordinates

# Plot the composite image
fig_hcc = plt.figure(figsize=(10, 10))
fig_hcc.tight_layout(h_pad=-50)
fig_hcc.suptitle(f'Heliocentric Cartesian Coordinates, GOES-{goes}')
ax_hcc = fig_hcc.add_subplot(projection=suvi_map)
suvi_map.plot(axes=ax_hcc, clip_interval=(0.1, 99.9) * u.percent)

chbnd_hcc = chbnd_nc['chbnd_loc_hcc'][:].data[0]

colors = cm.PiYG(np.linspace(0., 0.3, len(chbnd_hcc)))

for hole, c in zip(chbnd_hcc, colors):
    hole = [*hole, hole[0]]
    hole = np.array(hole, dtype=float)
    hole = np.where(hole == -9999., np.nan, hole)
    chbnd_hcc_sc = SkyCoord([(float(v[0]), float(v[1]), float(v[2])) * u.AU for v in hole],
                            obstime=date, observer=suvi_map.observer_coordinate, frame=frames.Heliocentric)

    # Plot flare
    ax_hcc.plot_coord(chbnd_hcc_sc, color=c, marker='o', markersize=2)

# Add legend for features
handles, labels = legend_handles()
plt.legend(handles, labels, loc=1, framealpha=1)

plt.show()
Heliocentric Cartesian Coordinates, GOES-16, SUVI $195 \; \mathrm{\mathring{A}}$ 2024-09-12 23:28:39

Heliocentric Radial Coordinates

chbnd_hcr = chbnd_nc['chbnd_loc_hcr'][:].data[0]

# Plot the composite image
fig = plt.figure(figsize=(10, 10))
fig.tight_layout(h_pad=-50)
fig.suptitle(f'Heliocentric Radial Coordinates, GOES-{goes}')
ax = fig.add_subplot(projection=suvi_map)
suvi_map.plot(axes=ax, clip_interval=(0.1, 99.9) * u.percent)
num_points = 100

colors = cm.BuPu(np.linspace(0.85, 1., len(chbnd_hcr)))

for hole, c in zip(chbnd_hcr, colors):
    hole = [*hole, hole[0]]
    hole = np.array(hole, dtype=float)
    hole = np.where(hole == -9999., np.nan, hole)

    # Need to rotate psi by 90 degrees, according to SkyCoord cylindrical specifications
    chbnd_hcr_sc = SkyCoord(
        [(float(v[0]) * u.solRad, float(v[1] + 90.) * u.deg, float(v[2]) * u.solRad) for v in hole],
        representation_type='cylindrical',
        obstime=date, observer=suvi_map.observer_coordinate, frame=frames.Heliocentric)

    # Plot flare
    ax.plot_coord(chbnd_hcr_sc, color=c, marker='o', markersize=2)

# Add legend for features
handles, labels = legend_handles()
plt.legend(handles, labels, loc=1, framealpha=1)

plt.show()
Heliocentric Radial Coordinates, GOES-16, SUVI $195 \; \mathrm{\mathring{A}}$ 2024-09-12 23:28:39

Total running time of the script: (2 minutes 54.409 seconds)

Gallery generated by Sphinx-Gallery