Dash for Raster Maps

I have a set of raster data for the years 2000 and 2020. I would like to create a dashboard using Dash. The dashboard should have five tabs, the including a link to the homepage.

Users should be able to select a year, and the corresponding maps for each raster data should be displayed.

Is it feasible to implement these features using Dash?

The homepage of the app should feature a project description and provide a link to explore the maps. While I am aware that similar functionality can be achieved with ArcGIS dashboards, I would like to use Dash for this purpose.

Here is what I have done so far:

Dash leaflet offers great capabilities for maps and also raster layers. Check out the documentation. On the left you find the topic “Raster Layers” with four subtopics.

Thank you. I will explore it

A quick one. Does it support TIFF files? I noticed it supports jpg files. However, what I want to do involves TIFF files. I also came across georaster-layer-for-leaflet, but I don’t know if it’s integrated into dash leaflet

hi @edak
If I remember correctly, Dash Leaflet does not natively support TIFF files. @Emil is that correct?

I removed “direct” support for (geo) tiff files in recent version of Dash, as loading these typically large files directly doesn’t provide the best user experience. Hence, at present you have two options,

  1. Use the ImageOverlay component, which supports e.g. jpg image. It suited for small-ish images (~ up to a few MB)
  2. Use a tile server (such as Terracotta) to serve e.g. (geo) tiff to a TileLayer component. This work flow is suited for large images

It sounds like the use case here is more (2) than (1). I made a small sample app for inspiraton some time ago.

1 Like

Cool. I will try it out

Thank you all for the suggestions. This is what I did:

I utilized GDAL to transform my TIFF file into a cloud-optimized GeoTIFF format, subsequently uploading it to my Google Cloud Storage bucket. Next, I used titiler and dash-leafmap to serve the GeoTIFF file directly from Google Cloud, integrating it into my app.

That sounds like an interesting solution. Could you post/link the code here for inspiration to others? :slight_smile:

Sure

import httpx
import dash_leaflet as dl
from dash import Dash, html

# Convert raster to Cloud-optimized GeoTiff 
gdal_translate input.tif output_cog.tif -of COG -co COMPRESS=LZW


# Set up titiler endpoint and url to COG 
titiler_endpoint = "https://titiler.xyz"
url = "https://storage.googleapis.com/landcover_classes/agb_cog.tif"

# Fetch File Metadata to get min/max rescaling values
r = httpx.get(
    f"{titiler_endpoint}/cog/statistics",
    params = {
        "url": url,
    }
).json()

# Get minimum and maximum raster values
minv = (r["b1"]["min"]) # b1:  band 1
maxv = (r["b1"]["max"])

# Get tile map from titiler endpoint and url , and scale to min and max values 
r = httpx.get(
    f"{titiler_endpoint}/cog/tilejson.json",
    params = {
        "url": url,
        "rescale": f"{minv},{maxv}",
        "colormap_name": "magma"
    }
).json()



app = Dash(__name__)

colorscale = ['#000004', '#3b0f70', '#8c2981', '#de4968', '#fe9f6d', '#fcfdbf']

# Create app layout
app.layout = html.Div([
                      dl.Map(
                          style = 
                             {'height': '700px',
                                       'width': '1500px'},
                                    center = [5.814379, 0.843645],
                                    zoom = 12,
                                    id = "leaflet-map",
                                    children = [
                                              dl.LayersControl([
                                                            dl.Overlay(dl.LayerGroup(dl.TileLayer(url = "https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_nolabels/{z}/{x}/{y}.png",id = "TileMap")), name = "Carto DB",checked=False),
                                                             dl.Overlay(dl.LayerGroup(dl.TileLayer(url = 'https://api.mapbox.com/styles/v1/mapbox/dark-v10/tiles/{z}/{x}/{y}?access_token=ACCESS TOKEN')), name = "Map Box",checked=True),
                                                            # COG fed into Tilelayer using TiTiler url (taken from r["tiles"][0])
                                                            dl.Overlay(dl.LayerGroup(dl.TileLayer(url = r["tiles"][0], opacity = 0.8,id = "carbon_2000")), name = "Carbon_Stock_2000", checked = True),
                                                            dl.LayerGroup(id = "layer"),
                                                            # Set colorbar and location in app
                                                            dl.Colorbar(colorscale = colorscale, width = 20, height = 150, min = minv, max = maxv, position = "bottomright"),
                                                            # info,
                                                              ])
                                                ]
                             )
])
if __name__ == '__main__':
    app.run_server()