Source code for sunpy.map.sources.hinode

"""Hinode XRT and SOT Map subclass definitions"""
import astropy.units as u
from astropy.visualization import ImageNormalize, LogStretch

from sunpy.map import GenericMap
from sunpy.map.sources.source_type import source_stretch

__author__ = ["Jack Ireland, Jose Ivan Campos-Rozo, David Perez-Suarez"]
__email__ = "jack.ireland@nasa.gov"
__all__ = ['XRTMap', 'SOTMap']


def _lower_list(alist):
    return [item.lower() for item in alist]


[docs] class XRTMap(GenericMap): """ Hinode XRT map definition. The X-Ray Telescope (XRT) is a high resolution grazing incidence telescope, which is a successor to Yohkoh. It provides 2-arcsecond resolution images of the highest temperature solar coronal material, from 1,000,000 to 10,000,000 Kelvin. Hinode was launched on 22 September 2006 into a sun-synchronous orbit. Notes ----- XRT files do not normally specify the heliographic longitude of the spacecraft, so sunpy silently assumes that the spacecraft is at zero Stonyhurst heliographic longitude (i.e., the same longitude as Earth) for L1 files. This assumption is safe for nearly all analyses due to Hinode's orbital altitude of only ~600 km. This assumption is not made if ``HGLN_OBS`` and ``HGLT_OBS`` values have been explicitly added to the metadata. References ---------- * `Hinode Mission Page <https://solarb.msfc.nasa.gov/index.html>`_ * `XRT Instrument Page <http://xrt.cfa.harvard.edu>`_ * `Fits header reference <http://hinode.nao.ac.jp/uploads/2016/04/22/SB_MW_Key13.pdf>`_ * `Hinode User Guide <http://hinode.nao.ac.jp/en/for-researchers/analysis-guide/>`_ * `XRT Analysis Guide <http://xrt.cfa.harvard.edu/science/tutorials.php>`_ * `Coronal Temperature Diagnostic Capability of the Hinode/X-Ray Telescope Based on Self-Consistent Calibration <https://arxiv.org/abs/1011.2867>`_ """ filter_wheel1_measurements = ["Al_med", "Al_poly", "Be_med", "Be_thin", "C_poly", "Open"] filter_wheel2_measurements = ["Open", "Al_mesh", "Al_thick", "Be_thick", "Gband", "Ti_poly"] def __init__(self, data, header, **kwargs): fw1 = header.get('EC_FW1_', '') if fw1.lower() not in _lower_list(self.filter_wheel1_measurements): raise ValueError(f'Unexpected filter wheel 1 {fw1} in header.') fw2 = header.get('EC_FW2_', '') if fw2.lower() not in _lower_list(self.filter_wheel2_measurements): raise ValueError(f'Unexpected filter wheel 2 {fw2} in header.') super().__init__(data, header, **kwargs) self.plot_settings['cmap'] = 'hinodexrt' self.plot_settings['norm'] = ImageNormalize( stretch=source_stretch(self.meta, LogStretch()), clip=False) @property def _timesys(self): if self.meta.get('timesys', '').upper() == 'UTC (TBR)': return 'UTC' return super()._timesys @property def _supported_observer_coordinates(self): # Assume observer is at zero Stonyhurst heliographic longitude if not otherwise specified # https://community.openastronomy.org/t/sunpymetadatawarnings-when-using-hinode-xrt-data/393/7 for more information return (super()._supported_observer_coordinates + [(('solar_b0', 'dsun_obs'), {'lon': 0*u.deg, 'lat': self.meta.get('solar_b0'), 'radius': self.meta.get('dsun_obs'), 'unit': (u.deg, u.deg, u.m), 'frame': "heliographic_stonyhurst"})]) @property def detector(self): return "XRT" @property def observatory(self): return "Hinode" @property def measurement(self): fw1 = self.meta.get('EC_FW1_').replace("_", " ") fw2 = self.meta.get('EC_FW2_').replace("_", " ") return f"{fw1}-{fw2}" @property def processing_level(self): lvl = self.meta.get('DATA_LEV', None) if lvl is None: return return int(lvl) @property def unit(self): # XRT data values are in DN and are converted into DN/s if the data has been normalized. # A tag starting with "XRT_RENORMALIZE" is added to the HISTORY tag in that case. # See Table 1.1 and Section 2.11 of the XRT Analysis Guide. unit = super().unit if not unit: unit = u.ct history = self.meta.get('HISTORY', '') if "xrt_renormalize" in history.lower(): unit = u.ct / u.second return unit
[docs] @classmethod def is_datasource_for(cls, data, header, **kwargs): """Determines if header corresponds to an XRT image""" return header.get('instrume') == 'XRT'
[docs] class SOTMap(GenericMap): """Hinode SOT Image Map definition. The Hinode Solar Optical Telescope (SOT) consists of a 50 cm diffraction-limited Gregorian telescope. It is optimized for accurate measurement of the vector magnetic field in the photosphere and dynamics of both the photosphere and chromosphere associated with the magnetic fields. Hinode was launched on 22 September 2006 into a sun-synchronous orbit. References ---------- * `Hinode Mission Page <http://solarb.msfc.nasa.gov/index.html>`_ * `Hinode SOT Instrument Page <http://sot.lmsal.com>`_ * `Hinode SOT Instrument Paper <https://arxiv.org/abs/0711.1715>`_ * `Data Analsis Guide <https://sot.lmsal.com/doc/rep/sot254/fid366/SOT00042_33_SOT_Analysis_Guide_SAG.pdf>`_ """ # TODO: get a link for the SOT FITS headers # Add in some information about the the possible instrument, observation # type, observable ion and wavelength Instruments = ['SOT/WB', 'SOT/NB', 'SOT/SP', 'SOT/CT'] Waves = ['6302A', 'BFI no move', 'CN bandhead 3883', 'Ca II H line', 'G band 4305', 'NFI no move', 'TF Fe I 6302', 'TF Mg I 5172', 'TF Na I 5896', 'blue cont 4504', 'green cont 5550', 'red cont 6684'] Observation_Type = ['FG (simple)', 'FG focus scan', 'FG shuttered I and V', 'FG shutterless I and V', 'FG shutterless I and V with 0.2s intervals', 'FG shutterless Stokes', 'SP IQUV 4D array'] def __init__(self, data, header, **kwargs): super().__init__(data, header, **kwargs) self._nickname = self.detector # TODO (add other options, Now all treated as intensity. This follows # Hinode SDC archive) StokesQUV -> grey, Velocity -> EIS, Width -> EIS, # Mag Field Azi -> IDL 5 (STD gamma II) # 'WB' -> red # 'NB'(0 = red); (>0 = gray), # nb has 1 stokes I, the rest quv # 'SP' (<=1 = red); (>1 = gray) #sp has 2 stokes I, the rest quv color = {'SOT/WB': 'intensity', 'SOT/NB': 'intensity', # For the 1st dimension 'SOT/SP': 'intensity', # For the 1st 2 dimensions } self.plot_settings['cmap'] = 'hinodesot' + color[self.instrument] @property def detector(self): return "SOT" @property def observatory(self): return "Hinode"
[docs] @classmethod def is_datasource_for(cls, data, header, **kwargs): """Determines if header corresponds to an SOT image.""" return header.get('instrume') in cls.Instruments