data = np.array([[[1, 2, 3, 4], [2, 4, 5, 3], [0, 1, 2, 3]], [[2, 4, 5, 1], [10, 5, 2, 2], [10, 3, 3, 0]]]) data_2D = np.array([[1, 2, 3, 4], [2, 4, 5, 3]]) data_1D = np.array([1, 2]) data_4D = np.array([[[[1, 2, 3, 4], [2, 4, 5, 3], [0, 1, 2, 3]], [[2, 4, 5, 1], [10, 5, 2, 2], [10, 3, 3, 0]]], [[[1, 2, 3, 4], [2, 4, 5, 3], [0, 1, 2, 3]], [[2, 4, 5, 1], [10, 5, 2, 2], [10, 3, 3, 0]]]]) header = {'CTYPE1': 'HPLN-TAN', 'CUNIT1': 'arcsec', 'CDELT1': 0.4, 'CRPIX1': 0, 'CRVAL1': 0, 'NAXIS1': 4, 'CTYPE2': 'HPLT-TAN', 'CUNIT2': 'arcsec', 'CDELT2': 0.5, 'CRPIX2': 0, 'CRVAL2': 0, 'NAXIS2': 3, 'CTYPE3': 'Time ', 'CUNIT3': 'seconds', 'CDELT3': 0.3, 'CRPIX3': 0, 'CRVAL3': 0, 'NAXIS3': 2} wcs = WCS(header=header, naxis=3) header_2D = {'CTYPE1': 'Time ', 'CUNIT1': 'seconds', 'CDELT1': 0.4, 'CRPIX1': 0, 'CRVAL1': 0, 'NAXIS1': 4, 'CTYPE2': 'HPLT-TAN', 'CUNIT2': 'arcsec', 'CDELT2': 0.5, 'CRPIX2': 0, 'CRVAL2': 0, 'NAXIS2': 2} wcs_2D = WCS(header=header_2D, naxis=2) header_4D = {'CTYPE1': 'Time ', 'CUNIT1': 'seconds', 'CDELT1': 0.4, 'CRPIX1': 0, 'CRVAL1': 0, 'NAXIS1': 4, 'CTYPE2': 'HPLT-TAN', 'CUNIT2': 'arcsec', 'CDELT2': 0.5, 'CRPIX2': 0, 'CRVAL2': 0, 'NAXIS2': 3, 'CTYPE3': 'Time ', 'CUNIT3': 'seconds', 'CDELT3': 0.4, 'CRPIX3': 0, 'CRVAL3': 0, 'NAXIS3': 2, 'CTYPE4': 'HPLN-TAN', 'CUNIT4': 'arcsec', 'CDELT4': 0.5, 'CRPIX4': 0, 'CRVAL4': 0, 'NAXIS4': 2} wcs_4D = WCS(header=header_4D, naxis=4) header_1D = {'CTYPE1': 'Time ', 'CUNIT1': 'seconds', 'CDELT1': 0.4,
[[2.252, 4.528, -5.372], [-2.876, 5.764, 6.264]]]) SOURCE_UNCERTAINTY_PHOTONS_NUV = np.sqrt(SOURCE_DATA_PHOTONS_NUV) SOURCE_UNCERTAINTY_PHOTONS_FUV = np.sqrt(SOURCE_DATA_PHOTONS_FUV) time_dim_len = SOURCE_DATA_DN.shape[0] single_exposure_time = 2. EXPOSURE_TIME = u.Quantity(np.zeros(time_dim_len)+single_exposure_time, unit=u.s) # Define an sample wcs object h0 = { 'CTYPE1': 'WAVE ', 'CUNIT1': 'Angstrom', 'CDELT1': 0.2, 'CRPIX1': 0, 'CRVAL1': 10, 'NAXIS1': 3, 'CTYPE2': 'HPLT-TAN', 'CUNIT2': 'deg', 'CDELT2': 0.5, 'CRPIX2': 2, 'CRVAL2': 0.5, 'NAXIS2': 2, 'CTYPE3': 'HPLN-TAN', 'CUNIT3': 'deg', 'CDELT3': 0.4, 'CRPIX3': 2, 'CRVAL3': 1, 'NAXIS3': 2, } wcs0 = WCS(header=h0, naxis=3) # Define sample meta meta0 = {"detector type": "FUV", "OBSID": 1, "spectral window": "C II 1336"} # Define sample extra coords extra_coords0 = [("time", 0, np.array([datetime.datetime(2017, 1, 1)+datetime.timedelta(seconds=i) for i in range(time_dim_len)])), ("exposure time", 0, EXPOSURE_TIME)] extra_coords1 = [("time", 0, np.array([datetime.datetime(2017, 1, 1)+datetime.timedelta(seconds=i) for i in range(time_dim_len, time_dim_len*2)])), ("exposure time", 0, EXPOSURE_TIME)] # Define IRISSpectrogramCubes in various units.
def read_iris_spectrograph_level2_fits(filenames, spectral_windows=None): """ Reads IRIS level 2 spectrograph FITS from an OBS into an IRISSpectrograph instance. Parameters ---------- filenames: `list` of `str` or `str` Filename of filenames to be read. They must all be associated with the same OBS number. spectral_windows: iterable of `str` or `str` Spectral windows to extract from files. Default=None, implies, extract all spectral windows. Returns ------- result: `irispy.spectrograph.IRISSpectrograph` """ if type(filenames) is str: filenames = [filenames] for f, filename in enumerate(filenames): hdulist = fits.open(filename) hdulist.verify('fix') if f == 0: # Determine number of raster positions in a scan raster_positions_per_scan = int(hdulist[0].header["NRASTERP"]) # Collecting the window observations. windows_in_obs = np.array([ hdulist[0].header["TDESC{0}".format(i)] for i in range(1, hdulist[0].header["NWIN"] + 1) ]) # If spectral_window is not set then get every window. # Else take the appropriate windows if not spectral_windows: spectral_windows_req = windows_in_obs window_fits_indices = range(1, len(hdulist) - 2) else: if type(spectral_windows) is str: spectral_windows_req = [spectral_windows] spectral_windows_req = np.asarray(spectral_windows_req, dtype="U") window_is_in_obs = np.asarray([ window in windows_in_obs for window in spectral_windows_req ]) if not all(window_is_in_obs): missing_windows = window_is_in_obs == False raise ValueError( "Spectral windows {0} not in file {1}".format( spectral_windows[missing_windows], filenames[0])) window_fits_indices = np.nonzero( np.in1d(windows_in_obs, spectral_windows))[0] + 1 # Generate top level meta dictionary from first file # main header. top_meta = { "TELESCOP": hdulist[0].header["TELESCOP"], "INSTRUME": hdulist[0].header["INSTRUME"], "DATA_LEV": hdulist[0].header["DATA_LEV"], "OBSID": hdulist[0].header["OBSID"], "OBS_DESC": hdulist[0].header["OBS_DESC"], "STARTOBS": parse_time(hdulist[0].header["STARTOBS"]), "ENDOBS": parse_time(hdulist[0].header["ENDOBS"]), "SAT_ROT": hdulist[0].header["SAT_ROT"] * u.deg, "AECNOBS": int(hdulist[0].header["AECNOBS"]), "FOVX": hdulist[0].header["FOVX"] * u.arcsec, "FOVY": hdulist[0].header["FOVY"] * u.arcsec, "SUMSPTRN": hdulist[0].header["SUMSPTRN"], "SUMSPTRF": hdulist[0].header["SUMSPTRF"], "SUMSPAT": hdulist[0].header["SUMSPAT"], "NEXPOBS": hdulist[0].header["NEXPOBS"], "NRASTERP": hdulist[0].header["NRASTERP"], "KEYWDDOC": hdulist[0].header["KEYWDDOC"] } # Initialize meta dictionary for each spectral_window window_metas = {} for i, window_name in enumerate(spectral_windows_req): if "FUV" in hdulist[0].header["TDET{0}".format( window_fits_indices[i])]: spectral_summing = hdulist[0].header["SUMSPTRF"] else: spectral_summing = hdulist[0].header["SUMSPTRN"] window_metas[window_name] = { "detector type": hdulist[0].header["TDET{0}".format( window_fits_indices[i])], "spectral window": hdulist[0].header["TDESC{0}".format( window_fits_indices[i])], "brightest wavelength": hdulist[0].header["TWAVE{0}".format( window_fits_indices[i])], "min wavelength": hdulist[0].header["TWMIN{0}".format( window_fits_indices[i])], "max wavelength": hdulist[0].header["TWMAX{0}".format( window_fits_indices[i])], "SAT_ROT": hdulist[0].header["SAT_ROT"], "spatial summing": hdulist[0].header["SUMSPAT"], "spectral summing": spectral_summing } # Create a empty list for every spectral window and each # spectral window is a key for the dictionary. data_dict = dict([(window_name, list()) for window_name in spectral_windows_req]) # Determine extra coords for this raster. times = np.array([ parse_time(hdulist[0].header["STARTOBS"]) + datetime.timedelta(seconds=s) for s in hdulist[-2].data[:, hdulist[-2].header["TIME"]] ]) raster_positions = np.arange(int(hdulist[0].header["NRASTERP"])) pztx = hdulist[-2].data[:, hdulist[-2].header["PZTX"]] * u.arcsec pzty = hdulist[-2].data[:, hdulist[-2].header["PZTY"]] * u.arcsec xcenix = hdulist[-2].data[:, hdulist[-2].header["XCENIX"]] * u.arcsec ycenix = hdulist[-2].data[:, hdulist[-2].header["YCENIX"]] * u.arcsec obs_vrix = hdulist[-2].data[:, hdulist[-2].header["OBS_VRIX"]] * u.m / u.s ophaseix = hdulist[-2].data[:, hdulist[-2].header["OPHASEIX"]] exposure_times_fuv = hdulist[-2].data[:, hdulist[-2]. header["EXPTIMEF"]] * u.s exposure_times_nuv = hdulist[-2].data[:, hdulist[-2]. header["EXPTIMEN"]] * u.s # If OBS is raster, include raster positions. Otherwise don't. if top_meta["NRASTERP"] > 1: general_extra_coords = [("time", 0, times), ("raster position", 0, np.arange(top_meta["NRASTERP"])), ("pztx", 0, pztx), ("pzty", 0, pzty), ("xcenix", 0, xcenix), ("ycenix", 0, ycenix), ("obs_vrix", 0, obs_vrix), ("ophaseix", 0, ophaseix)] else: general_extra_coords = [("time", 0, times), ("pztx", 0, pztx), ("pzty", 0, pzty), ("xcenix", 0, xcenix), ("ycenix", 0, ycenix), ("obs_vrix", 0, obs_vrix), ("ophaseix", 0, ophaseix)] for i, window_name in enumerate(spectral_windows_req): # Determine values of properties dependent on detector type. if "FUV" in hdulist[0].header["TDET{0}".format( window_fits_indices[i])]: exposure_times = exposure_times_fuv DN_unit = iris_tools.DN_UNIT["FUV"] readout_noise = iris_tools.READOUT_NOISE["FUV"] elif "NUV" in hdulist[0].header["TDET{0}".format( window_fits_indices[i])]: exposure_times = exposure_times_nuv DN_unit = iris_tools.DN_UNIT["NUV"] readout_noise = iris_tools.READOUT_NOISE["NUV"] else: raise ValueError( "Detector type in FITS header not recognized.") # Derive WCS, data and mask for NDCube from file. # Sit-and-stare have a CDELT of 0 which causes issues in astropy WCS. # In this case, set CDELT to a tiny non-zero number. if hdulist[window_fits_indices[i]].header["CDELT3"] == 0: hdulist[window_fits_indices[i]].header["CDELT3"] = 1e-10 wcs_ = WCS(hdulist[window_fits_indices[i]].header) data_mask = hdulist[window_fits_indices[i]].data == -200. # Derive extra coords for this spectral window. window_extra_coords = copy.deepcopy(general_extra_coords) window_extra_coords.append(("exposure time", 0, exposure_times)) # Collect metadata relevant to single files. try: date_obs = parse_time(hdulist[0].header["DATE_OBS"]) except ValueError: date_obs = None try: date_end = parse_time(hdulist[0].header["DATE_END"]) except ValueError: date_end = None single_file_meta = { "SAT_ROT": hdulist[0].header["SAT_ROT"] * u.deg, "DATE_OBS": date_obs, "DATE_END": date_end, "HLZ": bool(int(hdulist[0].header["HLZ"])), "SAA": bool(int(hdulist[0].header["SAA"])), "DSUN_OBS": hdulist[0].header["DSUN_OBS"] * u.m, "IAECEVFL": hdulist[0].header["IAECEVFL"], "IAECFLAG": hdulist[0].header["IAECFLAG"], "IAECFLFL": hdulist[0].header["IAECFLFL"], "KEYWDDOC": hdulist[0].header["KEYWDDOC"], "detector type": hdulist[0].header["TDET{0}".format(window_fits_indices[i])], "spectral window": window_name, "OBSID": hdulist[0].header["OBSID"], "OBS_DESC": hdulist[0].header["OBS_DESC"], "STARTOBS": parse_time(hdulist[0].header["STARTOBS"]), "ENDOBS": parse_time(hdulist[0].header["ENDOBS"]) } # Derive uncertainty of data uncertainty = u.Quantity( np.sqrt((hdulist[window_fits_indices[i]].data * DN_unit).to(u.photon).value + readout_noise.to(u.photon).value**2), unit=u.photon).to(DN_unit).value # Appending NDCube instance to the corresponding window key in dictionary's list. data_dict[window_name].append( IRISSpectrogramCube(hdulist[window_fits_indices[i]].data, wcs_, uncertainty, DN_unit, single_file_meta, window_extra_coords, mask=data_mask)) hdulist.close() # Construct dictionary of IRISSpectrogramCubeSequences for spectral windows data = dict([(window_name, IRISSpectrogramCubeSequence(data_dict[window_name], window_metas[window_name], common_axis=0)) for window_name in spectral_windows_req]) # Initialize an IRISSpectrograph object. return IRISSpectrograph(data, meta=top_meta)
'NAXIS1': 4, 'CTYPE2': 'HPLT-TAN', 'CUNIT2': 'deg', 'CDELT2': 0.5, 'CRPIX2': 2, 'CRVAL2': 0.5, 'NAXIS2': 3, 'CTYPE3': 'HPLN-TAN', 'CUNIT3': 'deg', 'CDELT3': 0.4, 'CRPIX3': 2, 'CRVAL3': 1, 'NAXIS3': 2, } wt = WCS(header=ht, naxis=3) wm = WCS(header=hm, naxis=3) cube1 = NDCube(data, wt, missing_axes=[False, False, False, True], extra_coords=[ ('pix', 0, u.Quantity(range(data.shape[0]), unit=u.pix)), ('distance', None, u.Quantity(0, unit=u.cm)), ('time', None, datetime.datetime(2000, 1, 1, 0, 0)) ]) cube2 = NDCube(data, wm, extra_coords=[ ('pix', 0,
'CRVAL1': 10, 'NAXIS1': 3, 'CTYPE2': 'HPLT-TAN', 'CUNIT2': 'deg', 'CDELT2': 0.5, 'CRPIX2': 2, 'CRVAL2': 0.5, 'NAXIS2': 2, 'CTYPE3': 'HPLN-TAN', 'CUNIT3': 'deg', 'CDELT3': 0.4, 'CRPIX3': 2, 'CRVAL3': 1, 'NAXIS3': 2, } WCS0 = WCS(header=H0, naxis=3) H_NO_COORDS = { 'CTYPE1': 'PIX ', 'CUNIT1': '', 'CDELT1': 1, 'CRPIX1': 0, 'CRVAL1': 0, 'NAXIS1': 3, 'CTYPE2': 'PIX ', 'CUNIT2': '', 'CDELT2': 1, 'CRPIX2': 0, 'CRVAL2': 0, 'NAXIS2': 3, 'CTYPE3': 'PIX ',
import pytest import sunpy.map import numpy as np import astropy.units as u from ndcube import NDCube, NDCubeOrdered from ndcube.utils.wcs import WCS, _wcs_slicer from ndcube.tests import helpers # sample data for tests # TODO: use a fixture reading from a test file. file TBD. ht = {'CTYPE3': 'HPLT-TAN', 'CUNIT3': 'deg', 'CDELT3': 0.5, 'CRPIX3': 0, 'CRVAL3': 0, 'NAXIS3': 2, 'CTYPE2': 'WAVE ', 'CUNIT2': 'Angstrom', 'CDELT2': 0.2, 'CRPIX2': 0, 'CRVAL2': 0, 'NAXIS2': 3, 'CTYPE1': 'TIME ', 'CUNIT1': 'min', 'CDELT1': 0.4, 'CRPIX1': 0, 'CRVAL1': 0, 'NAXIS1': 4} wt = WCS(header=ht, naxis=3) data = np.array([[[1, 2, 3, 4], [2, 4, 5, 3], [0, -1, 2, 3]], [[2, 4, 5, 1], [10, 5, 2, 2], [10, 3, 3, 0]]]) hm = {'CTYPE1': 'WAVE ', 'CUNIT1': 'Angstrom', 'CDELT1': 0.2, 'CRPIX1': 0, 'CRVAL1': 10, 'NAXIS1': 4, 'CTYPE2': 'HPLT-TAN', 'CUNIT2': 'deg', 'CDELT2': 0.5, 'CRPIX2': 2, 'CRVAL2': 0.5, 'NAXIS2': 3, 'CTYPE3': 'HPLN-TAN', 'CUNIT3': 'deg', 'CDELT3': 0.4, 'CRPIX3': 2, 'CRVAL3': 1, 'NAXIS3': 2} wm = WCS(header=hm, naxis=3) h_disordered = { 'CTYPE1': 'TIME ', 'CUNIT1': 'min', 'CDELT1': 0.4, 'CRPIX1': 0, 'CRVAL1': 0, 'NAXIS1': 2, 'CTYPE2': 'WAVE ', 'CUNIT2': 'Angstrom', 'CDELT2': 0.2, 'CRPIX2': 0, 'CRVAL2': 10, 'NAXIS2': 4,
'NAXIS3': 2, 'CTYPE2': 'WAVE ', 'CUNIT2': 'Angstrom', 'CDELT2': 0.2, 'CRPIX2': 0, 'CRVAL2': 0, 'NAXIS2': 3, 'CTYPE1': 'TIME ', 'CUNIT1': 'min', 'CDELT1': 0.4, 'CRPIX1': 0, 'CRVAL1': 0, 'NAXIS1': 4 } wt = WCS(header=ht, naxis=3) cube1 = NDCube(data, wt, missing_axis=[False, False, False, True], extra_coords=[ ('pix', 0, u.Quantity(range(data.shape[0]), unit=u.pix)), ('hi', 1, u.Quantity(range(data.shape[1]), unit=u.s)), ('distance', None, u.Quantity(0, unit=u.cm)), ('time', None, datetime.datetime(2000, 1, 1, 0, 0)) ]) cube1_with_unit = NDCube( data, wt, missing_axis=[False, False, False, True],
import pytest import numpy as np import astropy.units as u from ndcube import NDCube, NDCubeOrdered from ndcube.utils.wcs import WCS, _wcs_slicer from ndcube.tests import helpers from ndcube.ndcube_sequence import NDCubeSequence # sample data for tests # TODO: use a fixture reading from a test file. file TBD. ht = {'CTYPE3': 'HPLT-TAN', 'CUNIT3': 'deg', 'CDELT3': 0.5, 'CRPIX3': 0, 'CRVAL3': 0, 'NAXIS3': 2, 'CTYPE2': 'WAVE ', 'CUNIT2': 'Angstrom', 'CDELT2': 0.2, 'CRPIX2': 0, 'CRVAL2': 0, 'NAXIS2': 3, 'CTYPE1': 'TIME ', 'CUNIT1': 'min', 'CDELT1': 0.4, 'CRPIX1': 0, 'CRVAL1': 0, 'NAXIS1': 4} wt = WCS(header=ht, naxis=3) data = np.array([[[1, 2, 3, 4], [2, 4, 5, 3], [0, -1, 2, 3]], [[2, 4, 5, 1], [10, 5, 2, 2], [10, 3, 3, 0]]]) hm = {'CTYPE1': 'WAVE ', 'CUNIT1': 'Angstrom', 'CDELT1': 0.2, 'CRPIX1': 0, 'CRVAL1': 10, 'NAXIS1': 4, 'CTYPE2': 'HPLT-TAN', 'CUNIT2': 'deg', 'CDELT2': 0.5, 'CRPIX2': 2, 'CRVAL2': 0.5, 'NAXIS2': 3, 'CTYPE3': 'HPLN-TAN', 'CUNIT3': 'deg', 'CDELT3': 0.4, 'CRPIX3': 2, 'CRVAL3': 1, 'NAXIS3': 2} wm = WCS(header=hm, naxis=3) h_disordered = { 'CTYPE1': 'TIME ', 'CUNIT1': 'min', 'CDELT1': 0.4, 'CRPIX1': 0, 'CRVAL1': 0, 'NAXIS1': 2, 'CTYPE2': 'WAVE ', 'CUNIT2': 'Angstrom', 'CDELT2': 0.2, 'CRPIX2': 0, 'CRVAL2': 10, 'NAXIS2': 4,
import pytest from ndcube.tests.helpers import assert_cubesequences_equal from ndcube.utils.wcs import WCS import astropy.units as u from astropy.time import Time, TimeDelta from sunraster import RasterSequence, SpectrogramCube, SpectrogramSequence # Define an sample wcs objects. H0 = { 'CTYPE1': 'WAVE ', 'CUNIT1': 'Angstrom', 'CDELT1': 0.2, 'CRPIX1': 0, 'CRVAL1': 10, 'NAXIS1': 3, 'CTYPE2': 'HPLT-TAN', 'CUNIT2': 'deg', 'CDELT2': 0.5, 'CRPIX2': 2, 'CRVAL2': 0.5, 'NAXIS2': 2, 'CTYPE3': 'HPLN-TAN', 'CUNIT3': 'deg', 'CDELT3': 0.4, 'CRPIX3': 2, 'CRVAL3': 1, 'NAXIS3': 2} WCS0 = WCS(header=H0, naxis=3) h2 = { 'CTYPE1': 'HPLN-TAN', 'CUNIT1': 'deg', 'CDELT1': 0.2, 'CRPIX1': 0, 'CRVAL1': 10, 'NAXIS1': 3, 'CTYPE2': 'HPLT-TAN', 'CUNIT2': 'deg', 'CDELT2': 0.5, 'CRPIX2': 2, 'CRVAL2': 0.5, 'NAXIS2': 2, 'CTYPE3': 'WAVE ',
from sunpy.visualization.animator import ImageAnimatorWCS, LineAnimator except ImportError: from sunpy.visualization.imageanimator import ImageAnimatorWCS, LineAnimator from ndcube import NDCube from ndcube.utils.wcs import WCS from ndcube.mixins import plotting # sample data for tests # TODO: use a fixture reading from a test file. file TBD. ht = {'CTYPE3': 'HPLT-TAN', 'CUNIT3': 'deg', 'CDELT3': 0.5, 'CRPIX3': 0, 'CRVAL3': 0, 'NAXIS3': 2, 'CTYPE2': 'WAVE ', 'CUNIT2': 'Angstrom', 'CDELT2': 0.2, 'CRPIX2': 0, 'CRVAL2': 0, 'NAXIS2': 3, 'CTYPE1': 'TIME ', 'CUNIT1': 'min', 'CDELT1': 0.4, 'CRPIX1': 0, 'CRVAL1': 0, 'NAXIS1': 4} wt = WCS(header=ht, naxis=3) hm = {'CTYPE1': 'WAVE ', 'CUNIT1': 'Angstrom', 'CDELT1': 0.2, 'CRPIX1': 0, 'CRVAL1': 10, 'NAXIS1': 4, 'CTYPE2': 'HPLT-TAN', 'CUNIT2': 'deg', 'CDELT2': 0.5, 'CRPIX2': 2, 'CRVAL2': 0.5, 'NAXIS2': 3, 'CTYPE3': 'HPLN-TAN', 'CUNIT3': 'deg', 'CDELT3': 0.4, 'CRPIX3': 2, 'CRVAL3': 1, 'NAXIS3': 2} wm = WCS(header=hm, naxis=3) spatial = { 'CTYPE1': 'HPLT-TAN', 'CUNIT1': 'deg', 'CDELT1': 0.5, 'CRPIX1': 2, 'CRVAL1': 0.5, 'NAXIS1': 3, 'CTYPE2': 'HPLN-TAN', 'CUNIT2': 'deg', 'CDELT2': 0.4, 'CRPIX2': 2, 'CRVAL2': 1, 'NAXIS2': 2 } spatial = WCS(header=spatial, naxis=2)