Embedding a 1D Flare Spectra in a 2D Image#
We have a 1D spectra as a function of wavelength. To convert this to a 3D data cube (2 spatial dimensions, 1 wavelength dimension), we need to:
Choose a spatial location for the flare
Create an array to embed spectra in with dimensions \((N_\lambda,2N+1,2N+1)\), where \(N\) is the flare kernel size in pixel space
Create a celestial WCS
Interpolate spectra to constant wavelength bins
Create the combined WCS
Create spectral cube using blurred data and combined WCS
[1]:
import pathlib
import asdf
import ndcube
import numpy as np
import astropy.io.fits
import astropy.units as u
import astropy.wcs
from fiasco.io import Parser
from scipy.interpolate import PchipInterpolator
import sunpy.map
import sunpy.io._fits as sunpy_fits
from sunpy.coordinates import get_earth, Helioprojective
from astropy.coordinates import SkyCoord
from astropy.wcs.utils import wcs_to_celestial_frame
from synthesizAR.instruments.util import add_wave_keys_to_header
from mocksipipeline.util import read_data_cube
from mocksipipeline.instrument.configuration import moxsi_slot
[4]:
goes_class = ['a1', 'b1', 'b7', 'm1', 'm5', 'x5']
flare_spectra = []
with asdf.open('../data/reference_spectra/caspi_flare_spectra.asdf', copy_arrays=True) as af:
for gc in goes_class:
flare_spectra.append((gc, ndcube.NDCube(af.tree[gc]['data'], wcs=af.tree[gc]['wcs'])))
flare_spectra = ndcube.NDCollection(flare_spectra, aligned_axes=(0,))
WARNING: UnitsWarning: The unit 'Angstrom' has been deprecated in the VOUnit standard. Suggested: 0.1nm. [astropy.units.format.utils]
Interpolate each of the spectra to a common wavelength axis because we need them to be sampled regularly
[5]:
wave_min = 0.1 * u.AA
wave_max = 80 * u.AA
flare_spectra_interp = {}
for k in flare_spectra:
energy_axis = flare_spectra[k].axis_world_coords(0)[0]
wavelength_axis = energy_axis.to('AA', equivalencies=u.spectral())
delta_wave = np.min(np.fabs(np.diff(wavelength_axis))) * 50 # Don't need the full resolution
wavelength_axis_norm = u.Quantity(np.arange(wave_min.to_value('AA'), wave_max.to_value('AA'), delta_wave.to_value('AA')), 'AA')
f_interp = PchipInterpolator(energy_axis.to_value('keV'), flare_spectra[k].data, extrapolate=True)
data_interp = f_interp(wavelength_axis_norm.to_value('keV', equivalencies=u.spectral())) * flare_spectra[k].unit
flare_spectra_interp[k] = (wavelength_axis_norm, data_interp)
[6]:
earth_observer = get_earth('2020-01-01')
ref_coord = SkyCoord(0, 0, unit='arcsec', frame=Helioprojective(observer=earth_observer))
array_size = (30, 130) # this should always be even
flare_spectra_interp_cubes = {}
for k in flare_spectra_interp:
wavelength, data = flare_spectra_interp[k]
data_array = np.zeros(wavelength.shape+array_size) * data.unit
data_array[:, array_size[0]//2-1:array_size[0]//2+1, array_size[1]//2-1:array_size[1]//2+1] = data[:, None, None]
header = sunpy.map.make_fitswcs_header(
array_size,
ref_coord,
scale=moxsi_slot.optical_design.spatial_plate_scale,
unit=data.unit,
)
header = add_wave_keys_to_header(wavelength, header)
wcs = astropy.wcs.WCS(header=header)
flare_spectra_interp_cubes[k] = ndcube.NDCube(data_array, wcs=wcs, meta=header)
WARNING: FITSFixedWarning: The WCS transformation has more axes (3) than the image it is associated with (2) [astropy.wcs.wcs]
WARNING: FITSFixedWarning: The WCS transformation has more axes (3) than the image it is associated with (2) [astropy.wcs.wcs]
WARNING: FITSFixedWarning: The WCS transformation has more axes (3) than the image it is associated with (2) [astropy.wcs.wcs]
WARNING: FITSFixedWarning: The WCS transformation has more axes (3) than the image it is associated with (2) [astropy.wcs.wcs]
WARNING: FITSFixedWarning: The WCS transformation has more axes (3) than the image it is associated with (2) [astropy.wcs.wcs]
WARNING: FITSFixedWarning: The WCS transformation has more axes (3) than the image it is associated with (2) [astropy.wcs.wcs]
[7]:
results_root = pathlib.Path('/Users/wtbarnes/Documents/codes/mocksipipeline/pipeline/results/')
[9]:
for k in flare_spectra_interp_cubes:
results_dir = results_root / f'caspi_spectra_{k}'
results_dir.mkdir(exist_ok=True)
sunpy_fits.write(results_dir / 'spectral_cube.fits',
flare_spectra_interp_cubes[k].data,
flare_spectra_interp_cubes[k].meta,
overwrite=True)
WARNING: VerifyWarning: Verification reported errors: [astropy.io.fits.verify]
WARNING: VerifyWarning: HDU 0: [astropy.io.fits.verify]
WARNING: VerifyWarning: 'NAXIS3' card at the wrong place (card 35). Fixed by moving it to the right place (card 5). [astropy.io.fits.verify]
WARNING: VerifyWarning: Note: astropy.io.fits uses zero-based indexing.
[astropy.io.fits.verify]
[ ]: