Use CopPhil JupyterLab and Python to find all Sentinel 2 products over Manila in 2024

Typical uses of Sentinel 2 Level data are

  • land cover and vegetation analysis

  • agricultural monitoring

  • water quality and inland water monitoring

  • soil and land surface monitoring

  • urban and coastal management

  • disaster and emergency management

  • climate change research

In this article, we cover an example of creating a search query for CopPhil OData API using CopPhil Data Explorer. We are going to discover products available from Sentinel-2 Level 2 data, acquired over Manila from 2024-01-01 to 2024-09-30.

Prerequisites

No. 1 Access to CopPhil site

You need a CopPhil hosting account, available at https://infra.copphil.philsa.gov.ph.

No. 2 Access to JupyterLab

JupyterLab used in this article is available here: https://jupyter.infra.copphil.philsa.gov.ph/hub/login?next=%2Fhub%2F.

No. 3 Working knowledge of JupyterLab

See article Introduction to JupyterLab on CopPhil

No. 4 Using API

This is an introductory example of obtaining EODATA using API calls, in Python:

Download satellite data using API on CopPhil

No. 5 Information on Sentinel-2 mission

Page Sentinel-2 mission shows basic information on Sentinel-2 mission, which is used in this article as a source of information.

What We Are Going To Cover

  • Preparing your environment

  • Generating a query using Python and API structure

    • Building a query

    • Generated URL

    • Inspecting the results of the request

    • Number of the found products

    • Metadata of the found products

    • Additional filters

    • Generated url

    • Inspecting results of the request

    • Number of the found products

    • Metadata for the found products

Prepare your environment

Import necessary python libraries.

# HTTP requests
import requests

# JSON parser
import json

# data manipulation
import pandas as pd

Generate a query using python and API structure

Now, let us build a query for Sentinel-2 Level 2 data acquired over Manila from 2024-01-01 to 2024-09-30.

Build a query

In order to find desired products it is needed to determine specific filters:

collection_name

Sentinel-1, Sentinel-2 etc.

product_type

MSIL1C, MSIL2A

aoi

extent (coordinates) of the area of interest (WGS84)

search_period_start

time range - start date

search_period_end

time range - end date

Filters above correspond to the filters which are provided via GUI.

# base URL of the product catalogue
catalogue_odata_url = "https://catalogue.infra.copphil.philsa.gov.ph/odata/v1"

# search parameters
collection_name = "SENTINEL-2"
product_type = "S2MSI2A"
aoi = "POLYGON((120.962986 14.598416, 120.995964 14.599182, 120.999658 14.563436, 120.960348 14.567522, 120.962986 14.598416))"
search_period_start = "2024-01-01T00:00:00.000Z"
search_period_end = "2024-09-30T00:00:00.000Z"

Generated url

Show the generated query as url.

search_query = f"{catalogue_odata_url}/Products?$filter=Collection/Name eq '{collection_name}' and Attributes/OData.CSC.StringAttribute/any(att:att/Name eq 'productType' and att/OData.CSC.StringAttribute/Value eq '{product_type}') and OData.CSC.Intersects(area=geography'SRID=4326;{aoi}') and ContentDate/Start gt {search_period_start} and ContentDate/Start lt {search_period_end}"

print(f"""\n{search_query.replace(' ', "%20")}\n""")

This would be the result:

Inspect the results of the request

Get the results and verify whether query was executed properly (and whether it works). If Status code is 200, it works fine. Convert the content of the response to JSON and inspect it.

response = requests.get(search_query)
print(f'Status code is {response.status_code}')
response = requests.get(search_query).json()
Status code is 200

Number of the found products

Show the number of found products which fits into filters requirements.

result = pd.DataFrame.from_dict(response["value"])
len(result)
20

Metadata of the found products

Inspect the metadata of the products which fits into query requirements. Use pandas library to visualize metadata in table format.

