1
|
|
|
#!/usr/bin/env python |
2
|
|
|
# -*- coding: utf-8 -*- |
3
|
|
|
|
4
|
|
|
# Copyright (c) 2018 Adam.Dybbroe |
5
|
|
|
|
6
|
|
|
# Author(s): |
7
|
|
|
|
8
|
|
|
# Adam.Dybbroe <[email protected]> |
9
|
|
|
|
10
|
|
|
# This program is free software: you can redistribute it and/or modify |
11
|
|
|
# it under the terms of the GNU General Public License as published by |
12
|
|
|
# the Free Software Foundation, either version 3 of the License, or |
13
|
|
|
# (at your option) any later version. |
14
|
|
|
|
15
|
|
|
# This program is distributed in the hope that it will be useful, |
16
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
17
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18
|
|
|
# GNU General Public License for more details. |
19
|
|
|
|
20
|
|
|
# You should have received a copy of the GNU General Public License |
21
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
22
|
|
|
|
23
|
|
|
""" |
24
|
|
|
Reading the original agency formattet Sentinel-2 MSI relative spectral responses |
25
|
|
|
|
26
|
|
|
https://earth.esa.int/documents/247904/685211/S2-SRF_COPE-GSEG-EOPG-TN-15-0007_3.0.xlsx |
27
|
|
|
|
28
|
|
|
""" |
29
|
|
|
|
30
|
|
|
import os |
31
|
|
|
from xlrd import open_workbook |
32
|
|
|
import numpy as np |
33
|
|
|
from pyspectral.utils import convert2hdf5 as tohdf5 |
34
|
|
|
from pyspectral.raw_reader import InstrumentRSR |
35
|
|
|
import logging |
36
|
|
|
LOG = logging.getLogger(__name__) |
37
|
|
|
|
38
|
|
|
|
39
|
|
|
MSI_BAND_NAMES = {} |
40
|
|
|
MSI_BAND_NAMES['S2A'] = {'S2A_SR_AV_B1': 'B01', |
41
|
|
|
'S2A_SR_AV_B2': 'B02', |
42
|
|
|
'S2A_SR_AV_B3': 'B03', |
43
|
|
|
'S2A_SR_AV_B4': 'B04', |
44
|
|
|
'S2A_SR_AV_B5': 'B05', |
45
|
|
|
'S2A_SR_AV_B6': 'B06', |
46
|
|
|
'S2A_SR_AV_B7': 'B07', |
47
|
|
|
'S2A_SR_AV_B8': 'B08', |
48
|
|
|
'S2A_SR_AV_B8A': 'B8A', |
49
|
|
|
'S2A_SR_AV_B9': 'B09', |
50
|
|
|
'S2A_SR_AV_B10': 'B10', |
51
|
|
|
'S2A_SR_AV_B11': 'B11', |
52
|
|
|
'S2A_SR_AV_B12': 'B12'} |
53
|
|
|
MSI_BAND_NAMES['S2B'] = {'S2B_SR_AV_B1': 'B01', |
54
|
|
|
'S2B_SR_AV_B2': 'B02', |
55
|
|
|
'S2B_SR_AV_B3': 'B03', |
56
|
|
|
'S2B_SR_AV_B4': 'B04', |
57
|
|
|
'S2B_SR_AV_B5': 'B05', |
58
|
|
|
'S2B_SR_AV_B6': 'B06', |
59
|
|
|
'S2B_SR_AV_B7': 'B07', |
60
|
|
|
'S2B_SR_AV_B8': 'B08', |
61
|
|
|
'S2B_SR_AV_B8A': 'B8A', |
62
|
|
|
'S2B_SR_AV_B9': 'B09', |
63
|
|
|
'S2B_SR_AV_B10': 'B10', |
64
|
|
|
'S2B_SR_AV_B11': 'B11', |
65
|
|
|
'S2B_SR_AV_B12': 'B12'} |
66
|
|
|
|
67
|
|
|
SHEET_HEADERS = {'Spectral Responses (S2A)': 'S2A', |
68
|
|
|
'Spectral Responses (S2B)': 'S2B'} |
69
|
|
|
|
70
|
|
|
PLATFORM_SHORT_NAME = {'Sentinel-2A': 'S2A', |
71
|
|
|
'Sentinel-2B': 'S2B'} |
72
|
|
|
|
73
|
|
|
|
74
|
|
|
class MsiRSR(InstrumentRSR): |
75
|
|
|
|
76
|
|
|
"""Class for Sentinel-2 MSI RSR""" |
77
|
|
|
|
78
|
|
|
def __init__(self, bandname, platform_name): |
79
|
|
|
""" |
80
|
|
|
Read the Sentinel-2 MSI relative spectral responses for all channels. |
81
|
|
|
|
82
|
|
|
""" |
83
|
|
|
super(MsiRSR, self).__init__(bandname, platform_name) |
84
|
|
|
|
85
|
|
|
self.instrument = 'msi' |
86
|
|
|
self._get_options_from_config() |
87
|
|
|
|
88
|
|
|
LOG.debug("Filename: %s", str(self.path)) |
89
|
|
|
if os.path.exists(self.path): |
90
|
|
|
self._load() |
91
|
|
|
else: |
92
|
|
|
raise IOError("Couldn't find an existing file for this band: " + |
93
|
|
|
str(self.bandname)) |
94
|
|
|
|
95
|
|
|
def _load(self, scale=0.001): |
96
|
|
|
"""Load the Sentinel-2 MSI relative spectral responses |
97
|
|
|
""" |
98
|
|
|
|
99
|
|
|
with open_workbook(self.path) as wb_: |
100
|
|
|
for sheet in wb_.sheets(): |
101
|
|
|
if sheet.name not in SHEET_HEADERS.keys(): |
102
|
|
|
continue |
103
|
|
|
|
104
|
|
|
plt_short_name = PLATFORM_SHORT_NAME.get(self.platform_name) |
105
|
|
|
if plt_short_name != SHEET_HEADERS.get(sheet.name): |
106
|
|
|
continue |
107
|
|
|
|
108
|
|
|
wvl = sheet.col_values(0, 1) |
109
|
|
|
for idx in range(1, sheet.row_len(0)): |
110
|
|
|
ch_name = MSI_BAND_NAMES[plt_short_name].get(str(sheet.col_values(idx, 0, 1)[0])) |
111
|
|
|
if ch_name != self.bandname: |
112
|
|
|
continue |
113
|
|
|
|
114
|
|
|
resp = sheet.col_values(idx, 1) |
115
|
|
|
resp = np.array(resp) |
116
|
|
|
resp = np.where(resp == '', 0, resp).astype('float32') |
117
|
|
|
mask = np.less_equal(resp, 0.00001) |
118
|
|
|
wvl0 = np.ma.masked_array(wvl, mask=mask) |
119
|
|
|
wvl_mask = np.ma.masked_outside(wvl, wvl0.min() - 2, wvl0.max() + 2) |
120
|
|
|
|
121
|
|
|
wvl = wvl_mask.compressed() |
122
|
|
|
resp = np.ma.masked_array(resp, mask=wvl_mask.mask).compressed() |
123
|
|
|
self.rsr = {'wavelength': wvl / 1000., 'response': resp} |
124
|
|
|
|
125
|
|
|
break |
126
|
|
|
|
127
|
|
|
break |
128
|
|
|
|
129
|
|
|
|
130
|
|
|
def main(): |
131
|
|
|
"""Main""" |
132
|
|
|
bands = MSI_BAND_NAMES['S2A'].values() |
133
|
|
|
bands.sort() |
134
|
|
|
for platform_name in ['Sentinel-2A', ]: |
135
|
|
|
tohdf5(MsiRSR, platform_name, bands) |
136
|
|
|
|
137
|
|
|
bands = MSI_BAND_NAMES['S2B'].values() |
138
|
|
|
bands.sort() |
139
|
|
|
for platform_name in ['Sentinel-2B', ]: |
140
|
|
|
tohdf5(MsiRSR, platform_name, bands) |
141
|
|
|
|
142
|
|
|
|
143
|
|
|
if __name__ == "__main__": |
144
|
|
|
main() |
145
|
|
|
|