Skip to article frontmatterSkip to article content

High rate SEVIRI Level 1.5 Image Data MSG - Data Access

This notebook demonstrates how to access SEVIRI data using HDA and how to read, process and visualize it.

🚀 Launch in JupyterHub
Prerequisites:
  • To search and access DEDL data a DestinE user account is needed

  • References:
  • DestinE Data Lake (DEDL) Harmonized Data Access (HDA) documentation

  • High Rate SEVIRI Level 1.5 Image Data - MSG - 0 degree

  • Credit:
    This notebook uses Satpy
    © 2014–2025 PyTroll community
    Licensed under PyGNU GPL v3

    This notebook demonstrates how to search and access MSG data using HDA and how to read, process and visualize it using satpy

    The Spinning Enhanced Visible and InfraRed Imager (SEVIRI) is MSG’s primary instrument and has the capacity to observe the Earth in 12 spectral channels.

    Throughout this notebook, you will learn:

    1. Authenticate: How to authenticate for searching and access DEDL collections.

    2. Search: How to search DEDL data using datetime and bbox filters.

    3. Download: How to download DEDL data through HDA.

    4. Read and visualize MSG data: How to load process and visualize MSG data using Satpy.

    Authenticate

    import destinelab as deauth
    import requests
    import json
    import os
    import zipfile
    import datetime
    import shutil
    from getpass import getpass
    DESP_USERNAME = input("Please input your DESP username or email: ")
    DESP_PASSWORD = getpass("Please input your DESP password: ")
    
    auth = deauth.AuthHandler(DESP_USERNAME, DESP_PASSWORD)
    access_token = auth.get_token()
    if access_token is not None:
        print("DEDL/DESP Access Token Obtained Successfully")
    else:
        print("Failed to Obtain DEDL/DESP Access Token")
    
    auth_headers = {"Authorization": f"Bearer {access_token}"}
    Please input your DESP username or email:  eum-dedl-user
    Please input your DESP password:  ········
    
    Response code: 200
    DEDL/DESP Access Token Obtained Successfully
    
    Response code: 200
    DEDL/DESP Access Token Obtained Successfully
    

    HDA endpoint

    HDA API is based on the Spatio Temporal Asset Catalog specification (STAC), it is convenient define a costant with its endpoint.

    HDA_STAC_ENDPOINT="https://hda.data.destination-earth.eu/stac/v2"
    COLLECTION_ID = "EO.EUM.DAT.MSG.HRSEVIRI"
    response = requests.post(HDA_STAC_ENDPOINT+"/search", headers=auth_headers, json={
        "collections": [COLLECTION_ID],
        "datetime": "2023-08-06T08:00:00Z/2023-08-07T00:00:00Z"
    })
    
    from IPython.display import JSON
    
    product = response.json()["features"][0]
    JSON(product)
    Loading...

    Download

    from tqdm import tqdm
    import time
    
    # Define a list of assets to download
    #assets = ["Oa08_radiance.nc", "Oa06_radiance.nc", "Oa02_radiance.nc"]
    assets = ["downloadLink"]
    
    for asset in assets:
        download_url = product["assets"][asset]["href"]
        print(download_url)
        filename = asset
        print(filename)
        response = requests.get(download_url, headers=auth_headers)
        total_size = int(response.headers.get("content-length", 0))
    
        print(f"downloading {filename}")
    
        with tqdm(total=total_size, unit="B", unit_scale=True) as progress_bar:
            with open(filename, 'wb') as f:
                for data in response.iter_content(1024):
                    progress_bar.update(len(data))
                    f.write(data)
    https://hda-download.lumi.data.destination-earth.eu/data/eumetsat/EO.EUM.DAT.MSG.HRSEVIRI/MSG3-SEVI-MSG15-0100-NA-20230806081241.839000000Z-NA/downloadLink
    downloadLink
    downloading downloadLink
    
    174MB [00:00, 410MB/s] 
    
    zf=zipfile.ZipFile(filename)
    with zipfile.ZipFile(filename, 'r') as zip_ref:
        zip_ref.extractall('.')

    Satpy

    The Python package satpy supports reading and loading data from many input files. For MSG data and the Native format, we can use the satpy reader 'seviri_l1b_native.

    pip install --quiet satpy
    Note: you may need to restart the kernel to use updated packages.
    

    Import required libraries

    from packaging.version import Version
    import satpy
    from satpy.scene import Scene
    
    print(satpy.__version__)
    if Version(satpy.__version__) < Version("0.57"):
        from satpy.composites import GenericCompositor
        from satpy.writers import to_image
        from satpy.resample import get_area_def
    elif Version(satpy.__version__) == Version("0.57"):
        from satpy.composites import GenericCompositor
        from satpy.area import get_area_def
    else:
        from satpy.composites.core import GenericCompositor
        from satpy.area import get_area_def
    from satpy import available_readers
    
    import warnings
    warnings.filterwarnings('ignore')
    warnings.simplefilter(action = "ignore", category = RuntimeWarning)
    0.59.0
    
    file='MSG3-SEVI-MSG15-0100-NA-20230806081241.839000000Z-NA.nat'

    Read and load data

    We use the Scene constructor from the satpy library, a Scene object represents a single geographic region of data. Once loaded we can list all the available bands (spectral channel) for that scene.

    # read the file
    scn = Scene(reader='seviri_l1b_native', filenames=[file])
    # print available datasets
    scn.available_dataset_names()
    ['HRV', 'IR_016', 'IR_039', 'IR_087', 'IR_097', 'IR_108', 'IR_120', 'IR_134', 'VIS006', 'VIS008', 'WV_062', 'WV_073']

    With the function load(), you can specify an individual band by name. If you then select the loaded band, you see the xarray.DataArray band object

    # load bands 
    scn.load(['HRV','IR_108'])
    scn['IR_108']
    Loading...
    scn['IR_108'].attrs.keys()
    dict_keys(['orbital_parameters', 'units', 'wavelength', 'standard_name', 'platform_name', 'sensor', 'georef_offset_corrected', 'time_parameters', 'start_time', 'end_time', 'reader', 'area', 'name', 'resolution', 'calibration', 'modifiers', '_satpy_id', 'ancillary_variables'])
    scn['IR_108'].attrs['wavelength']
    WavelengthRange(min=9.8, central=10.8, max=11.8, unit='µm')

    Visualize data combining bands

    The Satpy function available_composite_ids() returns a list of available composite IDs.

    scn = Scene(reader="seviri_l1b_native", 
                 filenames=[file])
    scn.available_composite_ids()
    [DataID(name='24h_microphysics'), DataID(name='airmass'), DataID(name='ash'), DataID(name='cloud_phase_distinction'), DataID(name='cloud_phase_distinction_raw'), DataID(name='cloudtop'), DataID(name='cloudtop_daytime'), DataID(name='colorized_ir_clouds'), DataID(name='convection'), DataID(name='day_microphysics'), DataID(name='day_microphysics_winter'), DataID(name='day_severe_storms'), DataID(name='day_severe_storms_tropical'), DataID(name='dust'), DataID(name='fog'), DataID(name='green_snow'), DataID(name='hrv_clouds'), DataID(name='hrv_fog'), DataID(name='hrv_severe_storms'), DataID(name='hrv_severe_storms_masked'), DataID(name='ir108_3d'), DataID(name='ir_cloud_day'), DataID(name='ir_overview'), DataID(name='ir_sandwich'), DataID(name='natural_color'), DataID(name='natural_color_nocorr'), DataID(name='natural_color_raw'), DataID(name='natural_color_raw_with_night_ir'), DataID(name='natural_color_with_night_ir'), DataID(name='natural_color_with_night_ir_hires'), DataID(name='natural_enh'), DataID(name='natural_enh_with_night_ir'), DataID(name='natural_enh_with_night_ir_hires'), DataID(name='natural_with_night_fog'), DataID(name='night_fog'), DataID(name='night_ir_alpha'), DataID(name='night_ir_with_background'), DataID(name='night_ir_with_background_hires'), DataID(name='night_microphysics'), DataID(name='night_microphysics_tropical'), DataID(name='overshooting_tops'), DataID(name='overview'), DataID(name='overview_raw'), DataID(name='realistic_colors'), DataID(name='rocket_plume_day'), DataID(name='rocket_plume_night'), DataID(name='snow'), DataID(name='vis_sharpened_ir')]
    composite_id = ["natural_color"]
    scn.load(composite_id, upper_right_corner="NE")
    
    scn_cropped = scn.crop(ll_bbox=(-5, 31, 20, 51))
    scn_cropped.show("natural_color")
    <trollimage.xrimage.XRImage at 0x7f6d30221610>
    
    composite_id = ["colorized_ir_clouds"]
    scn.load(composite_id, upper_right_corner="NE")
    scn_cropped = scn.crop(ll_bbox=(-5, 31, 20, 51))
    scn_cropped.show("colorized_ir_clouds")
    <trollimage.xrimage.XRImage at 0x7f6d348606d0>