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 convert script for MERSI-1 on FY-3A/B/C #223

Merged
merged 1 commit into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions pyspectral/etc/pyspectral.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,74 @@ download_from_internet: True
# ch9: rtcoef_electro-l_2_msugs_srf_ch09.txt
# ch10: rtcoef_electro-l_2_msugs_srf_ch10.txt

# FY-3A-mersi-1:
# path: D:/MERSI1
# ch1: FY3A_mersi_srf_func_b01.txt
# ch2: FY3A_mersi_srf_func_b02.txt
# ch3: FY3A_mersi_srf_func_b03.txt
# ch4: FY3A_mersi_srf_func_b04.txt
# ch5: FY3A_mersi_srf_func_b05.txt
# ch6: FY3A_mersi_srf_func_b06.txt
# ch7: FY3A_mersi_srf_func_b07.txt
# ch8: FY3A_mersi_srf_func_b08.txt
# ch9: FY3A_mersi_srf_func_b09.txt
# ch10: FY3A_mersi_srf_func_b10.txt
# ch11: FY3A_mersi_srf_func_b11.txt
# ch12: FY3A_mersi_srf_func_b12.txt
# ch13: FY3A_mersi_srf_func_b13.txt
# ch14: FY3A_mersi_srf_func_b14.txt
# ch15: FY3A_mersi_srf_func_b15.txt
# ch16: FY3A_mersi_srf_func_b16.txt
# ch17: FY3A_mersi_srf_func_b17.txt
# ch18: FY3A_mersi_srf_func_b18.txt
# ch19: FY3A_mersi_srf_func_b19.txt
# ch20: FY3A_mersi_srf_func_b20.txt

# FY-3B-mersi-1:
# path: D:/MERSI1
# ch1: FY3B_mersi_srf_B1-4_B8-20.txt
# ch2: FY3B_mersi_srf_B1-4_B8-20.txt
# ch3: FY3B_mersi_srf_B1-4_B8-20.txt
# ch4: FY3B_mersi_srf_B1-4_B8-20.txt
# ch6: FY3B_mersi_srf_B6-7.txt
# ch7: FY3B_mersi_srf_B6-7.txt
# ch8: FY3B_mersi_srf_B1-4_B8-20.txt
# ch9: FY3B_mersi_srf_B1-4_B8-20.txt
# ch10: FY3B_mersi_srf_B1-4_B8-20.txt
# ch11: FY3B_mersi_srf_B1-4_B8-20.txt
# ch12: FY3B_mersi_srf_B1-4_B8-20.txt
# ch13: FY3B_mersi_srf_B1-4_B8-20.txt
# ch14: FY3B_mersi_srf_B1-4_B8-20.txt
# ch15: FY3B_mersi_srf_B1-4_B8-20.txt
# ch16: FY3B_mersi_srf_B1-4_B8-20.txt
# ch17: FY3B_mersi_srf_B1-4_B8-20.txt
# ch18: FY3B_mersi_srf_B1-4_B8-20.txt
# ch19: FY3B_mersi_srf_B1-4_B8-20.txt
# ch20: FY3B_mersi_srf_B1-4_B8-20.txt

# FY-3C-mersi-1:
# path: D:/MERSI1
# ch1: FY3C_mersi_srf_b01.txt
# ch2: FY3C_mersi_srf_b02.txt
# ch3: FY3C_mersi_srf_b03.txt
# ch4: FY3C_mersi_srf_b04.txt
# ch5: FY3C_mersi_srf_b05.txt
# ch6: FY3C_mersi_srf_b06.txt
# ch7: FY3C_mersi_srf_b07.txt
# ch8: FY3C_mersi_srf_b08.txt
# ch9: FY3C_mersi_srf_b09.txt
# ch10: FY3C_mersi_srf_b10.txt
# ch11: FY3C_mersi_srf_b11.txt
# ch12: FY3C_mersi_srf_b12.txt
# ch13: FY3C_mersi_srf_b13.txt
# ch14: FY3C_mersi_srf_b14.txt
# ch15: FY3C_mersi_srf_b15.txt
# ch16: FY3C_mersi_srf_b16.txt
# ch17: FY3C_mersi_srf_b17.txt
# ch18: FY3C_mersi_srf_b18.txt
# ch19: FY3C_mersi_srf_b19.txt
# ch20: FY3C_mersi_srf_b20.txt

#FY-3B-virr:
# path: /Users/davidh/repos/git/pyspectral/virr_srf/FY3B-VIRR
# ch1: ch1.prn
Expand Down
5 changes: 3 additions & 2 deletions pyspectral/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,9 @@
'NOAA-20': 'viirs',
'NOAA-21': 'viirs',
'Suomi-NPP': 'viirs',
'FY-3B': 'virr',
'FY-3C': 'virr',
'FY-3A': ['virr', "mersi-1"],
'FY-3B': ['virr', "mersi-1"],
'FY-3C': ['virr', "mersi-1"],
'DSCOVR': 'epic'}


