[Git][debian-gis-team/pyspectral][upstream] New upstream version 0.10.6+ds
Antonio Valentino (@antonio.valentino)
gitlab at salsa.debian.org
Thu Dec 23 09:47:06 GMT 2021
Antonio Valentino pushed to branch upstream at Debian GIS Project / pyspectral
Commits:
0ec215a5 by Antonio Valentino at 2021-12-23T09:26:10+00:00
New upstream version 0.10.6+ds
- - - - -
20 changed files:
- CHANGELOG.md
- CONTRIBUTING.rst
- README.md
- RELEASING.md
- − compare2rsrfiles.py
- doc/conf.py
- doc/index.rst
- doc/platforms_supported.rst
- doc/rayleigh_correction.rst
- + pyspectral/bandnames.py
- pyspectral/near_infrared_reflectance.py
- pyspectral/rayleigh.py
- pyspectral/rsr_reader.py
- pyspectral/tests/test_rayleigh.py
- pyspectral/tests/test_rsr_reader.py
- pyspectral/tests/test_utils.py
- pyspectral/utils.py
- rsr_convert_scripts/abi_rsr.py
- setup.cfg
- setup.py
Changes:
=====================================
CHANGELOG.md
=====================================
@@ -1,3 +1,29 @@
+## Version <v0.10.6> (2021/12/22)
+
+### Issues Closed
+
+* [Issue 137](https://github.com/pytroll/pyspectral/issues/137) - Bug in rayleigh correction related to Dask version >= 2021.5.1 ([PR 138](https://github.com/pytroll/pyspectral/pull/138) by [@adybbroe](https://github.com/adybbroe))
+* [Issue 132](https://github.com/pytroll/pyspectral/issues/132) - Add GOES-18 and GOES-19 RSRs ([PR 142](https://github.com/pytroll/pyspectral/pull/142) by [@adybbroe](https://github.com/adybbroe))
+
+In this release 2 issues were closed.
+
+### Pull Requests Merged
+
+#### Bugs fixed
+
+* [PR 138](https://github.com/pytroll/pyspectral/pull/138) - Bugfix unittests rayleigh ([137](https://github.com/pytroll/pyspectral/issues/137))
+
+#### Features added
+
+* [PR 142](https://github.com/pytroll/pyspectral/pull/142) - Creating ABI RSR files for GOES 18 & 19 (FM3 & 4) ([132](https://github.com/pytroll/pyspectral/issues/132))
+* [PR 141](https://github.com/pytroll/pyspectral/pull/141) - Add technique to reduce Rayleigh contribution at high zenith angles
+* [PR 140](https://github.com/pytroll/pyspectral/pull/140) - Fix for deprecation warnings concerning clipping in Rayleigh part
+* [PR 135](https://github.com/pytroll/pyspectral/pull/135) - Remove all use of 'six'
+* [PR 134](https://github.com/pytroll/pyspectral/pull/134) - Change tested Python versions to 3.8, 3.9 and 3.10
+
+In this release 6 pull requests were closed.
+
+
## Version <v0.10.5> (2021/04/29)
### Pull Requests Merged
@@ -171,7 +197,7 @@ In this release 3 pull requests were closed.
### Issues Closed
* [Issue 92](https://github.com/pytroll/pyspectral/issues/92) - Fails to pull from Github because of a git-lfs quota limit ([PR 93](https://github.com/pytroll/pyspectral/pull/93))
-* [Issue 90](https://github.com/pytroll/pyspectral/issues/90) - CREFL rayleigh Goes-16 ABI L1B
+* [Issue 90](https://github.com/pytroll/pyspectral/issues/90) - CREFL rayleigh Goes-16 ABI L1B
In this release 2 issues were closed.
=====================================
CONTRIBUTING.rst
=====================================
@@ -125,7 +125,7 @@ Code of Conduct
Pyspectral follows the same code of conduct as the Pytroll project. For reference
it is copied to this repository in
-`CODE_OF_CONDUCT.md <https://github.com/pytroll/pyspectral/blob/master/CODE_OF_CONDUCT.md>`_.
+`CODE_OF_CONDUCT.md <https://github.com/pytroll/pyspectral/blob/main/CODE_OF_CONDUCT.md>`_.
As stated in the Pytroll home page, this code of conduct applies to the
project space (GitHub) as well as the public space online and offline when
@@ -148,4 +148,4 @@ determined by the maintainers and may include one or more of the following:
- Temporary or permanent ban from online communication (Slack, mailing list, etc)
For details see the official
-`code of conduct document <https://github.com/pytroll/pyspectral/blob/master/CODE_OF_CONDUCT.md>`_.
+`code of conduct document <https://github.com/pytroll/pyspectral/blob/main/CODE_OF_CONDUCT.md>`_.
=====================================
README.md
=====================================
@@ -2,10 +2,10 @@ Pyspectral
==========
-[![Build status](https://github.com/pytroll/pyspectral/workflows/CI/badge.svg?branch=master)](https://github.com/pytroll/pyspectral/workflows/CI/badge.svg?branch=master)
+[![Build status](https://github.com/pytroll/pyspectral/workflows/CI/badge.svg?branch=main)](https://github.com/pytroll/pyspectral/workflows/CI/badge.svg?branch=main)
[![Anaconda-Server Badge](https://anaconda.org/conda-forge/pyspectral/badges/version.svg)](https://anaconda.org/conda-forge/pyspectral)
[![Build status](https://ci.appveyor.com/api/projects/status/5lm42n0l65l5o9xn?svg=true)](https://ci.appveyor.com/project/pytroll/pyspectral)
-[![Coverage Status](https://coveralls.io/repos/github/pytroll/pyspectral/badge.svg?branch=master)](https://coveralls.io/github/pytroll/pyspectral?branch=master)
+[![Coverage Status](https://coveralls.io/repos/github/pytroll/pyspectral/badge.svg?branch=main)](https://coveralls.io/github/pytroll/pyspectral?branch=main)
[![PyPI version](https://badge.fury.io/py/pyspectral.svg)](https://badge.fury.io/py/pyspectral)
Given a passive sensor on a meteorological satellite Pyspectral provides the
@@ -22,4 +22,4 @@ scattering of molecules, absorption by atmospheric gases and aerosols, and Mie
scattering of aerosols.
Adam Dybbroe
-March 2018, Norrkoping, Sweden
+May 2021, Norrkoping, Sweden
=====================================
RELEASING.md
=====================================
@@ -3,7 +3,7 @@
prerequisites: `pip install setuptools twine`
-1. checkout master
+1. checkout main
2. pull from repo
3. run the unittests
4. run `loghub` and update the `CHANGELOG.md` file:
@@ -25,4 +25,13 @@ See [semver.org](http://semver.org/) on how to write a version number.
6. push changes to github `git push --follow-tags`
-7. Verify travis tests passed and deployed sdist and wheel to PyPI
+7. Verify the Github actions unit tests passed
+
+8. Create a "Release" on GitHub by going to
+ https://github.com/pytroll/pyspectral/releases and clicking "Draft a new
+ release". On the next page enter the newly created tag in the "Tag version"
+ field, "Version X.Y.Z" in the "Release title" field, and paste the markdown
+ from the changelog (the portion under the version section header) in the
+ "Describe this release" box. Finally click "Publish release".
+
+9. Verify the GitHub actions for deployment succeed and the release is on PyPI
=====================================
compare2rsrfiles.py deleted
=====================================
@@ -1,57 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2017 Adam.Dybbroe
-
-# Author(s):
-
-# Adam.Dybbroe <a000680 at c20671.ad.smhi.se>
-
-# 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/>.
-
-"""Compare the content of two hdf5 files with rsr data
-"""
-
-import pdb
-import numpy as np
-from pyspectral.rsr_reader import RelativeSpectralResponse
-
-#FILE1 = '/home/a000680/data/pyspectral/rsr_viirs_Suomi-NPP.h5'
-#FILE2 = '/home/a000680/data/pyspectral/BACKUP_rsr_viirs_Suomi-NPP.h5'
-FILE1 = "/home/a000680/data/pyspectral/OLDrsr_ahi_Himawari-8.h5"
-FILE2 = "/home/a000680/data/pyspectral/rsr_ahi_Himawari-8.h5"
-
-rsr_a = RelativeSpectralResponse(filename=FILE1)
-rsr_b = RelativeSpectralResponse(filename=FILE2)
-
-for band in rsr_a.rsr:
- for det in rsr_a.rsr[band]:
- wvl1 = rsr_a.rsr[band][det]['wavelength']
- wvl2 = rsr_b.rsr[band][det]['wavelength']
- try:
- if not np.allclose(wvl1, wvl2):
- pdb.set_trace()
- except ValueError:
- pdb.set_trace()
- resp1 = rsr_a.rsr[band][det]['response']
- resp2 = rsr_b.rsr[band][det]['response']
- try:
- if not np.allclose(resp1, resp2):
- pdb.set_trace()
- except ValueError:
- pdb.set_trace()
- cw1 = rsr_a.rsr[band][det]['central_wavelength']
- cw2 = rsr_b.rsr[band][det]['central_wavelength']
- if np.abs(cw1 - cw2) > 0.00001:
- pdb.set_trace()
=====================================
doc/conf.py
=====================================
@@ -106,7 +106,7 @@ master_doc = 'index'
# General information about the project.
project = u'Pyspectral'
-copyright = u'2013-2018, PyTroll'
+copyright = u'2013-2021, Pytroll'
# The language for content autogenerated by Sphinx. Refer to documentation
=====================================
doc/index.rst
=====================================
@@ -1,4 +1,4 @@
-.. Pyspectral documentation master file, created by
+.. Pyspectral documentation main file, created by
sphinx-quickstart on Tue Oct 15 13:31:45 2013.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
=====================================
doc/platforms_supported.rst
=====================================
@@ -2,7 +2,7 @@ Satellite sensors supported
===========================
Below we list the satellite sensors for which the relative spectral responses
-have been included in PySpectral.
+have been included in Pyspectral.
.. list-table:: Satellite sensors supported
:header-rows: 1
@@ -28,6 +28,12 @@ have been included in PySpectral.
* - GOES-17 abi
- `rsr_abi_GOES-17.h5`
- GOES-S_
+ * - GOES-18 abi
+ - `rsr_abi_GOES-18.h5`
+ - GOES-T_
+ * - GOES-19 abi
+ - `rsr_abi_GOES-19.h5`
+ - GOES-U_
* - Himawari-8 ahi
- `rsr_ahi_Himawari-8.h5`
- JMA_
@@ -70,6 +76,9 @@ have been included in PySpectral.
* - Sentinel-3A olci
- `rsr_olci_Sentinel-3A.h5`
- ESA-Sentinel-OLCI_
+ * - Sentinel-3B olci
+ - `rsr_olci_Sentinel-3B.h5`
+ - ESA-Sentinel-OLCI_
* - Sentinel-2A msi
- `rsr_msi_Sentinel-2A.h5`
- ESA-Sentinel-MSI_
@@ -104,8 +113,10 @@ have been included in PySpectral.
.. _Eumetsat: https://www.eumetsat.int/website/home/Data/Products/Calibration/MSGCalibration/index.html
.. _GSICS: https://www.star.nesdis.noaa.gov/smcd/GCC/instrInfo-srf.php
-.. _GOES-R: http://ncc.nesdis.noaa.gov/GOESR/docs/GOES-R_ABI_PFM_SRF_CWG_v3.zip
-.. _GOES-S: http://ncc.nesdis.noaa.gov/GOESR/docs/GOES-R_ABI_FM2_SRF_CWG.zip
+.. _GOES-R: https://ncc.nesdis.noaa.gov/GOESR/docs/GOES-R_ABI_PFM_SRF_CWG_v3.zip
+.. _GOES-S: https://ncc.nesdis.noaa.gov/GOESR/docs/GOES-R_ABI_FM2_SRF_CWG.zip
+.. _GOES-T: https://ncc.nesdis.noaa.gov/GOESR/docs/GOES-R_ABI_FM3_SRF_CWG.zip
+.. _GOES-U: https://ncc.nesdis.noaa.gov/GOESR/docs/GOES-R_ABI_FM4_SRF_CWG.zip
.. _JMA: http://www.data.jma.go.jp/mscweb/en/himawari89/space_segment/spsg_ahi.html#srf
.. _ESA-Envisat: http://envisat.esa.int/handbooks/aatsr/aux-files/consolidatedsrfs.xls
.. _ESA-Sentinel-OLCI: https://sentinel.esa.int/documents/247904/322304/OLCI+SRF+%28NetCDF%29/15cfd7a6-b7bc-4051-87f8-c35d765ae43a
=====================================
doc/rayleigh_correction.rst
=====================================
@@ -110,6 +110,31 @@ if you want another setup, e.g.:
[[ 10.01281363 9.65488615]
[ 9.78070046 9.70335278]]
+At high solar zenith angles the assumptions used in the simulations begin to break
+down, which can lead to unrealistic correction values. In particular, for true color
+imagery this often results in the red channel being too bright compared to the
+green and / or blue channels.
+We have implemented an optional scaling method to minimise this overcorrection at
+high solar zeniths, `reduce_rayleigh`:
+
+ >>> from pyspectral.rayleigh import Rayleigh
+ >>> import numpy as np
+ >>> viirs = Rayleigh('Suomi-NPP', 'viirs', atmosphere='midlatitude summer', rural_aerosol=True)
+ >>> sunz = np.array([[32., 40.], [80., 88.]])
+ >>> satz = np.array([[45., 20.], [46., 21.]])
+ >>> ssadiff = np.array([[110, 170], [120, 180]])
+ >>> refl_cor_m2 = viirs.get_reflectance(sunz, satz, ssadiff, 0.45, redband)
+ [[ 10.40291763 9.654881]
+ [ 30.9275331 39.41288558]]
+ >>> reduced_refl_cor_m2 = viirs.reduce_rayleigh_highzenith(sunz, refl_cor_m2, 70., 90., 1.)
+ [[ 10.40291763 9.654881],
+ [ 15.46376655 3.94128856]]
+
+These reduced atmospheric correction (primarily due to increased Rayleigh
+scattering in the clear atmosphere) values can then be used to correct the
+original satellite reflectance data to produce more visually pleasing imagery,
+also at low sun elevations. Due to the nature of this reduction method they
+should not be used for any scientific analysis.
.. _Satpy: http://www.github.com/pytroll/satpy
.. _zenodo: https://doi.org/10.5281/zenodo.1288441
=====================================
pyspectral/bandnames.py
=====================================
@@ -0,0 +1,195 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2021 Adam.Dybbroe
+
+# Author(s):
+
+# Adam Dybbroe <Firstname.Lastname at smhi.se>
+
+# 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/>.
+
+"""Band name translations."""
+
+BANDNAMES = {}
+BANDNAMES['generic'] = {'VIS006': 'VIS0.6',
+ 'VIS008': 'VIS0.8',
+ 'IR_016': 'NIR1.6',
+ 'IR_039': 'IR3.9',
+ 'WV_062': 'IR6.2',
+ 'WV_073': 'IR7.3',
+ 'IR_087': 'IR8.7',
+ 'IR_097': 'IR9.7',
+ 'IR_108': 'IR10.8',
+ 'IR_120': 'IR12.0',
+ 'IR_134': 'IR13.4',
+ 'HRV': 'HRV',
+ 'I01': 'I1',
+ 'I02': 'I2',
+ 'I03': 'I3',
+ 'I04': 'I4',
+ 'I05': 'I5',
+ 'M01': 'M1',
+ 'M02': 'M2',
+ 'M03': 'M3',
+ 'M04': 'M4',
+ 'M05': 'M5',
+ 'M06': 'M6',
+ 'M07': 'M7',
+ 'M08': 'M8',
+ 'M09': 'M9',
+ 'C01': 'ch1',
+ 'C02': 'ch2',
+ 'C03': 'ch3',
+ 'C04': 'ch4',
+ 'C05': 'ch5',
+ 'C06': 'ch6',
+ 'C07': 'ch7',
+ 'C08': 'ch8',
+ 'C09': 'ch9',
+ 'C10': 'ch10',
+ 'C11': 'ch11',
+ 'C12': 'ch12',
+ 'C13': 'ch13',
+ 'C14': 'ch14',
+ 'C15': 'ch15',
+ 'C16': 'ch16',
+ }
+# handle arbitrary channel numbers
+for chan_num in range(1, 37):
+ BANDNAMES['generic'][str(chan_num)] = 'ch{:d}'.format(chan_num)
+
+# MODIS RSR files were made before 'chX' became standard in pyspectral
+BANDNAMES['modis'] = {str(chan_num): str(chan_num) for chan_num in range(1, 37)}
+
+BANDNAMES['seviri'] = {'VIS006': 'VIS0.6',
+ 'VIS008': 'VIS0.8',
+ 'IR_016': 'NIR1.6',
+ 'IR_039': 'IR3.9',
+ 'WV_062': 'IR6.2',
+ 'WV_073': 'IR7.3',
+ 'IR_087': 'IR8.7',
+ 'IR_097': 'IR9.7',
+ 'IR_108': 'IR10.8',
+ 'IR_120': 'IR12.0',
+ 'IR_134': 'IR13.4',
+ 'HRV': 'HRV'}
+
+BANDNAMES['viirs'] = {'I01': 'I1',
+ 'I02': 'I2',
+ 'I03': 'I3',
+ 'I04': 'I4',
+ 'I05': 'I5',
+ 'M01': 'M1',
+ 'M02': 'M2',
+ 'M03': 'M3',
+ 'M04': 'M4',
+ 'M05': 'M5',
+ 'M06': 'M6',
+ 'M07': 'M7',
+ 'M08': 'M8',
+ 'M09': 'M9',
+ }
+
+BANDNAMES['avhrr-3'] = {'1': 'ch1',
+ '2': 'ch2',
+ '3b': 'ch3b',
+ '3a': 'ch3a',
+ '4': 'ch4',
+ '5': 'ch5'}
+
+BANDNAMES['abi'] = {'C01': 'ch1',
+ 'C02': 'ch2',
+ 'C03': 'ch3',
+ 'C04': 'ch4',
+ 'C05': 'ch5',
+ 'C06': 'ch6',
+ 'C07': 'ch7',
+ 'C08': 'ch8',
+ 'C09': 'ch9',
+ 'C10': 'ch10',
+ 'C11': 'ch11',
+ 'C12': 'ch12',
+ 'C13': 'ch13',
+ 'C14': 'ch14',
+ 'C15': 'ch15',
+ 'C16': 'ch16'
+ }
+
+BANDNAMES['ahi'] = {'B01': 'ch1',
+ 'B02': 'ch2',
+ 'B03': 'ch3',
+ 'B04': 'ch4',
+ 'B05': 'ch5',
+ 'B06': 'ch6',
+ 'B07': 'ch7',
+ 'B08': 'ch8',
+ 'B09': 'ch9',
+ 'B10': 'ch10',
+ 'B11': 'ch11',
+ 'B12': 'ch12',
+ 'B13': 'ch13',
+ 'B14': 'ch14',
+ 'B15': 'ch15',
+ 'B16': 'ch16'
+ }
+
+BANDNAMES['ami'] = {'VI004': 'ch1',
+ 'VI005': 'ch2',
+ 'VI006': 'ch3',
+ 'VI008': 'ch4',
+ 'NR013': 'ch5',
+ 'NR016': 'ch6',
+ 'SW038': 'ch7',
+ 'WV063': 'ch8',
+ 'WV069': 'ch9',
+ 'WV073': 'ch10',
+ 'IR087': 'ch11',
+ 'IR096': 'ch12',
+ 'IR105': 'ch13',
+ 'IR112': 'ch14',
+ 'IR123': 'ch15',
+ 'IR133': 'ch16'
+ }
+
+BANDNAMES['fci'] = {'vis_04': 'ch1',
+ 'vis_05': 'ch2',
+ 'vis_06': 'ch3',
+ 'vis_08': 'ch4',
+ 'vis_09': 'ch5',
+ 'nir_13': 'ch6',
+ 'nir_16': 'ch7',
+ 'nir_22': 'ch8',
+ 'ir_38': 'ch9',
+ 'wv_63': 'ch10',
+ 'wv_73': 'ch11',
+ 'ir_87': 'ch12',
+ 'ir_97': 'ch13',
+ 'ir_105': 'ch14',
+ 'ir_123': 'ch15',
+ 'ir_133': 'ch16'
+ }
+
+BANDNAMES['slstr'] = {'S1': 'ch1',
+ 'S2': 'ch2',
+ 'S3': 'ch3',
+ 'S4': 'ch4',
+ 'S5': 'ch5',
+ 'S6': 'ch6',
+ 'S7': 'ch7',
+ 'S8': 'ch8',
+ 'S9': 'ch9',
+ 'F1': 'ch7',
+ 'F2': 'ch8',
+ }
=====================================
pyspectral/near_infrared_reflectance.py
=====================================
@@ -33,9 +33,9 @@ import os
import logging
import numpy as np
try:
- from dask.array import where, logical_or, asanyarray, array, isnan
+ from dask.array import where, logical_or, asanyarray, isnan
except ImportError:
- from numpy import where, logical_or, asanyarray, array, isnan
+ from numpy import where, logical_or, asanyarray, isnan
from pyspectral.solar import (SolarIrradianceSpectrum,
TOTAL_IRRADIANCE_SPECTRUM_2000ASTM)
=====================================
pyspectral/rayleigh.py
=====================================
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
-# Copyright (c) 2016-2020 Pytroll developers
+# Copyright (c) 2016-2021 Pytroll developers
#
# Author(s):
#
@@ -26,14 +26,13 @@
import os
import time
import logging
-from six import integer_types
import h5py
import numpy as np
try:
from dask.array import (where, zeros, clip, rad2deg, deg2rad, cos, arccos,
- atleast_2d, Array, map_blocks, from_array)
+ atleast_2d, Array, map_blocks, from_array, nan_to_num)
import dask.array as da
HAVE_DASK = True
# try:
@@ -42,7 +41,7 @@ try:
# except ImportError:
# pass
except ImportError:
- from numpy import where, zeros, clip, rad2deg, deg2rad, cos, arccos, atleast_2d
+ from numpy import where, zeros, clip, rad2deg, deg2rad, cos, arccos, atleast_2d, nan_to_num
da = None
map_blocks = None
from_array = None
@@ -65,6 +64,7 @@ LOG = logging.getLogger(__name__)
class BandFrequencyOutOfRange(ValueError):
"""Exception when the band frequency is out of the visible range."""
+
pass
@@ -184,10 +184,10 @@ class Rayleigh(RayleighConfigBaseClass):
"""Get the effective wavelength with Rayleigh scattering in mind."""
try:
rsr = RelativeSpectralResponse(self.platform_name, self.sensor)
- except(IOError, OSError):
+ except OSError:
LOG.exception(
"No spectral responses for this platform and sensor: %s %s", self.platform_name, self.sensor)
- if isinstance(bandname, (float, integer_types)):
+ if isinstance(bandname, (float, int)):
LOG.warning(
"Effective wavelength is set to the requested band wavelength = %f", bandname)
return bandname
@@ -198,14 +198,14 @@ class Rayleigh(RayleighConfigBaseClass):
if isinstance(bandname, str):
bandname = BANDNAMES.get(self.sensor, BANDNAMES['generic']).get(bandname, bandname)
- elif isinstance(bandname, (float, integer_types)):
+ elif isinstance(bandname, (float, int)):
if not(0.4 < bandname < 0.8):
raise BandFrequencyOutOfRange(
'Requested band frequency should be between 0.4 and 0.8 microns!')
bandname = get_bandname_from_wavelength(self.sensor, bandname, rsr.rsr)
- wvl, resp = rsr.rsr[bandname][
- 'det-1']['wavelength'], rsr.rsr[bandname]['det-1']['response']
+ wvl, resp = (rsr.rsr[bandname]['det-1']['wavelength'],
+ rsr.rsr[bandname]['det-1']['response'])
cwvl = get_central_wave(wvl, resp, weight=1. / wvl**4)
LOG.debug("Band name: %s Effective wavelength: %f", bandname, cwvl)
@@ -215,12 +215,13 @@ class Rayleigh(RayleighConfigBaseClass):
def get_reflectance_lut(self):
"""Get reflectance LUT.
- Read the LUT with reflectances as a function of wavelength, satellite zenith
+ If not already cached (read previously) read the file with Look-Up
+ Tables of reflectances as a function of wavelength, satellite zenith
secant, azimuth difference angle, and sun zenith secant.
"""
if self._rayl is None:
- lut_vars = get_reflectance_lut(self.reflectance_lut_filename)
+ lut_vars = get_reflectance_lut_from_file(self.reflectance_lut_filename)
self._rayl = lut_vars[0]
self._wvl_coord = lut_vars[1]
self._azid_coord = lut_vars[2]
@@ -235,6 +236,20 @@ class Rayleigh(RayleighConfigBaseClass):
res = minterp(interp_points2)
return res.reshape(sunzsec.shape)
+ def _clip_angles_inside_coordinate_range(self, zenith_angle, zenith_secant_max):
+ """Clipping solar- or satellite zenith angles to be inside the allowed coordinate range.
+
+ The "allowed" coordinate range is 0 to the angle corresponiding to a
+ maximum secant. The maximum secant is here the maximum available in the
+ Rayleigh LUT file.
+
+ Also the nan's in the angle array are filled with zeros (0)!
+
+ """
+ clip_angle = nan_to_num(rad2deg(arccos(1. / zenith_secant_max)))
+ zang = nan_to_num(zenith_angle)
+ return clip(zang, 0, clip_angle)
+
def get_reflectance(self, sun_zenith, sat_zenith, azidiff, bandname, redband=None):
"""Get the reflectance from the three sun-sat angles."""
# Get wavelength in nm for band:
@@ -259,15 +274,15 @@ class Rayleigh(RayleighConfigBaseClass):
if redband is not None:
redband = from_array(redband, chunks=redband.shape)
- clip_angle = rad2deg(arccos(1. / sunz_sec_coord.max()))
- sun_zenith = clip(sun_zenith, 0, clip_angle)
+ sun_zenith = self._clip_angles_inside_coordinate_range(sun_zenith, sunz_sec_coord.max())
sunzsec = 1. / cos(deg2rad(sun_zenith))
- clip_angle = rad2deg(arccos(1. / satz_sec_coord.max()))
- sat_zenith = clip(sat_zenith, 0, clip_angle)
+
+ sat_zenith = self._clip_angles_inside_coordinate_range(sat_zenith, satz_sec_coord.max())
satzsec = 1. / cos(deg2rad(sat_zenith))
+
shape = sun_zenith.shape
- if not(wvl_coord.min() < wvl < wvl_coord.max()):
+ if not wvl_coord.min() < wvl < wvl_coord.max():
LOG.warning(
"Effective wavelength for band %s outside 400-800 nm range!",
str(bandname))
@@ -315,19 +330,32 @@ class Rayleigh(RayleighConfigBaseClass):
res = where(redband < 20., res,
(1 - (redband - 20) / 80) * res)
- res = clip(res, 0, 100)
+ res = clip(nan_to_num(res), 0, 100)
if compute:
res = res.compute()
return res
+ @staticmethod
+ def reduce_rayleigh_highzenith(zenith, rayref, thresh_zen, maxzen, strength):
+ """Reduce the Rayleigh correction amount at high zenith angles.
+ This linearly scales the Rayleigh reflectance, `rayref`, for solar or satellite zenith angles, `zenith`,
+ above a threshold angle, `thresh_zen`. Between `thresh_zen` and `maxzen` the Rayleigh reflectance will
+ be linearly scaled, from one at `thresh_zen` to zero at `maxzen`..
+ """
+ LOG.info("Reducing Rayleigh effect at high zenith angles.")
+ factor = 1. - strength * where(zenith < thresh_zen, 0, (zenith - thresh_zen) / (maxzen - thresh_zen))
+ # For low zenith factor can be greater than one, so we need to clip it into a sensible range.
+ factor = clip(factor, 0, 1)
+ return rayref * factor
+
-def get_reflectance_lut(filename):
- """
- Get reflectance LUT.
+def get_reflectance_lut_from_file(filename):
+ """Get reflectance LUT.
- Read the LUT with reflectances as a function of wavelength, satellite
- zenith secant, azimuth difference angle, and sun zenith secant
+ Read the Look-Up Tables from file with reflectances as a function of
+ wavelength, satellite zenith secant, azimuth difference angle, and sun
+ zenith secant
"""
h5f = h5py.File(filename, 'r')
=====================================
pyspectral/rsr_reader.py
=====================================
@@ -30,6 +30,7 @@ from os.path import expanduser
from pyspectral.config import get_config
from pyspectral.utils import WAVE_NUMBER
from pyspectral.utils import WAVE_LENGTH
+from pyspectral.utils import BANDNAMES
from pyspectral.utils import (INSTRUMENTS, download_rsr)
from pyspectral.utils import (RSR_DATA_VERSION_FILENAME, RSR_DATA_VERSION)
from pyspectral.utils import (convert2wavenumber, get_central_wave)
@@ -46,6 +47,24 @@ OSCAR_PLATFORM_NAMES = {'eos-2': 'EOS-Aqua',
'meteosat-8': 'Meteosat-8'}
+class RSRDict(dict):
+ def __init__(self, instrument=None):
+ self.instrument = instrument
+ dict.__init__(self)
+
+ def __getitem__(self, key):
+ try:
+ val = dict.__getitem__(self, key)
+ except KeyError:
+ if key in BANDNAMES[self.instrument]:
+ val = dict.__getitem__(self, BANDNAMES[self.instrument][key])
+ elif key in BANDNAMES['generic']:
+ val = dict.__getitem__(self, BANDNAMES['generic'][key])
+ else:
+ raise KeyError(f'Band not found in RSR for {self.instrument}: {key}')
+ return val
+
+
class RSRDataBaseClass(object):
"""Data container for the Relative Spectral Responses for all (supported) satellite sensors."""
@@ -56,7 +75,7 @@ class RSRDataBaseClass(object):
filename and load the data.
"""
- self.rsr = {}
+ self.rsr = RSRDict()
self.description = "Unknown"
self.band_names = None
self.unit = '1e-6 m'
@@ -105,6 +124,7 @@ class RelativeSpectralResponse(RSRDataBaseClass):
self.platform_name = platform_name
self.instrument = instrument
self.filename = None
+ self.rsr.instrument = self.instrument
if not self.instrument or not self.platform_name:
if 'filename' in kwargs:
self.filename = kwargs['filename']
=====================================
pyspectral/tests/test_rayleigh.py
=====================================
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
-# Copyright (c) 2016-2019 Pytroll developers
+# Copyright (c) 2016-2019, 2021 Pytroll developers
#
# Author(s):
#
@@ -36,20 +36,17 @@ from pyspectral.tests.data import (
TEST_RAYLEIGH_WVL_COORD)
from pyspectral.utils import RSR_DATA_VERSION
-if sys.version_info < (2, 7):
- import unittest2 as unittest
-else:
- import unittest
-
-if sys.version_info < (3,):
- from mock import patch
-else:
- from unittest.mock import patch
+import unittest
+from unittest.mock import patch
TEST_RAYLEIGH_RESULT1 = np.array([10.40727436, 8.69775471], dtype='float32')
-TEST_RAYLEIGH_RESULT2 = np.array([9.71695252, 8.51415601], dtype='float32')
+TEST_RAYLEIGH_RESULT2 = np.array([9.71696059, 8.51415689], dtype='float32')
TEST_RAYLEIGH_RESULT3 = np.array([5.61532271, 8.69267476], dtype='float32')
+TEST_RAYLEIGH_RESULT4 = np.array([0.0, 8.69775471], dtype='float32')
+TEST_RAYLEIGH_RESULT_R1 = np.array([16.66666667, 20.83333333, 25.], dtype='float32')
+TEST_RAYLEIGH_RESULT_R2 = np.array([0., 6.25, 12.5], dtype='float32')
+TEST_ZENITH_ANGLES_RESULTS = np.array([68.67631374, 68.67631374, 32., 0.])
# Mock some modules, so we don't need them for tests.
@@ -90,6 +87,148 @@ class RelativeSpectralResponseTestData(object):
self.rsr[chname]['det-1']['response'] = ch3_resp
+class TestRayleighDask(unittest.TestCase):
+ """Class for testing pyspectral.rayleigh - with dask-arrays as input."""
+
+ def setUp(self):
+ """Set up the test."""
+ self.cwvl = 0.4440124
+ self.rsr = RelativeSpectralResponseTestData()
+ self._res1 = da.from_array(TEST_RAYLEIGH_RESULT1, chunks=2)
+ self._res2 = da.from_array(TEST_RAYLEIGH_RESULT2, chunks=2)
+ self._res3 = da.from_array(TEST_RAYLEIGH_RESULT3, chunks=2)
+
+ self.rayl = da.from_array(TEST_RAYLEIGH_LUT, chunks=(10, 10, 10, 10))
+ self.wvl_coord = TEST_RAYLEIGH_WVL_COORD
+ self.azid_coord = da.from_array(TEST_RAYLEIGH_AZID_COORD, chunks=(1000,))
+ self.sunz_sec_coord = da.from_array(TEST_RAYLEIGH_SUNZ_COORD,
+ chunks=(1000,))
+ self.satz_sec_coord = da.from_array(TEST_RAYLEIGH_SATZ_COORD,
+ chunks=(1000,))
+
+ # mymock:
+ with patch('pyspectral.rayleigh.RelativeSpectralResponse') as mymock:
+ instance = mymock.return_value
+ instance.rsr = RelativeSpectralResponseTestData().rsr
+ instance.unit = '1e-6 m'
+ instance.si_scale = 1e-6
+
+ self.viirs_rayleigh = rayleigh.Rayleigh('NOAA-20', 'viirs', atmosphere='midlatitude summer')
+
+ @patch('os.path.exists')
+ @patch('pyspectral.utils.download_luts')
+ @patch('pyspectral.rayleigh.get_reflectance_lut_from_file')
+ @patch('pyspectral.rsr_reader.RelativeSpectralResponse.'
+ '_get_rsr_data_version')
+ @patch('pyspectral.rayleigh.Rayleigh.get_effective_wavelength')
+ def test_dask_cliping_angles_with_nans(self, get_effective_wvl,
+ get_rsr_version, get_reflectance_lut_from_file,
+ download_luts, exists):
+ """Test the cliping of angles outside coordinate range - with nan's in input."""
+ get_reflectance_lut_from_file.return_value = (self.rayl, self.wvl_coord, self.azid_coord,
+ self.satz_sec_coord, self.sunz_sec_coord)
+ download_luts.return_code = None
+ exists.return_code = True
+ get_rsr_version.return_code = RSR_DATA_VERSION
+ get_effective_wvl.return_value = self.cwvl
+
+ zenith_angle = da.array([79., 69., 32., np.nan])
+ result = self.viirs_rayleigh._clip_angles_inside_coordinate_range(zenith_angle, 2.75)
+
+ np.testing.assert_allclose(result, TEST_ZENITH_ANGLES_RESULTS)
+
+ @patch('os.path.exists')
+ @patch('pyspectral.utils.download_luts')
+ @patch('pyspectral.rayleigh.get_reflectance_lut_from_file')
+ @patch('pyspectral.rsr_reader.RelativeSpectralResponse.'
+ '_get_rsr_data_version')
+ @patch('pyspectral.rayleigh.Rayleigh.get_effective_wavelength')
+ def test_get_reflectance_dask_redband_outside_clip(self, get_effective_wvl,
+ get_rsr_version, get_reflectance_lut_from_file,
+ download_luts, exists):
+ """Test getting the reflectance correction with dask inputs - using red band reflections outside 20-100."""
+ get_reflectance_lut_from_file.return_value = (self.rayl, self.wvl_coord, self.azid_coord,
+ self.satz_sec_coord, self.sunz_sec_coord)
+ download_luts.return_code = None
+ exists.return_code = True
+ get_rsr_version.return_code = RSR_DATA_VERSION
+ get_effective_wvl.return_value = self.cwvl
+
+ sun_zenith = da.array([67., 32.])
+ sat_zenith = da.array([45., 18.])
+ azidiff = da.array([150., 110.])
+ redband_refl = da.array([108., -0.5])
+ refl_corr = self.viirs_rayleigh.get_reflectance(sun_zenith, sat_zenith, azidiff, 'M2', redband_refl)
+ np.testing.assert_allclose(refl_corr, TEST_RAYLEIGH_RESULT4)
+ self.assertIsInstance(refl_corr, da.Array)
+
+ @patch('os.path.exists')
+ @patch('pyspectral.utils.download_luts')
+ @patch('pyspectral.rayleigh.get_reflectance_lut_from_file')
+ @patch('pyspectral.rsr_reader.RelativeSpectralResponse.'
+ '_get_rsr_data_version')
+ @patch('pyspectral.rayleigh.Rayleigh.get_effective_wavelength')
+ def test_get_reflectance_dask(self, get_effective_wvl,
+ get_rsr_version, get_reflectance_lut_from_file,
+ download_luts, exists):
+ """Test getting the reflectance correction with dask inputs."""
+ get_reflectance_lut_from_file.return_value = (self.rayl, self.wvl_coord, self.azid_coord,
+ self.satz_sec_coord, self.sunz_sec_coord)
+ download_luts.return_code = None
+ exists.return_code = True
+ get_rsr_version.return_code = RSR_DATA_VERSION
+ get_effective_wvl.return_value = self.cwvl
+
+ sun_zenith = da.array([67., 32.])
+ sat_zenith = da.array([45., 18.])
+ azidiff = da.array([150., 110.])
+ redband_refl = da.array([14., 5.])
+ refl_corr = self.viirs_rayleigh.get_reflectance(sun_zenith, sat_zenith, azidiff, 'M2', redband_refl)
+ np.testing.assert_allclose(refl_corr, TEST_RAYLEIGH_RESULT1)
+ self.assertIsInstance(refl_corr, da.Array)
+
+ sun_zenith = da.array([60., 20.])
+ sat_zenith = da.array([49., 26.])
+ azidiff = da.array([140., 130.])
+ redband_refl = da.array([12., 8.])
+ refl_corr = self.viirs_rayleigh.get_reflectance(sun_zenith, sat_zenith, azidiff, 'M2', redband_refl)
+ np.testing.assert_allclose(refl_corr, TEST_RAYLEIGH_RESULT2)
+ self.assertIsInstance(refl_corr, da.Array)
+
+ @patch('os.path.exists')
+ @patch('pyspectral.utils.download_luts')
+ @patch('pyspectral.rayleigh.get_reflectance_lut_from_file')
+ @patch('pyspectral.rsr_reader.RelativeSpectralResponse.'
+ '_get_rsr_data_version')
+ @patch('pyspectral.rayleigh.Rayleigh.get_effective_wavelength')
+ def test_get_reflectance_numpy_dask(self, get_effective_wvl,
+ get_rsr_version, get_reflectance_lut_from_file,
+ download_luts, exists):
+ """Test getting the reflectance correction with dask inputs."""
+ get_reflectance_lut_from_file.return_value = (self.rayl, self.wvl_coord, self.azid_coord,
+ self.satz_sec_coord, self.sunz_sec_coord)
+ download_luts.return_code = None
+ exists.return_code = True
+ get_rsr_version.return_code = RSR_DATA_VERSION
+ get_effective_wvl.return_value = self.cwvl
+
+ sun_zenith = np.array([67., 32.])
+ sat_zenith = np.array([45., 18.])
+ azidiff = np.array([150., 110.])
+ redband_refl = np.array([14., 5.])
+ refl_corr = self.viirs_rayleigh.get_reflectance(sun_zenith, sat_zenith, azidiff, 'M2', redband_refl)
+ np.testing.assert_allclose(refl_corr, TEST_RAYLEIGH_RESULT1)
+ self.assertIsInstance(refl_corr, np.ndarray)
+
+ sun_zenith = np.array([60., 20.])
+ sat_zenith = np.array([49., 26.])
+ azidiff = np.array([140., 130.])
+ redband_refl = np.array([12., 8.])
+ refl_corr = self.viirs_rayleigh.get_reflectance(sun_zenith, sat_zenith, azidiff, 'M2', redband_refl)
+ np.testing.assert_allclose(refl_corr, TEST_RAYLEIGH_RESULT2)
+ self.assertIsInstance(refl_corr, np.ndarray)
+
+
class TestRayleigh(unittest.TestCase):
"""Class for testing pyspectral.rayleigh."""
@@ -101,6 +240,12 @@ class TestRayleigh(unittest.TestCase):
self._res2 = da.from_array(TEST_RAYLEIGH_RESULT2, chunks=2)
self._res3 = da.from_array(TEST_RAYLEIGH_RESULT3, chunks=2)
+ self.rayl = TEST_RAYLEIGH_LUT
+ self.wvl_coord = TEST_RAYLEIGH_WVL_COORD
+ self.azid_coord = TEST_RAYLEIGH_AZID_COORD
+ self.sunz_sec_coord = TEST_RAYLEIGH_SUNZ_COORD
+ self.satz_sec_coord = TEST_RAYLEIGH_SATZ_COORD
+
# mymock:
with patch('pyspectral.rayleigh.RelativeSpectralResponse') as mymock:
instance = mymock.return_value
@@ -163,107 +308,96 @@ class TestRayleigh(unittest.TestCase):
this = rayleigh.Rayleigh('NOAA-19', 'avhrr/3', atmosphere='tropical')
self.assertTrue(this.sensor == 'avhrr3')
- @patch('pyspectral.rayleigh.HAVE_DASK', False)
@patch('os.path.exists')
@patch('pyspectral.utils.download_luts')
- @patch('pyspectral.rayleigh.get_reflectance_lut')
- @patch('pyspectral.rsr_reader.RelativeSpectralResponse._get_rsr_data_version')
+ @patch('pyspectral.rayleigh.get_reflectance_lut_from_file')
+ @patch('pyspectral.rsr_reader.RelativeSpectralResponse.'
+ '_get_rsr_data_version')
@patch('pyspectral.rayleigh.Rayleigh.get_effective_wavelength')
- def test_get_reflectance(self, get_effective_wvl,
- get_rsr_version, get_reflectance_lut, download_luts, exists):
- """Test getting the reflectance correction."""
- rayl = TEST_RAYLEIGH_LUT
- wvl_coord = TEST_RAYLEIGH_WVL_COORD
- azid_coord = TEST_RAYLEIGH_AZID_COORD
- sunz_sec_coord = TEST_RAYLEIGH_SUNZ_COORD
- satz_sec_coord = TEST_RAYLEIGH_SATZ_COORD
-
- get_reflectance_lut.return_value = (rayl, wvl_coord, azid_coord,
- satz_sec_coord, sunz_sec_coord)
+ def test_cliping_angles_with_nans(self, get_effective_wvl,
+ get_rsr_version, get_reflectance_lut_from_file,
+ download_luts, exists):
+ """Test the cliping of angles outside coordinate range - with nan's in input."""
+ get_reflectance_lut_from_file.return_value = (self.rayl, self.wvl_coord, self.azid_coord,
+ self.satz_sec_coord, self.sunz_sec_coord)
download_luts.return_code = None
exists.return_code = True
get_rsr_version.return_code = RSR_DATA_VERSION
get_effective_wvl.return_value = self.cwvl
- sun_zenith = np.array([67., 32.])
- sat_zenith = np.array([45., 18.])
- azidiff = np.array([150., 110.])
- blueband = np.array([14., 5.])
- retv = self.viirs_rayleigh.get_reflectance(
- sun_zenith, sat_zenith, azidiff, 'M2', blueband)
- self.assertTrue(np.allclose(retv, TEST_RAYLEIGH_RESULT1))
+ zenith_angle = np.array([79., 69., 32., np.nan])
+ result = self.viirs_rayleigh._clip_angles_inside_coordinate_range(zenith_angle, 2.75)
- sun_zenith = np.array([60., 20.])
- sat_zenith = np.array([49., 26.])
- azidiff = np.array([140., 130.])
- blueband = np.array([12., 8.])
- retv = self.viirs_rayleigh.get_reflectance(
- sun_zenith, sat_zenith, azidiff, 'M2', blueband)
- self.assertTrue(np.allclose(retv, TEST_RAYLEIGH_RESULT2))
+ np.testing.assert_allclose(result, TEST_ZENITH_ANGLES_RESULTS)
+
+ def test_rayleigh_reduction(self):
+ """Test the code that reduces Rayleigh correction for high zenith angles."""
+
+ # Test the Rayleigh reduction code
+ sun_zenith = np.array([70., 65., 60.])
+ in_rayleigh = [50, 50, 50]
+ # Test case where no reduction is done.
+ retv = self.viirs_rayleigh.reduce_rayleigh_highzenith(sun_zenith, in_rayleigh, 70., 90., 1)
+ self.assertTrue(np.allclose(retv, in_rayleigh))
+ # Test case where moderate reduction is performed.
+ retv = self.viirs_rayleigh.reduce_rayleigh_highzenith(sun_zenith, in_rayleigh, 30., 90., 1)
+ self.assertTrue(np.allclose(retv, TEST_RAYLEIGH_RESULT_R1))
+ # Test case where extreme reduction is performed.
+ retv = self.viirs_rayleigh.reduce_rayleigh_highzenith(sun_zenith, in_rayleigh, 30., 90., 1.5)
+ self.assertTrue(np.allclose(retv, TEST_RAYLEIGH_RESULT_R2))
+ @patch('pyspectral.rayleigh.HAVE_DASK', False)
@patch('os.path.exists')
@patch('pyspectral.utils.download_luts')
- @patch('pyspectral.rayleigh.get_reflectance_lut')
- @patch('pyspectral.rsr_reader.RelativeSpectralResponse.'
- '_get_rsr_data_version')
+ @patch('pyspectral.rayleigh.get_reflectance_lut_from_file')
+ @patch('pyspectral.rsr_reader.RelativeSpectralResponse._get_rsr_data_version')
@patch('pyspectral.rayleigh.Rayleigh.get_effective_wavelength')
- def test_get_reflectance_dask(self, get_effective_wvl,
- get_rsr_version, get_reflectance_lut,
- download_luts, exists):
- """Test getting the reflectance correction with dask inputs."""
- rayl = da.from_array(TEST_RAYLEIGH_LUT, chunks=(10, 10, 10, 10))
- wvl_coord = da.from_array(TEST_RAYLEIGH_WVL_COORD,
- chunks=(100,)).persist()
- azid_coord = da.from_array(TEST_RAYLEIGH_AZID_COORD, chunks=(1000,))
- sunz_sec_coord = da.from_array(TEST_RAYLEIGH_SUNZ_COORD,
- chunks=(1000,))
- satz_sec_coord = da.from_array(TEST_RAYLEIGH_SATZ_COORD,
- chunks=(1000,))
-
- get_reflectance_lut.return_value = (rayl, wvl_coord, azid_coord,
- satz_sec_coord, sunz_sec_coord)
+ def test_get_reflectance_redband_outside_clip(self, get_effective_wvl,
+ get_rsr_version, get_reflectance_lut_from_file,
+ download_luts, exists):
+ """Test getting the reflectance correction - using red band reflections outside 20 to 100."""
+ get_reflectance_lut_from_file.return_value = (self.rayl, self.wvl_coord, self.azid_coord,
+ self.satz_sec_coord, self.sunz_sec_coord)
download_luts.return_code = None
exists.return_code = True
get_rsr_version.return_code = RSR_DATA_VERSION
get_effective_wvl.return_value = self.cwvl
- sun_zenith = da.from_array(np.array([67., 32.]), chunks=2)
- sat_zenith = da.from_array(np.array([45., 18.]), chunks=2)
- azidiff = da.from_array(np.array([150., 110.]), chunks=2)
- blueband = da.from_array(np.array([14., 5.]), chunks=2)
- retv = self.viirs_rayleigh.get_reflectance(sun_zenith, sat_zenith, azidiff, 'M2', blueband)
- self.assertTrue(np.allclose(retv, TEST_RAYLEIGH_RESULT1))
- self.assertIsInstance(retv, da.Array)
-
- sun_zenith = da.from_array(np.array([60., 20.]), chunks=2)
- sat_zenith = da.from_array(np.array([49., 26.]), chunks=2)
- azidiff = da.from_array(np.array([140., 130.]), chunks=2)
- blueband = da.from_array(np.array([12., 8.]), chunks=2)
- retv = self.viirs_rayleigh.get_reflectance(sun_zenith, sat_zenith, azidiff, 'M2', blueband)
- self.assertTrue(np.allclose(retv, TEST_RAYLEIGH_RESULT2))
- self.assertIsInstance(retv, da.Array)
+ sun_zenith = np.array([67., 32.])
+ sat_zenith = np.array([45., 18.])
+ azidiff = np.array([150., 110.])
+ redband_refl = np.array([100., 20.])
+ refl_corr1 = self.viirs_rayleigh.get_reflectance(
+ sun_zenith, sat_zenith, azidiff, 'M2', redband_refl)
+
+ np.testing.assert_allclose(refl_corr1, TEST_RAYLEIGH_RESULT4)
+ rng = np.random.default_rng(12345)
+ rints_low = rng.integers(low=-10, high=20, size=2).astype('float')
+ rints_high = rng.integers(low=100, high=200, size=2).astype('float')
+
+ redband_refl = np.array([rints_high[0], rints_low[0]])
+ refl_corr2 = self.viirs_rayleigh.get_reflectance(
+ sun_zenith, sat_zenith, azidiff, 'M2', redband_refl)
+
+ redband_refl = np.array([rints_high[1], rints_low[1]])
+ refl_corr3 = self.viirs_rayleigh.get_reflectance(
+ sun_zenith, sat_zenith, azidiff, 'M2', redband_refl)
+
+ np.testing.assert_allclose(refl_corr1, refl_corr2)
+ np.testing.assert_allclose(refl_corr2, refl_corr3)
+
+ @patch('pyspectral.rayleigh.HAVE_DASK', False)
@patch('os.path.exists')
@patch('pyspectral.utils.download_luts')
- @patch('pyspectral.rayleigh.get_reflectance_lut')
- @patch('pyspectral.rsr_reader.RelativeSpectralResponse.'
- '_get_rsr_data_version')
+ @patch('pyspectral.rayleigh.get_reflectance_lut_from_file')
+ @patch('pyspectral.rsr_reader.RelativeSpectralResponse._get_rsr_data_version')
@patch('pyspectral.rayleigh.Rayleigh.get_effective_wavelength')
- def test_get_reflectance_numpy_dask(self, get_effective_wvl,
- get_rsr_version, get_reflectance_lut,
- download_luts, exists):
- """Test getting the reflectance correction with dask inputs."""
- rayl = da.from_array(TEST_RAYLEIGH_LUT, chunks=(10, 10, 10, 10))
- wvl_coord = da.from_array(TEST_RAYLEIGH_WVL_COORD,
- chunks=(100,)).persist()
- azid_coord = da.from_array(TEST_RAYLEIGH_AZID_COORD, chunks=(1000,))
- sunz_sec_coord = da.from_array(TEST_RAYLEIGH_SUNZ_COORD,
- chunks=(1000,))
- satz_sec_coord = da.from_array(TEST_RAYLEIGH_SATZ_COORD,
- chunks=(1000,))
-
- get_reflectance_lut.return_value = (rayl, wvl_coord, azid_coord,
- satz_sec_coord, sunz_sec_coord)
+ def test_get_reflectance(self, get_effective_wvl,
+ get_rsr_version, get_reflectance_lut_from_file, download_luts, exists):
+ """Test getting the reflectance correction."""
+ get_reflectance_lut_from_file.return_value = (self.rayl, self.wvl_coord, self.azid_coord,
+ self.satz_sec_coord, self.sunz_sec_coord)
download_luts.return_code = None
exists.return_code = True
get_rsr_version.return_code = RSR_DATA_VERSION
@@ -272,33 +406,28 @@ class TestRayleigh(unittest.TestCase):
sun_zenith = np.array([67., 32.])
sat_zenith = np.array([45., 18.])
azidiff = np.array([150., 110.])
- blueband = np.array([14., 5.])
- retv = self.viirs_rayleigh.get_reflectance(sun_zenith, sat_zenith, azidiff, 'M2', blueband)
- self.assertTrue(np.allclose(retv, TEST_RAYLEIGH_RESULT1))
- self.assertIsInstance(retv, np.ndarray)
+ redband_refl = np.array([14., 5.])
+ refl_corr = self.viirs_rayleigh.get_reflectance(
+ sun_zenith, sat_zenith, azidiff, 'M2', redband_refl)
+ np.testing.assert_allclose(refl_corr, TEST_RAYLEIGH_RESULT1)
sun_zenith = np.array([60., 20.])
sat_zenith = np.array([49., 26.])
azidiff = np.array([140., 130.])
- blueband = np.array([12., 8.])
- retv = self.viirs_rayleigh.get_reflectance(sun_zenith, sat_zenith, azidiff, 'M2', blueband)
- self.assertTrue(np.allclose(retv, TEST_RAYLEIGH_RESULT2))
- self.assertIsInstance(retv, np.ndarray)
+ redband_refl = np.array([12., 8.])
+ refl_corr = self.viirs_rayleigh.get_reflectance(
+ sun_zenith, sat_zenith, azidiff, 'M2', redband_refl)
+
+ np.testing.assert_allclose(refl_corr, TEST_RAYLEIGH_RESULT2)
@patch('pyspectral.rayleigh.HAVE_DASK', False)
@patch('os.path.exists')
@patch('pyspectral.utils.download_luts')
- @patch('pyspectral.rayleigh.get_reflectance_lut')
- def test_get_reflectance_no_rsr(self, get_reflectance_lut, download_luts, exists):
+ @patch('pyspectral.rayleigh.get_reflectance_lut_from_file')
+ def test_get_reflectance_no_rsr(self, get_reflectance_lut_from_file, download_luts, exists):
"""Test getting the reflectance correction, simulating that we have no RSR data."""
- rayl = TEST_RAYLEIGH_LUT
- wvl_coord = TEST_RAYLEIGH_WVL_COORD
- azid_coord = TEST_RAYLEIGH_AZID_COORD
- sunz_sec_coord = TEST_RAYLEIGH_SUNZ_COORD
- satz_sec_coord = TEST_RAYLEIGH_SATZ_COORD
-
- get_reflectance_lut.return_value = (rayl, wvl_coord, azid_coord,
- satz_sec_coord, sunz_sec_coord)
+ get_reflectance_lut_from_file.return_value = (self.rayl, self.wvl_coord, self.azid_coord,
+ self.satz_sec_coord, self.sunz_sec_coord)
download_luts.return_code = None
exists.return_code = True
@@ -311,8 +440,8 @@ class TestRayleigh(unittest.TestCase):
sun_zenith = np.array([50., 10.])
sat_zenith = np.array([39., 16.])
azidiff = np.array([170., 110.])
- blueband = np.array([29., 12.])
+ redband_refl = np.array([29., 12.])
ufo = rayleigh.Rayleigh('UFO', 'unknown')
- retv = ufo.get_reflectance(sun_zenith, sat_zenith, azidiff, 0.441, blueband)
- self.assertTrue(np.allclose(retv, TEST_RAYLEIGH_RESULT3))
+ refl_corr = ufo.get_reflectance(sun_zenith, sat_zenith, azidiff, 0.441, redband_refl)
+ np.testing.assert_allclose(refl_corr, TEST_RAYLEIGH_RESULT3)
=====================================
pyspectral/tests/test_rsr_reader.py
=====================================
@@ -1,11 +1,12 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
-# Copyright (c) 2017-2020 Pytroll developers
+# Copyright (c) 2017-2021 Pytroll developers
#
# Author(s):
#
-# Adam.Dybbroe <a000680 at c20671.ad.smhi.se>
+# Adam Dybbroe <adam.dybbroe at smhi.se>
+# Simon Proud
#
# 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
@@ -22,27 +23,18 @@
"""Unit testing the generic rsr hdf5 reader."""
-import sys
import os.path
import numpy as np
import xarray as xr
+import unittest
+from unittest.mock import patch
import pytest
-from pyspectral.rsr_reader import RelativeSpectralResponse
+
+from pyspectral.rsr_reader import RelativeSpectralResponse, RSRDict
from pyspectral.utils import WAVE_NUMBER
from pyspectral.utils import RSR_DATA_VERSION
from pyspectral.tests.unittest_helpers import assertNumpyArraysEqual
-
-if sys.version_info < (2, 7):
- import unittest2 as unittest
-else:
- import unittest
-
-if sys.version_info < (3,):
- from mock import patch
-else:
- from unittest.mock import patch
-
TEST_RSR = {'20': {}, }
TEST_RSR['20']['det-1'] = {}
TEST_RSR['20']['det-1']['central_wavelength'] = 3.75
@@ -174,7 +166,10 @@ class TestRsrReader(unittest.TestCase):
class MyHdf5Mock(object):
+ """A Mock for the RSR data normally stored in a HDF5 file."""
+
def __init__(self, attrs):
+ """Initialize the mock class."""
self.attrs = attrs
@@ -237,7 +232,6 @@ class TestPopulateRSRObject(unittest.TestCase):
@patch('pyspectral.rsr_reader.RelativeSpectralResponse._check_instrument')
def test_create_rsr_instance(self, check_instrument, get_filename, check_filename_exist, load):
"""Test creating the instance."""
-
load.return_value = None
check_filename_exist.return_value = None
get_filename.return_value = None
@@ -256,7 +250,6 @@ class TestPopulateRSRObject(unittest.TestCase):
@patch('pyspectral.rsr_reader.RelativeSpectralResponse._check_instrument')
def test_set_description(self, check_instrument, get_filename, check_filename_exist, load):
"""Test setting the description."""
-
load.return_value = None
check_filename_exist.return_value = None
get_filename.return_value = None
@@ -278,7 +271,6 @@ class TestPopulateRSRObject(unittest.TestCase):
@patch('pyspectral.rsr_reader.RelativeSpectralResponse._check_instrument')
def test_set_platform_name(self, check_instrument, get_filename, check_filename_exist, load):
"""Test setting the platform name."""
-
load.return_value = None
check_filename_exist.return_value = None
get_filename.return_value = None
@@ -323,7 +315,6 @@ class TestPopulateRSRObject(unittest.TestCase):
@patch('pyspectral.rsr_reader.RelativeSpectralResponse._check_instrument')
def test_set_instrument(self, check_instrument, get_filename, check_filename_exist, load):
"""Test setting the instrument name."""
-
load.return_value = None
check_filename_exist.return_value = None
get_filename.return_value = None
@@ -353,7 +344,6 @@ class TestPopulateRSRObject(unittest.TestCase):
@patch('pyspectral.rsr_reader.RelativeSpectralResponse._check_instrument')
def test_set_band_names(self, check_instrument, get_filename, check_filename_exist, load):
"""Test setting the band names."""
-
load.return_value = None
check_filename_exist.return_value = None
get_filename.return_value = None
@@ -372,7 +362,6 @@ class TestPopulateRSRObject(unittest.TestCase):
check_instrument, get_filename,
check_filename_exist, load):
"""Test setting the band specific central wavelength for a detector."""
-
load.return_value = None
check_filename_exist.return_value = None
get_filename.return_value = None
@@ -399,7 +388,6 @@ class TestPopulateRSRObject(unittest.TestCase):
check_instrument, get_filename,
check_filename_exist, load):
"""Test setting the band wavelengths for a detector."""
-
load.return_value = None
check_filename_exist.return_value = None
get_filename.return_value = None
@@ -428,7 +416,6 @@ class TestPopulateRSRObject(unittest.TestCase):
check_instrument, get_filename,
check_filename_exist, load):
"""Test setting the band responses for a detector."""
-
load.return_value = None
check_filename_exist.return_value = None
get_filename.return_value = None
@@ -447,3 +434,18 @@ class TestPopulateRSRObject(unittest.TestCase):
expected = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
assertNumpyArraysEqual(test_rsr.rsr['M1']['det-1']['response'].data, expected)
+
+ def test_rsr_dict(self):
+ """Test finding correct band names from utils dicts."""
+ test_rsr = RSRDict(instrument='viirs')
+ test_rsr['M1'] = 0
+ test_rsr['VIS0.6'] = 1
+ # Check for correct band name
+ self.assertEqual(test_rsr['M1'], 0)
+ # Check for alternative band name on same instrument
+ self.assertEqual(test_rsr['M01'], 0)
+ # Check for generic band name
+ self.assertEqual(test_rsr['VIS006'], 1)
+ # Check exception raised if incorrect band name given
+ with self.assertRaises(KeyError):
+ print('d', test_rsr['VIS030'])
=====================================
pyspectral/tests/test_utils.py
=====================================
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
-# Copyright (c) 2014-2020 Pytroll developers
+# Copyright (c) 2014-2021 Pytroll developers
#
# Author(s):
#
@@ -150,10 +150,10 @@ class TestUtils(unittest.TestCase):
self.assertEqual(bname, ['ch13', 'ch14'])
# uses generic channel mapping where '20' -> 'ch20'
- bandname = utils.get_bandname_from_wavelength('abi', 3.7, TEST_RSR)
+ bandname = utils.get_bandname_from_wavelength('ufo', 3.7, TEST_RSR)
self.assertEqual(bandname, 'ch20')
- bandname = utils.get_bandname_from_wavelength('abi', 3.0, TEST_RSR)
+ bandname = utils.get_bandname_from_wavelength('ufo', 3.0, TEST_RSR)
self.assertIsNone(bandname)
@staticmethod
=====================================
pyspectral/utils.py
=====================================
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
-# Copyright (c) 2014-2020 Pytroll developers
+# Copyright (c) 2014-2021 Pytroll developers
#
# Author(s):
#
@@ -28,136 +28,13 @@ import logging
import tempfile
import numpy as np
from pyspectral.config import get_config
+from pyspectral.bandnames import BANDNAMES
LOG = logging.getLogger(__name__)
WAVE_LENGTH = 'wavelength'
WAVE_NUMBER = 'wavenumber'
-BANDNAMES = {}
-BANDNAMES['generic'] = {'VIS006': 'VIS0.6',
- 'VIS008': 'VIS0.8',
- 'IR_016': 'NIR1.6',
- 'IR_039': 'IR3.9',
- 'WV_062': 'IR6.2',
- 'WV_073': 'IR7.3',
- 'IR_087': 'IR8.7',
- 'IR_097': 'IR9.7',
- 'IR_108': 'IR10.8',
- 'IR_120': 'IR12.0',
- 'IR_134': 'IR13.4',
- 'HRV': 'HRV',
- 'I01': 'I1',
- 'I02': 'I2',
- 'I03': 'I3',
- 'I04': 'I4',
- 'I05': 'I5',
- 'M01': 'M1',
- 'M02': 'M2',
- 'M03': 'M3',
- 'M04': 'M4',
- 'M05': 'M5',
- 'M06': 'M6',
- 'M07': 'M7',
- 'M08': 'M8',
- 'M09': 'M9',
- 'C01': 'ch1',
- 'C02': 'ch2',
- 'C03': 'ch3',
- 'C04': 'ch4',
- 'C05': 'ch5',
- 'C06': 'ch6',
- 'C07': 'ch7',
- 'C08': 'ch8',
- 'C09': 'ch9',
- 'C10': 'ch10',
- 'C11': 'ch11',
- 'C12': 'ch12',
- 'C13': 'ch13',
- 'C14': 'ch14',
- 'C15': 'ch15',
- 'C16': 'ch16',
- }
-# handle arbitrary channel numbers
-for chan_num in range(1, 37):
- BANDNAMES['generic'][str(chan_num)] = 'ch{:d}'.format(chan_num)
-
-# MODIS RSR files were made before 'chX' became standard in pyspectral
-BANDNAMES['modis'] = {str(chan_num): str(chan_num) for chan_num in range(1, 37)}
-
-BANDNAMES['avhrr-3'] = {'1': 'ch1',
- '2': 'ch2',
- '3b': 'ch3b',
- '3a': 'ch3a',
- '4': 'ch4',
- '5': 'ch5'}
-
-BANDNAMES['ahi'] = {'B01': 'ch1',
- 'B02': 'ch2',
- 'B03': 'ch3',
- 'B04': 'ch4',
- 'B05': 'ch5',
- 'B06': 'ch6',
- 'B07': 'ch7',
- 'B08': 'ch8',
- 'B09': 'ch9',
- 'B10': 'ch10',
- 'B11': 'ch11',
- 'B12': 'ch12',
- 'B13': 'ch13',
- 'B14': 'ch14',
- 'B15': 'ch15',
- 'B16': 'ch16'
- }
-
-BANDNAMES['ami'] = {'VI004': 'ch1',
- 'VI005': 'ch2',
- 'VI006': 'ch3',
- 'VI008': 'ch4',
- 'NR013': 'ch5',
- 'NR016': 'ch6',
- 'SW038': 'ch7',
- 'WV063': 'ch8',
- 'WV069': 'ch9',
- 'WV073': 'ch10',
- 'IR087': 'ch11',
- 'IR096': 'ch12',
- 'IR105': 'ch13',
- 'IR112': 'ch14',
- 'IR123': 'ch15',
- 'IR133': 'ch16'
- }
-
-BANDNAMES['fci'] = {'vis_04': 'ch1',
- 'vis_05': 'ch2',
- 'vis_06': 'ch3',
- 'vis_08': 'ch4',
- 'vis_09': 'ch5',
- 'nir_13': 'ch6',
- 'nir_16': 'ch7',
- 'nir_22': 'ch8',
- 'ir_38': 'ch9',
- 'wv_63': 'ch10',
- 'wv_73': 'ch11',
- 'ir_87': 'ch12',
- 'ir_97': 'ch13',
- 'ir_105': 'ch14',
- 'ir_123': 'ch15',
- 'ir_133': 'ch16'
- }
-
-BANDNAMES['slstr'] = {'S1': 'ch1',
- 'S2': 'ch2',
- 'S3': 'ch3',
- 'S4': 'ch4',
- 'S5': 'ch5',
- 'S6': 'ch6',
- 'S7': 'ch7',
- 'S8': 'ch8',
- 'S9': 'ch9',
- 'F1': 'ch7',
- 'F2': 'ch8',
- }
INSTRUMENTS = {'NOAA-19': 'avhrr/3',
'NOAA-18': 'avhrr/3',
@@ -193,11 +70,10 @@ INSTRUMENTS = {'NOAA-19': 'avhrr/3',
'MTG-I1': 'fci'
}
-
-HTTP_PYSPECTRAL_RSR = "https://zenodo.org/record/4305549/files/pyspectral_rsr_data.tgz"
+HTTP_PYSPECTRAL_RSR = "https://zenodo.org/record/5797957/files/pyspectral_rsr_data.tgz"
RSR_DATA_VERSION_FILENAME = "PYSPECTRAL_RSR_VERSION"
-RSR_DATA_VERSION = "v1.0.16"
+RSR_DATA_VERSION = "v1.0.17"
ATM_CORRECTION_LUT_VERSION = {}
ATM_CORRECTION_LUT_VERSION['antarctic_aerosol'] = {'version': 'v1.0.1',
@@ -209,7 +85,7 @@ ATM_CORRECTION_LUT_VERSION['continental_clean_aerosol'] = {'version': 'v1.0.1',
ATM_CORRECTION_LUT_VERSION['continental_polluted_aerosol'] = {'version': 'v1.0.1',
'filename': 'PYSPECTRAL_ATM_CORR_LUT_CPA'}
ATM_CORRECTION_LUT_VERSION['desert_aerosol'] = {'version': 'v1.0.1',
- 'filename': 'PYSPECTRAL_ATM_CORR_LUT_DA'}
+ 'filename': 'PYSPECTRAL_ATM_CORR_LUT_DA'}
ATM_CORRECTION_LUT_VERSION['marine_clean_aerosol'] = {'version': 'v1.0.1',
'filename': 'PYSPECTRAL_ATM_CORR_LUT_MCA'}
ATM_CORRECTION_LUT_VERSION['marine_polluted_aerosol'] = {'version': 'v1.0.1',
@@ -223,7 +99,6 @@ ATM_CORRECTION_LUT_VERSION['urban_aerosol'] = {'version': 'v1.0.1',
ATM_CORRECTION_LUT_VERSION['rayleigh_only'] = {'version': 'v1.0.1',
'filename': 'PYSPECTRAL_ATM_CORR_LUT_RO'}
-
AEROSOL_TYPES = ['antarctic_aerosol', 'continental_average_aerosol',
'continental_clean_aerosol', 'continental_polluted_aerosol',
'desert_aerosol', 'marine_clean_aerosol',
@@ -234,7 +109,6 @@ ATMOSPHERES = {'subarctic summer': 4, 'subarctic winter': 5,
'midlatitude summer': 6, 'midlatitude winter': 7,
'tropical': 8, 'us-standard': 9}
-
HTTPS_RAYLEIGH_LUTS = {}
URL_PREFIX = "https://zenodo.org/record/1288441/files/pyspectral_atm_correction_luts"
for atype in AEROSOL_TYPES:
@@ -242,7 +116,6 @@ for atype in AEROSOL_TYPES:
url = "{prefix}_{name}.tgz".format(prefix=URL_PREFIX, name=name)
HTTPS_RAYLEIGH_LUTS[atype] = url
-
CONF = get_config()
LOCAL_RSR_DIR = CONF.get('rsr_dir')
LOCAL_RAYLEIGH_DIR = CONF.get('rayleigh_dir')
@@ -470,7 +343,7 @@ def download_luts(**kwargs):
else:
aerosol_types = HTTPS_RAYLEIGH_LUTS.keys()
- chunk_size = 1024*1024 # 1 MB
+ chunk_size = 1024 * 1024 # 1 MB
for subname in aerosol_types:
@@ -582,8 +455,10 @@ def get_wave_range(in_chan, threshold=0.15):
def convert2str(value):
"""Convert a value to string.
+
Args:
value: Either a str, bytes or 1-element numpy array
+
"""
value = bytes2string(value)
return np2str(value)
@@ -591,11 +466,13 @@ def convert2str(value):
def np2str(value):
"""Convert an `numpy.string_` to str.
+
Args:
value (ndarray): scalar or 1-element numpy array to convert
Raises:
ValueError: if value is array larger than 1-element or it is not of
type `numpy.string_` or it is not a numpy array
+
"""
if isinstance(value, str):
return value
=====================================
rsr_convert_scripts/abi_rsr.py
=====================================
@@ -1,11 +1,11 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
-# Copyright (c) 2016 - 2018 Pytroll developers
+# Copyright (c) 2016 - 2021 Pytroll developers
#
# Author(s):
#
-# Adam.Dybbroe <adam.dybbroe at smhi.se>
+# Adam Dybbroe <Firstname.Lastname at smhi.se>
#
# 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
@@ -20,7 +20,9 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-"""Reading the original raw GOES-R ABI spectral responses and generating the
+"""Read raw GOES-R series ABI RSR and generate HDF5 files.
+
+Reading the original raw GOES-R ABI spectral responses and generating the
internal pyspectral formatet hdf5.
https://ncc.nesdis.noaa.gov/GOESR/ABI.php
@@ -42,14 +44,10 @@ ABI_BAND_NAMES = ['ch1', 'ch2', 'ch3', 'ch4',
class AbiRSR(InstrumentRSR):
-
- """Class for GOES-R ABI RSR"""
+ """Class for GOES-R ABI RSR."""
def __init__(self, bandname, platform_name):
- """
- Read the GOES-R ABI relative spectral responses for all channels..
-
- """
+ """Read the GOES-R ABI relative spectral responses for all channels."""
super(AbiRSR, self).__init__(bandname, platform_name,
ABI_BAND_NAMES)
@@ -69,27 +67,21 @@ class AbiRSR(InstrumentRSR):
self.filename = self.requested_band_filename
def _load(self, scale=1.0):
- """Load the ABI relative spectral responses
- """
-
+ """Load the ABI relative spectral responses."""
LOG.debug("File: %s", str(self.requested_band_filename))
data = np.genfromtxt(self.requested_band_filename,
unpack=True,
- names=['wavelength',
- 'wavenumber',
- 'response'],
skip_header=2)
-
- wvl = data['wavelength'] * scale
- resp = data['response']
+ wvl = data[0] * scale
+ resp = data[2]
self.rsr = {'wavelength': wvl, 'response': resp}
def main():
- """Main"""
- for platform_name in ['GOES-16', 'GOES-17', ]:
+ """Create pyspectral hdf5 RSR files for all GOES sats."""
+ for platform_name in ['GOES-16', 'GOES-17', 'GOES-18', 'GOES-19']:
tohdf5(AbiRSR, platform_name, ABI_BAND_NAMES)
=====================================
setup.cfg
=====================================
@@ -6,7 +6,7 @@ setup_requires =
[bdist_rpm]
provides=pyspectral
-requires=numpy h5py python-geotiepoints dask PyYAML python-requests python-six python-appdirs
+requires=numpy h5py python-geotiepoints dask PyYAML python-requests python-appdirs
release=1
[bdist_wheel]
=====================================
setup.py
=====================================
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (c) 2013-2020 Pytroll
+# Copyright (c) 2013-2021 Pytroll
# Author(s):
@@ -20,10 +20,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import sys
-from setuptools import setup, find_packages
-import os.path
+"""Setup for the Pyspectral package."""
+import os.path
+from setuptools import setup, find_packages
try:
# HACK: https://github.com/pypa/setuptools_scm/issues/190#issuecomment-351181286
@@ -45,19 +45,11 @@ except IOError:
requires = ['docutils>=0.3', 'numpy>=1.5.1', 'scipy>=0.14',
'python-geotiepoints>=1.1.1',
- 'h5py>=2.5', 'requests', 'six', 'pyyaml',
+ 'h5py>=2.5', 'requests', 'pyyaml',
'appdirs']
dask_extra = ['dask[array]']
test_requires = ['pyyaml', 'dask[array]', 'xlrd', 'pytest', 'xarray']
-if sys.version < '3.0':
- test_requires.append('mock')
- try:
- # This is needed in order to let the unittests pass
- # without complaining at the end on certain systems
- import multiprocessing
- except ImportError:
- pass
NAME = 'pyspectral'
View it on GitLab: https://salsa.debian.org/debian-gis-team/pyspectral/-/commit/0ec215a5953d3ac9d188c11769a94c1f417fa49d
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/pyspectral/-/commit/0ec215a5953d3ac9d188c11769a94c1f417fa49d
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20211223/8bb13992/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list