opengeos/leafmap

Leafmap add_raster() won't display in solara

jmarokhovsky opened this issue · 6 comments

Environment Information

  • leafmap version: 0.35.2
  • Python version: 3.12.3
  • Operating System: Docker container and OSX 14.4.1

Docker Container info:

Dockerfile

# This Dockerfile was derived from giswqs's solara-template Dockerfile
# link: https://huggingface.co/spaces/giswqs/solara-template/tree/main
FROM osgeo/gdal:ubuntu-full-3.6.3

ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8

RUN apt-get update
RUN apt-get install sudo python3-pip python3-venv git -y

COPY requirements.txt .
RUN pip install -r requirements.txt

RUN mkdir ./aqua_app
COPY /aqua_app ./aqua_app

ENV PYTHONPATH "${PYTHONPATH}:/aqua_app/src"

USER root
USER ${NB_USER}

EXPOSE 8765

CMD ["solara", "run", "./aqua_app/pages", "--host=0.0.0.0"]
requirements.txt

solara
geojson==3.1.0
geopandas==0.14.3
ipywidgets==8.1.2
leafmap==0.35.2
rioxarray
python-dotenv==1.0.1
localtileserver==0.10.3

Description

When attempting to display a local raster in solara, leafmap loads and centers on where the raster should be, but does not display the raster. I have encountered this issue using different tif files and whether I am deploying solara locally or deploying via docker

What I Did

Local command: solara run aqua_app/pages --host=0.0.0.0 --log-level-uvicorn=warning --workers=10 --access-log --pdb
I attempt to run the above command to render the page below, but only end up seeing the openmaps map zoomed in to where the raster layer should be, but unable to see the raster itself.

import leafmap.leafmap as leafmap
from reacton import component as component
import solara


class Map(leafmap.Map):
    """
    This is the map which will be displayed in the solara webapp
    """
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        cog_file_loc = "/aqua_app/data/foo.tif"
        self.add_raster(
            cog_file_loc,
            colormap="Reds",
            layer_name="Ecuador2022",
            zoom_to_layer=True,
        )


zoom = solara.reactive(7)
center = solara.reactive((20, 30))


@component
def Page():
    css = """
        .v-application .primary {
          background-color: #c00 !important;
        }
    """
    solara.Style(css)
    with solara.Column(style={"min_width": "500px"}):
        Map.element(  # type: ignore
            zoom=zoom.value,
            on_zoom=zoom.set,
            center=center.value,
            on_center=center.set,
            scroll_wheel_zoom=True,
            toolbar_ctrl=False,
            draw_control=True,
            height="780px",
        )

The add_raster() function relies on localtileserver, which needs to spin up a flask server to serve the tiles. It does not support streamlit. I guess solara is not supported either. Try out the following example with localtileserve without leafmap. If it does not work, then it is a localtileserver issue. Report it here.

Relevant issue: banesullivan/localtileserver#213

from localtileserver import TileClient, get_leaflet_tile_layer, examples
from ipyleaflet import Map

# Create a TileClient from a raster file
# client = TileClient('path/to/geo.tif')
client = examples.get_san_francisco()  # use example data

# Create ipyleaflet TileLayer from that server
t = get_leaflet_tile_layer(client)
# Create ipyleaflet map, add tile layer, and display
m = Map(center=client.center(), zoom=client.default_zoom)
m.add(t)
m

Alternatively, make the raster accessible through http, then use Map.add_cog_layer() to load the raster.
https://leafmap.org/notebooks/03_cog_stac

The add_raster() function relies on localtileserver, which needs to spin up a flask server to serve the tiles. It does not support streamlit. I guess solara is not supported either. Try out the following example with localtileserve without leafmap. If it does not work, then it is a localtileserver issue. Report it here.

Relevant issue: banesullivan/localtileserver#213

from localtileserver import TileClient, get_leaflet_tile_layer, examples
from ipyleaflet import Map

# Create a TileClient from a raster file
# client = TileClient('path/to/geo.tif')
client = examples.get_san_francisco()  # use example data

# Create ipyleaflet TileLayer from that server
t = get_leaflet_tile_layer(client)
# Create ipyleaflet map, add tile layer, and display
m = Map(center=client.center(), zoom=client.default_zoom)
m.add(t)
m

Tried to translate that into a solara page and it's not rendering as well like you predicted (code below). I'll report a bug in localtileserver.

solara page:

from localtileserver import TileClient, get_leaflet_tile_layer, examples
from ipyleaflet import Map
from reacton import component as component
import solara


class LMap(Map):
    def __init__(self, **kwargs):
        # client = examples.get_san_francisco()  # use example data
        client = TileClient("/aqua_app/data/foo.tif")
        super().__init__(center=client.center(), zoom=client.default_zoom, **kwargs)

        # Create ipyleaflet TileLayer from that server
        t = get_leaflet_tile_layer(client)
        # Create ipyleaflet map, add tile layer, and display
        self.add(t)


@component
def Page():
    with solara.Column(style={"min_width": "500px"}):
        LMap.element()

Alternatively, make the raster accessible through http, then use Map.add_cog_layer() to load the raster. https://leafmap.org/notebooks/03_cog_stac

Eventually the application I'm making will be using this, I just encountered this issue while sanity checking the rest of my code while I had the cogs available locally.

Thanks for all the help! I'll post the corresponding bug number when I have made it

Opened this: banesullivan/localtileserver#215. Feel free to close this bug if necessary