jerlov 0.2.1__tar.gz → 0.2.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.2.1/jerlov.egg-info → jerlov-0.2.2}/PKG-INFO +10 -9
- {jerlov-0.2.1 → jerlov-0.2.2}/README.md +9 -8
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/__init__.py +1 -1
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/colour.py +10 -7
- {jerlov-0.2.1 → jerlov-0.2.2/jerlov.egg-info}/PKG-INFO +10 -9
- {jerlov-0.2.1 → jerlov-0.2.2}/pyproject.toml +1 -1
- {jerlov-0.2.1 → jerlov-0.2.2}/tests/test_colour.py +8 -3
- {jerlov-0.2.1 → jerlov-0.2.2}/tests/test_packaging.py +64 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/LICENSE +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/NOTICE +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/_data.py +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/__init__.py +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/austin1986_kd.csv +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/austin1986_model.csv +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/cie1931_2deg_cmf.csv +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/cie_d65.csv +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/jerlov1968_kd.csv +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/jerlov1968_total_irradiance.csv +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/jerlov1976_kd.csv +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/paulson1977_shortwave.csv +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/smart2007_b_from_c.csv +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/solonenko2015_iop.csv +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/williamson2022_iop.csv +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/williamson2022_measured.csv +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/data/williamson2023_depth.csv +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/scene.py +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/shortwave.py +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/sources.py +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov/water.py +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov.egg-info/SOURCES.txt +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov.egg-info/dependency_links.txt +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov.egg-info/requires.txt +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/jerlov.egg-info/top_level.txt +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/setup.cfg +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/tests/test_api.py +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/tests/test_depth.py +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/tests/test_reproduces_papers.py +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/tests/test_scene.py +0 -0
- {jerlov-0.2.1 → jerlov-0.2.2}/tests/test_shortwave.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jerlov
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.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
|
|
@@ -257,16 +257,17 @@ rather than substituting a neighbour.
|
|
|
257
257
|
## Examples
|
|
258
258
|
|
|
259
259
|
```
|
|
260
|
-
python examples/sources_disagree.py
|
|
261
|
-
python examples/
|
|
260
|
+
python examples/sources_disagree.py why the source is an argument
|
|
261
|
+
python examples/from_one_measurement.py from an instrument reading
|
|
262
|
+
python examples/synthetic_underwater_images.py appearance at range and depth
|
|
263
|
+
python examples/solar_heating.py for ocean circulation models
|
|
264
|
+
python examples/what_an_eye_sees.py any spectral sensitivity
|
|
262
265
|
```
|
|
263
266
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
Both are run by CI, so an example that has stopped working is a failed build.
|
|
267
|
+
Five scripts, each aimed at a different reader; `examples/README.md` says
|
|
268
|
+
which to start with. CI runs all of them on every push, so an example that has
|
|
269
|
+
stopped working is a failed build. Every one ends with the assumptions it
|
|
270
|
+
made.
|
|
270
271
|
|
|
271
272
|
## Provenance and design
|
|
272
273
|
|
|
@@ -232,16 +232,17 @@ rather than substituting a neighbour.
|
|
|
232
232
|
## Examples
|
|
233
233
|
|
|
234
234
|
```
|
|
235
|
-
python examples/sources_disagree.py
|
|
236
|
-
python examples/
|
|
235
|
+
python examples/sources_disagree.py why the source is an argument
|
|
236
|
+
python examples/from_one_measurement.py from an instrument reading
|
|
237
|
+
python examples/synthetic_underwater_images.py appearance at range and depth
|
|
238
|
+
python examples/solar_heating.py for ocean circulation models
|
|
239
|
+
python examples/what_an_eye_sees.py any spectral sensitivity
|
|
237
240
|
```
|
|
238
241
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
Both are run by CI, so an example that has stopped working is a failed build.
|
|
242
|
+
Five scripts, each aimed at a different reader; `examples/README.md` says
|
|
243
|
+
which to start with. CI runs all of them on every push, so an example that has
|
|
244
|
+
stopped working is a failed build. Every one ends with the assumptions it
|
|
245
|
+
made.
|
|
245
246
|
|
|
246
247
|
## Provenance and design
|
|
247
248
|
|
|
@@ -151,15 +151,18 @@ def integrate_response(spectrum, wavelengths, response, response_wavelengths,
|
|
|
151
151
|
if wavelengths.size < 2:
|
|
152
152
|
raise ValueError("at least two wavelengths are needed to integrate")
|
|
153
153
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
)
|
|
154
|
+
covered = [_coverage(wavelengths, response_wavelengths, response[:, k])
|
|
155
|
+
for k in range(response.shape[1])]
|
|
156
|
+
worst = min(covered)
|
|
158
157
|
if worst < 0.999:
|
|
158
|
+
which = (f"channel {covered.index(worst)} of {len(covered)}"
|
|
159
|
+
if len(covered) > 1 else "it")
|
|
159
160
|
warnings.warn(
|
|
160
|
-
f"the spectrum spans {wavelengths[0]:g}-{wavelengths[-1]:g} nm
|
|
161
|
-
f"
|
|
162
|
-
"
|
|
161
|
+
f"the spectrum spans {wavelengths[0]:g}-{wavelengths[-1]:g} nm; "
|
|
162
|
+
f"of the {name}, {which} is only {worst:.1%} covered "
|
|
163
|
+
f"(all channels: {', '.join(f'{c:.1%}' for c in covered)}). "
|
|
164
|
+
"The integral is over the overlap and is biased by what was left "
|
|
165
|
+
"out",
|
|
163
166
|
CoverageWarning,
|
|
164
167
|
stacklevel=2,
|
|
165
168
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jerlov
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.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
|
|
@@ -257,16 +257,17 @@ rather than substituting a neighbour.
|
|
|
257
257
|
## Examples
|
|
258
258
|
|
|
259
259
|
```
|
|
260
|
-
python examples/sources_disagree.py
|
|
261
|
-
python examples/
|
|
260
|
+
python examples/sources_disagree.py why the source is an argument
|
|
261
|
+
python examples/from_one_measurement.py from an instrument reading
|
|
262
|
+
python examples/synthetic_underwater_images.py appearance at range and depth
|
|
263
|
+
python examples/solar_heating.py for ocean circulation models
|
|
264
|
+
python examples/what_an_eye_sees.py any spectral sensitivity
|
|
262
265
|
```
|
|
263
266
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
Both are run by CI, so an example that has stopped working is a failed build.
|
|
267
|
+
Five scripts, each aimed at a different reader; `examples/README.md` says
|
|
268
|
+
which to start with. CI runs all of them on every push, so an example that has
|
|
269
|
+
stopped working is a failed build. Every one ends with the assumptions it
|
|
270
|
+
made.
|
|
270
271
|
|
|
271
272
|
## Provenance and design
|
|
272
273
|
|
|
@@ -73,7 +73,7 @@ def test_each_primary_lights_only_its_own_channel():
|
|
|
73
73
|
def test_a_narrow_spectrum_warns():
|
|
74
74
|
"""450-650 nm looks like a full spectrum but is not."""
|
|
75
75
|
wl = np.arange(450.0, 651.0, 1.0)
|
|
76
|
-
with pytest.warns(CoverageWarning, match="
|
|
76
|
+
with pytest.warns(CoverageWarning, match="covered"):
|
|
77
77
|
spectrum_to_xyz(np.ones_like(wl), wl)
|
|
78
78
|
|
|
79
79
|
|
|
@@ -88,8 +88,13 @@ def test_the_warning_states_what_was_missed():
|
|
|
88
88
|
with pytest.warns(CoverageWarning) as caught:
|
|
89
89
|
spectrum_to_xyz(np.ones_like(wl), wl)
|
|
90
90
|
message = str(caught[0].message)
|
|
91
|
-
assert "500-600 nm" in message
|
|
92
|
-
assert "CIE 1931" in message
|
|
91
|
+
assert "500-600 nm" in message # the span it actually had
|
|
92
|
+
assert "CIE 1931" in message # what it was integrated against
|
|
93
|
+
assert "all channels:" in message # not just the worst one
|
|
94
|
+
# z-bar peaks at 445 nm, so 500-600 nm barely touches it. Naming the
|
|
95
|
+
# channel matters: "4.1% covered" alone reads as if the whole observer
|
|
96
|
+
# were 4.1% covered, which would be wrong.
|
|
97
|
+
assert "channel 2 of 3" in message
|
|
93
98
|
|
|
94
99
|
|
|
95
100
|
# -- white, the other one ------------------------------------------------
|
|
@@ -76,3 +76,67 @@ def test_every_shipped_table_has_a_build_script_or_is_explained():
|
|
|
76
76
|
scripts = " ".join(p.read_text() for p in (ROOT / "tools").glob("*.py"))
|
|
77
77
|
for csv in sorted((ROOT / "jerlov" / "data").glob("*.csv")):
|
|
78
78
|
assert csv.name in scripts, f"no build script writes {csv.name}"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# -- the documentation counts itself -------------------------------------
|
|
82
|
+
|
|
83
|
+
_SPELLED = ["zero", "one", "two", "three", "four", "five", "six", "seven",
|
|
84
|
+
"eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
|
|
85
|
+
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen",
|
|
86
|
+
"twenty", "twenty-one", "twenty-two", "twenty-three",
|
|
87
|
+
"twenty-four", "twenty-five"]
|
|
88
|
+
WORDS = {word: value for value, word in enumerate(_SPELLED)}
|
|
89
|
+
WORDS.update({word.capitalize(): value
|
|
90
|
+
for value, word in enumerate(_SPELLED)})
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _numbered_sections(text: str) -> int:
|
|
94
|
+
return len(re.findall(r"^## \d+\. ", text, re.MULTILINE))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _confirmed_sections(text: str) -> int:
|
|
98
|
+
return len(re.findall(r"^## \d+\..*\(confirmed", text, re.MULTILINE))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@source_tree
|
|
102
|
+
def test_DATA_md_counts_its_own_sections():
|
|
103
|
+
"""The opening summary is written by hand and has drifted three times."""
|
|
104
|
+
text = (ROOT / "DATA.md").read_text()
|
|
105
|
+
match = re.search(r"^(\w+) entries are recorded below\. (\w+) are confirmed",
|
|
106
|
+
text, re.MULTILINE)
|
|
107
|
+
assert match, "DATA.md no longer opens with a countable summary"
|
|
108
|
+
claimed_total, claimed_confirmed = (WORDS[g] for g in match.groups())
|
|
109
|
+
assert claimed_total == _numbered_sections(text)
|
|
110
|
+
assert claimed_confirmed == _confirmed_sections(text)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@source_tree
|
|
114
|
+
def test_the_zenodo_record_will_carry_what_it_should():
|
|
115
|
+
"""`.zenodo.json` is only read at archive time, so nothing else checks it."""
|
|
116
|
+
import json
|
|
117
|
+
|
|
118
|
+
record = json.loads((ROOT / ".zenodo.json").read_text())
|
|
119
|
+
assert record["upload_type"] == "software"
|
|
120
|
+
assert record["license"] == "Apache-2.0"
|
|
121
|
+
assert record["creators"], "a record with no author is not citable"
|
|
122
|
+
for creator in record["creators"]:
|
|
123
|
+
assert creator.get("orcid"), (
|
|
124
|
+
f"{creator['name']} has no ORCID, so the record will not attach "
|
|
125
|
+
"to their publication list"
|
|
126
|
+
)
|
|
127
|
+
# Every source the package ships data from should be reachable from the
|
|
128
|
+
# record, not only from DATA.md.
|
|
129
|
+
derived = [r["identifier"] for r in record["related_identifiers"]
|
|
130
|
+
if r["relation"] == "isDerivedFrom"]
|
|
131
|
+
assert len(derived) >= 8, derived
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@source_tree
|
|
135
|
+
def test_the_README_agrees_with_DATA_md_on_the_count():
|
|
136
|
+
data = (ROOT / "DATA.md").read_text()
|
|
137
|
+
readme = (ROOT / "README.md").read_text()
|
|
138
|
+
match = re.search(r"(\w+) entries are\s+documented there: (\w+) confirmed",
|
|
139
|
+
readme)
|
|
140
|
+
assert match, "the README no longer states the count"
|
|
141
|
+
assert WORDS[match.group(1)] == _numbered_sections(data)
|
|
142
|
+
assert WORDS[match.group(2)] == _confirmed_sections(data)
|
|
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
|