result.head()
@odata.mediaContentType Id Name ContentType ContentLength OriginDate PublicationDate ModificationDate Online EvictionDate S3Path Checksum ContentDate Footprint GeoFootprint
0 application/octet-stream e672713e-49bb-4875-8801-ea9ac6f75c2b S2A_MSIL2A_20240117T022021_N0510_R003_T51PTS_2... application/octet-stream 1056120269 2024-01-17T06:19:12.000000Z 2024-01-17T06:32:29.344413Z 2024-03-13T18:34:26.338916Z True 9999-12-31T23:59:59.999999Z /eodata/Sentinel-2/MSI/L2A/2024/01/17/S2A_MSIL... [{'Value': 'a6a7342e05993610bbfc4e98f4a88c09',... {'Start': '2024-01-17T02:20:21.024000Z', 'End'... geography'SRID=4326;POLYGON ((120.205542908771... {'type': 'Polygon', 'coordinates': [[[120.2055...
1 application/octet-stream 6cd59c03-5f06-4778-9b5a-c3896289dd22 S2B_MSIL2A_20240312T021529_N0510_R003_T51PTS_2... application/octet-stream 835688199 2024-03-12T05:43:58.000000Z 2024-03-12T05:51:40.416293Z 2024-03-12T05:52:32.423248Z True 9999-12-31T23:59:59.999999Z /eodata/Sentinel-2/MSI/L2A/2024/03/12/S2B_MSIL... [{'Value': 'f60a7ea9494fddc85d8ae353a87aad77',... {'Start': '2024-03-12T02:15:29.024000Z', 'End'... geography'SRID=4326;POLYGON ((120.205542908771... {'type': 'Polygon', 'coordinates': [[[120.2055...
2 application/octet-stream c1e63eb7-c683-4f0b-b706-c24198c5b114 S2A_MSIL2A_20240127T021941_N0510_R003_T51PTS_2... application/octet-stream 1067374355 2024-01-27T06:26:14.000000Z 2024-01-27T06:48:55.704601Z 2024-03-13T09:08:15.643286Z True 9999-12-31T23:59:59.999999Z /eodata/Sentinel-2/MSI/L2A/2024/01/27/S2A_MSIL... [{'Value': '711e110e4b428370817bf0675fb77b7f',... {'Start': '2024-01-27T02:19:41.024000Z', 'End'... geography'SRID=4326;POLYGON ((120.205542908771... {'type': 'Polygon', 'coordinates': [[[120.2055...
3 application/octet-stream 8d4f4fee-6068-48d4-82b6-dd078aca3052 S2B_MSIL2A_20240102T022109_N0510_R003_T51PTS_2... application/octet-stream 1120991558 2024-01-02T05:39:37.416000Z 2024-01-02T06:00:52.579790Z 2024-03-13T12:26:57.315310Z True 9999-12-31T23:59:59.999999Z /eodata/Sentinel-2/MSI/L2A/2024/01/02/S2B_MSIL... [{'Value': '57958f2c5eda253d13181238541c85b1',... {'Start': '2024-01-02T02:21:09.024000Z', 'End'... geography'SRID=4326;POLYGON ((120.205542908771... {'type': 'Polygon', 'coordinates': [[[120.2055...
4 application/octet-stream 678423d6-f064-4bbb-a708-7f0a0068683a S2B_MSIL2A_20240112T022049_N0510_R003_T51PTS_2... application/octet-stream 1112555506 2024-01-16T15:55:45.000000Z 2024-01-16T16:38:59.547061Z 2024-03-13T18:31:18.750124Z True 9999-12-31T23:59:59.999999Z /eodata/Sentinel-2/MSI/L2A/2024/01/12/S2B_MSIL... [{'Value': 'b56b2774d43c66b7877f3a802374109d',... {'Start': '2024-01-12T02:20:49.024000Z', 'End'... geography'SRID=4326;POLYGON ((120.205542908771... {'type': 'Polygon', 'coordinates': [[[120.2055...

Additional filters

Add one more filter so that only the cloudless images will be listed.

max_cloud_cover

maximum cloud cover (%) fo the image

Generated url

Show the generated query as url.

max_cloud_cover = 20

search_query = f"{search_query} and Attributes/OData.CSC.DoubleAttribute/any(att:att/Name eq 'cloudCover' and att/OData.CSC.DoubleAttribute/Value le {max_cloud_cover})"
print(f"""\n{search_query.replace(' ', "%20")}\n""")

It yields:

Inspect results of the request

Get the results and verify whether the query was executed properly (and whether it works). If Status code is 200, it works fine. Convert content of the response to JSON format and inspect it.

response = requests.get(search_query)
print(f'Status code is {response.status_code}')
response = requests.get(search_query).json()
Status code is 200

Number of the found products

Show the number of found products which fits the requirements posed by the filters.

result = pd.DataFrame.from_dict(response["value"])
len(result)
6

Metadata for the found products

Inspect the metadata of the products which fits into query requirements. Use pandas library to visualize metadata in table format - first five rows.

result.head()
@odata.mediaContentType Id Name ContentType ContentLength OriginDate PublicationDate ModificationDate Online EvictionDate S3Path Checksum ContentDate Footprint GeoFootprint
0 application/octet-stream 51b58ff8-4fd5-4fe3-b2f0-beebfee95bab S2B_MSIL2A_20240211T021829_N0510_R003_T51PTS_2... application/octet-stream 1156520968 2024-02-11T06:09:02.000000Z 2024-02-11T06:18:35.134676Z 2024-03-13T10:30:49.000330Z True 9999-12-31T23:59:59.999999Z /eodata/Sentinel-2/MSI/L2A/2024/02/11/S2B_MSIL... [{'Value': 'fc89b2ffa223c038953f7e67ea9145c8',... {'Start': '2024-02-11T02:18:29.024000Z', 'End'... geography'SRID=4326;POLYGON ((120.205542908771... {'type': 'Polygon', 'coordinates': [[[120.2055...
1 application/octet-stream dfe46249-bc17-401f-bf9a-bcc05efe77c7 S2B_MSIL2A_20240302T021609_N0510_R003_T51PTS_2... application/octet-stream 1131528020 2024-03-02T05:42:43.000000Z 2024-03-02T05:54:12.768121Z 2024-03-02T05:55:36.451258Z True 9999-12-31T23:59:59.999999Z /eodata/Sentinel-2/MSI/L2A/2024/03/02/S2B_MSIL... [{'Value': '02fce369b36758079e58eafce7ef1e9b',... {'Start': '2024-03-02T02:16:09.024000Z', 'End'... geography'SRID=4326;POLYGON ((120.205542908771... {'type': 'Polygon', 'coordinates': [[[120.2055...
2 application/octet-stream 4acc616f-1f77-460b-867e-4d3452dee225 S2A_MSIL2A_20240426T021611_N0510_R003_T51PTS_2... application/octet-stream 1163640068 2024-04-26T08:56:54.000000Z 2024-04-26T09:04:35.755846Z 2024-04-26T09:06:00.728565Z True 9999-12-31T23:59:59.999999Z /eodata/Sentinel-2/MSI/L2A/2024/04/26/S2A_MSIL... [{'Value': '53179d9d86cb6687ffcb3a46866ebd51',... {'Start': '2024-04-26T02:16:11.024000Z', 'End'... geography'SRID=4326;POLYGON ((120.205542908771... {'type': 'Polygon', 'coordinates': [[[120.2055...
3 application/octet-stream f5c26c11-d72d-4c91-80ec-fd7428c0d518 S2A_MSIL2A_20240307T021541_N0510_R003_T51PTS_2... application/octet-stream 1130852495 2024-03-07T06:30:50.000000Z 2024-03-07T06:40:56.016476Z 2024-03-07T09:51:23.141122Z True 9999-12-31T23:59:59.999999Z /eodata/Sentinel-2/MSI/L2A/2024/03/07/S2A_MSIL... [{'Value': '83ad987c68029bd4359e28dafc9e8d6a',... {'Start': '2024-03-07T02:15:41.024000Z', 'End'... geography'SRID=4326;POLYGON ((120.205542908771... {'type': 'Polygon', 'coordinates': [[[120.2055...
4 application/octet-stream cbdd1d86-52ac-4ee7-aa33-306019d525db S2B_MSIL2A_20240421T021529_N0510_R003_T51PTS_2... application/octet-stream 1167844378 2024-04-21T05:42:13.000000Z 2024-04-21T05:56:32.735338Z 2024-04-21T05:58:09.183638Z True 9999-12-31T23:59:59.999999Z /eodata/Sentinel-2/MSI/L2A/2024/04/21/S2B_MSIL... [{'Value': 'f79de0b45c364db5e4a7354b39408f26',... {'Start': '2024-04-21T02:15:29.024000Z', 'End'... geography'SRID=4326;POLYGON ((120.205542908771... {'type': 'Polygon', 'coordinates': [[[120.2055...

What To Do Next

You can also use other satellites and their data to inspect conditions over Manila in a defined period of time. The following article uses

  • Sentinel-3 LST data with the GUI of

  • CopPhil Data Explorer

Use CopPhil Data Explorer to find all Sentinel-3 Land Surface Temperature products over Manila in January 2024