Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RSR reader for the EPIC instrument onboard DSCOVR #200

Merged
merged 8 commits into from
Oct 21, 2023
6 changes: 6 additions & 0 deletions CHANGELOG_RSR_DATA.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ Changelog for the Relative Spectral Response data
=================================================


Version <v1.2.3> (Fri Oct 20 01:58:29 2023)
-------------------------------------------

* Added RSR file for EPIC on DSCOVR (responses not normalized)


Version <v1.2.2> (Tue Nov 15 14:44:03 2022)
-------------------------------------------

Expand Down
12 changes: 11 additions & 1 deletion pyspectral/bandnames.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@
# MODIS RSR files were made before 'chX' became standard in pyspectral
BANDNAMES['modis'] = {str(chan_num): str(chan_num) for chan_num in range(1, 37)}


BANDNAMES['seviri'] = {'VIS006': 'VIS0.6',
'VIS008': 'VIS0.8',
'IR_016': 'NIR1.6',
Expand Down Expand Up @@ -177,6 +176,17 @@
'IR133': 'ch16'
}

BANDNAMES['epic'] = {'B317': 'T(317.5) %',
'B325': 'T(325) %',
'B340': 'T(340) %',
'B388': 'T(388) %',
'B443': 'T(443) %',
'B551': 'T(551) %',
'B680': 'T(680) %',
'B688': 'T(687.75) %',
'B764': 'T(764) %',
'B780': 'T(779.5) %'}

BANDNAMES['fci'] = {'vis_04': 'VIS0.4',
'vis_05': 'VIS0.5',
'vis_06': 'VIS0.6_HR',
Expand Down
3 changes: 3 additions & 0 deletions pyspectral/etc/pyspectral.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ download_from_internet: True
# path: /home/a000680/data/SpectralResponses/modis/aqua
# tb2rad_lut_filename: /path/to/radiance/tb/lut/data/tb2rad_lut_aqua_modis_ir3.7.npz

#dscovr-epic:
# path: C:/Users/Simon/Downloads/EPIC_Filters_Original_Data.xlsx


# NOAA-20-viirs:
# # J1_VIIRS_RSR_M1_Detector_Fused_V2.txt
Expand Down
9 changes: 6 additions & 3 deletions pyspectral/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014-2022 Pytroll developers
# Copyright (c) 2014-2023 Pytroll developers
#
#
# This program is free software: you can redistribute it and/or modify
Expand Down Expand Up @@ -91,17 +91,20 @@
'NOAA-21': 'viirs',
'Suomi-NPP': 'viirs',
'FY-3B': 'virr',
'FY-3C': 'virr'}
'FY-3C': 'virr',
'DSCOVR': 'epic'}


INSTRUMENT_TRANSLATION_DASH2SLASH = {'avhrr-1': 'avhrr/1',
'avhrr-2': 'avhrr/2',
'avhrr-3': 'avhrr/3'}

HTTP_PYSPECTRAL_RSR = "https://zenodo.org/record/7311143/files/pyspectral_rsr_data.tgz"
HTTP_PYSPECTRAL_RSR = "https://zenodo.org/records/10026657/files/pyspectral_rsr_data.tgz"


RSR_DATA_VERSION_FILENAME = "PYSPECTRAL_RSR_VERSION"
RSR_DATA_VERSION = "v1.2.2"
RSR_DATA_VERSION = "v1.2.3"

ATM_CORRECTION_LUT_VERSION = {}
ATM_CORRECTION_LUT_VERSION['antarctic_aerosol'] = {'version': 'v1.0.1',
Expand Down
120 changes: 120 additions & 0 deletions rsr_convert_scripts/epic_reader.py
adybbroe marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2023 Pytroll developers
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""Read the DSCOVR-EPIC spectral response functions.

Data from the NASA Goddard website:
https://avdc.gsfc.nasa.gov/pub/DSCOVR/EPIC_Filter_Data/

"""

import logging
import os

import numpy as np
import pandas as pd

from pyspectral.raw_reader import InstrumentRSR
from pyspectral.utils import convert2hdf5 as tohdf5

LOG = logging.getLogger(__name__)


EPIC_BAND_NAMES = {'B317': 'T(317.5) %',
'B325': 'T(325) %',
'B340': 'T(340) %',
'B388': 'T(388) %',
'B443': 'T(443) %',
'B551': 'T(551) %',
'B680': 'T(680) %',
'B688': 'T(687.75) %',
'B764': 'T(764) %',
'B780': 'T(779.5) %'}

#: Default time format
_DEFAULT_TIME_FORMAT = '%Y-%m-%d %H:%M:%S'

#: Default log format
_DEFAULT_LOG_FORMAT = '[%(levelname)s: %(asctime)s : %(name)s] %(message)s'


class EpicRSR(InstrumentRSR):
"""Container for the DSCOVR EPIC relative spectral response data."""

def __init__(self, bandname, platform_name):
"""Initialize the EPIC RSR class."""
super(EpicRSR, self).__init__(
bandname, platform_name, EPIC_BAND_NAMES.keys())

self.instrument = 'epic'
self._get_options_from_config()

LOG.debug("Filename: %s", str(self.path))
if os.path.exists(self.path):
self._load()

else:
LOG.warning("Couldn't find an existing file for this band: %s",
str(self.bandname))

# To be compatible with VIIRS....
self.filename = self.requested_band_filename

self.unit = 'micrometer'
self.wavespace = 'wavelength'

def _load(self, scale=10000.0):
"""Load the EPIC relative spectral responses."""
df1 = pd.read_excel(self.path,
sheet_name='Data',
skiprows=4,
engine='openpyxl')
# Remove empty row from the data
df1.drop(df1.index[0], inplace=True)
# Column names don't match band names - so we use a dict to find correct
# columns. We also need to find the column with the wavelength data.
# This is the column before the actual RSR data for each band.
col_pos = df1.columns.get_loc(EPIC_BAND_NAMES[self.bandname])
wvl_data = df1.iloc[:, col_pos - 1]
srf_data = df1.iloc[:, col_pos]

# Not all bands have an identical number of RSR points, so we need to
# remove NaNs from the data.
wvl_data.dropna(inplace=True)
srf_data.dropna(inplace=True)

# Data is in nanometers, so we need to convert to micrometers.
self.rsr = {'wavelength': np.array(wvl_data) / 1000,
'response': np.array(srf_data)}


if __name__ == "__main__":
import sys
LOG = logging.getLogger('epic_rsr')
handler = logging.StreamHandler(sys.stderr)

formatter = logging.Formatter(fmt=_DEFAULT_LOG_FORMAT,
datefmt=_DEFAULT_TIME_FORMAT)
handler.setFormatter(formatter)
handler.setLevel(logging.DEBUG)
LOG.setLevel(logging.DEBUG)
LOG.addHandler(handler)

for platform_name in ['dscovr', ]:
tohdf5(EpicRSR, platform_name, list(EPIC_BAND_NAMES.keys()))
Loading