Skip to content

Commit

Permalink
V34 changes (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
nabobalis authored Feb 23, 2023
1 parent c7aafea commit b39d203
Show file tree
Hide file tree
Showing 21 changed files with 706 additions and 227 deletions.
13 changes: 4 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
apt:
- ffmpeg
envs: |
- linux: py310
- linux: py311
test:
needs: [core]
Expand All @@ -44,16 +44,13 @@ jobs:
brew:
- ffmpeg
envs: |
- linux: py311
- windows: py39
- macos: py38
- linux: py38-oldestdeps
- windows: py310
- macos: py39-oldestdeps
docs:
needs: [core]
uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main
with:
default_python: '3.8'
submodules: false
pytest: false
cache-key: docs-${{ github.run_id }}
Expand All @@ -69,15 +66,14 @@ jobs:
needs: [core]
uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main
with:
default_python: '3.8'
submodules: false
coverage: codecov
posargs: -n auto --dist loadgroup
libraries: |
apt:
- ffmpeg
envs: |
- linux: py39-online
- linux: py311-online
cron:
if: |
Expand All @@ -87,7 +83,6 @@ jobs:
)
uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main
with:
default_python: '3.8'
submodules: false
coverage: codecov
posargs: -n auto
Expand Down
15 changes: 10 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,23 @@ repos:
- id: docformatter
args: [--in-place, --pre-summary-newline, --make-summary-multi]
- repo: https://github.com/myint/autoflake
rev: v2.0.0
rev: v2.0.1
hooks:
- id: autoflake
args: ['--in-place', '--remove-all-unused-imports', '--remove-unused-variable']
exclude: ".*(.fits|.fts|.fit|.txt|tca.*|extern.*|.rst|.md|__init__.py|docs/conf.py)$"
exclude: ".*(.fits|.fts|.fit|.txt|tca.*|extern.*|.rst|.md|docs/conf.py)$"
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: 'v0.0.247'
hooks:
- id: ruff
args: ['--fix']
- repo: https://github.com/psf/black
rev: 22.12.0
rev: 23.1.0
hooks:
- id: black
exclude: ".*(.fits|.fts|.fit|.txt|.csv)$"
- repo: https://github.com/timothycrosley/isort
rev: 5.11.4
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort
exclude: ".*(.fits|.fts|.fit|.txt|.csv)$"
Expand Down
7 changes: 4 additions & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
default_role = "obj"

# -- Options for hoverxref -----------------------------------------------------
import os
import os # NOQA

if os.environ.get("READTHEDOCS"):
# Building on Read the Docs
Expand Down Expand Up @@ -125,7 +125,7 @@
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
try:
from sunpy_sphinx_theme.conf import *
from sunpy_sphinx_theme.conf import * # NOQA
except ImportError:
html_theme = "default"

Expand All @@ -145,10 +145,11 @@
"examples_dirs": os.path.join("..", "examples"),
"within_subsection_order": ExampleTitleSortKey,
"gallery_dirs": os.path.join("generated", "gallery"),
"default_thumb_file": os.path.join(html_static_path[0], "img", "sunpy_icon_128x128.png"),
"default_thumb_file": os.path.join(html_static_path[0], "img", "sunpy_icon_128x128.png"), # NOQA
"abort_on_example_error": False,
"plot_gallery": "True",
"remove_config_comments": True,
"doc_module": ("sunpy"),
"only_warn_on_example_error": True,
"matplotlib_animations": True,
}
45 changes: 31 additions & 14 deletions examples/align_iris_aia.py → examples/align_iris_aia_rolled.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
"""
============================
Aligning IRIS SJI to SDO/AIA
============================
=====================================
Aligning IRIS SJI (rolled) to SDO/AIA
=====================================
In this example we will show how to align a rolled IRIS dataset to SDO/AIA.
You can get IRIS data with co-aligned SDO data (and more) from https://iris.lmsal.com/search/
"""
# sphinx_gallery_thumbnail_number = 5


import astropy.units as u
import matplotlib.pyplot as plt
import numpy as np
Expand All @@ -17,7 +18,7 @@
from aiapy.calibrate import update_pointing
from astropy.coordinates import SkyCoord
from astropy.time import Time, TimeDelta
from sunpy.coordinates.frames import Helioprojective
from astropy.wcs.utils import wcs_to_celestial_frame
from sunpy.net import Fido
from sunpy.net import attrs as a

Expand All @@ -33,7 +34,7 @@

sji_filename = pooch.retrieve(
"http://www.lmsal.com/solarsoft/irisa/data/level2_compressed/2014/09/19/20140919_051712_3860608353/iris_l2_20140919_051712_3860608353_SJI_2832_t000.fits.gz",
known_hash=None,
known_hash="02a1cdbe2014e24b04ff782dcfdbaf553c5a03404813888ddea8c50a9d6b2630",
)

###############################################################################
Expand Down Expand Up @@ -66,11 +67,11 @@
print(sji_cut)

