CryoTEMPO: Assessing Ice and Sea Level Dynamics near Petermann Glacier, Greenland

Introduction

In this example notebook, we use the CryoTEMPO Land Ice, Sea Ice and Polar Oceans data stored in Specklia to investigate the dynamics of Petermann Glacier and its surrounding environment over 12 years.

Petermann Glacier, one of Greenland’s largest marine-terminating glaciers, has experienced significant thinning in recent decades, leading to substantial loss of its floating ice shelf through calving events. These changes hold implications for sea level rise.

Petermann Glacier discharges into the Nares Strait, a critical pathway for sea ice exiting the Arctic. The glacier’s ice shelf is seasonally shielded by sea ice in this pathway. However, with the thinning of sea ice, it becomes more susceptible to faster floes, potentially increasing glacier calving rates.

This notebook aims to compare the long-term trends of sea-level fluctuations, sea ice thickness, and land ice thickness in and around Petermann Glacier using CryoSat’s CryoTEMPO products.

You can view the code below or click here to run it yourself in Google Colab!

Environment Setup

To run this notebook, you will need to make sure that the folllowing packages are installed in your python environment (all can be installed via pip/conda): - matplotlib - geopandas - contextily - ipykernel - shapely - specklia

If you are using the Google Colab environment, these packages will be installed in the next cell. Please note this step may take a few minutes.

[1]:
import sys
if 'google.colab' in sys.modules:
    %pip install rasterio --no-binary rasterio
    %pip install specklia
    %pip install matplotlib
    %pip install geopandas
    %pip install contextily
    %pip install shapely
    %pip install python-dotenv

Plot dataset spatial coverage

Let’s plot the geospatial coverage of the CryoTEMPO Polar Oceans, Sea Ice and Land Ice datasets, using Contextily to add a satellite background map. All background satellite imagery tiles are provided by the Esri World Imagery Service via Contextily.

[3]:
available_datasets = client.list_datasets()

cryotempo_datasets = {}
dataset_names = ['CryoTEMPO Polar Ocean Thematic Product Baseline B',
                 'CryoTEMPO Sea Ice Thematic Product Baseline B',
                 'CryoTEMPO Land Ice Thematic Product Baseline B']

for ds_name in dataset_names:
    cryotempo_datasets[ds_name] = available_datasets[
        available_datasets['dataset_name'] == ds_name].iloc[0]

    print(f"{ds_name} contains data timestamped between \n"
        f"{cryotempo_datasets[ds_name]['min_timestamp']} "
        f"and {cryotempo_datasets[ds_name]['max_timestamp']}\n")

    print(f"{ds_name} has the following columns:")
    pprint.PrettyPrinter(indent=2, width=120).pprint(cryotempo_datasets[ds_name]['columns'])
    print("\n\n")

    desired_dataset_spatial_coverage = gpd.GeoDataFrame(
        geometry=[cryotempo_datasets[ds_name]['epsg4326_coverage']], crs=4326)

    # we create two plots, one for each hemisphere, to minimise distortion
    # and illustrate that multiple regions may be present within the same dataset
    for crs, hemisphere_name, hemisphere_bounding_box in [
            (3413, 'northern', (-180, 0, 180, 90)),
            (3031, 'southern', (-180, -90, 180, 0))
            ]:

        cropped_data = desired_dataset_spatial_coverage.clip(hemisphere_bounding_box)

        if len(cropped_data) > 0:
            transformed_cropped_data = cropped_data.to_crs(crs)
            ax = transformed_cropped_data.plot(
                figsize=(10, 10), alpha=0.5, color=data_coverage_color, edgecolor=data_coverage_color)

            ax.set_xlabel('x (m)')
            ax.set_ylabel('y (m)')
            ax.set_title(f"{ds_name} spatial coverage, {hemisphere_name} hemisphere (EPSG {crs})")

            ctx.add_basemap(ax, source=ctx.providers.Esri.WorldImagery, crs=crs, attribution=False, zoom=2)
CryoTEMPO Polar Ocean Thematic Product Baseline B contains data timestamped between
2010-08-01 00:37:22 and 2023-12-31 23:55:31

