"""
Bounding regions for commonly plotted polar regions. In stereographic projections. The
format is (xmin, xmax, ymin, ymax), in meters.
"""
import typing
import pandas as pd
import verde as vd
from shapely import Polygon
from polartoolkit import ( # pylint: disable=import-self
maps,
regions, # noqa: PLW0406
utils,
)
try:
import ipyleaflet
except ImportError:
try:
from IPython.display import display
except ImportError:
#####
#####
# Antarctica
#####
#####
# regions
[docs]
antarctica = (-2800e3, 2800e3, -2800e3, 2800e3)
[docs]
west_antarctica = (-2740e3, 570e3, -2150e3, 1670e3)
[docs]
east_antarctica = (-840e3, 2880e3, -2400e3, 2600e3)
[docs]
antarctic_peninsula = (-2600e3, -1200e3, 170e3, 1800e3)
[docs]
marie_byrd_land = (-1500e3, -500e3, -1350e3, -800e3)
[docs]
victoria_land = (100e3, 1000e3, -2200e3, -1000e3)
# wilkes_land
# queen_maud_land
[docs]
saunders_coast = (-980e3, -600e3, -1350e3, -1100e3)
# study_sites
[docs]
roosevelt_island = (-480e3, -240e3, -1220e3, -980e3)
[docs]
ross_island = (210e3, 360e3, -1400e3, -1250e3)
[docs]
minna_bluff = (210e3, 390e3, -1310e3, -1120e3)
# discovery_deep
[docs]
mcmurdo_dry_valleys = (320e3, 480e3, -1400e3, -1220e3)
[docs]
siple_coast = (-700e3, 30e3, -1110e3, -450e3)
[docs]
crary_ice_rise = (-330e3, -40e3, -830e3, -480e3)
[docs]
siple_dome = (-630e3, -270e3, -970e3, -630e3)
# ice_shelves
# WEST ANTARCTICA
[docs]
ross_ice_shelf = (-680e3, 470e3, -1420e3, -310e3)
# withrow_ice_shelf =
# swinburne_ice_shelf =
# sulzberger_ice_shelf =
[docs]
nickerson_ice_shelf = (-980e3, -787e3, -1327e3, -1210e3)
# land_ice_shelf =
[docs]
getz_ice_shelf = (-1624e3, -1130e3, -1234e3, -664e3)
# dotson_ice_shelf = ()
# crosson_ice_shelf = ()
# thwaites_ice_shelf = ()
# pine_island_ice_shelf = ()
# cosgrove_ice_shelf = ()
# abbott_ice_shelf = ()
# venable_ice_shelf = ()
# ferrigno_ice_shelf = ()
# stange_ice_shelf = ()
# bach_ice_shelf = ()
# wilkins_ice_shelf = ()
[docs]
george_vi_ice_shelf = (-2150e3, -1690e3, 540e3, 860e3)
# wordie_ice_shelf = ()
[docs]
larsen_ice_shelf = (-2430e3, -1920e3, 900e3, 1400e3)
# larson_b_ice_shelf = ()
# larson_c_ice_shelf = ()
# larson_d_ice_shelf = ()
# larson_e_ice_shelf = ()
# larson_f_ice_shelf = ()
# larson_g_ice_shelf = ()
[docs]
ronne_filchner_ice_shelf = (-1550e3, -500e3, 80e3, 1100e3)
[docs]
ronne_ice_shelf = (-1550e3, -725e3, 45e3, 970e3)
# filchner_ice_shelf =
# EAST ANTARCTICA
# stancomb_brunt_ice_shelf = ()
# riiser_larsen_ice_shelf = ()
# quar_ice_shelf = ()
# ekstrom_ice_shelf = ()
# atka_ice_shelf = ()
# jelbart_ice_shelf = ()
[docs]
fimbul_ice_shelf = (-260e3, 430e3, 1900e3, 2350e3)
# vigrid_ice_shelf = ()
# nivl_ice_shelf = ()
# lazarev_ice_shelf = ()
# borchgrevink_ice_shelf = ()
[docs]
baudouin_ice_shelf = (855e3, 1250e3, 1790e3, 2080e3)
# prince_harald_ice_shelf = ()
# shirase_ice_shelf = ()
# rayner_ice_shelf = ()
# edward_vii_ice_shelf = ()
# wilma_ice_shelf = ()
# robert_ice_shelf = ()
# downer_ice_shelf = ()
[docs]
amery_ice_shelf = (1530e3, 2460e3, 430e3, 1000e3)
# publications_ice_shelf = ()
# west_ice_shelf = ()
# shackleton_ice_shelf = ()
# tracy_tremenchus_ice_shelf = ()
# conger_ice_shelf = ()
# vicennes_ice_shelf = ()
# totten_ice_shelf = ()
# moscow_university_ice_shelf = ()
# holmes_ice_shelf = ()
# dibble_ice_shelf = ()
# mertz_ice_shelf = ()
# ninnis_ice_shelf = ()
# cook_east_ice_shelf = ()
# rennick_ice_shelf = ()
# lillie_ice_shelf = ()
# mariner_ice_shelf = ()
# aviator_ice_shelf = ()
# nansen_ice_shelf = ()
# drygalski_ice_shelf = ()
# glaciers
# byrd_glacier
# nimrod_glacier
[docs]
pine_island_glacier = (-1720e3, -1480e3, -380e3, -70e3)
[docs]
thwaites_glacier = (-1650e3, -1200e3, -600e3, -300e3)
[docs]
kamb_ice_stream = (-620e3, -220e3, -800e3, -400e3)
# whillans_ice_stream = ()
# seas
[docs]
ross_sea = (-500e3, 450e3, -2100e3, -1300e3)
# amundsen_sea
# bellinghausen_sea
# weddell_sea
# subglacial lakes
[docs]
lake_vostok = (1100e3, 1535e3, -470e3, -230e3)
# ice catchements
#####
#####
# Greenland
#####
#####
# regions
[docs]
greenland = (-700e3, 900e3, -3400e3, -600e3)
[docs]
north_greenland = (-500e3, 600e3, -1200e3, -650e3)
# northwest_greenland = ()
# northeast_greenland = ()
# west_greenland = ()
# east_greenland = ()
# southeast_greenland = ()
# southwest_greenland = ()
# glaciers
[docs]
kangerlussuaq_glacier = (380e3, 550e3, -2340e3, -2140e3)
[docs]
def get_regions() -> dict[str, tuple[float, float, float, float]]:
"""
get all the regions defined in this module.
Returns
-------
dict[str, tuple[float, float, float, float] ]
dictionary of each defined region's name and values
"""
exclude_list = [
"__",
"pd",
"vd",
"utils",
"regions",
"TYPE_CHECKING",
"Union",
"maps",
"ipyleaflet",
"ipywidgets",
"Polygon",
"combine_regions",
"draw_region",
"get_regions",
"annotations",
"typing",
"display",
"alter_region",
"regions_overlap",
]
return {
k: v
for k, v in vars(regions).items()
if (k not in exclude_list) & (not k.startswith("_"))
}
[docs]
def alter_region(
starting_region: tuple[float, float, float, float],
zoom: float = 0,
n_shift: float = 0,
w_shift: float = 0,
) -> tuple[float, float, float, float]:
"""
Change a bounding region by shifting the box east/west or north/south, or zooming in
or out.
Parameters
----------
starting_region : tuple[float, float, float, float]
Initial region in meters in format [xmin, xmax, ymin, ymax]
zoom : float, optional
zoom in or out, in meters, by default 0
n_shift : float, optional
shift north, or south if negative, in meters, by default 0
w_shift : float, optional
shift west, or east if negative, in meters, by default 0
Returns
-------
tuple[float, float, float, float]
Returns the altered region
"""
starting_e, starting_w = starting_region[0], starting_region[1]
starting_n, starting_s = starting_region[2], starting_region[3]
xmin = starting_e + zoom + w_shift
xmax = starting_w - zoom + w_shift
ymin = starting_n + zoom - n_shift
ymax = starting_s - zoom - n_shift
return (xmin, xmax, ymin, ymax)
[docs]
def regions_overlap(
region1: tuple[float, float, float, float],
region2: tuple[float, float, float, float],
) -> tuple[float, float, float, float]:
"""
Get the overlap of 2 regions.
Parameters
----------
region1 : tuple[float, float, float, float]
first region, in the format (xmin, xmax, ymin, ymax)
region2 : tuple[float, float, float, float]
second region in the format (xmin, xmax, ymin, ymax)
Returns
-------
tuple[float, float, float, float]
Overlap of the 2 supplied regions.
"""
# create a polygon from the region
polygon1 = Polygon(
[
(region1[0], region1[2]),
(region1[0], region1[3]),
(region1[1], region1[3]),
(region1[1], region1[2]),
(region1[0], region1[2]),
]
)
polygon2 = Polygon(
[
(region2[0], region2[2]),
(region2[0], region2[3]),
(region2[1], region2[3]),
(region2[1], region2[2]),
(region2[0], region2[2]),
]
)
# get the intersection of the 2 polygons
intersection = polygon1.intersection(polygon2)
return utils.region_to_bounding_box(intersection.bounds)
[docs]
def combine_regions(
region1: tuple[float, float, float, float],
region2: tuple[float, float, float, float],
) -> tuple[float, float, float, float]:
"""
Get the bounding region of 2 regions.
Parameters
----------
region1 : tuple[float, float, float, float]
first region, in the format (xmin, xmax, ymin, ymax)
region2 : tuple[float, float, float, float]
second region in the format (xmin, xmax, ymin, ymax)
Returns
-------
tuple[float, float, float, float]
Bounding region of the 2 supplied regions.
"""
coords1 = utils.region_to_df(region1)
coords2 = utils.region_to_df(region2)
coords_combined = pd.concat((coords1, coords2))
reg: tuple[float, float, float, float] = vd.get_region(
(coords_combined.easting, coords_combined.northing)
)
return reg
[docs]
def draw_region(**kwargs: typing.Any) -> list[typing.Any]:
"""
Plot an interactive map, and use the "Draw a Rectangle" button to draw a rectangle
and get the bounding region. Vertices will be returned as the output of the
function.
Returns
-------
list[typing.Any]
Returns a list of list of vertices for each polyline.
Example
-------
>>> from polartoolkit import regions, utils
...
>>> polygon = regions.draw_region()
>>> region = utils.polygon_to_region(polygon, hemisphere="north")
"""
if ipyleaflet is None:
msg = """
Missing optional dependency 'ipyleaflet' required for interactive plotting.
"""
raise ImportError(msg)
if display is None:
msg = "Missing optional dependency 'ipython' required for interactive plotting."
raise ImportError(msg)
m = maps.interactive_map(**kwargs)
def clear_m() -> None:
global poly # pylint: disable=global-variable-undefined # noqa: PLW0603
poly = [] # type: ignore[name-defined]
clear_m()
mydrawcontrol = ipyleaflet.DrawControl(
polygon={
"shapeOptions": {
"fillColor": "#fca45d",
"color": "#fca45d",
"fillOpacity": 0.5,
}
},
polyline={},
circlemarker={},
rectangle={},
)
def handle_rect_draw(self: typing.Any, action: str, geo_json: typing.Any) -> None: # noqa: ARG001 # pylint: disable=unused-argument
global poly # noqa: PLW0602 # pylint: disable=global-variable-not-assigned
shapes = []
for coords in geo_json["geometry"]["coordinates"][0][:-1][:]:
shapes.append(list(coords))
shapes = list(shapes)
if action == "created":
poly.append(shapes) # type: ignore[name-defined]
mydrawcontrol.on_draw(handle_rect_draw)
m.add_control(mydrawcontrol)
clear_m()
display(m)
return poly # type: ignore[no-any-return, name-defined]