###############################################################################
# We need to create a coordinate frame for the IRIS data.
# We need to get the coordinate frame for the IRIS data.
# While this is stored in the WCS, getting a coordinate frame is a little more involved.
# We will use this to do a cutout later on but for now we will plot it.

sji_frame = Helioprojective(observer="earth", obstime="2014-09-19T05:17:31.110")
sji_frame = wcs_to_celestial_frame(sji_cut.basic_wcs)
bbox = [
SkyCoord(-750 * u.arcsec, 90 * u.arcsec, frame=sji_frame),
SkyCoord(-750 * u.arcsec, 95 * u.arcsec, frame=sji_frame),
Expand Down Expand Up @@ -139,7 +140,7 @@

###############################################################################
# The fact that it is rolled 45 degrees makes manual alignment tricky
# and will illustrate the power of working with WCS.
# and will illustrate the usefulness of working with WCS.
# We will download an AIA 170 nm image from the VSO.
# Once we have acquired it, we will need to use **aiapy** to prep this image.

Expand Down Expand Up @@ -182,36 +183,52 @@
edgecolor="green",
linestyle="--",
linewidth=2,
transform=ax.get_transform(sji_frame),
# transform=ax.get_transform(sji_frame),
)

plt.show()

# ###############################################################################
# # Now let's plot the IRIS field of view on the AIA image using the information
# # from the WCS coordinates. This IRIS basic WCS has no observer coordinate information
# # so we are just going to pretend it's at AIA for this example.
# # This will allow us to transform from IRIS to SDO/AIA.

# sji_corrected_wcs = copy(sji_cut.basic_wcs)
# sji_corrected_wcs.wcs.dateobs = sji_cut.isot
# sji_corrected_wcs.wcs.aux.hgln_obs = aia_map.observer_coordinate.lon.to_value(u.deg)
# sji_corrected_wcs.wcs.aux.hglt_obs = aia_map.observer_coordinate.lat.to_value(u.deg)
# sji_corrected_wcs.wcs.aux.rsun_ref = aia_map.observer_coordinate.rsun.to_value(u.m)

# # We have to re-create the coordinate frame.
# sji_frame_corrected = wcs_to_celestial_frame(sji_corrected_wcs)

###############################################################################
# We have a green square showing the region of the IRIS observation.
# To work with both IRIS and AIA data, it helps if the image axes are aligned,
# and for this we need to rotate one of them. We can either rotate SDO/AIA to the
# IRIS frame, or vice-versa.
#
# We will rotate the AIA data, using `.reproject_to`.
# As `sunpy` does not support gWCS, we have to use the basic WCS.

aia_rot = aia_sub.reproject_to(sji_2832[time_index].wcs)
aia_rot = aia_sub.reproject_to(sji_cut.basic_wcs)

# Crop the AIA FOV to match IRIS.
bl = aia_rot.wcs.world_to_pixel(sji_2832[time_index].wcs.pixel_to_world(*(0, 0) * u.pix))
bl = aia_rot.wcs.world_to_pixel(sji_cut.basic_wcs.pixel_to_world(*(0, 0) * u.pix))
tr = aia_rot.wcs.world_to_pixel(
sji_2832[time_index].wcs.pixel_to_world(*(sji_cut.data.shape[0], sji_cut.data.shape[1]) * u.pix)
sji_cut.basic_wcs.pixel_to_world(*(sji_cut.data.shape[0], sji_cut.data.shape[1]) * u.pix)
)

###############################################################################
# Finally we will plot the results.

fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1, projection=sji_frame)
ax1 = fig.add_subplot(1, 2, 1, projection=sji_cut.basic_wcs)
aia_rotate_crop = aia_rot.submap(bl * u.pix, top_right=tr * u.pix)
aia_rotate_crop.plot(axes=ax1, autoalign=True)

ax2 = fig.add_subplot(1, 2, 2, projection=sji_cut)
ax2 = fig.add_subplot(1, 2, 2, projection=sji_cut.basic_wcs)
sji_cut.plot(axes=ax2, cmap="irissji2832", vmin=0, vmax=4500)
ax2.set_title(f"IRIS SJI {sji_2832.meta['TWAVE1']}Å")
ax2.grid(color="w", ls=":")
Expand Down
150 changes: 150 additions & 0 deletions examples/raster.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
"""
====================================
Working with IRIS spectrograph files
====================================
In this example, we will showcase how to use ``irispy-lmsal`` to open, crop and plot IRIS spectrograph data.
"""
import astropy.units as u
import matplotlib.pyplot as plt
import numpy as np
import pooch
from astropy.coordinates import SkyCoord, SpectralCoord
from sunpy.coordinates.frames import Helioprojective

from irispy.io import read_files

###############################################################################
# We start with getting the data.
# This is done by downloading the data from the IRIS archive.
#
# In this case, we will use ``pooch`` to keep this example self contained
# but using your browser will also work.

raster_filename = pooch.retrieve(
"http://www.lmsal.com/solarsoft/irisa/data/level2_compressed/2018/01/02/20180102_153155_3610108077/iris_l2_20180102_153155_3610108077_raster.tar.gz",
known_hash="0ec2b7b20757c52b02e0d92c27a5852b6e28759512c3d455f8b6505d4e1f5cd6",
)