Expand Down
119 changes: 119 additions & 0 deletions rsr_convert_scripts/mersi1_rsr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2018-2024 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 MERSI-1 relative spectral responses.

Data available from NSMC:
https://img.nsmc.org.cn/PORTAL/NSMC/DATASERVICE/SRF/FY3A/FY3A_MERSI_SRF.rar
https://img.nsmc.org.cn/PORTAL/NSMC/DATASERVICE/SRF/FY3B/FY3B_MERSI_SRF.rar
https://img.nsmc.org.cn/PORTAL/NSMC/DATASERVICE/SRF/FY3C/FY3C_MERSI_SRF.rar

"""
import logging
import os

import numpy as np

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

LOG = logging.getLogger(__name__)

MERSI1_FY3AC_BAND_NAMES = ['ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6', 'ch7', 'ch8',
'ch9', 'ch10', 'ch11', 'ch12', 'ch13', 'ch14', 'ch15', 'ch16',
'ch17', 'ch18', 'ch19', 'ch20']
MERSI1_FY3B_BAND_NAMES = ['ch1', 'ch2', 'ch3', 'ch4', 'ch6', 'ch7', 'ch8',
'ch9', 'ch10', 'ch11', 'ch12', 'ch13', 'ch14', 'ch15', 'ch16',
'ch17', 'ch18', 'ch19', 'ch20']


class Mersi1FY3ABRSR(InstrumentRSR):
"""Container for the FY3A/B/C MERSI-1 RSR data."""

def __init__(self, bandname, platform_name):
"""Initialize the MERSI-1 RSR class."""
# FY-3B RSR doesn't have ch5(IR) band
mersi1_band_names = MERSI1_FY3AC_BAND_NAMES if platform_name != "FY-3B" else MERSI1_FY3B_BAND_NAMES
super(Mersi1FY3ABRSR, self).__init__(bandname, platform_name, mersi1_band_names)

self.instrument = INSTRUMENTS.get(platform_name, 'mersi-1')
if type(self.instrument) is list:
self.instrument = 'mersi-1'

self._get_options_from_config()
self._get_bandfilenames()

LOG.debug("Filenames: %s", str(self.filenames))
if self.filenames[bandname] and os.path.exists(self.filenames[bandname]):
self.requested_band_filename = self.filenames[bandname]
self._load()

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

self.filename = self.requested_band_filename

def _load(self, scale=0.001):
"""Load the MERSI-1 RSR data for the band requested.

Wavelength is given in nanometers.
"""
data = np.genfromtxt(self.requested_band_filename,
unpack=True,
skip_header=0)
wavelength = data[0] * scale

if self.platform_name != "FY-3B":
response = data[1]
else:
# FY-3B RSRs are organized in two files
fy3b_file1_bands_part1 = ["ch1", "ch2", "ch3", "ch4"]
fy3b_file1_bands_part2 = ["ch8", "ch9", "ch10", "ch11", "ch12", "ch13", "ch14", "ch15", "ch16", "ch17",
"ch18", "ch19", "ch20"]
fy3b_file2_bands = ["ch6", "ch7"]
if self.bandname in fy3b_file1_bands_part1:
response = data[fy3b_file1_bands_part1.index(self.bandname) + 1]
elif self.bandname in fy3b_file1_bands_part2:
response = data[fy3b_file1_bands_part2.index(self.bandname) + 4]
else:
response = data[fy3b_file2_bands.index(self.bandname) + 1]

# Cut unneeded points
pts = np.argwhere(response > 0.001)
wavelength = np.squeeze(wavelength[pts])
response = np.squeeze(response[pts])

# It is possible that some points of bands 1/2/3 where wavelength > 800 still has response > 0.001
# They're out of the wavelength range of the band.
# And will trigger a warning in pyspectral when doing atmospheric corrections
# So let's cut these points
if self.bandname in ["1", "2", "3"]:
pts2 = np.argwhere(data['wavelength'] < 800)
wavelength = np.squeeze(wavelength[pts2])
response = np.squeeze(response[pts2])

self.rsr = {'wavelength': wavelength, 'response': response}


if __name__ == "__main__":
for platform_name in ["FY-3A", "FY-3B", "FY-3C"]:
band_list = MERSI1_FY3AC_BAND_NAMES if platform_name != "FY-3B" else MERSI1_FY3B_BAND_NAMES
tohdf5(Mersi1FY3ABRSR, platform_name, band_list)
Loading