From e42d9f0b004bfb515b62bb34ccace5b8c9722735 Mon Sep 17 00:00:00 2001 From: Manny7717 Date: Fri, 28 Aug 2026 17:22:49 -0500 Subject: [PATCH 1/2] fix(seviri): include the first IR row when converting RSR data xlrd is 0-indexed, so spreadsheet line 13 corresponds to row index 12. The IR-channel loader started at row 13 instead, skipping the first wavelength/response entry (for example IR7.3 starts at 6.35 in the workbook but loaded as 6.37). Read rows 12..111 for the IR block and add a regression test against the bundled workbook. Closes #253 --- pyspectral/tests/test_seviri_rsr.py | 41 +++++++++++++++++++++++++++++ rsr_convert_scripts/seviri_rsr.py | 18 ++++++------- 2 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 pyspectral/tests/test_seviri_rsr.py diff --git a/pyspectral/tests/test_seviri_rsr.py b/pyspectral/tests/test_seviri_rsr.py new file mode 100644 index 0000000..f70bda8 --- /dev/null +++ b/pyspectral/tests/test_seviri_rsr.py @@ -0,0 +1,41 @@ +import importlib +import sys +import types +from pathlib import Path + +from xlrd import open_workbook + + +def _import_seviri_module(repo_root: Path): + sys.modules.pop("rsr_convert_scripts.seviri_rsr", None) + sys.modules["pkg_resources"] = types.SimpleNamespace( + resource_filename=lambda package, resource: str(repo_root / "pyspectral" / "data") + ) + return importlib.import_module("rsr_convert_scripts.seviri_rsr") + + +def test_ir_channels_include_the_first_spreadsheet_row(monkeypatch): + repo_root = Path(__file__).resolve().parents[2] + xls_path = repo_root / "pyspectral" / "data" / "MSG_SEVIRI_Spectral_Response_Characterisation.XLS" + workbook = open_workbook(str(xls_path)) + sheet = workbook.sheet_by_name("IR7.3") + + # The issue's concrete repro: the first wavelength/data row is line 13 in the + # spreadsheet UI, which is row index 12 for xlrd. + assert sheet.cell_value(12, 0) == 6.35 + assert sheet.cell_value(13, 0) == 6.37 + + seviri_rsr = _import_seviri_module(repo_root) + monkeypatch.setattr( + seviri_rsr, + "get_config", + lambda: { + "seviri": {"path": str(xls_path), "filename": xls_path.name}, + "rsr_dir": str(repo_root / "tmp-rsr"), + }, + ) + + seviri = seviri_rsr.Seviri() + + assert seviri.rsr["IR7.3"]["wavelength"][0] == sheet.cell_value(12, 0) + assert seviri.rsr["IR7.3"]["Meteosat-11"]["95"][0] == sheet.cell_value(12, 7) diff --git a/rsr_convert_scripts/seviri_rsr.py b/rsr_convert_scripts/seviri_rsr.py index 2b3daeb..abae7fb 100644 --- a/rsr_convert_scripts/seviri_rsr.py +++ b/rsr_convert_scripts/seviri_rsr.py @@ -91,23 +91,23 @@ def _load(self, filename=None): self.rsr[ch_name]['Meteosat-11'] = met11 elif ch_name.startswith('IR'): wvl = np.array( - sheet.col_values(0, start_rowx=13, end_rowx=113)) + sheet.col_values(0, start_rowx=12, end_rowx=112)) met8_95 = np.array( - sheet.col_values(1, start_rowx=13, end_rowx=113)) + sheet.col_values(1, start_rowx=12, end_rowx=112)) met9_95 = np.array( - sheet.col_values(3, start_rowx=13, end_rowx=113)) + sheet.col_values(3, start_rowx=12, end_rowx=112)) met10_95 = np.array( - sheet.col_values(5, start_rowx=13, end_rowx=113)) + sheet.col_values(5, start_rowx=12, end_rowx=112)) met11_95 = np.array( - sheet.col_values(7, start_rowx=13, end_rowx=113)) + sheet.col_values(7, start_rowx=12, end_rowx=112)) met8_85 = np.array( - sheet.col_values(2, start_rowx=13, end_rowx=113)) + sheet.col_values(2, start_rowx=12, end_rowx=112)) met9_85 = np.array( - sheet.col_values(4, start_rowx=13, end_rowx=113)) + sheet.col_values(4, start_rowx=12, end_rowx=112)) met10_85 = np.array( - sheet.col_values(6, start_rowx=13, end_rowx=113)) + sheet.col_values(6, start_rowx=12, end_rowx=112)) met11_85 = np.array( - sheet.col_values(8, start_rowx=13, end_rowx=113)) + sheet.col_values(8, start_rowx=12, end_rowx=112)) self.rsr[ch_name]['Meteosat-8'] = {'95': met8_95, '85': met8_85} self.rsr[ch_name]['Meteosat-9'] = {'95': met9_95, From 7eb0722e487c60b4374a6bb054302ff4f59d967d Mon Sep 17 00:00:00 2001 From: Manny7717 Date: Fri, 28 Aug 2026 17:36:40 -0500 Subject: [PATCH 2/2] style: add docstrings to SEVIRI RSR regression tests --- pyspectral/tests/test_seviri_rsr.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyspectral/tests/test_seviri_rsr.py b/pyspectral/tests/test_seviri_rsr.py index f70bda8..eb737f4 100644 --- a/pyspectral/tests/test_seviri_rsr.py +++ b/pyspectral/tests/test_seviri_rsr.py @@ -1,3 +1,9 @@ +"""Regression tests for the SEVIRI RSR converter. + +Ensures the first spreadsheet row of each IR channel is included when +converting the bundled MSG SEVIRI spectral response workbook (issue #253). +""" + import importlib import sys import types @@ -15,6 +21,7 @@ def _import_seviri_module(repo_root: Path): def test_ir_channels_include_the_first_spreadsheet_row(monkeypatch): + """IR channel RSR data must start at spreadsheet row 12, not row 13.""" repo_root = Path(__file__).resolve().parents[2] xls_path = repo_root / "pyspectral" / "data" / "MSG_SEVIRI_Spectral_Response_Characterisation.XLS" workbook = open_workbook(str(xls_path))