CryoTEMPO Polar Ocean Thematic Product Baseline B has the following columns:
[ { 'description': 'dynamic ocean topography',
    'max_value': 9.969209968386869e+36,
    'min_value': -32.98397505254174,
    'name': 'dynamic_ocean_topography',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'Filtered dynamic ocean topography',
    'max_value': 9.969209968386869e+36,
    'min_value': -18.683891201057097,
    'name': 'dynamic_ocean_topography_filtered',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'dynamic ocean topography uncertainty',
    'max_value': 9.969209968386869e+36,
    'min_value': 0.012529066903526604,
    'name': 'dynamic_ocean_topography_uncertainty',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'SIRAL instrument mode flag - please refer to product handbook for flag value meaning',
    'max_value': 3.0,
    'min_value': 1.0,
    'name': 'instrument_mode',
    'type': 'float',
    'unit': 'NA'},
  { 'description': 'sea level anomaly',
    'max_value': 9.969209968386869e+36,
    'min_value': -32.76168093769796,
    'name': 'sea_level_anomaly',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'inverse barometric range correction',
    'max_value': 9.969209968386869e+36,
    'min_value': -1.5924998212270827,
    'name': 'inverse_barometric',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'Filtered sea level anomaly',
    'max_value': 9.969209968386869e+36,
    'min_value': -42352.73606459396,
    'name': 'sea_level_anomaly_filtered',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'sea level anomaly unsmoothed 20 Hz values',
    'max_value': 9.969209968386869e+36,
    'min_value': -32.76168093769796,
    'name': 'sea_level_anomaly_raw',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'sea level anomaly uncertainty',
    'max_value': 9.969209968386869e+36,
    'min_value': 0.004,
    'name': 'sea_level_anomaly_uncertainty',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'region id - please refer to product handbook for flag value meaning',
    'max_value': 18.0,
    'min_value': 0.0,
    'name': 'region_code',
    'type': 'float',
    'unit': 'NA'}]



CryoTEMPO Sea Ice Thematic Product Baseline B contains data timestamped between
2010-11-01 00:22:24 and 2023-12-31 23:55:31

CryoTEMPO Sea Ice Thematic Product Baseline B has the following columns:
[ { 'description': 'SIRAL instrument mode flag - please refer to product handbook for flag value meaning',
    'max_value': 3.0,
    'min_value': 2.0,
    'name': 'instrument_mode',
    'type': 'float',
    'unit': 'NA'},
  { 'description': 'Radar freeboard',
    'max_value': 968.5565185546875,
    'min_value': -167.90652465820312,
    'name': 'radar_freeboard',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'Radar freeboard uncertainty',
    'max_value': 0.1414213478565216,
    'min_value': 0.1019805297255516,
    'name': 'radar_freeboard_uncertainty',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'region id - please refer to product handbook for flag value meaning',
    'max_value': 18.0,
    'min_value': 0.0,
    'name': 'region_code',
    'type': 'float',
    'unit': 'NA'},
  { 'description': 'freeboard of the sea ice layer',
    'max_value': 2.2499988079071045,
    'min_value': -0.25,
    'name': 'sea_ice_freeboard',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'smoothed freeboard of the sea ice layer',
    'max_value': 66.54676604268523,
    'min_value': -19.452557027337747,
    'name': 'sea_ice_freeboard_filtered',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'sea ice freeboard uncertainty',
    'max_value': 0.14916853606700897,
    'min_value': 0.1019805297255516,
    'name': 'sea_ice_freeboard_uncertainty',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'snow depth',
    'max_value': 0.4512886530080971,
    'min_value': 0.0,
    'name': 'snow_depth',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'snow depth uncertainty',
    'max_value': 0.19134312379075316,
    'min_value': 0.0,
    'name': 'snow_depth_uncertainty',
    'type': 'float',
    'unit': 'm'}]



CryoTEMPO Land Ice Thematic Product Baseline B contains data timestamped between
2010-07-16 00:08:47 and 2024-01-01 00:00:16

CryoTEMPO Land Ice Thematic Product Baseline B has the following columns:
[ { 'description': 'CryoSat SIRAL instrument operating mode - please refer to product handbook for flag value meaning',
    'max_value': 3.0,
    'min_value': 1.0,
    'name': 'instrument_mode',
    'type': 'float',
    'unit': 'NA'},
  { 'description': 'ice sheet elevation LMC Retracker',
    'max_value': 4666.404627441429,
    'min_value': -210.18170151300728,
    'name': 'elevation',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'backscatter coefficient',
    'max_value': 62.6580864575041,
    'min_value': -54.502500548483525,
    'name': 'backscatter',
    'type': 'float',
    'unit': 'dB'},
  { 'description': 'surface type from mask - please refer to product handbook for flag value meaning',
    'max_value': 4,
    'min_value': 0,
    'name': 'surface_type',
    'type': 'int',
    'unit': 'NA'},
  { 'description': 'reference elevation from external Digital Elevation Model',
    'max_value': 4640.933787743923,
    'min_value': -329.80018062294215,
    'name': 'reference_dem',
    'type': 'float',
    'unit': 'm'},
  { 'description': 'Glacialogical basin identification number',
    'max_value': 27,
    'min_value': 0,
    'name': 'basin_id',
    'type': 'int',
    'unit': 'basin number'},
  { 'description': 'Glacialogical basin identification number',
    'max_value': 19,
    'min_value': -24,
    'name': 'basin_id2',
    'type': 'int',
    'unit': 'basin number'},
  { 'description': 'uncertainty of elevation parameter',
    'max_value': 2.415915353790031,
    'min_value': 0.11680662750683299,
    'name': 'uncertainty',
    'type': 'float',
    'unit': 'm'}]



