The world’s leading publication for data science, AI, and ML professionals.

Monitoring Sea Surface Temperature at the global level with GEE

How to create a Streamlit app for ocean monitoring with Python

Image by the Author. Monitor of SST on Jan 14th of 2023 with GEE
Image by the Author. Monitor of SST on Jan 14th of 2023 with GEE

Introduction

The development of Earth Observation and its technological infrastructure has increased considerably in the last decade. Many satellite constellations give open and handy access to their data and researchers can easily access it. For example, Google Earth Engine is a cloud infrastructure that gives access to data from many providers such as Modis, NOAA, ASTER, Lansat, and others, that you can explore and analyze straightforwardly. Give it a look in GEE. In case you want to use the API in Python you can do it with the geemap python library developed by Qiusheng Wu which has wonderful functionalities and can be used as it is in this tutorial.

The infrastructure models are running in near real-time so it is possible to get up-to-date data that helps monitor land and ocean. For this tutorial, we are going to work with the HYCOM dataset which contains a data-assimilative hybrid model that displays the Sea Surface Temperature and Salinity at the global level. The model contains depth values for each temporal layer so users can visualize the ocean at certain depths and dates. The Hybrid Coordinate Ocean Model has been part of many publications and the website contains a lot of documentation about the dataset. If you want to know more I recommend you to give a look at the official website.

App

Get access to the app in the next link:

🌡 ️ SST Global Monitoring – App

Image by the Author. Brief view of the app. 100-meter depth on January 15th, 2023
Image by the Author. Brief view of the app. 100-meter depth on January 15th, 2023

Objective

What I want with this tutorial is to create an easy-to-use app that is able to display the Sea Surface Temperature at the global level. The features of the app should be:

  • Selection of time
  • Selection of depth
  • Configuration of legend

Once the interaction is done we will deploy the app in the Streamlit cloud.

Data License

The HYCOM dataset is published as a Public Domain Mark 1.0. Users are able to copy, modify, and redistribute, even for commercial purposes. The distribution officially by HYCOM is US DOD Distribution A which expresses public release and unlimited distribution.

Coding tutorial

I hope you are familiar with Python programming before starting this tutorial. If not, then no worries just ask for help in this tutorial and I can suggest educational material. Generally, Python can be used nicely in Anaconda. I would recommend you have it and get familiar with package installation before starting. In any case, you will be able to deploy this app.

Libraries

Let’s start creating a python file and importing the needed libraries.

import json
from datetime import datetime, timedelta, date

import ee
import geemap.colormaps as cm
import geemap.foliumap as geemap
import streamlit as st

To make it work in Streamlit you might need to do GEE authentication with a key. The instruction about how to do it is already written in this clear and excellent tutorial by Mykola Kozyr.

Using Google Earth Engine in a Streamlit app

Follow carefully the instructions given before and add your own credentials to the app.py file. It might look like this.

# ______ GEE Authenthication ______

# _____ STREAMLIT _______

# Secrets
json_data = st.secrets["json_data"]
service_account = st.secrets["service_account"]

# Preparing values
json_object = json.loads(json_data, strict=False)
json_object = json.dumps(json_object)

# Authorising the app
credentials = ee.ServiceAccountCredentials(service_account, key_data=json_object)
ee.Initialize(credentials)

Environment

To deploy in Streamlit you should add a requirements.txt file that contains the needed packages for deployment. In this case, we will add requirements and an additional file packages.txt Both files were taken from the gishub of geemap.

Add to the repo a requirements.txt file with:

--find-links=https://girder.github.io/large_image_wheels GDAL
# cartopy
geemap
geopandas
ee
jupyter-server-proxy
leafmap
localtileserver
nbserverproxy
owslib
palettable
plotly
streamlit==1.12.2
streamlit-bokeh-events
streamlit-folium
tropycal

Also, an additional packages.txt file with:

ffmpeg
gifsicle
build-essential
python3-dev
gdal-bin
libgdal-dev
libproj-dev
libgeos-dev
proj-bin

Layout configuration

Here we will add a title to the page, define a wide layout of Streamlit, and give tight limits to our canvas that will make the map looks nicer.

# _______________________ LAYOUT CONFIGURATION __________________________

st.set_page_config(page_title='SST monitor', layout="wide")

# shape the map
st.markdown(
        f"""
<style>
    .appview-container .main .block-container{{

        padding-top: {3}rem;
        padding-right: {2}rem;
        padding-left: {0}rem;
        padding-bottom: {0}rem;
    }}

</style>
""",
        unsafe_allow_html=True,
    )

Sidebar configuration and parameters input

Here we will add aform that will be used to input the parameters of the map such as depth and date. The current map is always displayed with the last available layer which is 2 days before the current date. Some comments in help are added.

Check the inline comments that describe the code.

## ___________________ SIDEBAR PARAMETERS ___________________________

st.sidebar.info('### ***Welcome***n###### ***Sea Surface Temperature (SST) monitor*** 🧐🌊🌡 ️')

