Download notebook

Search SWOT

This notebook demonstrates how to find half orbits intersecting a given geographical area.

Tutorial Objectives

  • Retrieve the half-orbit numbers intersecting a given geographical area.

Note

Required environment to run this notebook:

  • geopandas+shapely

  • matplotlib+cartopy

  • fcollections: available here.

Import + code

import warnings
warnings.filterwarnings('ignore')
import geopandas as gpd
from shapely import geometry
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import matplotlib.patches as patches
def get_half_orbits_intersect(bbox):
    """Get half orbits that intersect a bounding box.

    Parameters
    ----------
    bbox: 
        the bounding box
        
    Returns
    -------
     gpd.GeoDataFrame:
        A Geopandas dataframe containing intersecting half orbits numbers and geometries
    """
    swath_geometries = gpd.read_file(GEOMETRIES_FILE)

    bbox_polygon = geometry.box(*bbox)

    def _filter_intersect(row, polygon):
        half_orbit_polygon = row.geometry
        return polygon.intersects(half_orbit_polygon)

    select = swath_geometries.apply(_filter_intersect, polygon=bbox_polygon, axis=1)
    return swath_geometries[select]
def plot_geometries(geometries, lon_range, lat_range, title, plot_extent=None):
    fig, ax = plt.subplots(ncols=1, figsize=(12, 8), subplot_kw={'projection': ccrs.PlateCarree()})

    gpd.GeoSeries(geometries.geometry).plot(ax=ax,transform=ccrs.PlateCarree(),alpha=1)
    
    square = patches.Rectangle((lon_range[0], lat_range[0]), lon_range[1]-lon_range[0], lat_range[1]-lat_range[0], edgecolor='orange', facecolor='none', transform=ccrs.PlateCarree())
    ax.add_patch(square)

    ax.set_title(title)
    ax.coastlines()
    if plot_extent:
        ax.set_extent(plot_extent, crs=ccrs.PlateCarree())

Parameters

Define a geographical area

# Mediterranean sea
lon_range = 6, 11
lat_range = 38, 43
bbox = [lon_range[0], lat_range[0], lon_range[1], lat_range[1]]
plot_extent = [lon_range[0], lon_range[1], lat_range[0], lat_range[1]]
# science, calval
phase = "science"

Getting Swot geometries file using fcollections.sad

import fcollections.sad
fcollections.sad.summary()
┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Type              Available  Keys                                                 Lookup Folders             ┃
┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ gshhg            │ 0/15      │ GSHHS_c,GSHHS_f,GSHHS_h,GSHHS_i,GSHHS_l,border_c,bo │ /home/atonneau/.config/sad │
│                  │           │ rder_f,border_h,border_i,border_l,river_c,river_f,r │                            │
│                  │           │ iver_h,river_i,river_l                              │                            │
│ karin_footprints │ 2/2       │ calval,science                                      │ /home/atonneau/.config/sad │
└──────────────────┴───────────┴─────────────────────────────────────────────────────┴────────────────────────────┘
aux = fcollections.sad.KarinFootprints()
aux.keys
{'calval', 'science'}
GEOMETRIES_FILE = aux[phase]

Search for matching half orbits

swath_geoms = get_half_orbits_intersect(bbox)
swath_geoms
pass_number geometry
0 1 POLYGON ((-83.3713 -77.05377, -82.41365 -77.05...
28 29 POLYGON ((-85.83706 -77.05377, -84.8794 -77.05...
235 236 POLYGON ((-65.48095 78.27207, -64.06949 78.268...
250 251 POLYGON ((-79.67267 -77.05377, -78.71502 -77.0...
263 264 POLYGON ((-67.94671 78.27207, -67.15265 78.270...
278 279 POLYGON ((-82.13843 -77.05377, -81.18077 -77.0...
291 292 POLYGON ((-70.41246 78.27207, -69.001 78.26856...
306 307 POLYGON ((-84.60418 -77.05377, -83.64652 -77.0...
513 514 POLYGON ((-64.24808 78.27207, -63.45402 78.270...
541 542 POLYGON ((-66.71383 78.27207, -65.30237 78.268...
556 557 POLYGON ((-80.90555 -77.05377, -79.94789 -77.0...
569 570 POLYGON ((-69.17958 78.27207, -67.76812 78.268...
half_orbits = list(swath_geoms['pass_number'])
half_orbits
[1, 29, 236, 251, 264, 279, 292, 307, 514, 542, 557, 570]

Plot geometries

plot_geometries(swath_geoms, lon_range, lat_range, f"Swot {phase} Geometries")
../_images/b562629c2045ba4b794568bd270f56b930cc8d8dd20991af56c1f8621bab5479.png
half_orbit_num = 264
plot_geometries(swath_geoms[swath_geoms['pass_number']==half_orbit_num], lon_range, lat_range, f"Swot {phase} Geometry, half orbit={half_orbit_num}", plot_extent)
../_images/2aecd11d1128bc8b4c168edc30476ad844af9b23d285344d5c71b5a00f8018a5.png

Download notebook