jerlov 0.7.0__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.
Files changed (49) hide show
  1. {jerlov-0.7.0/jerlov.egg-info → jerlov-0.7.2}/PKG-INFO +6 -3
  2. {jerlov-0.7.0 → jerlov-0.7.2}/README.md +5 -2
  3. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/__init__.py +1 -1
  4. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/backscattering.py +8 -1
  5. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/scene.py +4 -2
  6. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/water.py +8 -1
  7. {jerlov-0.7.0 → jerlov-0.7.2/jerlov.egg-info}/PKG-INFO +6 -3
  8. {jerlov-0.7.0 → jerlov-0.7.2}/pyproject.toml +1 -1
  9. {jerlov-0.7.0 → jerlov-0.7.2}/tests/test_api.py +30 -0
  10. {jerlov-0.7.0 → jerlov-0.7.2}/tests/test_backscattering.py +12 -0
  11. {jerlov-0.7.0 → jerlov-0.7.2}/tests/test_quoted_figures.py +108 -1
  12. {jerlov-0.7.0 → jerlov-0.7.2}/tests/test_scene.py +8 -0
  13. {jerlov-0.7.0 → jerlov-0.7.2}/LICENSE +0 -0
  14. {jerlov-0.7.0 → jerlov-0.7.2}/NOTICE +0 -0
  15. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/_data.py +0 -0
  16. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/colour.py +0 -0
  17. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/__init__.py +0 -0
  18. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/austin1986_kd.csv +0 -0
  19. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/austin1986_model.csv +0 -0
  20. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/boss2001_chi.csv +0 -0
  21. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/cie1931_2deg_cmf.csv +0 -0
  22. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/cie_d65.csv +0 -0
  23. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/jerlov1968_kd.csv +0 -0
  24. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/jerlov1968_total_irradiance.csv +0 -0
  25. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/jerlov1976_kd.csv +0 -0
  26. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/paulson1977_shortwave.csv +0 -0
  27. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/petzold1972_stations.csv +0 -0
  28. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/petzold1972_vsf.csv +0 -0
  29. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/smart2007_b_from_c.csv +0 -0
  30. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/solonenko2015_iop.csv +0 -0
  31. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/williamson2022_aw.csv +0 -0
  32. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/williamson2022_iop.csv +0 -0
  33. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/williamson2022_measured.csv +0 -0
  34. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/data/williamson2023_depth.csv +0 -0
  35. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/petzold.py +0 -0
  36. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/py.typed +0 -0
  37. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/shortwave.py +0 -0
  38. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov/sources.py +0 -0
  39. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov.egg-info/SOURCES.txt +0 -0
  40. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov.egg-info/dependency_links.txt +0 -0
  41. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov.egg-info/requires.txt +0 -0
  42. {jerlov-0.7.0 → jerlov-0.7.2}/jerlov.egg-info/top_level.txt +0 -0
  43. {jerlov-0.7.0 → jerlov-0.7.2}/setup.cfg +0 -0
  44. {jerlov-0.7.0 → jerlov-0.7.2}/tests/test_colour.py +0 -0
  45. {jerlov-0.7.0 → jerlov-0.7.2}/tests/test_depth.py +0 -0
  46. {jerlov-0.7.0 → jerlov-0.7.2}/tests/test_packaging.py +0 -0
  47. {jerlov-0.7.0 → jerlov-0.7.2}/tests/test_petzold.py +0 -0
  48. {jerlov-0.7.0 → jerlov-0.7.2}/tests/test_reproduces_papers.py +0 -0
  49. {jerlov-0.7.0 → 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.0
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 2.6.
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
@@ -333,9 +333,12 @@ python examples/from_one_measurement.py from an instrument reading
333
333
  python examples/synthetic_underwater_images.py appearance at range and depth
334
334
  python examples/solar_heating.py for ocean circulation models
335
335
  python examples/what_an_eye_sees.py any spectral sensitivity
336
+ python examples/light_at_depth.py light through the depth profile
337
+ python examples/measured_scattering.py Petzold's measured bb/b
338
+ python examples/what_is_in_the_water.py absorption without the water
336
339
  ```
337
340
 
338
- Five scripts, each aimed at a different reader; `examples/README.md` says
341
+ Eight scripts, each aimed at a different reader; `examples/README.md` says
339
342
  which to start with. CI runs all of them on every push, so an example that has
340
343
  stopped working is a failed build. Every one ends with the assumptions it
341
344
  made.
@@ -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 2.6.
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
@@ -308,9 +308,12 @@ python examples/from_one_measurement.py from an instrument reading
308
308
  python examples/synthetic_underwater_images.py appearance at range and depth
309
309
  python examples/solar_heating.py for ocean circulation models
310
310
  python examples/what_an_eye_sees.py any spectral sensitivity
311
+ python examples/light_at_depth.py light through the depth profile
312
+ python examples/measured_scattering.py Petzold's measured bb/b
313
+ python examples/what_is_in_the_water.py absorption without the water
311
314
  ```
312
315
 
313
- Five scripts, each aimed at a different reader; `examples/README.md` says
316
+ Eight scripts, each aimed at a different reader; `examples/README.md` says
314
317
  which to start with. CI runs all of them on every push, so an example that has
315
318
  stopped working is a failed build. Every one ends with the assumptions it
316
319
  made.
@@ -96,4 +96,4 @@ __all__ = [
96
96
  "MissingQuantityError",
97
97
  ]
98
98
 
99
- __version__ = "0.7.0"
99
+ __version__ = "0.7.2"
@@ -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
- return (1.38 * (np.asarray(wavelength_nm, dtype=float) / 500.0) ** -4.32
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
- self.wavelengths = np.asarray(wavelengths, dtype=float)
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.asarray(downwelling, dtype=float)
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
- query = _as_array(wavelengths)
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.0
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 2.6.
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
@@ -333,9 +333,12 @@ python examples/from_one_measurement.py from an instrument reading
333
333
  python examples/synthetic_underwater_images.py appearance at range and depth
334
334
  python examples/solar_heating.py for ocean circulation models
335
335
  python examples/what_an_eye_sees.py any spectral sensitivity
336
+ python examples/light_at_depth.py light through the depth profile
337
+ python examples/measured_scattering.py Petzold's measured bb/b
338
+ python examples/what_is_in_the_water.py absorption without the water
336
339
  ```
337
340
 
338
- Five scripts, each aimed at a different reader; `examples/README.md` says
341
+ Eight scripts, each aimed at a different reader; `examples/README.md` says
339
342
  which to start with. CI runs all of them on every push, so an example that has
340
343
  stopped working is a failed build. Every one ends with the assumptions it
341
344
  made.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jerlov"
7
- version = "0.7.0"
7
+ version = "0.7.2"
8
8
  description = "Inherent optical properties of Jerlov water types, with provenance"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -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
- """README and sources_disagree.py both say 3.8 for Jerlov III."""
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():
@@ -263,3 +287,86 @@ def test_DATA_md_section_13_states_where_the_coastal_profiles_end():
263
287
  for t, depth in (("3C", 70.5), ("9C", 10.5), ("5C", 20.5), ("7C", 20.5)):
264
288
  with pytest.raises(jerlov.MissingQuantityError):
265
289
  jerlov.descend(t, depth, 500.0)
290
+
291
+
292
+ def test_DATA_md_section_20_on_the_measurements_at_715_nm():
293
+ """1.004 with no spread for 1C, 3C, 5C; 1.018 for III; 14 to 16 percent
294
+ above the fit, which is aw there."""
295
+ import numpy as np
296
+
297
+ excess = []
298
+ for t in ("III", "1C", "3C", "5C"):
299
+ m = jerlov.measured_points(t, "a")
300
+ k = int(np.where(m.wavelengths == 715.0)[0][0])
301
+ if t == "III":
302
+ assert m.values[k] == pytest.approx(1.018, abs=0.0005)
303
+ else:
304
+ assert m.values[k] == 1.004
305
+ assert m.std_dev[k] < 1e-12
306
+ with warnings.catch_warnings():
307
+ warnings.simplefilter("ignore", jerlov.ProvenanceWarning)
308
+ fitted = jerlov.water(t).a(715.0)
309
+ assert fitted == pytest.approx(jerlov.pure_water_absorption(715.0),
310
+ rel=0.01)
311
+ excess.append(100 * (m.values[k] / fitted - 1))
312
+ assert 13.5 < min(excess) and max(excess) < 16.0
313
+
314
+
315
+ def test_examples_README_figures_for_the_depth_profile():
316
+ """3C receives 530 times more light at 60 m, I a third less; the 1
317
+ percent level of I rises from 197 to 133 m (all at 490 nm)."""
318
+ import math
319
+
320
+ def one_kd(t, z):
321
+ return math.exp(-jerlov.water(t, source="jerlov1976").kd(490.0) * z)
322
+
323
+ ratio_3c = jerlov.descend("3C", 60.0, 490.0).transmittance / one_kd("3C", 60.0)
324
+ ratio_i = jerlov.descend("I", 60.0, 490.0).transmittance / one_kd("I", 60.0)
325
+ assert round(ratio_3c, -1) == 530
326
+ assert ratio_i == pytest.approx(2 / 3, abs=0.02)
327
+
328
+ def depth_of_one_percent(t, layered):
329
+ for z in [k / 2 for k in range(1, 401)]:
330
+ t_z = (jerlov.descend(t, z, 490.0).transmittance if layered
331
+ else one_kd(t, z))
332
+ if t_z <= 0.01:
333
+ return z
334
+
335
+ assert depth_of_one_percent("I", False) == 197.0
336
+ assert depth_of_one_percent("I", True) == 133.0
337
+
338
+
339
+ def test_examples_README_figures_for_absorption_by_the_contents():
340
+ """Twelve times at 412 nm; pure water 78 to 98 percent at 600 nm."""
341
+ aw412, aw600 = (jerlov.pure_water_absorption(nm) for nm in (412, 600))
342
+ ratio = ((jerlov.water("5C").a(412) - aw412)
343
+ / (jerlov.water("IB").a(412) - aw412))
344
+ assert round(ratio) == 12
345
+ shares = [aw600 / jerlov.water(t).a(600)
346
+ for t in jerlov.get_source("williamson2022").water_types]
347
+ assert (round(100 * min(shares)), round(100 * max(shares))) == (78, 98)
348
+
349
+
350
+ def test_examples_README_figure_for_measured_backscatter_ratios():
351
+ """measured_scattering.py: contrast at 5 m from 4.0 to 2.6 at 550 nm
352
+ across the coastal and harbor stations' ratios."""
353
+ import numpy as np
354
+
355
+ wl = np.arange(450.0, 651.0, 50.0)
356
+ w = jerlov.water("1C")
357
+ with warnings.catch_warnings():
358
+ warnings.simplefilter("ignore", jerlov.ProvenanceWarning)
359
+ scene = jerlov.Scene.at_depth(
360
+ w, 10.0, np.interp(wl, *jerlov.d65()), wl,
361
+ kd=jerlov.water("1C", source="austin1986"))
362
+ contrasts = []
363
+ for s in jerlov.PETZOLD_STATIONS:
364
+ if s.startswith("AUTEC"):
365
+ continue
366
+ ratio = jerlov.petzold_scattering(s).backscatter_ratio
367
+ b_inf = jerlov.veiling_radiance_estimate(
368
+ w, scene.downwelling, wl, backscatter_ratio=ratio)
369
+ seen = scene.observe(np.full(wl.size, 0.3), 5.0,
370
+ veiling_radiance=b_inf)
371
+ contrasts.append(seen.contrast(b_inf)[2])
372
+ assert (round(max(contrasts), 1), round(min(contrasts), 1)) == (4.0, 2.6)
@@ -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