###############################################################################
# Note that when ``memmap=True``, the data values are read from the FITS file
# directly without the scaling to Float32, the data values are no longer in DN,
# but in scaled integer units that start at −2$^{16}$/2.

raster = read_files(raster_filename, memmap=True, uncertainty=False)
# Provide an overview of the data
print(raster)
# Will give us all the keys that corresponds to wavelengths.
print(raster.keys())

###############################################################################
# We will now access one wavelength window and plot it.

mg_ii = raster["Mg II k 2796"][0]

plt.figure()
mg_ii.plot()

plt.show()

###############################################################################
# We can index to get the first index and plot it.

plt.figure()
mg_ii[0].plot()

plt.show()

###############################################################################
# Or we can get the spectrum directly.

plt.figure()
mg_ii[120, 200].plot()

plt.show()

###############################################################################
# The default plots take the units and labels from the FITS WCS information,
# and often do not come in the most useful units (e.g. wavelengths in metres).
# We can read the wavelengths of the Mg window by calling axis_world_coords for wl
# (wavelength), and redo the plot with a better scale:

(mg_wave,) = mg_ii.axis_world_coords("wl")
mg_wave.to("m")

fig, ax = plt.subplots()
# Here we index the data directly instead of other methods to get access to the data and plot it "raw"
plt.plot(mg_wave.to("nm"), mg_ii.data[120, 200])

plt.show()

###############################################################################
# When we use the underlying data directly, we lose all the metadata and WCS information,
# so we would suggest not doing it normally but there will be times you will need to do this.
# If you are unfamiliar with WCS, the following links are quite useful:
# The base comes from astropy: https://docs.astropy.org/en/stable/wcs/index.html
# The plotting makes use of WCSAxes: https://docs.astropy.org/en/stable/visualization/wcsaxes/index.html
# Some of the higher-level utils are via NDCube, e.g. coordinate transformations: https://docs.sunpy.org/projects/ndcube/en/v2.0.0rc2/coordinates.html.
# We can also improve on the default spectrogram plot by adjusting some options:

plt.figure()
mg_ii[0].plot(aspect="auto", cmap="irissjiNUV")
ax = plt.gca()
ax.coords[0].set_major_formatter("x.x")
ax.coords[0].set_format_unit(u.nm)
ax.set_xlabel("Wavelength (nm)")
ax.set_ylabel("Helioprojective latitude [Solar Y] (arcsec)")
# Remove longitude ticks
ax.coords[2].set_ticks([] * u.degree)

plt.show()

###############################################################################
# What is the wavelength position that corresponds to Mg II k core (279.63 nm)?

wcs_loc = mg_ii.wcs.world_to_pixel(
SpectralCoord(279.63, unit=u.nm),
SkyCoord(0 * u.arcsec, 0 * u.arcsec, frame=Helioprojective),
)
mg_index = int(np.round(wcs_loc[0]))
print(mg_index)

###############################################################################
# Now we will plot spectroheliogram for Mg II k core wavelength.
# We can use a new feature in ndcube 2.0 called crop to get this information
# that will require a SkyCoord and SpectralCoord object from astropy.
# In this case, we only need to use a SpectralCoord.

lower_corner = [SpectralCoord(280, unit=u.nm), None]
upper_corner = [SpectralCoord(280, unit=u.nm), None]
mg_crop = mg_ii.crop(lower_corner, upper_corner)

ax = mg_crop.plot()
plt.xlabel("Solar X")
plt.ylabel("Solar Y")

plt.show()

###############################################################################
# Imagine there's a really cool feature at (-338", 275"), how can you plot
# the spectrum at that location?

lower_corner = [None, SkyCoord(-338 * u.arcsec, 275 * u.arcsec, frame=Helioprojective)]
upper_corner = [None, SkyCoord(-338 * u.arcsec, 275 * u.arcsec, frame=Helioprojective)]
mg_ii.crop(lower_corner, upper_corner).plot()

plt.show()

###############################################################################
# Now, you may also be interested in knowing the time that was this observation taken.
# There is some information in ``.meta``.

print(mg_ii.meta)

###############################################################################
# But this is mostly about the observation in general.
# Times of individual scans are saved in .extra_coords['time'].
# Getting access to it can be done in the following way:

# The first index is to escape the tuple that ``axis_world_coords`` returns
print(mg_ii.axis_world_coords("time", wcs=mg_ii.extra_coords)[0][0].isot)
2 changes: 1 addition & 1 deletion examples/skip_umbral_flashes.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
# time array for the 1400 SJI.

# We will take the first 50 to cut down on the size of the data for this example.
# This also lines up with the amount of data from the raster.
# This is memory intensive and that an upstream bug needs to be fixed.
times_sji = sji_1400.time[:50]

###############################################################################
Expand Down
Loading

0 comments on commit b39d203

Please sign in to comment.