form = st.sidebar.form('Ocean data')

with form:

    # depths in slider
    depth_options = [0, 2, 4, 6, 8, 10, 12, 15, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100, 125, 150, 200, 250, 300, 350, 400, 500, 600, 700, 800, 900, 1000, 1250, 1500, 2000, 2500, 3000, 4000, 5000]

    depth = st.select_slider('Depth (m)', options = depth_options, value = 0, help = 'Depth in ocean to fetch temperature layer' )

    # dates of sst
    ocean_date = st.date_input('Date', min_value=datetime.strptime('1992-10-02', '%Y-%m-%d'), max_value = datetime.now(), help = 'Selected date of temperature to be displayed')

    # conditions to get the available layer 2 days before today
    if str(ocean_date) == str(date.today()):
        ocean_date = ocean_date - timedelta(2)

    if str(ocean_date) == str(date.today() - timedelta(1)):
        ocean_date = ocean_date - timedelta(1)

    # visualization threshold
    min, max = st.slider('Min and Max (°C)', 0, 40, value=(10, 32), help='Threshold of visualization in Celsius')

    # button to update visualization
    update_depth = st.form_submit_button('Update')

Define map instance

In the map instance, we will add an ocean base map and call the ImageCollection, then we select the temperature layer from the first date in the collection. Take a look the image variable.

To display the temperature correctly we use multiply and add. These parameters come by default in the GEE. Finally, we add the layer and a legend with a color bar. The depth and date will be displayed in the legend.

# __________________ MAP INSTANCE _________________

# add a map instance
Map = geemap.Map(zoom=3, center=(-10, -55))

Map.add_basemap('Esri.OceanBasemap') # "HYBRID"

# get the layer with current date
sst_thumb = ee.ImageCollection('HYCOM/sea_temp_salinity').filterDate(str(ocean_date)) #('2022-01-10', '2022-01-15')

# get fist date just in case, and select the depth, and transform the values
image = sst_thumb.limit(1, 'system:time_start', False).first().select(f'water_temp_{depth}').multiply(0.001).add(20)

vis_param = {'min': min,
             'max': max, 'alpha': 0.4, 
             'palette': cm.palettes.jet,
             }

# add image
Map.addLayer(image, vis_param)

# add color bar with depth and date info
Map.add_colorbar(vis_param, label = f'Sea Surface Temperature (C°) at {depth} depth on {ocean_date}', layer_name = f"SST at {depth} depth", discrete=False)

Map to Streamlit

Then, we send the map instance to Streamlit

# _______ DISPLAY ON STREAMLIT _______
Map.to_streamlit(height=600,  responsive=True, scrolling=False)

Add extra information

We can add more information like the link to this tutorial, author, reference to the dataset, or any other extra info you want.

# _______ ADDITIONAL INFORMATION AND LINKS ________

st.sidebar.success('##### **Author and coding tutorial**n###### ***Bryan R. Vallejo***n##### ***[How to create a web app for ocean monitoring?](https://medium.com/@bryanvallejo16/monitoring-sea-surface-temperature-at-the-global-level-with-gee-1d7349c7da6)***n###### ***[Get ful access to more tutorials](https://bryanvallejo16.medium.com/membership)***')

st.sidebar.warning('##### **Dataset**n###### ***J. A. Cummings and O. M. Smedstad. 2013: Variational Data Assimilation for the Global Ocean. Data Assimilation for Atmospheric, Oceanic and Hydrologic Applications vol II, chapter 13, 303-343***n###### ***In [Google Earth Engine](https://developers.google.com/earth-engine/datasets/catalog/HYCOM_sea_temp_salinity#description)***')

st.sidebar.error('##### Notes: n###### ***The last STT layer availabe is 2 days before current date***')

st.sidebar.error('##### Related stories: n###### ***[Ocean currents seasonality in the Galapagos Islands, Ecuador](https://towardsdatascience.com/ocean-currents-seasonality-in-the-galapagos-islands-ecuador-9197f0b721c0)***n###### ***[Earth observation and biologging data for marine conservation](https://medium.com/gis4-wildlife-tracking/earth-observation-and-biologging-data-for-marine-conservation-989f2b3dc71d)***')

Limitation

The limitation we have for real-time ocean monitoring is that HYCOM has the last layer available for 2 days before the current date. Not really a limitation because 2 days are not a big difference for ocean temperature seasonality.

One common limitation is to display a global layer fast but thanks to geemap and its integration of folium it is possible to have fast and light visualization.

Future development

I imagine that future development might contain more features of the app for example adding more layers like salinity. If you have recommendations or needs for your own work do not hesitate to leave a comment.

Conclusion

The monitoring of the seasonalities of the ocean can be possible with a simple configuration of inputs and GEE. The development of the GEE API in python has made it possible to display easily and can support the monitoring of seasons. Also, it can be used for other purposes for example users can check which month has the best temperature for their next vacation beach.

Written by:

Bryan R. Vallejo – LinkedIn profile


Related Articles