# If needed you can install a package in the current AppHub Jupyter environment using pip
# For instance, we will need at least the following libraries
import sys
!{sys.executable} -m pip install --upgrade pyeodh geopandas matplotlib numpy folium xarray geoviews hvplot holoviews datashader cartopy
Pathfinder Phase Workshop: Visualising Data
Description & purpose: This Notebook is designed to showcase the functionality of the Earth Observation Data Hub (EODH) as the project approaches the end of the Pathfinder Phase. It provides a snapshot of the Hub, the pyeodh
API client and the various datasets as of February 2025.
Author(s): Alastair Graham, Dusan Figala, James Hinton, Daniel Westwood
Date created: 2025-02-18
Date last modified: 2025-02-25
Licence: This notebook is licensed under Creative Commons Attribution-ShareAlike 4.0 International. The code is released using the BSD-2-Clause license.
Copyright (c) , All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Presentation set up
The following cell only needs to be run on the EODH AppHub. If you have a local Python environment running, please install the required packages as you would normally. If running locally, it’s easiest to install all dependencies using uv
(https://docs.astral.sh/uv/getting-started/installation/) by running uv sync
in the root directory of the repository.
Introduction
In this notebook we will explore different ways to visualise data held on the Hub. The Notebooks can be run on the JupyterHub instance on the Hub (linked to your user account) or locally with a suitably set up environment.
# Imports
import os
# Import the Python API Client
import pyeodh
import folium
import xarray as xr
import hvplot.xarray # Needed for xarray plotting with geoviews
import holoviews as hv
import datashader as ds
from holoviews import opts
from holoviews.operation.datashader import rasterize
import cartopy.crs as ccrs # For coordinate reference systems
import geoviews as gv
import requests
from IPython.display import Image, display
# Parameterise geoviews
"bokeh", "matplotlib") gv.extension(
Accessing Different DataTypes
For this part of the workshop exercises we are going to look at how to visualise two different datasets. This should give you the foundation and understanding about how you could do this for other data held on the Hub and elsewhere. The first thing we need to do is connect to the EODH and get information about the collections we are interested in: cmip6 and the sentinel 2 ARD.
# Connect to the Hub
# Change base_url to point to the server that you want to connect to
= pyeodh.Client(base_url="https://eodatahub.org.uk").get_catalog_service()
client
= client.get_catalog("public/catalogs/ceda-stac-catalogue")
catalog
# Get each collection
= catalog.get_collection("cmip6")
cmip6 = catalog.get_collection("sentinel2_ard") sentinel2_ard
We can interrogate the temporal and spatial extents of the data holdings. Below, we have printed out one of each for each dataset that we have connected to. This can help us understand what date ranges or spatial extents we can use when visualising the data.
# Get the collection metadata
= ["spatial", "temporal"]
extent
print("Dataset extent - CMIP6: ", cmip6.extent.to_dict()[extent[1]])
print("Dataset extent - Sentinel 2 ARD: ", sentinel2_ard.extent.to_dict()[extent[0]])
Dataset extent - CMIP6: {'interval': [['1850-01-01T00:00:00Z', '4114-12-16T12:00:00Z']]}
Dataset extent - Sentinel 2 ARD: {'bbox': [[-9.00034454651177, 49.48562028352171, 3.1494256015866995, 61.33444247301668]]}
As this is an exercise, we have already chosen some data to look at.
The CMIP6 item has been generated using the CIESM model, running the high-emission SSP5-8.5 scenario. It contains monthly-averaged upward shortwave radiation at the surface (rsus) on a regular grid.
The Sentinel 2 ARD image covers an area acros sthe south of England, including the Solent.
# Look for a specific item
= cmip6.get_item(
cmip6_item "CMIP6.ScenarioMIP.THU.CIESM.ssp585.r1i1p1f1.Amon.rsus.gr.v20200806"
)= sentinel2_ard.get_item(
sentinel_item "neodc.sentinel_ard.data.sentinel_2.2023.11.17.S2A_20231117_latn509lonw0008_T30UXB_ORB137_20231117131218_utm30n_osgb"
)
# Get information and links to the item assets held in STAC
print("---" * 20, "CMIP6", "---" * 20)
print(cmip6_item.assets)
print("")
print("---" * 20, "SENTINEL 2", "---" * 20)
print(sentinel_item.assets)
------------------------------------------------------------ CMIP6 ------------------------------------------------------------
{'reference_file': <Asset href=https://dap.ceda.ac.uk/badc/cmip6/metadata/kerchunk/pipeline1/ScenarioMIP/THU/CIESM/kr1.0/CMIP6_ScenarioMIP_THU_CIESM_ssp585_r1i1p1f1_Amon_rsus_gr_v20200806_kr1.0.json>, 'data0001': <Asset href=https://dap.ceda.ac.uk/badc/cmip6/data/CMIP6/ScenarioMIP/THU/CIESM/ssp585/r1i1p1f1/Amon/rsus/gr/v20200806/rsus_Amon_CIESM_ssp585_r1i1p1f1_gr_402901-411412.nc>}
------------------------------------------------------------ SENTINEL 2 ------------------------------------------------------------
{'cloud': <Asset href=https://dap.ceda.ac.uk/neodc/sentinel_ard/data/sentinel_2/2023/11/17/S2A_20231117_latn509lonw0008_T30UXB_ORB137_20231117131218_utm30n_osgb_clouds.tif>, 'cloud_probability': <Asset href=https://dap.ceda.ac.uk/neodc/sentinel_ard/data/sentinel_2/2023/11/17/S2A_20231117_latn509lonw0008_T30UXB_ORB137_20231117131218_utm30n_osgb_clouds_prob.tif>, 'cog': <Asset href=https://dap.ceda.ac.uk/neodc/sentinel_ard/data/sentinel_2/2023/11/17/S2A_20231117_latn509lonw0008_T30UXB_ORB137_20231117131218_utm30n_osgb_vmsk_sharp_rad_srefdem_stdsref.tif>, 'metadata': <Asset href=https://dap.ceda.ac.uk/neodc/sentinel_ard/data/sentinel_2/2023/11/17/S2A_20231117_latn509lonw0008_T30UXB_ORB137_20231117131218_utm30n_osgb_vmsk_sharp_rad_srefdem_stdsref_meta.xml>, 'saturated_pixels': <Asset href=https://dap.ceda.ac.uk/neodc/sentinel_ard/data/sentinel_2/2023/11/17/S2A_20231117_latn509lonw0008_T30UXB_ORB137_20231117131218_utm30n_osgb_sat.tif>, 'thumbnail': <Asset href=https://dap.ceda.ac.uk/neodc/sentinel_ard/data/sentinel_2/2023/11/17/S2A_20231117_latn509lonw0008_T30UXB_ORB137_20231117131218_utm30n_osgb_vmsk_sharp_rad_srefdem_stdsref_thumbnail.jpg>, 'topographic_shadow': <Asset href=https://dap.ceda.ac.uk/neodc/sentinel_ard/data/sentinel_2/2023/11/17/S2A_20231117_latn509lonw0008_T30UXB_ORB137_20231117131218_utm30n_osgb_toposhad.tif>, 'valid_pixels': <Asset href=https://dap.ceda.ac.uk/neodc/sentinel_ard/data/sentinel_2/2023/11/17/S2A_20231117_latn509lonw0008_T30UXB_ORB137_20231117131218_utm30n_osgb_valid.tif>}
We can then use the information above to gather links to the asset data
= cmip6_item.assets["reference_file"]
cmip6_kerchunk_asset = sentinel_item.assets["cog"]
sentinel2_ard_cog_asset
# print the href
print(cmip6_kerchunk_asset.href)
print(sentinel2_ard_cog_asset.href)
https://dap.ceda.ac.uk/badc/cmip6/metadata/kerchunk/pipeline1/ScenarioMIP/THU/CIESM/kr1.0/CMIP6_ScenarioMIP_THU_CIESM_ssp585_r1i1p1f1_Amon_rsus_gr_v20200806_kr1.0.json
https://dap.ceda.ac.uk/neodc/sentinel_ard/data/sentinel_2/2023/11/17/S2A_20231117_latn509lonw0008_T30UXB_ORB137_20231117131218_utm30n_osgb_vmsk_sharp_rad_srefdem_stdsref.tif
Manipulating and plotting data
Plot a single timestep
For the next part of this exercise we will undertake the following steps:
- Access our CMIP6 Dataset
- Extract the dataset (Kerchunk)
- Select a single timestep
- Plot resulting image
# Get information on the cloud product
= cmip6_item.get_cloud_products()
product product
<DataPointCloudProduct: CMIP6.ScenarioMIP.THU.CIESM.ssp585.r1i1p1f1.Amon.rsus.gr.v20200806-reference_file (Format: kerchunk)>
- bbox: [-180.0, -90.0, 178.75, 90.0]
- asset_id: CMIP6.ScenarioMIP.THU.CIESM.ssp585.r1i1p1f1.Amon.rsus.gr.v20200806-reference_file
- cloud_format: kerchunk
Attributes:
- title: CMIP6.ScenarioMIP.THU.CIESM.ssp585.r1i1p1f1.Amon.rsus.gr.v20200806
- datetime: 4072-01-01T00:00:00Z
- created: 2025-01-24T14:29:23.741213Z
- updated: 2025-08-29T03:10:04.291804Z
- start_datetime: 4029-01-16T12:00:00Z
- end_datetime: 4114-12-16T12:00:00Z
- cmip6:further_info_url: https://furtherinfo.es-doc.org/CMIP6.THU.CIESM.ssp585.none.r1i1p1f1
- cmip6:source_type: AOGCM
- cmip6:institution_id: THU
- cmip6:variable_long_name: Surface Upwelling Shortwave Radiation
- cmip6:mip_era: CMIP6
- project: CMIP6
- cmip6:access: ['HTTPServer']
- cmip6:nominal_resolution: 100 km
- cmip6:sub_experiment_id: none
- cmip6:frequency: mon
- cmip6:experiment_id: ssp585
- cmip6:table_id: Amon
- cmip6:activity_id: ScenarioMIP
- product: model-output
- model_cohort: Registered
- cmip6:grid_label: gr
- cmip6:cf_standard_name: surface_upwelling_shortwave_flux_in_air
- cmip6:data_specs_version: 01.00.29
- cmip6:variable_id: rsus
- cmip6:variable_units: W m-2
- cmip6:source_id: CIESM
- cmip6:experiment_title: update of RCP8.5 based on SSP5
- cmip6:citation_url: http://cera-www.dkrz.de/WDCC/meta/CMIP6/CMIP6.ScenarioMIP.THU.CIESM.ssp585.r1i1p1f1.Amon.rsus.gr.v20200806.json
- cmip6:variant_label: r1i1p1f1
- realm: ['atmos']
- cmip6:retracted: False
- cmip6:grid: gs1x1
We can see that this item contains a single product, a kerchunk reference file which allows us to access the dataset as a single object. The format doesn’t actually matter here, as the tools we are using here allows us to open any recognised format into xarray with minimal understanding of the data format on the user side.
The following code cell opens the file as an xarray dataset and presents the user with information about the array structure.
= product.open_dataset()
ds ds
<xarray.Dataset> Size: 228MB Dimensions: (lat: 192, bnds: 2, lon: 288, time: 1032) Coordinates: * lat (lat) float64 2kB -90.0 -89.06 -88.12 -87.17 ... 88.12 89.06 90.0 * lon (lon) float64 2kB 0.0 1.25 2.5 3.75 ... 355.0 356.2 357.5 358.8 * time (time) object 8kB 4029-01-16 12:00:00 ... 4114-12-16 12:00:00 Dimensions without coordinates: bnds Data variables: lat_bnds (lat, bnds) float64 3kB dask.array<chunksize=(192, 2), meta=np.ndarray> lon_bnds (lon, bnds) float64 5kB dask.array<chunksize=(288, 2), meta=np.ndarray> rsus (time, lat, lon) float32 228MB dask.array<chunksize=(1, 192, 288), meta=np.ndarray> time_bnds (time, bnds) object 17kB dask.array<chunksize=(1, 2), meta=np.ndarray> Attributes: (12/46) Conventions: CF-1.7 CMIP-6.2 activity_id: ScenarioMIP branch_method: standard branch_time_in_child: 735110.0 branch_time_in_parent: 735110.0 cmor_version: 3.6.0 ... ... table_id: Amon table_info: Creation Date:(20 February 2019) MD5:510997cd0a2c... title: CIESM output prepared for CMIP6 tracking_id: hdl:21.14100/26602daf-2379-491b-ad98-2ebb2f581db7 variable_id: rsus variant_label: r1i1p1f1
Looking at the output above we can see that the dataset has four Data variables
. We can perform various selections on the data but specifically we need to choose the variable containng the data to plot, and then select the time step we are interested in. We will use the geoviews
package to plot the resulting map.
= list(ds.data_vars)[2] # Choose the data variable (modify if needed)
data_var print("Variable: ", data_var)
= 555 # choose any number within the range presented in the xarray oiutput i.e. up to 1032 in this case timestep
Variable: rsus
= ds[data_var].isel(time=timestep) # Select the data for the time step
selected_data
# Plot the data
= selected_data.hvplot.quadmesh(
plot ="lon",
x="lat",
y="plasma",
cmap=True,
geo=ccrs.PlateCarree(),
projection=True,
coastline=f"Time Step: {ds.time.values[timestep]}",
title
) plot
/home/figi/software/work/eodh/eodh-training/.venv/lib/python3.10/site-packages/cartopy/io/__init__.py:242: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/110m_physical/ne_110m_coastline.zip
warnings.warn(f'Downloading: {url}', DownloadWarning)
Plot an NDVI Analysis
Next we will use the Sentinel 2 ARD dataset to create a simple normalised difference vegetation index (NDVI) - the ‘Hello World’ of the Earth observation sector!
NDVI is a widely used metric that assesses vegetation health and density by measuring the difference between near-infrared (NIR) and red light reflectance. Healthy vegetation absorbs most red light for photosynthesis while reflecting NIR, resulting in high NDVI values (close to +1). Sparse or unhealthy vegetation has lower values, while barren areas like water or built-up surfaces have values near zero or negative.
We will undertake the following steps:
- Access a Sentinel 2 ARD Dataset.
- Open the dataset (COG) file.
- Perform calculation for NDVI analysis over an AOI.
- Plot resulting image.
We can access the selected search result as before, and open the cloud product which this time is a Cloud Optimised GeoTiff (COG) file.
= sentinel_item.get_cloud_products()
product print(product)
= product.open_dataset()
ds1 ds1
<DataPointCloudProduct: neodc.sentinel_ard.data.sentinel_2.2023.11.17.S2A_20231117_latn509lonw0008_T30UXB_ORB137_20231117131218_utm30n_osgb-cog (Format: cog)>
<xarray.DataArray (band: 10, y: 11127, x: 11126)> Size: 2GB [1237990020 values with dtype=uint16] Coordinates: * band (band) int64 80B 1 2 3 4 5 6 7 8 9 10 * x (x) float64 89kB 4.291e+05 4.291e+05 ... 5.404e+05 5.404e+05 * y (y) float64 89kB 1.716e+05 1.716e+05 ... 6.032e+04 6.032e+04 spatial_ref int64 8B 0 Attributes: (12/18) AREA_OR_POINT: Area ATTRIBUTETABLE_CHUNKSIZE: 1000 LAYER_TYPE: athematic STATISTICS_EXCLUDEDVALUES: 0 STATISTICS_HISTOBINFUNCTION: linear STATISTICS_HISTOMAX: 1314 ... ... STATISTICS_MODE: 72.8046875 STATISTICS_STDDEV: 31.65248448151489 _FillValue: 0 scale_factor: 1.0 add_offset: 0.0 long_name: ('Blue', 'Green', 'Red', 'RE_B5', 'RE_B6', ...
We are using a very simple area of interest (AOI) for this exercise - we define the AOI as slice ranges to apply to the xarray DataArray.
There are other spatially contiguous methods for defining AOIs that require handling of projections and spatial file formats that are out of scope for this exercise. These would all work using the data we are manipuulating here.
# Create a data slice to act as an AOI
= ds1.isel(x=slice(1200, 2200), y=slice(2200, 3200)) crop_ds1
# Extract the red and nir bands for the AOI
= crop_ds1.isel(band=2)
red = crop_ds1.isel(band=6)
nir
# Calculate NDVI
= (nir - red) / (nir + red) ndvi
# Plot the NDVI output
# Note: clim sets the colourmap limits to allow a data stretch
= ndvi.hvplot.quadmesh(
plot ="x",
x="y",
y="RdYlGn",
cmap=True,
colorbar=(0, 1),
clim="Vegetation (NDVI) Plot",
title
) plot
Streaming data using Titiler
In this section we will investigate how to access tiled data that is being served by titiler
. Titiler is a lightweight, fast and customisable dynamic tile server for geospatial data, built on FastAPI and Rasterio. It enables on-the-fly serving of raster tiles, mosaics, and previews from cloud-optimized GeoTIFFs (COGs) and other raster sources. Designed for scalability and efficiency, Titiler supports advanced features like dynamic tiling, custom styling, and integration with modern web mapping applications. It is increasingly used in geospatial analysis, remote sensing, and web-based GIS applications.
Using Preview with COGs
Here we can use the Preview
feature to customise some of the parameters we are going to use to dynamically visualise the data.
bidx
is the band index we want to preview. In this case, we are previewing the first band.rescale
is the range of values we want to display. In this case, we are rescaling the values between 9 and 255.colormap_name
is the name of the colormap we want to use. In this case, we are using therain_r
colormap.
For testing, experiment with different colormaps, here’s a few to try:
'accent', 'afmhot', 'afmhot_r', 'algae', 'algae_r', 'amp_r', 'autumn', 'balance', 'binary', 'binary_r', 'blues', 'bone', 'bone_r', 'hot', 'viridis', ...
= "https://eodatahub.org.uk/titiler/core/cog/preview"
COG_PREVIEW_URL = {
COG_PREVIEW_PARAMS "url": sentinel2_ard_cog_asset.href,
"bidx": 1,
"rescale": "9,255",
"colormap_name": "rain_r",
}
# Request the titiler preview
= requests.get(COG_PREVIEW_URL, params=COG_PREVIEW_PARAMS)
response
# Display the image
= Image(response.content)
image display(image)
Using Preview with Kerchunk
Lets follow a similar approach for the xarray data. This xarray data is a Kerchunk dataset - remember that it contains a single variable called rsus
. We can preview the data similarly to how we previewed the COG data.
This time, focus on the rescale
parameter. This parameter is used to rescale the values of the data. In this example we are rescaling between -50,100
, but try something new like 50,400
and see how the data changes.
= "https://eodatahub.org.uk/titiler/xarray/tiles/0/0/0"
XARRAY_PREVIEW_URL = {
XARRAY_PARAMS "url": cmip6_kerchunk_asset.href,
"variable": "rsus",
"rescale": "-50,100",
"colormap_name": "plasma",
"reference": "true",
}
# Build the request
= f"{XARRAY_PREVIEW_URL}?url={cmip6_kerchunk_asset.href}&variable=rsus&rescale=35,400&colormap_name=plasma&reference=true"
constructed_url print(constructed_url)
# Request the titiler preview
= requests.get(XARRAY_PREVIEW_URL, params=XARRAY_PARAMS)
response
# Display the image
= Image(response.content)
image display(image)
https://eodatahub.org.uk/titiler/xarray/tiles/0/0/0?url=https://dap.ceda.ac.uk/badc/cmip6/metadata/kerchunk/pipeline1/ScenarioMIP/THU/CIESM/kr1.0/CMIP6_ScenarioMIP_THU_CIESM_ssp585_r1i1p1f1_Amon_rsus_gr_v20200806_kr1.0.json&variable=rsus&rescale=35,400&colormap_name=plasma&reference=true
Exploring the Data Using OGC XYZ Tiles
Now that we have previewed the datasets, we can use third party tools to also explore the data. To do this, we are going to create an XYZ
tile endpoint for both the COG data and the Kerchunk data. This can then be used in any third-party tool that supports XYZ tiles e.g. QGIS, OpenLayers, Leaflet, etc.
The following code cell builds the URLs we require based on some of the variables that we have already set. It then prints the two URLS that we will need to display andvisualise the data.
# Generate XYZ For COG
= (
COG_OGC_URL "https://eodatahub.org.uk/titiler/core/cog/tiles/WebMercatorQuad/{z}/{x}/{y}"
)= (
COG_XYZ + "?" + "&".join([f"{k}={v}" for k, v in COG_PREVIEW_PARAMS.items()])
COG_OGC_URL
)
# Generate XYZ For Xarray
= (
XARRAY_OGC_URL "https://eodatahub.org.uk/titiler/xarray/tiles/WebMercatorQuad/{z}/{x}/{y}"
)= (
XARRAY_XYZ + "?" + "&".join([f"{k}={v}" for k, v in XARRAY_PARAMS.items()])
XARRAY_OGC_URL
)
print("Cog XYZ: ", COG_XYZ)
print("Kerchunk XYZ", XARRAY_XYZ)
Cog XYZ: https://eodatahub.org.uk/titiler/core/cog/tiles/WebMercatorQuad/{z}/{x}/{y}?url=https://dap.ceda.ac.uk/neodc/sentinel_ard/data/sentinel_2/2023/11/17/S2A_20231117_latn509lonw0008_T30UXB_ORB137_20231117131218_utm30n_osgb_vmsk_sharp_rad_srefdem_stdsref.tif&bidx=1&rescale=9,255&colormap_name=rain_r
Kerchunk XYZ https://eodatahub.org.uk/titiler/xarray/tiles/WebMercatorQuad/{z}/{x}/{y}?url=https://dap.ceda.ac.uk/badc/cmip6/metadata/kerchunk/pipeline1/ScenarioMIP/THU/CIESM/kr1.0/CMIP6_ScenarioMIP_THU_CIESM_ssp585_r1i1p1f1_Amon_rsus_gr_v20200806_kr1.0.json&variable=rsus&rescale=-50,100&colormap_name=plasma&reference=true
We can then use a map viewer package such as folium
to ingest the titiler
URL and display it in an interactive way. We do this below for both datasets.
# For the Sentinel dataset
= folium.Map(location=[54.5, -4.5], zoom_start=6)
m
# Add the TiTiler layer
folium.raster_layers.TileLayer(=COG_XYZ, attr="TiTiler", name="Sentinel 2 ARD Scene", overlay=True
tiles
).add_to(m)
# Add a layer control
folium.LayerControl().add_to(m)
# Display the map
m
# For the CMIP6 dataset
= folium.Map(location=[0, 0], zoom_start=2)
m
# Add the TiTiler layer
folium.raster_layers.TileLayer(=XARRAY_XYZ,
tiles="TiTiler",
attr="CMIP6 Surface Upwelling Shortwave Radiation (W m-2)",
name=True,
overlay
).add_to(m)
# Add a layer control
folium.LayerControl().add_to(m)
# Display the map
m
In this notebook, we have seen how to access and visualise different data types in different ways.
Extra functionality includes the ability to visualise your own Workspace data by passing in your Workspace API key (that you can generate from the Workspace
tab). You can then visualise your own data on a map.
This means you can visualise any of your workflow outputs, commercial data or any other visualisable data you have in your Workspace.
An example request would be:
= f'https://eodatahub.org.uk/titiler/core/cog/preview'
TITILER_PREVIEW_URL = {
TITILER_PREVIEW_PARAMS 'url': WORKFLOW_OUTPUT_ASSET,
'bidx': 1,
'rescale': '9,255',
'colormap_name': 'rain_r'
}
= requests.get(TITILER_PREVIEW_URL, params=TITILER_PREVIEW_PARAMS, headers={'Authorization': f'Bearer {WORKSPACE_API_KEY}'}) # Note the headers parameter response
Here we are passing the WORKSPACE_API_KEY
in the headers of the request. This will allow you to visualise your own private data straight from the Platform.