diff --git a/docs/aggregation.rst b/docs/aggregation.rst index 98c48d66..7302b337 100644 --- a/docs/aggregation.rst +++ b/docs/aggregation.rst @@ -4,7 +4,8 @@ Aggregate Existing Features =========================== The :py:mod:`geometric_features.aggregation` module contains functions used to -aggregate existing features to make new, larger ones. +aggregate existing features to make new, larger ones. An example usage of these +aggregation functions is to create masks for regional averaging. Aggregating Ocean Features @@ -13,11 +14,55 @@ Aggregating Ocean Features Ocean Sub-basins ~~~~~~~~~~~~~~~~ -The only aggregation function that is currently available is -:py:func:`geometric_features.aggregation.ocean.subbasins`, which aggregates -oceanic regions to make the following ocean subbasins: North and South Atlantic, -North and South Pacific, Indian Basin, Arctic Basin, and Southern Ocean Basin. +The function :py:func:`geometric_features.aggregation.ocean.subbasins` +aggregates oceanic regions to make the following ocean subbasins: North and +South Atlantic, North and South Pacific, Indian Basin, Arctic Basin, and +Southern Ocean Basin. .. image:: images/subbasins.png :width: 500 px :align: center + +Ocean Basins +~~~~~~~~~~~~ + +The function :py:func:`geometric_features.aggregation.ocean.basins` aggregates +oceanic regions to make the following ocean basins: Atlantic, Pacific, Indian, +Arctic, Southern Ocean, Mediterranean, Global Ocean, Global Ocean 65N to 65S, +Global Ocean 15S to 15N. + +Meridional Overturning Circulation Basins +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The function :py:func:`geometric_features.aggregation.ocean.moc` aggregates +basins for computing the MOC: Atlantic, IndoPacific, Pacific and Indian + +Antarctic Regions +~~~~~~~~~~~~~~~~~ + +The function :py:func:`geometric_features.aggregation.ocean.antarctic` aggregates +regions of the Antarctic: Southern Ocean, Southern Ocean 60S, +Eastern Weddell Sea Shelf, Eastern Weddell Sea Deep, Western Weddell Sea Shelf, +Western Weddell Sea Deep, Weddell Sea Shelf, Weddell Sea Deep, +Bellingshausen Sea Shelf, Bellingshausen Sea Deep, Amundsen Sea Shelf, +Amundsen Sea Deep, Eastern Ross Sea Shelf, Eastern Ross Sea Deep, +Western Ross Sea Shelf, Western Ross Sea Deep, East Antarctic Seas Shelf, +East Antarctic Seas Deep. + +Ice-shelf Regions +~~~~~~~~~~~~~~~~~ + +The function :py:func:`geometric_features.aggregation.ocean.ice_shelves` +aggregates ice shelves and ice-shelf regions. There are 106 regions, so they +won't all be listed. See the resulting feature collection or the code itself +for the full list. + +Transport Transects +~~~~~~~~~~~~~~~~~~~ + +The function :py:func:`geometric_features.aggregation.ocean.transport` +aggregates transport transects: Africa-Ant, Agulhas, Antilles Inflow, +Barents Sea Opening, Bering Strait, Davis Strait, Drake Passage, +Florida-Bahamas, Florida-Cuba, Fram Strait", Indonesian Throughflow, +Lancaster Sound, Mona Passage", Mozambique Channel, Nares Strait, Tasmania-Ant +Windward Passage. diff --git a/docs/api.rst b/docs/api.rst index e64f712b..70af6d42 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -89,3 +89,9 @@ Aggregation aggregation aggregation.ocean aggregation.ocean.subbasins + aggregation.ocean.basins + aggregation.ocean.moc + aggregation.ocean.arctic + aggregation.ocean.antarctic + aggregation.ocean.ice_shelves + aggregation.ocean.transport diff --git a/geometric_features/aggregation/ocean/__init__.py b/geometric_features/aggregation/ocean/__init__.py index a066d0fd..23e59338 100644 --- a/geometric_features/aggregation/ocean/__init__.py +++ b/geometric_features/aggregation/ocean/__init__.py @@ -1 +1,6 @@ from geometric_features.aggregation.ocean.subbasin_regions import subbasins +from geometric_features.aggregation.ocean.ocean_basins import basins +from geometric_features.aggregation.ocean.antarctic_regions import antarctic +from geometric_features.aggregation.ocean.ice_shelf_regions import ice_shelves +from geometric_features.aggregation.ocean.moc_basins import moc +from geometric_features.aggregation.ocean.transport_transects import transport diff --git a/geometric_features/aggregation/ocean/antarctic_regions.py b/geometric_features/aggregation/ocean/antarctic_regions.py new file mode 100644 index 00000000..36b3af2d --- /dev/null +++ b/geometric_features/aggregation/ocean/antarctic_regions.py @@ -0,0 +1,32 @@ +def antarctic(gf): + """ + Aggregate Antarctic regions similar to Timmermann et al. (2013) + + Parameters + ---------- + gf : geometric_features.GeometricFeatures + An object that knows how to download and read geometric features + + Returns + ------- + fc : geometric_features.FeatureCollection + The new feature collection with antarctic regions + """ + # Authors + # ------- + # Xylar Asay-Davis + + regions = ['Southern Ocean', 'Southern Ocean 60S', + 'Eastern Weddell Sea Shelf', 'Eastern Weddell Sea Deep', + 'Western Weddell Sea Shelf', 'Western Weddell Sea Deep', + 'Weddell Sea Shelf', 'Weddell Sea Deep', + 'Bellingshausen Sea Shelf', 'Bellingshausen Sea Deep', + 'Amundsen Sea Shelf', 'Amundsen Sea Deep', + 'Eastern Ross Sea Shelf', 'Eastern Ross Sea Deep', + 'Western Ross Sea Shelf', 'Western Ross Sea Deep', + 'East Antarctic Seas Shelf', 'East Antarctic Seas Deep'] + + fc = gf.read(componentName='ocean', objectType='region', + featureNames=regions) + + return fc diff --git a/geometric_features/aggregation/ocean/ice_shelf_regions.py b/geometric_features/aggregation/ocean/ice_shelf_regions.py new file mode 100644 index 00000000..a62c8bcb --- /dev/null +++ b/geometric_features/aggregation/ocean/ice_shelf_regions.py @@ -0,0 +1,171 @@ +from geometric_features import FeatureCollection + + +def ice_shelves(gf): + """ + Aggregate 106 Antarctic ice shelves and ice-shelf regions + + Parameters + ---------- + gf : geometric_features.GeometricFeatures + An object that knows how to download and read geometric features + + Returns + ------- + fc : geometric_features.FeatureCollection + The new feature collection with ice shelves + """ + # Authors + # ------- + # Xylar Asay-Davis + + iceShelfNames = ['Abbot', + 'Amery', + 'Atka', + 'Aviator', + 'Bach', + 'Baudouin', + 'Borchgrevink', + 'Brahms', + 'Brunt_Stancomb', + 'Campbell', + 'Cheetham', + 'Conger_Glenzer', + 'Cook', + 'Cosgrove', + 'Crosson', + 'Dennistoun', + 'Dibble', + 'Dotson', + 'Drygalski', + 'Edward_VIII', + 'Ekstrom', + 'Ferrigno', + 'Filchner', + 'Fimbul', + 'Fitzgerald', + 'Frost', + 'GeikieInlet', + 'George_VI', + 'Getz', + 'Gillet', + 'Hamilton', + 'Hannan', + 'HarbordGlacier', + 'Helen', + 'Holmes', + 'HolmesWest', + 'Hull', + 'Jelbart', + 'Land', + 'Larsen_B', + 'Larsen_C', + 'Larsen_D', + 'Larsen_E', + 'Larsen_F', + 'Larsen_G', + 'Lazarev', + 'Lillie', + 'Mariner', + 'Matusevitch', + 'Mendelssohn', + 'Mertz', + 'Moscow_University', + 'Moubray', + 'Mulebreen', + 'Myers', + 'Nansen', + 'Nickerson', + 'Ninnis', + 'Nivl', + 'Noll', + 'Nordenskjold', + 'Pine_Island', + 'PourquoiPas', + 'Prince_Harald', + 'Publications', + 'Quar', + 'Rayner_Thyer', + 'Rennick', + 'Richter', + 'Riiser-Larsen', + 'Ronne', + 'Western_Ross', + 'Eastern_Ross', + 'Shackleton', + 'Shirase', + 'Slava', + 'SmithInlet', + 'Stange', + 'Sulzberger', + 'Suvorov', + 'Swinburne', + 'Thwaites', + 'Tinker', + 'Totten', + 'Tracy_Tremenchus', + 'Tucker', + 'Underwood', + 'Utsikkar', + 'Venable', + 'Verdi', + 'Vigrid', + 'Vincennes', + 'Voyeykov', + 'West', + 'Wilkins', + 'Wilma_Robert_Downer', + 'Withrow', + 'Wordie', + 'Wylde', + 'Zubchatyy'] + + combinedIceShelves = {'Filchner-Ronne': ['Filchner', 'Ronne'], + 'Ross': ['Western_Ross', 'Eastern_Ross'], + 'Antarctica': ['AntarcticPenninsulaIMBIE', + 'WestAntarcticaIMBIE', + 'EastAntarcticaIMBIE'], + 'Peninsula': ['AntarcticPenninsulaIMBIE'], + 'West Antarctica': ['WestAntarcticaIMBIE'], + 'East Antarctica': ['EastAntarcticaIMBIE']} + + nIMBIEBasins = 27 + for basinNumber in range(1, nIMBIEBasins + 1): + basinName = 'Antarctica_IMBIE{}'.format(basinNumber) + combinedIceShelves['IMBIE{}'.format(basinNumber)] = [basinName] + + # create a FeatureCollection containing all ice shelves and combined + # ice-shelf regions + fc = FeatureCollection() + + # build analysis regions from combining ice shelves from regions with the + # appropriate tags + for shelfName in combinedIceShelves: + subNames = combinedIceShelves[shelfName] + print(shelfName) + + print(' * merging features') + fcShelf = gf.read(componentName='iceshelves', objectType='region', + tags=subNames, allTags=False) + + print(' * combining features') + fcShelf = fcShelf.combine(featureName=shelfName) + + # merge the feature for the basin into the collection of all basins + fc.merge(fcShelf) + + # build ice shelves from regions with the appropriate tags + for shelfName in iceShelfNames: + print(shelfName) + + print(' * merging features') + fcShelf = gf.read(componentName='iceshelves', objectType='region', + tags=[shelfName]) + + print(' * combining features') + fcShelf = fcShelf.combine(featureName=shelfName) + + # merge the feature for the basin into the collection of all basins + fc.merge(fcShelf) + + return fc diff --git a/geometric_features/aggregation/ocean/moc_basins.py b/geometric_features/aggregation/ocean/moc_basins.py new file mode 100644 index 00000000..ac5c2bd3 --- /dev/null +++ b/geometric_features/aggregation/ocean/moc_basins.py @@ -0,0 +1,120 @@ +import shapely.geometry +import shapely.ops +import copy + +from geometric_features import FeatureCollection + + +def moc(gf): + """ + Aggregate features defining the ocean basins used in computing the + meridional overturning circulation (MOC) + + Parameters + ---------- + gf : ``GeometricFeatures`` + An object that knows how to download and read geometric featuers + + Returns + ------- + fc : ``FeatureCollection`` + The new feature collection + """ + # Authors + # ------- + # Xylar Asay-Davis + + MOCSubBasins = {'Atlantic': ['Atlantic', 'Mediterranean'], + 'IndoPacific': ['Pacific', 'Indian'], + 'Pacific': ['Pacific'], + 'Indian': ['Indian']} + + MOCSouthernBoundary = {'Atlantic': '34S', + 'IndoPacific': '34S', + 'Pacific': '6S', + 'Indian': '6S'} + + fc = FeatureCollection() + fc.set_group_name(groupName='MOCBasinRegionsGroup') + + # build MOC basins from regions with the appropriate tags + for basinName in MOCSubBasins: + tags = ['{}_Basin'.format(basin) for basin in + MOCSubBasins[basinName]] + + fcBasin = gf.read(componentName='ocean', objectType='region', + tags=tags, allTags=False) + + fcBasin = fcBasin.combine(featureName='{}_MOC'.format(basinName)) + + maskName = 'MOC mask {}'.format(MOCSouthernBoundary[basinName]) + fcMask = gf.read(componentName='ocean', objectType='region', + featureNames=[maskName]) + # mask out the region covered by the mask + fcBasin = fcBasin.difference(fcMask) + + # remove various small polygons that are not part of the main MOC + # basin shapes. Most are tiny but one below Australia is about 20 + # deg^2, so make the threshold 100 deg^2 to be on the safe side. + fcBasin = _remove_small_polygons(fcBasin, minArea=100.) + + # add this basin to the full feature collection + fc.merge(fcBasin) + + return fc + + +def _remove_small_polygons(fc, minArea): + """ + A helper function to remove small polygons from a feature collection + + Parameters + ---------- + fc : ``FeatureCollection`` + The feature collection to remove polygons from + + minArea : float + The minimum area (in square degrees) below which polygons should be + removed + + Returns + ------- + fcOut : ``FeatureCollection`` + The new feature collection with small polygons removed + """ + # Authors + # ------- + # Xylar Asay-Davis + + fcOut = FeatureCollection() + + removedCount = 0 + for feature in fc.features: + geom = feature['geometry'] + add = False + if geom['type'] not in ['Polygon', 'MultiPolygon']: + # no area to check, so just add it + fcOut.add_feature(copy.deepcopy(feature)) + else: + featureShape = shapely.geometry.shape(geom) + if featureShape.type == 'Polygon': + if featureShape.area > minArea: + add = True + else: + removedCount += 1 + else: + # a MultiPolygon + outPolygons = [] + for polygon in featureShape: + if polygon.area > minArea: + outPolygons.append(polygon) + else: + removedCount += 1 + if len(outPolygons) > 0: + outShape = shapely.ops.cascaded_union(outPolygons) + feature['geometry'] = shapely.geometry.mapping(outShape) + add = True + if add: + fcOut.add_feature(copy.deepcopy(feature)) + + return fcOut diff --git a/geometric_features/aggregation/ocean/ocean_basins.py b/geometric_features/aggregation/ocean/ocean_basins.py new file mode 100644 index 00000000..89e9128d --- /dev/null +++ b/geometric_features/aggregation/ocean/ocean_basins.py @@ -0,0 +1,49 @@ +from geometric_features import FeatureCollection + + +def basins(gf): + """ + Aggregate Global Ocean as well as Atlantic, Pacific, Indian, Arctic, + Southern Ocean, Equatorial (global 15S-15N), and Mediterranean basins + + Parameters + ---------- + gf : geometric_features.GeometricFeatures + An object that knows how to download and read geometric features + + Returns + ------- + fc : geometric_features.FeatureCollection + The new feature collection with ocean basins + """ + # Authors + # ------- + # Xylar Asay-Davis + + fc = FeatureCollection() + fc.set_group_name(groupName='OceanBasinRegionsGroup') + + # build ocean basins from regions with the appropriate tags + for oceanName in ['Atlantic', 'Pacific', 'Indian', 'Arctic', + 'Southern_Ocean', 'Mediterranean']: + + basinName = '{}_Basin'.format(oceanName) + print(oceanName) + + print(' * merging features') + fcBasin = gf.read(componentName='ocean', objectType='region', + tags=[basinName]) + + print(' * combining features') + fcBasin = fcBasin.combine(featureName=basinName) + + fc.merge(fcBasin) + + # add the global ocean, global ocean between 65S and 65S, and + # equatorial region + fc.merge(gf.read(componentName='ocean', objectType='region', + featureNames=['Global Ocean', + 'Global Ocean 65N to 65S', + 'Global Ocean 15S to 15N'])) + + return fc diff --git a/geometric_features/aggregation/ocean/subbasin_regions.py b/geometric_features/aggregation/ocean/subbasin_regions.py index d8095a56..6dcbb131 100644 --- a/geometric_features/aggregation/ocean/subbasin_regions.py +++ b/geometric_features/aggregation/ocean/subbasin_regions.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python def subbasins(gf): diff --git a/geometric_features/aggregation/ocean/transport_transects.py b/geometric_features/aggregation/ocean/transport_transects.py new file mode 100644 index 00000000..2d7df715 --- /dev/null +++ b/geometric_features/aggregation/ocean/transport_transects.py @@ -0,0 +1,23 @@ +def transport(gf): + """ + Aggregate standard transport transects + + Parameters + ---------- + gf : geometric_features.GeometricFeatures + An object that knows how to download and read geometric features + + Returns + ------- + fc : geometric_features.FeatureCollection + The new feature collection with transport transects + """ + # Authors + # ------- + # Xylar Asay-Davis + + # create a FeatureCollection to which we will add all regions + fc = gf.read(componentName='ocean', objectType='transect', + tags=['standard_transport_sections']) + + return fc