../_images/example_notebooks_cryotempo_petermann_glacier_6_1.png
../_images/example_notebooks_cryotempo_petermann_glacier_6_2.png
../_images/example_notebooks_cryotempo_petermann_glacier_6_3.png
../_images/example_notebooks_cryotempo_petermann_glacier_6_4.png

Define area of interest

Lets define a rough boundary encompassing the terminus of Petermann Glacier and the adjacent ocean..

[4]:
petermann_extent = shapely.Polygon((
    (-64.53, 80.99), (-63.87, 81.16), (-62.84, 81.19), (-61.9, 81.02), (-61.3, 80.65),
    (-59., 80.2), (-58., 80.4), (-60., 80.7), (-61.73, 81.29), (-61.3, 81.51),
    (-61.71, 81.78), (-62.86, 81.97), (-67.4, 81.42), (-64.53, 80.99)))
petermann_extent_gdf = gpd.GeoSeries(petermann_extent, crs=4326)

ax = petermann_extent_gdf.to_crs(nps_epsg_code).plot(
    figsize=(10, 10), alpha=0.5, color=geo_filter_colour, edgecolor=geo_filter_colour)

ax.set_xlabel('x (meters)')
ax.set_ylabel('y (meters)')
ax.set_title("Query extent covering Peterman Glacier and Surrounding Ocean")
ctx.add_basemap(ax, source=ctx.providers.Esri.WorldImagery, crs=nps_epsg_code, attribution=False, zoom=8)
../_images/example_notebooks_cryotempo_petermann_glacier_8_0.png

Query data

Now that we’ve defined our query extent, lets retrieve data from the CryoTEMPO Polar Ocean Thematic Product, CryoTEMPO Sea Ice Thematic Product, and CryoTEMPO Land Ice Thematic Product from Specklia.

Whilst we do so, we’ll apply some uncertainty filtering and filter the CryoTEMPO Land Ice data on surface type to retrieve measurements from grounded (surface_type=1) and floating ice (surface_type=2) only. Note that the surface type definitions can be found in the CryoTEMPO Product Handbook.

[5]:
cryotempo_data = {}
sources = {}
query_parameters = {
    'CryoTEMPO Polar Ocean Thematic Product Baseline B': {
        'filters': [{'column': 'sea_level_anomaly_uncertainty', 'operator': '<=', 'threshold': .05}],
        'columns': ['sea_level_anomaly_filtered', 'timestamp']},
    'CryoTEMPO Sea Ice Thematic Product Baseline B': {
        'filters': [{'column': 'sea_ice_freeboard_uncertainty', 'operator': '<=', 'threshold': .15}],
        'columns': ['sea_ice_freeboard_filtered', 'timestamp']},
    'CryoTEMPO Land Ice Thematic Product Baseline B': {
        'filters': [{'column': 'uncertainty', 'operator': '<=', 'threshold': 1.5},
                    {'column': 'surface_type', 'operator': '>=', 'threshold': 1.},
                    {'column': 'surface_type', 'operator': '<=', 'threshold': 2.}],
        'columns': ['elevation', 'reference_dem', 'timestamp', 'surface_type']}}

for ds_name in dataset_names:
    dataset = available_datasets[available_datasets['dataset_name'] == ds_name].iloc[0]
    query_start_time = perf_counter()
    cryotempo_data[ds_name], sources[ds_name] = client.query_dataset(
        dataset_id=dataset['dataset_id'],
        epsg4326_polygon=petermann_extent,
        min_datetime=datetime(2011, 1, 1),
        max_datetime=datetime(2023, 12, 1),
        columns_to_return=query_parameters[ds_name]['columns'],
        additional_filters=query_parameters[ds_name]['filters'])

    print(f'Query took {perf_counter()-query_start_time:.2f} seconds to complete.')
    print(f'{ds_name} Query complete, {len(cryotempo_data[ds_name])} points returned, '
            f'drawn from {len(sources[ds_name])} original sources.')
    print(f'Columns within the data: {cryotempo_data[ds_name].columns}\n\n')
Query took 19.70 seconds to complete.
CryoTEMPO Polar Ocean Thematic Product Baseline B Query complete, 296802 points returned, drawn from 1453 original sources.
Columns within the data: Index(['sea_level_anomaly_filtered', 'timestamp', 'source_id', 'source_row_id',
       'geometry'],
      dtype='object')


Query took 15.90 seconds to complete.
CryoTEMPO Sea Ice Thematic Product Baseline B Query complete, 21309 points returned, drawn from 805 original sources.
Columns within the data: Index(['sea_ice_freeboard_filtered', 'timestamp', 'source_id', 'source_row_id',
       'geometry'],
      dtype='object')


Query took 13.54 seconds to complete.
CryoTEMPO Land Ice Thematic Product Baseline B Query complete, 83055 points returned, drawn from 1460 original sources.
Columns within the data: Index(['elevation', 'reference_dem', 'timestamp', 'surface_type', 'source_id',
       'source_row_id', 'geometry'],
      dtype='object')