File: oli_tirs_reader.py

package info (click to toggle)
pyspectral 0.13.6%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,184 kB
  • sloc: python: 6,070; makefile: 123
file content (124 lines) | stat: -rw-r--r-- 4,852 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017-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/>.

"""Landsat-8/9 OLI/TIRS reader.

This reader generates spectral responses for OLI and TIRS instruments aboard Landsat-8 and -9.
We assume that the instruments are one combined instrument from the user perspective, called `oli_tirs` rather
than generating RSRs for the two instruments separately.
The original spectral response data can be found at the links below.
Landsat-8/OLI:
 = https://landsat.gsfc.nasa.gov/wp-content/uploads/2014/09/Ball_BA_RSR.v1.2.xlsx
Landsat-9/OLI-2:
 = https://landsat.gsfc.nasa.gov/wp-content/uploads/2024/03/L9_OLI2_Ball_BA_RSR.v2-1.xlsx
Landsat-8/TIRS:
 = https://landsat.gsfc.nasa.gov/wp-content/uploads/2013/06/TIRS_Relative_Spectral_Responses.BA_.v1.xlsx
Landsat-9/TIRS-2:
 = https://landsat.gsfc.nasa.gov/wp-content/uploads/2021-10/L9_TIRS2_Relative_Spectral_Responses.BA.v1.0.xlsx
"""

import logging
from pathlib import Path

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__)

OLI_BAND_NAMES = {"B1": "CoastalAerosol",
                  "B2": "Blue",
                  "B3": "Green",
                  "B4": "Red",
                  "B5": "NIR",
                  "B6": "Cirrus",
                  "B7": "SWIR1",
                  "B8": "SWIR2",
                  "B9": "Pan"}

TIRS_SHEETNAMES_L8 = {"B10": "TIRS BA RSR",
                      "B11": "TIRS BA RSR"}
TIRS_BAND_NAMES_L8 = {"B10": "TIRS1 10.8um band average",
                      "B11": "TIRS2 12.0um band average"}

TIRS_SHEETNAMES_L9 = {"B10": "TIRS Band 10 BA RSR",
                      "B11": "TIRS Band 11 BA RSR"}
TIRS_BAND_NAMES_L9 = {"B10": "Band 10 Band=Average RSR",
                      "B11": "Band 11 Band-Average RSR"}


class OliRSR(InstrumentRSR):
    """Class for Landsat OLI RSR."""

    def __init__(self, bandname, platform_name):
        """Read the Landsat OLI relative spectral responses for all channels."""
        super(OliRSR, self).__init__(bandname, platform_name)
        self.instrument = "oli_tirs"
        self._get_options_from_config()
        self.band = bandname
        opts = self.options[f"{platform_name}-{self.instrument}"]
        if bandname in OLI_BAND_NAMES:
            self.path = Path(opts["path"]) / Path(opts["oli"])
        elif bandname in TIRS_BAND_NAMES_L8:
            self.path = Path(opts["path"]) / Path(opts["tirs"])
        else:
            raise ValueError(f"Unknown band name: {bandname}")

        LOG.debug(f"Filename: {self.path}")
        if self.path.exists():
            self._load()
        else:
            raise IOError("Couldn't find an existing file for this band: " +
                          str(self.bandname))

    def _load(self, scale=0.001):
        """Load the Landsat OLI relative spectral responses."""
        if self.band in OLI_BAND_NAMES:
            df = pd.read_excel(self.path, engine="openpyxl", sheet_name=OLI_BAND_NAMES[self.band])
            wvl = np.array(df["Wavelength"]) / 1000.
            resp = np.array(df["BA RSR [watts]"])
        else:
            if self.platform_name == "Landsat-8":
                sheet_name = TIRS_SHEETNAMES_L8[self.band]
                band_name = TIRS_BAND_NAMES_L8[self.band]
            elif self.platform_name == "Landsat-9":
                sheet_name = TIRS_SHEETNAMES_L9[self.band]
                band_name = TIRS_BAND_NAMES_L9[self.band]
            else:
                raise ValueError(f"Unknown platform: {self.platform_name}")
            df = pd.read_excel(self.path, engine="openpyxl", sheet_name=sheet_name)

            wvl = np.array(df["wavelength [um]"]) / 1000.
            resp = np.array(df[band_name])

        # Cut unneeded points
        pts = np.argwhere(resp > 0.002)
        wvl = np.squeeze(wvl[pts])
        resp = np.squeeze(resp[pts])

        self.rsr = {"wavelength": wvl,
                    "response": resp}


if __name__ == "__main__":
    bands = sorted(OLI_BAND_NAMES.keys()) + sorted(TIRS_BAND_NAMES_L8.keys())
    for platform_name in ["Landsat-8", "Landsat-9"]:
        tohdf5(OliRSR, platform_name, bands)