Skip to content

Commit e060cac

Browse files
authored
Merge branch 'master' into fix/invalid-param-error-messages
2 parents 5414435 + 5b82f0b commit e060cac

6 files changed

Lines changed: 80 additions & 11 deletions

File tree

malariagen_data/anoph/frq_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ def plot_frequencies_heatmap(
227227
**kwargs,
228228
) -> plotly_params.figure:
229229
# Check len of input.
230-
if max_len and len(df) > max_len:
230+
if max_len is not None and len(df) > max_len:
231231
raise ValueError(
232232
dedent(
233233
f"""

malariagen_data/anoph/g123.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,9 @@ def _garud_g123(gt):
629629
# convert to array of sorted frequencies
630630
f = np.sort(np.fromiter(frq_counter.values(), dtype=float))[::-1]
631631

632+
if f.size == 0:
633+
return np.nan
634+
632635
# compute G123
633636
g123 = np.sum(f[:3]) ** 2 + np.sum(f[3:] ** 2)
634637

malariagen_data/anoph/h12.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,9 @@ def _garud_h12(ht):
848848
# Convert to array of sorted frequencies.
849849
f = np.sort(np.fromiter(frq_counter.values(), dtype=float))[::-1]
850850

851+
if f.size == 0:
852+
return np.nan
853+
851854
# Compute H12.
852855
h12 = np.sum(f[:2]) ** 2 + np.sum(f[2:] ** 2)
853856

malariagen_data/anoph/map_params.py

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Parameters for functions plotting maps using ipyleaflet."""
22

3+
import warnings
34
from typing import Dict, Tuple, Union
45

56
import ipyleaflet # type: ignore
@@ -17,22 +18,70 @@
1718

1819
zoom_default: zoom = 3
1920

20-
basemap_abbrevs = {
21-
"mapnik": ipyleaflet.basemaps.OpenStreetMap.Mapnik,
22-
"natgeoworldmap": ipyleaflet.basemaps.Esri.NatGeoWorldMap,
23-
"opentopomap": ipyleaflet.basemaps.OpenTopoMap,
24-
"positron": ipyleaflet.basemaps.CartoDB.Positron,
25-
"satellite": ipyleaflet.basemaps.Gaode.Satellite,
26-
"worldimagery": ipyleaflet.basemaps.Esri.WorldImagery,
27-
"worldstreetmap": ipyleaflet.basemaps.Esri.WorldStreetMap,
28-
"worldtopomap": ipyleaflet.basemaps.Esri.WorldTopoMap,
21+
# Candidate basemap abbreviations — loaded lazily to avoid import failures
22+
# if a provider has been decommissioned upstream.
23+
_basemap_abbrev_candidates = {
24+
"mapnik": lambda: ipyleaflet.basemaps.OpenStreetMap.Mapnik,
25+
"natgeoworldmap": lambda: ipyleaflet.basemaps.Esri.NatGeoWorldMap,
26+
"opentopomap": lambda: ipyleaflet.basemaps.OpenTopoMap,
27+
"positron": lambda: ipyleaflet.basemaps.CartoDB.Positron,
28+
"satellite": lambda: ipyleaflet.basemaps.Gaode.Satellite,
29+
"worldimagery": lambda: ipyleaflet.basemaps.Esri.WorldImagery,
30+
"worldstreetmap": lambda: ipyleaflet.basemaps.Esri.WorldStreetMap,
31+
"worldtopomap": lambda: ipyleaflet.basemaps.Esri.WorldTopoMap,
2932
}
3033

34+
_basemap_abbrevs: dict | None = None
35+
36+
37+
def get_basemap_abbrevs() -> dict:
38+
"""Return available basemap abbreviations, skipping any unavailable providers."""
39+
global _basemap_abbrevs
40+
if _basemap_abbrevs is None:
41+
_basemap_abbrevs = {}
42+
for key, provider_fn in _basemap_abbrev_candidates.items():
43+
try:
44+
_basemap_abbrevs[key] = provider_fn()
45+
except Exception:
46+
warnings.warn(
47+
f"Basemap provider {key!r} is not available and will be skipped.",
48+
stacklevel=2,
49+
)
50+
return _basemap_abbrevs
51+
52+
53+
# Keep basemap_abbrevs as a property-like alias for backwards compatibility.
54+
# Code that does `map_params.basemap_abbrevs` will call get_basemap_abbrevs().
55+
class _BasemapAbbrevProxy:
56+
def __getattr__(self, item):
57+
return getattr(get_basemap_abbrevs(), item)
58+
59+
def __iter__(self):
60+
return iter(get_basemap_abbrevs())
61+
62+
def __getitem__(self, item):
63+
return get_basemap_abbrevs()[item]
64+
65+
def __contains__(self, item):
66+
return item in get_basemap_abbrevs()
67+
68+
def keys(self):
69+
return get_basemap_abbrevs().keys()
70+
71+
def values(self):
72+
return get_basemap_abbrevs().values()
73+
74+
def items(self):
75+
return get_basemap_abbrevs().items()
76+
77+
78+
basemap_abbrevs = _BasemapAbbrevProxy()
79+
3180
basemap: TypeAlias = Annotated[
3281
Union[str, Dict, ipyleaflet.TileLayer, xyzservices.lib.TileProvider],
3382
f"""
3483
Basemap from ipyleaflet or other TileLayer provider. Strings are abbreviations mapped to corresponding
35-
basemaps, available values are {list(basemap_abbrevs.keys())}.
84+
basemaps, available values are {list(_basemap_abbrev_candidates.keys())}.
3685
""",
3786
]
3887

tests/anoph/test_g123.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,10 @@ def test_g123_calibration(fixture, api: AnophelesG123Analysis):
265265
# Run plotting function.
266266
fig = api.plot_g123_calibration(**g123_params, show=False)
267267
assert isinstance(fig, bokeh.models.Plot)
268+
269+
270+
def test_garud_g123_empty_window():
271+
import numpy as np
272+
from malariagen_data.anoph.g123 import _garud_g123
273+
274+
assert np.isnan(_garud_g123(np.empty((0, 0), dtype=int)))

tests/anoph/test_h12.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,3 +328,10 @@ def test_h12_gwss_multi_with_analysis(fixture, api: AnophelesH12Analysis):
328328
params["min_cohort_size"] = n2 + 1
329329
with pytest.raises(ValueError):
330330
api.plot_h12_gwss_multi_panel(**params)
331+
332+
333+
def test_garud_h12_empty_window():
334+
import numpy as np
335+
from malariagen_data.anoph.h12 import _garud_h12
336+
337+
assert np.isnan(_garud_h12(np.empty((0, 0), dtype=int)))

0 commit comments

Comments
 (0)