Skip to content

Commit

Permalink
Further enhancements towards unified reading
Browse files Browse the repository at this point in the history
  • Loading branch information
adybbroe committed Apr 1, 2014
1 parent 68573e5 commit 71d99a9
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 27 deletions.
26 changes: 25 additions & 1 deletion etc/pyspectral.cfg_template
@@ -1,7 +1,31 @@
[general]
rsr_dir = /path/to/internal/rsr_data


[seviri]
path = /path/to/unzipped/seviri/data/MSG_SEVIRI_Spectral_Response_Characterisation.XLS

[viirs]

mband_visnir_path = /path/to/viirs/data/GT_F1_SC_RSR_Release1.0_Best_Mbands/
mband_visnir_names = GT_F1_SC_RSR_Release1.0_Best_%(bandname)s_V2.71_ib_oob.txt

mband_ir_path = /path/to/viirs/data/GT_F1_CFPA_RSR_Release1.0_Best/
mband_ir_names = GT_F1_CFPA_RSR_Release1.0_Best_%(bandname)s_v3_ib_oob.txt

iband_ir_path = /path/to/viirs/data/GT_F1_CFPA_RSR_Release1.0_Best/
iband_ir_names = GT_F1_CFPA_RSR_Release1.0_Best_%(bandname)s_S0_v3_ib_oob.txt
# We take the S0 subsample. It is anyhow in close agreement with the S1
# subsample

iband_visnir_path = /path/to/viirs/data/GT_F1_SC_RSR_Release1.0_Best_Ibands
iband_visnir_names = GT_F1_SC_RSR_Release1.0_Best_%(bandname)s_V2.72_ib_oob.txt

[noaa19-avhrr]

path = /path/to/avhrr/data
ch1 = NOAA_19_A308C001.txt
ch2 = NOAA_19_A308C002.txt
ch3a = NOAA_19_A308C03A.txt
ch3b = NOAA_19_A308C03B.txt
ch4 = NOAA_19_A308C004.txt
ch5 = NOAA_19_A308C005.txt
12 changes: 4 additions & 8 deletions pyspectral/avhrr_rsr.py
Expand Up @@ -31,6 +31,7 @@
import os
import numpy as np

from pyspectral.utils import get_central_wave

try:
CONFIG_FILE = os.environ['PSP_CONFIG_FILE']
Expand Down Expand Up @@ -113,24 +114,19 @@ def _load(self, scale=1.0):

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

def get_central_wave(wavl, resp):
"""Calculate the central wavelength or the central wavenumber, depending on
what is input"""

return np.trapz(resp*wavl, wavl) / np.trapz(resp, wavl)

if __name__ == "__main__":

import h5py

platform_id, sat_number = "noaa", 19
avhrr = AvhrrRSR('ch1', 'noaa19')
platform_id, sat_number = "noaa", 18
avhrr = AvhrrRSR('ch1', 'noaa18')
filename = os.path.join(avhrr.output_dir,
"rsr_avhrr_%s%d.h5" % (platform_id, sat_number))

with h5py.File(filename, "w") as h5f:
for chname in AVHRR_BAND_NAMES:
avhrr = AvhrrRSR(chname, 'noaa19')
avhrr = AvhrrRSR(chname, 'noaa18')
h5f.attrs['description'] = 'Relative Spectral Responses for AVHRR'
h5f.attrs['platform'] = platform_id
h5f.attrs['sat_number'] = sat_number
Expand Down
139 changes: 121 additions & 18 deletions pyspectral/viirs_rsr.py
Expand Up @@ -23,7 +23,6 @@
"""Interface to VIIRS relative spectral responses
"""


import logging
LOG = logging.getLogger(__name__)

Expand All @@ -41,6 +40,19 @@
"variable PSP_CONFIG_FILE is not a file or does not exist!")

import numpy as np
from pyspectral.utils import get_central_wave

VIIRS_BAND_NAMES = ['M1', 'M2', 'M3', 'M4', 'M5',
'M6', 'M7', 'M8', 'M9', 'M10',
'M11', 'M12', 'M13', 'M14', 'M15', 'M16',
'I1', 'I2', 'I3', 'I4', 'I5',
'DNB']

#: 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 ViirsRSR(object):
"""Container for the (S-NPP) VIIRS RSR data"""
Expand All @@ -52,38 +64,55 @@ def __init__(self, bandname, satname='npp'):
self.filename = None
self.rsr = None

self._get_bandfile()
LOG.debug("Filename: " + str(self.filename))
self._load()

def _get_bandfile(self):
"""Get the VIIRS rsr filename"""

band_file = None
conf = ConfigParser.ConfigParser()
try:
conf.read(CONFIG_FILE)
except ConfigParser.NoSectionError:
LOG.exception('Failed reading configuration file: ' + str(CONFIG_FILE))
LOG.exception('Failed reading configuration file: ' +
str(CONFIG_FILE))
raise

