Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oceans674 #689

Merged
merged 13 commits into from
Jul 6, 2022
33 changes: 26 additions & 7 deletions pyaerocom/region.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from pyaerocom._lowlevel_helpers import BrowseDict
from pyaerocom.config import ALL_REGION_NAME
from pyaerocom.helpers_landsea_masks import load_region_mask_xr
from pyaerocom.helpers_landsea_masks import get_mask_value, load_region_mask_xr
from pyaerocom.region_defs import HTAP_REGIONS # list of HTAP regions
from pyaerocom.region_defs import REGION_DEFS # all region definitions
from pyaerocom.region_defs import OLD_AEROCOM_REGIONS, REGION_NAMES # custom names (dict)
Expand Down Expand Up @@ -142,8 +142,23 @@ def contains_coordinate(self, lat, lon):
bool
True if coordinate is contained in this region, False if not
"""
lat_ok = self.lat_range[0] <= lat <= self.lat_range[1]
lon_ok = self.lon_range[0] <= lon <= self.lon_range[1]

lat_lb = self.lat_range[0]
lat_ub = self.lat_range[1]
lon_lb = self.lon_range[0]
lon_ub = self.lon_range[1]
# latitude bounding boxes should always be defined with the southern most boundary less than the northernmost
lat_ok = lat_lb <= lat <= lat_ub
# if the longitude bounding box has a lowerbound less than the upperbound
if lon_lb < lon_ub:
# it suffices to check that lon is between these values
lon_ok = lon_lb <= lon <= lon_ub
# if the longitude lowerbound has a value lessthan the upperbound
elif lon_ub < lon_lb:
# lon is contained in the bounding box in two cases
lon_ok = lon < lon_ub or lon > lon_lb
else:
lon_ok = False # safeguard
return lat_ok * lon_ok

def mask_available(self):
Expand Down Expand Up @@ -310,7 +325,7 @@ def get_all_default_regions():

#: ToDO: check how to handle methods properly with HTAP regions...
def get_regions_coord(lat, lon, regions=None):
"""Get all regions that contain input coordinate
"""Get the region that contains an input coordinate
Note
----
Expand All @@ -332,14 +347,18 @@ def get_regions_coord(lat, lon, regions=None):
list
list of regions that contain this coordinate
"""

matches = []
if regions is None:
regions = get_all_default_regions()
ocean_mask = load_region_mask_xr("OCN")
on_ocean = get_mask_value(lat, lon, ocean_mask)
for rname, reg in regions.items():
if rname == ALL_REGION_NAME: # always True
if rname == ALL_REGION_NAME: # always True for ALL_REGION_NAME
continue
if reg.contains_coordinate(lat, lon):
# OCN needs special handling determined by the rname, not hardcoded to return OCN b/c of HTAP issues
if reg.contains_coordinate(lat, lon) and not on_ocean:
matches.append(rname)
if rname == "OCN" and on_ocean:
matches.append(rname)
if len(matches) == 0:
matches.append(ALL_REGION_NAME)
Expand Down
65 changes: 65 additions & 0 deletions tests/test_region.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import pytest

from pyaerocom.region import Region, get_regions_coord


@pytest.mark.parametrize(
"region_name, lat, lon",
[
("ALL", 0, 0),
("NAM", 39.7555, -105.2211),
("NAM", 19.5364, -155.5765),
("PAN", -37.8136, 144.9631),
("RBU", 50.4501, 30.5234),
("EUR", 59.9139, 10.7522),
],
)
def test_contains_coordinate(region_name, lat, lon):
reg = Region(region_name)
assert reg.contains_coordinate(lat, lon)


@pytest.mark.parametrize(
"region_name, lat, lon",
[
("EAS", 0, 0),
("MCA", 51.5072, 0.1276),
("MDE", 10.4806, -66.9036),
("SEA", -33.9249, 18.4241),
],
)
def test_does_not_contain_coordinate(region_name, lat, lon):
reg = Region(region_name)
assert not reg.contains_coordinate(lat, lon)


# This test needs work because Region() can accept almost any key in region_defs.py and they are not consistent.
# NAF, NAFRICA, N Africa, for example. Running in a debugger exposes the inconsistencies
@pytest.mark.parametrize(
"region_name, lat, lon",
[
("EUROPE", 48.864716, 2.349014),
("NAFRICA", 30.033333, 31.233334),
("ALL", 0.0, 0.0),
],
)
def test_get_regions_coord(region_name, lat, lon):
reg = Region(region_name)
assert reg.region_id in get_regions_coord(lat, lon)


@pytest.mark.parametrize(
"region_name, lat, lon",
[
("SAM", -33.447487, -70.673676),
("ASIA", 39.916668, 116.383331),
("OCN", 0.0, 0.0),
],
)
def test_get_regions_coord_with_supplied_regions_dict(region_name, lat, lon):
oceans = Region("OCN")
sam = Region("SAM")
asia = Region("ASIA")
regions = {"OCN": oceans, "SAM": sam, "ASIA": asia}
reg = Region(region_name)
assert reg.region_id in get_regions_coord(lat, lon, regions)