jerlov 0.7.1__tar.gz → 0.7.2__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.
- {jerlov-0.7.1/jerlov.egg-info → jerlov-0.7.2}/PKG-INFO +2 -2
- {jerlov-0.7.1 → jerlov-0.7.2}/README.md +1 -1
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/__init__.py +1 -1
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/backscattering.py +8 -1
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/scene.py +4 -2
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/water.py +8 -1
- {jerlov-0.7.1 → jerlov-0.7.2/jerlov.egg-info}/PKG-INFO +2 -2
- {jerlov-0.7.1 → jerlov-0.7.2}/pyproject.toml +1 -1
- {jerlov-0.7.1 → jerlov-0.7.2}/tests/test_api.py +30 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/tests/test_backscattering.py +12 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/tests/test_quoted_figures.py +25 -1
- {jerlov-0.7.1 → jerlov-0.7.2}/tests/test_scene.py +8 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/LICENSE +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/NOTICE +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/_data.py +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/colour.py +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/__init__.py +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/austin1986_kd.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/austin1986_model.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/boss2001_chi.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/cie1931_2deg_cmf.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/cie_d65.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/jerlov1968_kd.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/jerlov1968_total_irradiance.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/jerlov1976_kd.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/paulson1977_shortwave.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/petzold1972_stations.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/petzold1972_vsf.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/smart2007_b_from_c.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/solonenko2015_iop.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/williamson2022_aw.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/williamson2022_iop.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/williamson2022_measured.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/data/williamson2023_depth.csv +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/petzold.py +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/py.typed +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/shortwave.py +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov/sources.py +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov.egg-info/SOURCES.txt +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov.egg-info/dependency_links.txt +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov.egg-info/requires.txt +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/jerlov.egg-info/top_level.txt +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/setup.cfg +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/tests/test_colour.py +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/tests/test_depth.py +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/tests/test_packaging.py +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/tests/test_petzold.py +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/tests/test_reproduces_papers.py +0 -0
- {jerlov-0.7.1 → jerlov-0.7.2}/tests/test_shortwave.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jerlov
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Summary: Inherent optical properties of Jerlov water types, with provenance
|
|
5
5
|
Author: T. Ishibashi
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -62,7 +62,7 @@ w.a(550), w.b(550), w.c(550)
|
|
|
62
62
|
The same Jerlov water type has different coefficients in different papers, and
|
|
63
63
|
the differences are not small. Solonenko & Mobley (2015) obtained a and b by
|
|
64
64
|
inverting Kd; Williamson & Hollins (2022) measured them. At 510 nm their
|
|
65
|
-
scattering coefficients differ by up to a factor of
|
|
65
|
+
scattering coefficients differ by up to a factor of 3.8, at Jerlov III.
|
|
66
66
|
|
|
67
67
|
The equations differ too. Both papers use the scattering model of Haltrin
|
|
68
68
|
(1999), but with different constants: Haltrin's Eq. (6) gives a
|
|
@@ -37,7 +37,7 @@ w.a(550), w.b(550), w.c(550)
|
|
|
37
37
|
The same Jerlov water type has different coefficients in different papers, and
|
|
38
38
|
the differences are not small. Solonenko & Mobley (2015) obtained a and b by
|
|
39
39
|
inverting Kd; Williamson & Hollins (2022) measured them. At 510 nm their
|
|
40
|
-
scattering coefficients differ by up to a factor of
|
|
40
|
+
scattering coefficients differ by up to a factor of 3.8, at Jerlov III.
|
|
41
41
|
|
|
42
42
|
The equations differ too. Both papers use the scattering model of Haltrin
|
|
43
43
|
(1999), but with different constants: Haltrin's Eq. (6) gives a
|
|
@@ -67,7 +67,14 @@ def _amplitude(wavelength_nm, salinity_psu) -> np.ndarray:
|
|
|
67
67
|
f"salinity_psu must be a finite number, 0 or more, not "
|
|
68
68
|
f"{salinity_psu!r}"
|
|
69
69
|
)
|
|
70
|
-
|
|
70
|
+
wavelength = np.asarray(wavelength_nm, dtype=float)
|
|
71
|
+
if not np.all(np.isfinite(wavelength)) or np.any(wavelength <= 0):
|
|
72
|
+
# Zero gave inf and a negative wavelength NaN, each with nothing but
|
|
73
|
+
# a NumPy RuntimeWarning.
|
|
74
|
+
raise ValueError(
|
|
75
|
+
f"wavelength_nm must be a positive number, not {wavelength_nm!r}"
|
|
76
|
+
)
|
|
77
|
+
return (1.38 * (wavelength / 500.0) ** -4.32
|
|
71
78
|
* (1 + 0.3 * salinity / 37.0) * 1e-4)
|
|
72
79
|
|
|
73
80
|
|
|
@@ -195,10 +195,12 @@ class Scene:
|
|
|
195
195
|
"the water must carry both a and b; c = a + b drives the path"
|
|
196
196
|
)
|
|
197
197
|
self.water = water
|
|
198
|
-
|
|
198
|
+
# Copies, so that changing the caller's arrays afterwards cannot
|
|
199
|
+
# leave the wavelengths out of step with c, evaluated once below.
|
|
200
|
+
self.wavelengths = np.array(wavelengths, dtype=float)
|
|
199
201
|
if self.wavelengths.ndim != 1 or self.wavelengths.size == 0:
|
|
200
202
|
raise ValueError("wavelengths must be a non-empty 1-D array")
|
|
201
|
-
self.downwelling = np.
|
|
203
|
+
self.downwelling = np.array(downwelling, dtype=float)
|
|
202
204
|
if self.downwelling.shape != self.wavelengths.shape:
|
|
203
205
|
raise ValueError("downwelling must have the same shape as wavelengths")
|
|
204
206
|
if np.any(self.downwelling < 0):
|
|
@@ -240,6 +240,9 @@ class Water:
|
|
|
240
240
|
f"(available: {available})"
|
|
241
241
|
)
|
|
242
242
|
query = _as_array(wl)
|
|
243
|
+
# NaN < lo is False, so a NaN wavelength passed the range check and
|
|
244
|
+
# came back as NaN, warned about the last sample of the table.
|
|
245
|
+
_require_number(query, "wavelength")
|
|
243
246
|
lo, hi = self.range_nm
|
|
244
247
|
if np.any(query < lo) or np.any(query > hi):
|
|
245
248
|
raise ValueError(
|
|
@@ -591,7 +594,8 @@ def descend(surface_water_type: str, depth_m: float, wavelengths, *,
|
|
|
591
594
|
f"{deepest:g} m, so there is no type to descend through to "
|
|
592
595
|
f"{depth_m:g} m"
|
|
593
596
|
)
|
|
594
|
-
|
|
597
|
+
# A copy: it is frozen below, and the caller's array must not be.
|
|
598
|
+
query = np.array(wavelengths, dtype=float, ndmin=1)
|
|
595
599
|
optical_depth = np.zeros_like(query)
|
|
596
600
|
layers: list[tuple[float, float, str]] = []
|
|
597
601
|
kd: dict[str, np.ndarray] = {}
|
|
@@ -723,6 +727,8 @@ def kd_spectrum(kd, wavelength_nm: float, at):
|
|
|
723
727
|
)
|
|
724
728
|
wavelength_nm = float(wavelength_nm)
|
|
725
729
|
query = _as_array(at)
|
|
730
|
+
_require_number(wavelength_nm, "wavelength_nm")
|
|
731
|
+
_require_number(query, "at")
|
|
726
732
|
for value, label in ((wavelength_nm, "wavelength_nm"), (query, "at")):
|
|
727
733
|
if np.any(np.asarray(value) < lo) or np.any(np.asarray(value) > hi):
|
|
728
734
|
raise ValueError(f"{label} outside the model range ({lo:g}-{hi:g} nm)")
|
|
@@ -800,6 +806,7 @@ def b_from_c(c, wavelength_nm, *, bw, cw, bound: str = "average"):
|
|
|
800
806
|
if bound not in ratios:
|
|
801
807
|
raise ValueError(f"bound must be one of {sorted(ratios)}")
|
|
802
808
|
query = _as_array(wavelength_nm)
|
|
809
|
+
_require_number(query, "wavelength_nm")
|
|
803
810
|
if np.any(query < wl[0]) or np.any(query > wl[-1]):
|
|
804
811
|
raise ValueError(
|
|
805
812
|
f"wavelength outside the measured range ({wl[0]:g}-{wl[-1]:g} nm)"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jerlov
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Summary: Inherent optical properties of Jerlov water types, with provenance
|
|
5
5
|
Author: T. Ishibashi
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -62,7 +62,7 @@ w.a(550), w.b(550), w.c(550)
|
|
|
62
62
|
The same Jerlov water type has different coefficients in different papers, and
|
|
63
63
|
the differences are not small. Solonenko & Mobley (2015) obtained a and b by
|
|
64
64
|
inverting Kd; Williamson & Hollins (2022) measured them. At 510 nm their
|
|
65
|
-
scattering coefficients differ by up to a factor of
|
|
65
|
+
scattering coefficients differ by up to a factor of 3.8, at Jerlov III.
|
|
66
66
|
|
|
67
67
|
The equations differ too. Both papers use the scattering model of Haltrin
|
|
68
68
|
(1999), but with different constants: Haltrin's Eq. (6) gives a
|
|
@@ -588,3 +588,33 @@ def test_c_warns_once_for_a_wavelength_flagged_in_both_a_and_b():
|
|
|
588
588
|
assert messages[0].startswith("c for Jerlov 3C")
|
|
589
589
|
assert "a missing at 675 nm" in messages[0]
|
|
590
590
|
assert "b reconstructed at 675 nm" in messages[0]
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
# -- 0.7.2: inputs that slipped through -------------------------------------
|
|
594
|
+
|
|
595
|
+
@pytest.mark.parametrize("call", [
|
|
596
|
+
lambda: jerlov.water("III").a(float("nan")),
|
|
597
|
+
lambda: jerlov.water("III").c([500.0, float("nan")]),
|
|
598
|
+
lambda: jerlov.water("I", source="jerlov1976").kd(float("nan")),
|
|
599
|
+
lambda: jerlov.water("III", source="solonenko2015").kd_hydrolight(
|
|
600
|
+
float("nan")),
|
|
601
|
+
lambda: jerlov.kd_spectrum(0.06, 490.0, float("nan")),
|
|
602
|
+
lambda: jerlov.kd_spectrum(0.06, float("nan"), 500.0),
|
|
603
|
+
lambda: jerlov.b_from_c(0.5, float("nan"), bw=0.002, cw=0.066),
|
|
604
|
+
])
|
|
605
|
+
def test_a_wavelength_that_is_not_a_number_is_refused(call):
|
|
606
|
+
"""NaN < lo is False, so NaN passed the range check, came back as NaN,
|
|
607
|
+
and warned about the last sample of the table instead."""
|
|
608
|
+
with warnings.catch_warnings():
|
|
609
|
+
warnings.simplefilter("error") # and no misleading warning
|
|
610
|
+
with pytest.raises(ValueError, match="NaN"):
|
|
611
|
+
call()
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
def test_descend_leaves_the_callers_array_alone():
|
|
615
|
+
wl = np.array([450.0, 550.0])
|
|
616
|
+
d = jerlov.descend("II", 30.0, wl)
|
|
617
|
+
assert wl.flags.writeable
|
|
618
|
+
wl[0] = 999.0
|
|
619
|
+
assert d.wavelengths[0] == 450.0
|
|
620
|
+
assert not d.wavelengths.flags.writeable
|
|
@@ -216,3 +216,15 @@ def test_a_salinity_that_is_not_one_is_refused():
|
|
|
216
216
|
with pytest.raises(ValueError, match="salinity_psu"):
|
|
217
217
|
call(bad)
|
|
218
218
|
jerlov.pure_water_vsf(120.0, 532.0, 0.0) # fresh water is fine
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def test_a_wavelength_that_is_not_one_is_refused():
|
|
222
|
+
for bad in (0.0, -500.0, float("nan"), float("inf")):
|
|
223
|
+
for call in (lambda w: jerlov.pure_water_vsf(120.0, w),
|
|
224
|
+
lambda w: jerlov.pure_water_backscattering(w),
|
|
225
|
+
lambda w: jerlov.pure_water_scattering(w),
|
|
226
|
+
lambda w: jerlov.bb_from_vsf(0.0021, 140.0, w)):
|
|
227
|
+
with warnings.catch_warnings():
|
|
228
|
+
warnings.simplefilter("error")
|
|
229
|
+
with pytest.raises(ValueError, match="wavelength_nm"):
|
|
230
|
+
call(bad)
|
|
@@ -37,7 +37,7 @@ def quiet():
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
def test_scattering_at_510nm_differs_by_the_stated_factor():
|
|
40
|
-
"""
|
|
40
|
+
"""sources_disagree.py says 3.8 for Jerlov III."""
|
|
41
41
|
with quiet():
|
|
42
42
|
warnings.simplefilter("ignore")
|
|
43
43
|
measured = float(jerlov.water("III").b(510))
|
|
@@ -45,6 +45,30 @@ def test_scattering_at_510nm_differs_by_the_stated_factor():
|
|
|
45
45
|
assert inverted / measured == pytest.approx(3.8, abs=0.05)
|
|
46
46
|
|
|
47
47
|
|
|
48
|
+
@source_tree
|
|
49
|
+
def test_the_readme_states_the_largest_disagreement_at_510nm():
|
|
50
|
+
"""The README said "up to a factor of 2.6" while this test's docstring
|
|
51
|
+
claimed it said 3.8; nothing read the README, so nothing noticed."""
|
|
52
|
+
from jerlov.sources import SOURCES
|
|
53
|
+
|
|
54
|
+
readme = (ROOT / "README.md").read_text()
|
|
55
|
+
match = re.search(r"differ by up to a factor of ([\d.]+), at Jerlov (\w+)",
|
|
56
|
+
readme)
|
|
57
|
+
assert match, "the README no longer states the factor at 510 nm"
|
|
58
|
+
common = set(SOURCES["williamson2022"].water_types) & set(
|
|
59
|
+
SOURCES["solonenko2015"].water_types)
|
|
60
|
+
with quiet():
|
|
61
|
+
warnings.simplefilter("ignore")
|
|
62
|
+
factors = {}
|
|
63
|
+
for t in common:
|
|
64
|
+
one = float(jerlov.water(t).b(510))
|
|
65
|
+
other = float(jerlov.water(t, source="solonenko2015").b(510))
|
|
66
|
+
factors[t] = max(one, other) / min(one, other)
|
|
67
|
+
worst = max(factors, key=factors.get)
|
|
68
|
+
assert worst == match.group(2)
|
|
69
|
+
assert factors[worst] == pytest.approx(float(match.group(1)), abs=0.05)
|
|
70
|
+
|
|
71
|
+
|
|
48
72
|
def test_the_disagreement_does_not_run_one_way():
|
|
49
73
|
"""sources_disagree.py claims Jerlov IB goes the other direction."""
|
|
50
74
|
with quiet():
|
|
@@ -353,3 +353,11 @@ def test_an_observation_with_no_light_has_a_quiet_repr():
|
|
|
353
353
|
with warnings.catch_warnings():
|
|
354
354
|
warnings.simplefilter("error")
|
|
355
355
|
assert "veiling undefined" in repr(o)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def test_a_scene_does_not_follow_later_changes_to_the_callers_arrays():
|
|
359
|
+
wl, ed = WL.copy(), np.ones(WL.size)
|
|
360
|
+
s = Scene(jerlov.water("II"), ed, wl)
|
|
361
|
+
wl[0], ed[0] = 999.0, -1.0
|
|
362
|
+
assert s.wavelengths[0] == WL[0]
|
|
363
|
+
assert s.downwelling[0] == 1.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|