options = {}
for option, value in conf.items('viirs', raw = True):
options[option] = value

values = {"bandname": self.bandname}
for option, value in conf.items('general', raw = True):
options[option] = value

self.output_dir = options.get('rsr_dir', './')

self._get_bandfile(**options)
LOG.debug("Filename: " + str(self.filename))
self._load()

def _get_bandfile(self, **options):
"""Get the VIIRS rsr filename"""

band_file = None

# Need to understand why there are A&B files for band M16. FIXME!
# Anyway, the absolute response differences are small, below 0.05
if self.bandname == 'M16':
values = {"bandname": 'M16A'}
else:
values = {"bandname": self.bandname}

paths = [options["iband_visnir_path"],
options["iband_ir_path"],
options["mband_visnir_path"],
options["mband_ir_path"]
options["mband_ir_path"],
options["dnb_path"]
]
fnames = [options["iband_visnir_names"] % values,
options["iband_ir_names"] % values,
options["mband_visnir_names"] % values,
options["mband_ir_names"] % values
options["mband_ir_names"] % values,
options["dnb_name"] % values
]

LOG.debug("paths = " + str(paths))
LOG.debug("fnames = " + str(fnames))

for path, fname in zip(paths, fnames):
band_file = os.path.join(path, fname)
if os.path.exists(band_file):
Expand All @@ -102,7 +131,7 @@ def _load(self, scale=0.001):

try:
data = np.genfromtxt(self.filename,
unpack=True,
unpack=True, skip_header=1,
names=['bandname',
'detector',
'subsample',
Expand All @@ -111,16 +140,29 @@ def _load(self, scale=0.001):
'asr',
'response',
'quality_flag',
'xtalk_flag'])
'xtalk_flag'],
dtype = [('bandname', '|S3'),
('detector', '<i4'),
('subsample', '<i4'),
('wavelength', '<f8'),
('band_avg_snr', '<f8'),
('asr', '<f8'),
('response', '<f8'),
('quality_flag', '<i4'),
('xtalk_flag', '<i4')])
except ValueError:
data = np.genfromtxt(self.filename,
unpack=True,
unpack=True, skip_header=1,
names=['bandname',
'detector',
'subsample',
'wavelength',
'response'])

'response'],
dtype = [('bandname', '|S3'),
('detector', '<i4'),
('subsample', '<i4'),
('wavelength', '<f8'),
('response', '<f8')])
wavelength = data['wavelength'] * scale
response = data['response']
det = data['detector']
Expand All @@ -132,4 +174,65 @@ def _load(self, scale=0.001):
detectors["det-%d" % (idx+1)]['response'] = np.repeat(response, np.equal(det,idx+1))

self.rsr = detectors


if __name__ == "__main__":

import sys
LOG = logging.getLogger('viirs_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)

import h5py

platform_id = "npp"
viirs = ViirsRSR('M1', 'npp')
filename = os.path.join(viirs.output_dir,
"rsr_viirs_%s.h5" % platform_id)

with h5py.File(filename, "w") as h5f:
for chname in VIIRS_BAND_NAMES:
viirs = ViirsRSR(chname)
h5f.attrs['description'] = 'Relative Spectral Responses for VIIRS'
h5f.attrs['platform'] = platform_id
h5f.attrs['sat_number'] = np.nan
grp = h5f.create_group(chname)
grp.attrs['number_of_detetors'] = len(viirs.rsr.keys())
# Loop over each detector to check if the sampling wavelengths are
# identical:
det_names = viirs.rsr.keys()
wvl = viirs.rsr[det_names[0]]['wavelength']
wvl_is_constant = True
for det in det_names[1:]:
if not np.alltrue(wvl == viirs.rsr[det_names[0]]['wavelength']):
wvl_is_constant = False

if wvl_is_constant:
arr = viirs.rsr[det_names[0]]['wavelength']
dset = grp.create_dataset('wavelength', arr.shape, dtype='f')
dset.attrs['unit'] = 'm'
dset.attrs['scale'] = 1e-06
dset[...] = arr

# Loop over each detector:
for det in viirs.rsr:
det_grp = grp.create_group(det)
wvl = viirs.rsr[det]['wavelength'][~np.isnan(viirs.rsr[det]['wavelength'])]
rsp = viirs.rsr[det]['response'][~np.isnan(viirs.rsr[det]['wavelength'])]
det_grp.attrs['central_wavelength'] = get_central_wave(wvl, rsp)
if not wvl_is_constant:
arr = viirs.rsr[det]['wavelength']
dset = det_grp.create_dataset('wavelength', arr.shape, dtype='f')
dset.attrs['unit'] = 'm'
dset.attrs['scale'] = 1e-06
dset[...] = arr

arr = viirs.rsr[det]['response']
dset = det_grp.create_dataset('response', arr.shape, dtype='f')
dset[...] = arr

0 comments on commit 71d99a9

Please sign in to comment.