coxmunk 1.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coxmunk-1.2.1/LICENSE +21 -0
- coxmunk-1.2.1/PKG-INFO +337 -0
- coxmunk-1.2.1/README.md +307 -0
- coxmunk-1.2.1/coxmunk/__init__.py +7 -0
- coxmunk-1.2.1/coxmunk/cox_munk_validate.py +87 -0
- coxmunk-1.2.1/coxmunk/coxmunk.py +745 -0
- coxmunk-1.2.1/coxmunk/test.py +49 -0
- coxmunk-1.2.1/coxmunk/visu.py +235 -0
- coxmunk-1.2.1/coxmunk/wind.py +282 -0
- coxmunk-1.2.1/coxmunk.egg-info/PKG-INFO +337 -0
- coxmunk-1.2.1/coxmunk.egg-info/SOURCES.txt +17 -0
- coxmunk-1.2.1/coxmunk.egg-info/dependency_links.txt +1 -0
- coxmunk-1.2.1/coxmunk.egg-info/entry_points.txt +2 -0
- coxmunk-1.2.1/coxmunk.egg-info/requires.txt +8 -0
- coxmunk-1.2.1/coxmunk.egg-info/top_level.txt +1 -0
- coxmunk-1.2.1/pyproject.toml +47 -0
- coxmunk-1.2.1/setup.cfg +4 -0
- coxmunk-1.2.1/tests/test_tilt.py +60 -0
- coxmunk-1.2.1/tests/test_wind.py +48 -0
coxmunk-1.2.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019-2026 Tristan Harmel
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
coxmunk-1.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: coxmunk
|
|
3
|
+
Version: 1.2.1
|
|
4
|
+
Summary: Sunglint (Stokes vector) computation from the Cox-Munk wave slope statistics
|
|
5
|
+
Author-email: "T. Harmel" <tristan.harmel@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Tristanovsk/coxmunk
|
|
8
|
+
Project-URL: Documentation, https://coxmunk.readthedocs.io
|
|
9
|
+
Project-URL: Repository, https://github.com/Tristanovsk/coxmunk
|
|
10
|
+
Project-URL: Issues, https://github.com/Tristanovsk/coxmunk/issues
|
|
11
|
+
Keywords: sunglint,Cox-Munk,sea surface,ocean color,remote sensing,polarization,wind speed
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: numpy
|
|
22
|
+
Requires-Dist: scipy
|
|
23
|
+
Requires-Dist: pandas
|
|
24
|
+
Requires-Dist: xarray
|
|
25
|
+
Requires-Dist: netCDF4
|
|
26
|
+
Requires-Dist: matplotlib
|
|
27
|
+
Requires-Dist: cmocean
|
|
28
|
+
Requires-Dist: docopt
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# coxmunk
|
|
32
|
+
|
|
33
|
+
Simple sunglint computation based on [Cox & Munk](https://www.osapublishing.org/josa/abstract.cfm?uri=josa-44-11-838) model.
|
|
34
|
+
The sunglint, sunlight reflected by the waves, induces different patterns at different spatial
|
|
35
|
+
(or temporal) scales, as in these examples:
|
|
36
|
+
|
|
37
|
+
- (a) sea surface under gust wind conditions (reflex digital camera);
|
|
38
|
+
- (b) aerial photograph of the sea surface with visible surfactant filaments;
|
|
39
|
+
- (c\) Sentinel-2A image (4 July 2015) in the 2190-nm channel, where sunglint is the most intense
|
|
40
|
+
signal over water; the glint highlights eddies, ship wakes and wave packets;
|
|
41
|
+
- (d) Sentinel-3 RGB image (10 May 2016) over the eastern Mediterranean Sea, with high sunglint on
|
|
42
|
+
the right side.
|
|
43
|
+
|
|
44
|
+

|
|
45
|
+
|
|
46
|
+
Credits: Neukermans, Harmel, Galí et al. (2018). Harnessing remote sensing to address critical
|
|
47
|
+
science questions on ocean-atmosphere interactions. *Elementa*, 6, 71,
|
|
48
|
+
[doi:10.1525/elementa.331](https://doi.org/10.1525/elementa.331) (Fig. 11, CC BY 4.0).
|
|
49
|
+
|
|
50
|
+
For more details on the statistics of the wave slopes (i.e., *Probability Distribution Function*), please refer to [Munk 2009](https://www.annualreviews.org/doi/abs/10.1146/annurev.marine.010908.163940).
|
|
51
|
+
|
|
52
|
+

|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
`coxmunk` requires Python >= 3.9. Its dependencies (numpy, scipy, pandas, xarray, netCDF4,
|
|
57
|
+
matplotlib, cmocean, docopt) are installed automatically by `pip`.
|
|
58
|
+
|
|
59
|
+
It is best installed in a virtual environment:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
python3 -m venv .venv
|
|
63
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
64
|
+
python -m pip install --upgrade pip
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
or in a conda environment:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
conda create -n coxmunk python=3.12
|
|
71
|
+
conda activate coxmunk
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### From PyPI
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
python -m pip install coxmunk
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Development version from GitHub
|
|
81
|
+
|
|
82
|
+
The `develop` branch contains the latest changes not yet released:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
python -m pip install "git+https://github.com/Tristanovsk/coxmunk.git@develop"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### From source, for development
|
|
89
|
+
|
|
90
|
+
Clone [the repository](https://github.com/Tristanovsk/coxmunk) and install it in editable mode
|
|
91
|
+
(code changes are picked up without reinstalling):
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
git clone https://github.com/Tristanovsk/coxmunk.git
|
|
95
|
+
cd coxmunk
|
|
96
|
+
python -m pip install -e .
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Run the tests with:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
python -m pip install pytest
|
|
103
|
+
python -m pytest tests
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
and build the documentation with:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
python -m pip install -r docs/requirements.txt
|
|
110
|
+
make -C docs html # output in docs/build/html
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Check the installation
|
|
114
|
+
|
|
115
|
+
The installation provides the `coxmunk` command:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
$ coxmunk --version
|
|
119
|
+
coxmunk 1.2.1
|
|
120
|
+
$ coxmunk
|
|
121
|
+
Usage:
|
|
122
|
+
coxmunk <sza> <wind_speed> [--stats <stats>] [--wind_azi <wind_azi>] [--shadow] [--slope] [--figname <figname>]
|
|
123
|
+
coxmunk -h | --help
|
|
124
|
+
coxmunk -v | --version
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The model can also be used from Python:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from coxmunk import sunglint
|
|
131
|
+
|
|
132
|
+
# geometry in degrees: solar zenith, viewing zenith, relative azimuth (180° = Sun and sensor in opposition)
|
|
133
|
+
I, Q, U, V = sunglint(sza=30, vza=30, azi=180).sunglint(ws=5, wazi=0, stats='bh2006', shadow=True)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The full documentation, with the API reference and tutorials, is on
|
|
137
|
+
[Read the Docs](https://coxmunk.readthedocs.io).
|
|
138
|
+
|
|
139
|
+
## Model description
|
|
140
|
+
|
|
141
|
+
The sea surface is described as a collection of plane facets whose slopes follow the
|
|
142
|
+
statistics of Cox & Munk (1954). The glint observed in a given direction comes from the
|
|
143
|
+
facets tilted so that the Sun is specularly reflected toward the sensor.
|
|
144
|
+
|
|
145
|
+
### Reflecting facet
|
|
146
|
+
|
|
147
|
+
With the solar and viewing zenith angles $\theta_s$, $\theta_v$ ($\mu = \cos\theta$) and the
|
|
148
|
+
relative azimuth $\phi$ (180° when Sun and sensor are in opposition), the scattering angle
|
|
149
|
+
$\Theta$, the angle of incidence on the facet $\omega$ and the facet tilt $\theta_n$ are
|
|
150
|
+
|
|
151
|
+
```math
|
|
152
|
+
\cos\Theta = -\mu_s\mu_v - \sin\theta_s\sin\theta_v\cos\phi, \qquad
|
|
153
|
+
\omega = \frac{\pi - \Theta}{2}, \qquad
|
|
154
|
+
\cos\theta_n = \frac{\mu_s + \mu_v}{2\cos\omega}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The facet slopes are computed in the Sun frame and rotated into the wind frame, with
|
|
158
|
+
$\phi_w$ the downwind direction counted counterclockwise from the Sun:
|
|
159
|
+
|
|
160
|
+
```math
|
|
161
|
+
z_x = -\frac{\sin\theta_v \cos\phi + \sin\theta_s}{\mu_s + \mu_v}, \quad
|
|
162
|
+
z_y = -\frac{\sin\theta_v \sin\phi}{\mu_s + \mu_v}, \quad
|
|
163
|
+
z_{up} = \cos\phi_w \, z_x + \sin\phi_w \, z_y, \quad
|
|
164
|
+
z_{cr} = -\sin\phi_w \, z_x + \cos\phi_w \, z_y
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Wave slope statistics
|
|
168
|
+
|
|
169
|
+
For the isotropic statistics (`cm_iso`), with the wind speed $U$ in m/s:
|
|
170
|
+
|
|
171
|
+
```math
|
|
172
|
+
\sigma^2 = 0.003 + 5.12\times10^{-3}\,U, \qquad
|
|
173
|
+
P = \frac{1}{\pi\sigma^2} \exp\left(-\frac{\tan^2\theta_n}{\sigma^2}\right)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
For the anisotropic statistics (`cm_dir`, `bh2006`), the Gram-Charlier expansion is written
|
|
177
|
+
with the convention of Munk (2009), with $\xi = z_{up}/\sigma_{up}$ and $\eta = z_{cr}/\sigma_{cr}$:
|
|
178
|
+
|
|
179
|
+
```math
|
|
180
|
+
P(\xi, \eta) = \frac{e^{-(\xi^2 + \eta^2)/2}}{2\pi\,\sigma_{up}\,\sigma_{cr}}
|
|
181
|
+
\Big[ 1
|
|
182
|
+
+ \tfrac{c_{12}}{2}\,\xi\,(1 - \eta^2)
|
|
183
|
+
- \tfrac{c_{30}}{6}\,\xi\,(3 - \xi^2)
|
|
184
|
+
+ \tfrac{c_{40}}{24}\,(3 - 6\xi^2 + \xi^4)
|
|
185
|
+
+ \tfrac{c_{22}}{4}\,(1 - \xi^2)(1 - \eta^2)
|
|
186
|
+
+ \tfrac{c_{04}}{24}\,(3 - 6\eta^2 + \eta^4)
|
|
187
|
+
\Big]
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
where $c_{12} = -c_{21}$ and $c_{30} = -c_{03}$, with the coefficients:
|
|
191
|
+
|
|
192
|
+
| Parameter | `cm_dir` (Cox & Munk, 1954) | `bh2006` (Bréon & Henriot, 2006) |
|
|
193
|
+
|---|---|---|
|
|
194
|
+
| $\sigma_{cr}^2$ | $0.003 + 1.92\times10^{-3}\,U$ | $0.003 + 1.85\times10^{-3}\,U$ |
|
|
195
|
+
| $\sigma_{up}^2$ | $3.16\times10^{-3}\,U$ | $0.001 + 3.16\times10^{-3}\,U$ |
|
|
196
|
+
| $c_{21}$ | $0.01 - 8.6\times10^{-3}\,U$ | $-9\times10^{-4}\,U^2$ |
|
|
197
|
+
| $c_{03}$ | $0.04 - 0.033\,U$ | $-0.45 / (1 + e^{7 - U})$ |
|
|
198
|
+
| $c_{40}$ | 0.40 | 0.30 |
|
|
199
|
+
| $c_{22}$ | 0.12 | 0.12 |
|
|
200
|
+
| $c_{04}$ | 0.23 | 0.40 |
|
|
201
|
+
|
|
202
|
+
### Fresnel reflection
|
|
203
|
+
|
|
204
|
+
With the refractive index of water $m$ (default 1.334), the reflection coefficients
|
|
205
|
+
parallel and perpendicular to the plane of incidence are
|
|
206
|
+
|
|
207
|
+
```math
|
|
208
|
+
r_l = \frac{\sqrt{m^2 - \sin^2\omega} - m^2\cos\omega}{\sqrt{m^2 - \sin^2\omega} + m^2\cos\omega},
|
|
209
|
+
\qquad
|
|
210
|
+
r_r = \frac{\cos\omega - \sqrt{m^2 - \sin^2\omega}}{\cos\omega + \sqrt{m^2 - \sin^2\omega}}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
giving the Mueller reflection matrix
|
|
214
|
+
|
|
215
|
+
```math
|
|
216
|
+
\mathbf{R}_F(\omega) = \frac{1}{2}
|
|
217
|
+
\begin{pmatrix}
|
|
218
|
+
r_l^2 + r_r^2 & r_l^2 - r_r^2 & 0 & 0 \\
|
|
219
|
+
r_l^2 - r_r^2 & r_l^2 + r_r^2 & 0 & 0 \\
|
|
220
|
+
0 & 0 & 2 r_l r_r & 0 \\
|
|
221
|
+
0 & 0 & 0 & 2 r_l r_r
|
|
222
|
+
\end{pmatrix}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
which is rotated from the meridian planes into the scattering plane,
|
|
226
|
+
$\mathbf{R} = \mathbf{L}(\pi - \sigma_2)\,\mathbf{R}_F\,\mathbf{L}(-\sigma_1)$.
|
|
227
|
+
|
|
228
|
+
### Shadowing and hiding
|
|
229
|
+
|
|
230
|
+
With `--shadow` (`shadow=True` in Python), the facets hidden by the waves are removed
|
|
231
|
+
with the Smith function (Ross & Dion, 2005, 2007):
|
|
232
|
+
|
|
233
|
+
```math
|
|
234
|
+
\Lambda(\theta, \varphi) = \frac{e^{-\nu^2} - \nu\sqrt{\pi}\,\mathrm{erfc}(\nu)}{2\,\nu\sqrt{\pi}},
|
|
235
|
+
\qquad
|
|
236
|
+
\nu = \frac{1}{\sqrt{2}\,\sigma(\varphi)\tan\theta},
|
|
237
|
+
\qquad
|
|
238
|
+
\sigma^2(\varphi) = \sigma_{up}^2\cos^2\varphi + \sigma_{cr}^2\sin^2\varphi
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
```math
|
|
242
|
+
SH = \frac{1}{1 + \Lambda(\theta_s, -\phi_w) + \Lambda(\theta_v, \phi - \phi_w)}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
where $\varphi$ is the azimuth of the direction relative to the upwind axis.
|
|
246
|
+
|
|
247
|
+
### Sunglint Stokes vector
|
|
248
|
+
|
|
249
|
+
The sunglint, in reflectance units, is finally
|
|
250
|
+
|
|
251
|
+
```math
|
|
252
|
+
\begin{pmatrix} I \\ Q \\ U \\ V \end{pmatrix}
|
|
253
|
+
= \frac{\pi \, P \, SH}{4 \, \mu_s \, \mu_v \cos^4\theta_n}
|
|
254
|
+
\begin{pmatrix} R_{11} \\ R_{21} \\ R_{31} \\ R_{41} \end{pmatrix}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### References
|
|
258
|
+
|
|
259
|
+
- Cox, C. and Munk, W. (1954). Measurement of the roughness of the sea surface from photographs of the Sun's glitter. *J. Opt. Soc. Am.*, 44(11), 838-850.
|
|
260
|
+
- Bréon, F.-M. and Henriot, N. (2006). Spaceborne observations of ocean glint reflectance and modeling of wave slope distributions. *J. Geophys. Res.*, 111, C06005.
|
|
261
|
+
- Munk, W. (2009). An inconvenient sea truth: spread, steepness, and skewness of surface slopes. *Annu. Rev. Mar. Sci.*, 1, 377-415.
|
|
262
|
+
- Ross, V., Dion, D. and Potvin, G. (2005). Detailed analytical approach to the Gaussian surface bidirectional reflectance distribution function specular component applied to the sea surface. *J. Opt. Soc. Am. A*, 22(11), 2442-2453.
|
|
263
|
+
- Harmel, T. and Chami, M. (2012). Determination of sea surface wind speed using the polarimetric and multidirectional properties of satellite measurements in visible bands. *Geophys. Res. Lett.*, 39, L19611, doi:10.1029/2012GL053508.
|
|
264
|
+
- Harmel, T. and Chami, M. (2013). Estimation of the sunglint radiance field from optical satellite imagery over open ocean: multidirectional approach and polarization aspects. *J. Geophys. Res. Oceans*, 118, doi:10.1029/2012JC008221.
|
|
265
|
+
- Ross, V. and Dion, D. (2007). Sea surface slope statistics derived from Sun glint radiance measurements and their apparent dependence on sensor elevation. *J. Geophys. Res.*, 112, C09015.
|
|
266
|
+
|
|
267
|
+
## Polarization and wind speed retrieval
|
|
268
|
+
|
|
269
|
+
Since the polarization of the glint only depends on the geometry while its amount depends on the
|
|
270
|
+
sea state, multidirectional and polarized measurements (e.g., POLDER/PARASOL) can be used to
|
|
271
|
+
retrieve the sunglint Stokes vector (Harmel & Chami, 2013) and the sea surface wind speed
|
|
272
|
+
(Harmel & Chami, 2012). The `coxmunk.wind` module implements the forward model (sunglint plus
|
|
273
|
+
whitecaps) and the Levenberg-Marquardt inversion of Harmel & Chami (2012):
|
|
274
|
+
|
|
275
|
+
```python
|
|
276
|
+
import numpy as np
|
|
277
|
+
from coxmunk.wind import glint_whitecap, retrieve_wind_speed
|
|
278
|
+
|
|
279
|
+
# 14 viewing directions along a satellite track: (sza, vza, azi) in degrees
|
|
280
|
+
geometries = np.array([(30, abs(v), 150 if v >= 0 else 330) for v in np.linspace(-55, 55, 14)])
|
|
281
|
+
observed = glint_whitecap(geometries, ws=8) # synthetic I, Q, U measurements
|
|
282
|
+
res = retrieve_wind_speed(observed, geometries) # -> res.ws, res.sigma, res.flag
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
See the [polarization](https://coxmunk.readthedocs.io/en/latest/polarization.html) and
|
|
286
|
+
[wind speed](https://coxmunk.readthedocs.io/en/latest/wind_speed.html) chapters of the documentation.
|
|
287
|
+
|
|
288
|
+
## Kumatage: from noise to signal
|
|
289
|
+
|
|
290
|
+

|
|
291
|
+
|
|
292
|
+
In 1822, Spooner named *Kumatage* (from the Greek κυμάτων, *of the waves*, and αὐγή, *splendour*)
|
|
293
|
+
"this remarkable appearance of light" of the Sun reflected by the waves, and established its first
|
|
294
|
+
equations. Navigators filtered it out as a glare, painters made it a subject, Cox & Munk turned it
|
|
295
|
+
into a measurement of the sea surface slopes, ocean color remote sensing removed it as a noise, and
|
|
296
|
+
it is now exploited as a signal on winds, waves, currents and slicks. The
|
|
297
|
+
[History section](https://coxmunk.readthedocs.io/en/latest/history/kumatage.html) of the documentation
|
|
298
|
+
retraces this history (adapted from Harmel, Bary, Gernez & Morin, OCEANEXT 2019), with paintings,
|
|
299
|
+
Cox & Munk and Sentinel-2 images.
|
|
300
|
+
|
|
301
|
+
## Examples
|
|
302
|
+
|
|
303
|
+
Examples for [Cox & Munk](https://www.osapublishing.org/josa/abstract.cfm?uri=josa-44-11-838) model with [Bréon & Henriot](https://agupubs.onlinelibrary.wiley.com/doi/full/10.1029/2005JC003343) statistics for:
|
|
304
|
+
- solar zenith angle = 39°
|
|
305
|
+
- wind azimuth from Sun = 75°
|
|
306
|
+
- wind speed = 0.2, 7.2, 14.2 m.s<sup>-1</sup>
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
$ coxmunk 39 0.2 --stats bh2006 --wind_azi 75 --figname illustration/coxmunk_fig_39_0.2_bh2006_75.png
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+

|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
```
|
|
316
|
+
$ coxmunk 39 7.2 --stats bh2006 --wind_azi 75
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+

|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
$ coxmunk 39 14.2 --stats bh2006 --wind_azi 75
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+

|
|
328
|
+
|
|
329
|
+
With the option `--slope` you can also check
|
|
330
|
+
the values of wave slopes upwind and crosswind,
|
|
331
|
+
the first term of the Fresnel matrix and the probability distribution function:
|
|
332
|
+
|
|
333
|
+
```
|
|
334
|
+
$ coxmunk 20 5 --stats bh2006 --wind_azi 60 --slope
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+

|
coxmunk-1.2.1/README.md
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
# coxmunk
|
|
2
|
+
|
|
3
|
+
Simple sunglint computation based on [Cox & Munk](https://www.osapublishing.org/josa/abstract.cfm?uri=josa-44-11-838) model.
|
|
4
|
+
The sunglint, sunlight reflected by the waves, induces different patterns at different spatial
|
|
5
|
+
(or temporal) scales, as in these examples:
|
|
6
|
+
|
|
7
|
+
- (a) sea surface under gust wind conditions (reflex digital camera);
|
|
8
|
+
- (b) aerial photograph of the sea surface with visible surfactant filaments;
|
|
9
|
+
- (c\) Sentinel-2A image (4 July 2015) in the 2190-nm channel, where sunglint is the most intense
|
|
10
|
+
signal over water; the glint highlights eddies, ship wakes and wave packets;
|
|
11
|
+
- (d) Sentinel-3 RGB image (10 May 2016) over the eastern Mediterranean Sea, with high sunglint on
|
|
12
|
+
the right side.
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
Credits: Neukermans, Harmel, Galí et al. (2018). Harnessing remote sensing to address critical
|
|
17
|
+
science questions on ocean-atmosphere interactions. *Elementa*, 6, 71,
|
|
18
|
+
[doi:10.1525/elementa.331](https://doi.org/10.1525/elementa.331) (Fig. 11, CC BY 4.0).
|
|
19
|
+
|
|
20
|
+
For more details on the statistics of the wave slopes (i.e., *Probability Distribution Function*), please refer to [Munk 2009](https://www.annualreviews.org/doi/abs/10.1146/annurev.marine.010908.163940).
|
|
21
|
+
|
|
22
|
+

|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
`coxmunk` requires Python >= 3.9. Its dependencies (numpy, scipy, pandas, xarray, netCDF4,
|
|
27
|
+
matplotlib, cmocean, docopt) are installed automatically by `pip`.
|
|
28
|
+
|
|
29
|
+
It is best installed in a virtual environment:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
python3 -m venv .venv
|
|
33
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
34
|
+
python -m pip install --upgrade pip
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
or in a conda environment:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
conda create -n coxmunk python=3.12
|
|
41
|
+
conda activate coxmunk
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### From PyPI
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
python -m pip install coxmunk
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Development version from GitHub
|
|
51
|
+
|
|
52
|
+
The `develop` branch contains the latest changes not yet released:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
python -m pip install "git+https://github.com/Tristanovsk/coxmunk.git@develop"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### From source, for development
|
|
59
|
+
|
|
60
|
+
Clone [the repository](https://github.com/Tristanovsk/coxmunk) and install it in editable mode
|
|
61
|
+
(code changes are picked up without reinstalling):
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
git clone https://github.com/Tristanovsk/coxmunk.git
|
|
65
|
+
cd coxmunk
|
|
66
|
+
python -m pip install -e .
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Run the tests with:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
python -m pip install pytest
|
|
73
|
+
python -m pytest tests
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
and build the documentation with:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
python -m pip install -r docs/requirements.txt
|
|
80
|
+
make -C docs html # output in docs/build/html
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Check the installation
|
|
84
|
+
|
|
85
|
+
The installation provides the `coxmunk` command:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
$ coxmunk --version
|
|
89
|
+
coxmunk 1.2.1
|
|
90
|
+
$ coxmunk
|
|
91
|
+
Usage:
|
|
92
|
+
coxmunk <sza> <wind_speed> [--stats <stats>] [--wind_azi <wind_azi>] [--shadow] [--slope] [--figname <figname>]
|
|
93
|
+
coxmunk -h | --help
|
|
94
|
+
coxmunk -v | --version
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The model can also be used from Python:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from coxmunk import sunglint
|
|
101
|
+
|
|
102
|
+
# geometry in degrees: solar zenith, viewing zenith, relative azimuth (180° = Sun and sensor in opposition)
|
|
103
|
+
I, Q, U, V = sunglint(sza=30, vza=30, azi=180).sunglint(ws=5, wazi=0, stats='bh2006', shadow=True)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The full documentation, with the API reference and tutorials, is on
|
|
107
|
+
[Read the Docs](https://coxmunk.readthedocs.io).
|
|
108
|
+
|
|
109
|
+
## Model description
|
|
110
|
+
|
|
111
|
+
The sea surface is described as a collection of plane facets whose slopes follow the
|
|
112
|
+
statistics of Cox & Munk (1954). The glint observed in a given direction comes from the
|
|
113
|
+
facets tilted so that the Sun is specularly reflected toward the sensor.
|
|
114
|
+
|
|
115
|
+
### Reflecting facet
|
|
116
|
+
|
|
117
|
+
With the solar and viewing zenith angles $\theta_s$, $\theta_v$ ($\mu = \cos\theta$) and the
|
|
118
|
+
relative azimuth $\phi$ (180° when Sun and sensor are in opposition), the scattering angle
|
|
119
|
+
$\Theta$, the angle of incidence on the facet $\omega$ and the facet tilt $\theta_n$ are
|
|
120
|
+
|
|
121
|
+
```math
|
|
122
|
+
\cos\Theta = -\mu_s\mu_v - \sin\theta_s\sin\theta_v\cos\phi, \qquad
|
|
123
|
+
\omega = \frac{\pi - \Theta}{2}, \qquad
|
|
124
|
+
\cos\theta_n = \frac{\mu_s + \mu_v}{2\cos\omega}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The facet slopes are computed in the Sun frame and rotated into the wind frame, with
|
|
128
|
+
$\phi_w$ the downwind direction counted counterclockwise from the Sun:
|
|
129
|
+
|
|
130
|
+
```math
|
|
131
|
+
z_x = -\frac{\sin\theta_v \cos\phi + \sin\theta_s}{\mu_s + \mu_v}, \quad
|
|
132
|
+
z_y = -\frac{\sin\theta_v \sin\phi}{\mu_s + \mu_v}, \quad
|
|
133
|
+
z_{up} = \cos\phi_w \, z_x + \sin\phi_w \, z_y, \quad
|
|
134
|
+
z_{cr} = -\sin\phi_w \, z_x + \cos\phi_w \, z_y
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Wave slope statistics
|
|
138
|
+
|
|
139
|
+
For the isotropic statistics (`cm_iso`), with the wind speed $U$ in m/s:
|
|
140
|
+
|
|
141
|
+
```math
|
|
142
|
+
\sigma^2 = 0.003 + 5.12\times10^{-3}\,U, \qquad
|
|
143
|
+
P = \frac{1}{\pi\sigma^2} \exp\left(-\frac{\tan^2\theta_n}{\sigma^2}\right)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
For the anisotropic statistics (`cm_dir`, `bh2006`), the Gram-Charlier expansion is written
|
|
147
|
+
with the convention of Munk (2009), with $\xi = z_{up}/\sigma_{up}$ and $\eta = z_{cr}/\sigma_{cr}$:
|
|
148
|
+
|
|
149
|
+
```math
|
|
150
|
+
P(\xi, \eta) = \frac{e^{-(\xi^2 + \eta^2)/2}}{2\pi\,\sigma_{up}\,\sigma_{cr}}
|
|
151
|
+
\Big[ 1
|
|
152
|
+
+ \tfrac{c_{12}}{2}\,\xi\,(1 - \eta^2)
|
|
153
|
+
- \tfrac{c_{30}}{6}\,\xi\,(3 - \xi^2)
|
|
154
|
+
+ \tfrac{c_{40}}{24}\,(3 - 6\xi^2 + \xi^4)
|
|
155
|
+
+ \tfrac{c_{22}}{4}\,(1 - \xi^2)(1 - \eta^2)
|
|
156
|
+
+ \tfrac{c_{04}}{24}\,(3 - 6\eta^2 + \eta^4)
|
|
157
|
+
\Big]
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
where $c_{12} = -c_{21}$ and $c_{30} = -c_{03}$, with the coefficients:
|
|
161
|
+
|
|
162
|
+
| Parameter | `cm_dir` (Cox & Munk, 1954) | `bh2006` (Bréon & Henriot, 2006) |
|
|
163
|
+
|---|---|---|
|
|
164
|
+
| $\sigma_{cr}^2$ | $0.003 + 1.92\times10^{-3}\,U$ | $0.003 + 1.85\times10^{-3}\,U$ |
|
|
165
|
+
| $\sigma_{up}^2$ | $3.16\times10^{-3}\,U$ | $0.001 + 3.16\times10^{-3}\,U$ |
|
|
166
|
+
| $c_{21}$ | $0.01 - 8.6\times10^{-3}\,U$ | $-9\times10^{-4}\,U^2$ |
|
|
167
|
+
| $c_{03}$ | $0.04 - 0.033\,U$ | $-0.45 / (1 + e^{7 - U})$ |
|
|
168
|
+
| $c_{40}$ | 0.40 | 0.30 |
|
|
169
|
+
| $c_{22}$ | 0.12 | 0.12 |
|
|
170
|
+
| $c_{04}$ | 0.23 | 0.40 |
|
|
171
|
+
|
|
172
|
+
### Fresnel reflection
|
|
173
|
+
|
|
174
|
+
With the refractive index of water $m$ (default 1.334), the reflection coefficients
|
|
175
|
+
parallel and perpendicular to the plane of incidence are
|
|
176
|
+
|
|
177
|
+
```math
|
|
178
|
+
r_l = \frac{\sqrt{m^2 - \sin^2\omega} - m^2\cos\omega}{\sqrt{m^2 - \sin^2\omega} + m^2\cos\omega},
|
|
179
|
+
\qquad
|
|
180
|
+
r_r = \frac{\cos\omega - \sqrt{m^2 - \sin^2\omega}}{\cos\omega + \sqrt{m^2 - \sin^2\omega}}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
giving the Mueller reflection matrix
|
|
184
|
+
|
|
185
|
+
```math
|
|
186
|
+
\mathbf{R}_F(\omega) = \frac{1}{2}
|
|
187
|
+
\begin{pmatrix}
|
|
188
|
+
r_l^2 + r_r^2 & r_l^2 - r_r^2 & 0 & 0 \\
|
|
189
|
+
r_l^2 - r_r^2 & r_l^2 + r_r^2 & 0 & 0 \\
|
|
190
|
+
0 & 0 & 2 r_l r_r & 0 \\
|
|
191
|
+
0 & 0 & 0 & 2 r_l r_r
|
|
192
|
+
\end{pmatrix}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
which is rotated from the meridian planes into the scattering plane,
|
|
196
|
+
$\mathbf{R} = \mathbf{L}(\pi - \sigma_2)\,\mathbf{R}_F\,\mathbf{L}(-\sigma_1)$.
|
|
197
|
+
|
|
198
|
+
### Shadowing and hiding
|
|
199
|
+
|
|
200
|
+
With `--shadow` (`shadow=True` in Python), the facets hidden by the waves are removed
|
|
201
|
+
with the Smith function (Ross & Dion, 2005, 2007):
|
|
202
|
+
|
|
203
|
+
```math
|
|
204
|
+
\Lambda(\theta, \varphi) = \frac{e^{-\nu^2} - \nu\sqrt{\pi}\,\mathrm{erfc}(\nu)}{2\,\nu\sqrt{\pi}},
|
|
205
|
+
\qquad
|
|
206
|
+
\nu = \frac{1}{\sqrt{2}\,\sigma(\varphi)\tan\theta},
|
|
207
|
+
\qquad
|
|
208
|
+
\sigma^2(\varphi) = \sigma_{up}^2\cos^2\varphi + \sigma_{cr}^2\sin^2\varphi
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
```math
|
|
212
|
+
SH = \frac{1}{1 + \Lambda(\theta_s, -\phi_w) + \Lambda(\theta_v, \phi - \phi_w)}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
where $\varphi$ is the azimuth of the direction relative to the upwind axis.
|
|
216
|
+
|
|
217
|
+
### Sunglint Stokes vector
|
|
218
|
+
|
|
219
|
+
The sunglint, in reflectance units, is finally
|
|
220
|
+
|
|
221
|
+
```math
|
|
222
|
+
\begin{pmatrix} I \\ Q \\ U \\ V \end{pmatrix}
|
|
223
|
+
= \frac{\pi \, P \, SH}{4 \, \mu_s \, \mu_v \cos^4\theta_n}
|
|
224
|
+
\begin{pmatrix} R_{11} \\ R_{21} \\ R_{31} \\ R_{41} \end{pmatrix}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### References
|
|
228
|
+
|
|
229
|
+
- Cox, C. and Munk, W. (1954). Measurement of the roughness of the sea surface from photographs of the Sun's glitter. *J. Opt. Soc. Am.*, 44(11), 838-850.
|
|
230
|
+
- Bréon, F.-M. and Henriot, N. (2006). Spaceborne observations of ocean glint reflectance and modeling of wave slope distributions. *J. Geophys. Res.*, 111, C06005.
|
|
231
|
+
- Munk, W. (2009). An inconvenient sea truth: spread, steepness, and skewness of surface slopes. *Annu. Rev. Mar. Sci.*, 1, 377-415.
|
|
232
|
+
- Ross, V., Dion, D. and Potvin, G. (2005). Detailed analytical approach to the Gaussian surface bidirectional reflectance distribution function specular component applied to the sea surface. *J. Opt. Soc. Am. A*, 22(11), 2442-2453.
|
|
233
|
+
- Harmel, T. and Chami, M. (2012). Determination of sea surface wind speed using the polarimetric and multidirectional properties of satellite measurements in visible bands. *Geophys. Res. Lett.*, 39, L19611, doi:10.1029/2012GL053508.
|
|
234
|
+
- Harmel, T. and Chami, M. (2013). Estimation of the sunglint radiance field from optical satellite imagery over open ocean: multidirectional approach and polarization aspects. *J. Geophys. Res. Oceans*, 118, doi:10.1029/2012JC008221.
|
|
235
|
+
- Ross, V. and Dion, D. (2007). Sea surface slope statistics derived from Sun glint radiance measurements and their apparent dependence on sensor elevation. *J. Geophys. Res.*, 112, C09015.
|
|
236
|
+
|
|
237
|
+
## Polarization and wind speed retrieval
|
|
238
|
+
|
|
239
|
+
Since the polarization of the glint only depends on the geometry while its amount depends on the
|
|
240
|
+
sea state, multidirectional and polarized measurements (e.g., POLDER/PARASOL) can be used to
|
|
241
|
+
retrieve the sunglint Stokes vector (Harmel & Chami, 2013) and the sea surface wind speed
|
|
242
|
+
(Harmel & Chami, 2012). The `coxmunk.wind` module implements the forward model (sunglint plus
|
|
243
|
+
whitecaps) and the Levenberg-Marquardt inversion of Harmel & Chami (2012):
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
import numpy as np
|
|
247
|
+
from coxmunk.wind import glint_whitecap, retrieve_wind_speed
|
|
248
|
+
|
|
249
|
+
# 14 viewing directions along a satellite track: (sza, vza, azi) in degrees
|
|
250
|
+
geometries = np.array([(30, abs(v), 150 if v >= 0 else 330) for v in np.linspace(-55, 55, 14)])
|
|
251
|
+
observed = glint_whitecap(geometries, ws=8) # synthetic I, Q, U measurements
|
|
252
|
+
res = retrieve_wind_speed(observed, geometries) # -> res.ws, res.sigma, res.flag
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
See the [polarization](https://coxmunk.readthedocs.io/en/latest/polarization.html) and
|
|
256
|
+
[wind speed](https://coxmunk.readthedocs.io/en/latest/wind_speed.html) chapters of the documentation.
|
|
257
|
+
|
|
258
|
+
## Kumatage: from noise to signal
|
|
259
|
+
|
|
260
|
+

|
|
261
|
+
|
|
262
|
+
In 1822, Spooner named *Kumatage* (from the Greek κυμάτων, *of the waves*, and αὐγή, *splendour*)
|
|
263
|
+
"this remarkable appearance of light" of the Sun reflected by the waves, and established its first
|
|
264
|
+
equations. Navigators filtered it out as a glare, painters made it a subject, Cox & Munk turned it
|
|
265
|
+
into a measurement of the sea surface slopes, ocean color remote sensing removed it as a noise, and
|
|
266
|
+
it is now exploited as a signal on winds, waves, currents and slicks. The
|
|
267
|
+
[History section](https://coxmunk.readthedocs.io/en/latest/history/kumatage.html) of the documentation
|
|
268
|
+
retraces this history (adapted from Harmel, Bary, Gernez & Morin, OCEANEXT 2019), with paintings,
|
|
269
|
+
Cox & Munk and Sentinel-2 images.
|
|
270
|
+
|
|
271
|
+
## Examples
|
|
272
|
+
|
|
273
|
+
Examples for [Cox & Munk](https://www.osapublishing.org/josa/abstract.cfm?uri=josa-44-11-838) model with [Bréon & Henriot](https://agupubs.onlinelibrary.wiley.com/doi/full/10.1029/2005JC003343) statistics for:
|
|
274
|
+
- solar zenith angle = 39°
|
|
275
|
+
- wind azimuth from Sun = 75°
|
|
276
|
+
- wind speed = 0.2, 7.2, 14.2 m.s<sup>-1</sup>
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
$ coxmunk 39 0.2 --stats bh2006 --wind_azi 75 --figname illustration/coxmunk_fig_39_0.2_bh2006_75.png
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+

|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
$ coxmunk 39 7.2 --stats bh2006 --wind_azi 75
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+

|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
$ coxmunk 39 14.2 --stats bh2006 --wind_azi 75
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+

|
|
298
|
+
|
|
299
|
+
With the option `--slope` you can also check
|
|
300
|
+
the values of wave slopes upwind and crosswind,
|
|
301
|
+
the first term of the Fresnel matrix and the probability distribution function:
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
$ coxmunk 20 5 --stats bh2006 --wind_azi 60 --slope
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+

|