plotly / plotly.py

The interactive graphing library for Python :sparkles: This project now includes Plotly Express!
https://plotly.com/python/
MIT License
16.27k stars 2.55k forks source link

add support for WMS or TMS tiles #1610

Open njanakiev opened 5 years ago

njanakiev commented 5 years ago

First of all, thanks for this wonderful project!

I find the support for mapbox tiles great and fairly intuitive, but I think it would be a nice feature to support some of the standard tile formats like WMS, TMS and XYZ tiles similar to the way they are implemented in Leaflet or Openlayers. This would make it easier to use self-hosted tile servers or for example OpenStreetMap tiles.

jonmmease commented 5 years ago

Thanks for the suggestion @njanakiev. The MapBox JavaScript library supports rendering external (not provided by MapBox) tiles as raster layers. We're looking into adding support for these through the Plotly API. Would this satisfy the use cases you have in mind?

njanakiev commented 5 years ago

Thank you for the fast reply. Do you mean like shown in this documentation? I suppose this should support arbitrary WMS servers. What I also had in mind is support for TMS tiles as they are also fairly common. You can see how Leaflet uses WMS and TMS tiles in these examples. They also support TMS tile layers with endpoints of the form:

http://base_url/tms/1.0.0/ {tileset} / {z} / {x} / {y} .png

An OpenStreetMap tile example would look like:

https://tile.openstreetmap.org/7/63/42.png

Is this something that MapBox can also support with the raster layers?

joshwarren commented 5 years ago

I think you probably can by using mapbox with a custom layer, but I haven't quite got it working yet (see here: https://plot.ly/python/mapbox-layers/).

import plotly.graph_objects as go

fig = go.Figure()

fig.update_layout(
    mapbox_style="white-bg",
    mapbox_layers=[
        {
            "below": 'traces',
            "sourcetype": "raster",
            "source": ["http://localhost:8080/myWMSServer/wms?"]
        }
      ])

fig.show()

I'm not sure if it's not working because I'm getting the source incorrect (I've tried using an address that will serve me a png map in the browser but that didn't work either) or if this idea will simply not work at all...

I'd be grateful if anyone has any suggestions.

nicolaskruchten commented 5 years ago

I'm sorry our docs are not sufficiently clear on this point... The contents of the source array are passed to Mapbox.js and according to their docs, should be TileJSON-compliant. Basically this means that these URLs should have {x}, {y} and {z} placeholders OR a {bbox-epsg-3857} placeholder. We have an example in our docs with both in the same map here: https://plot.ly/python/mapbox-layers/#base-tiles-from-the-usgs-radar-overlay-from-environment-canada-no-token-needed

maurerle commented 3 years ago

Could you please add support for setting the scheme parameter to the mapbox_layers? This is done for most params shown at the mapbox documentation: https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#raster-scheme

like minzoom and maxzoom. So there is no point in leaving the scheme param as mapbox supports it.

giswqs commented 2 years ago

Mapbox supports adding a WMS source. It would be nice to have the same support for plotly. https://docs.mapbox.com/mapbox-gl-js/example/wms/

Ma-Schw commented 1 year ago

Being able to usw WMS-sources in plotly for background maps (e.g. in px.choropleth_mapbox) would greatly help in projects where it is mandatory that no data from servers in foreign countries (in this case servers from Mapbox) is requested. At least in Germany most services for background maps are WMS and not TileJSON-compliant.

In leaflet the use of WMS is already possible: https://dash-leaflet.herokuapp.com/#wsm_tile_layer

Masoudas commented 1 year ago

@nicolaskruchten Hi, and thanks for the wonderful work you do. I'm in dire need of showing a WMS layer in mapbox as well. Any progress on this front so far? Does it need an access token? I use it offline? Also, if not, do you have an alternative?

Masoudas commented 1 year ago

Actually, I've found a way right now to use a redirection and the mercantile library to convert xyz to a bbox for WMS layer. But for some reason when I add this redirection, mapbox shows the layer, but it somehow freezes and stops working. The code is something like this (not a working example, but you get the idea I guess):

mapbox_layers.append( { "below": 'traces', "sourcetype": "raster",

"sourceattribution": "United States Geological Survey",

            "source": [
                "http://0.0.0.0/my_redirection_to_wms/" + "/{z}/{y}/{x}"
            ]
        }
    )

The redirection url

@app.server.route('/my_redirection_to_wms///', methods=['GET']) def getGISData(username: str, layers: str, z: str, x: str, y: str): bound = mercantile.bounds(int(y), int(x), int(z)) omoor_gis = get_gis_omoor_username(username).omoorBoundary

if not omoor_gis.intersects(Point((bound.west, bound.south))) \
        and not omoor_gis.intersects(Point((bound.east, bound.north))):
    return b""

layers_list = ",".join(layers.split("0"))

redirect_url = f"{gis_wms_route}/qgis-server?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX={bound.west},{bound.south},{bound.east},{bound.north}&CRS=CRS:84&WIDTH=256&HEIGHT=256&LAYERS={layers_list}&FORMAT=image/png&DPI=48&MAP_RESOLUTION=48&FORMAT_OPTIONS=dpi:96&TRANSPARENT=True"

return requests.get(redirect_url).content
makmegs commented 1 year ago

Like @Masoudas, I also have a strong need for showing WMS layers as TMS is EXTREMELY limiting. Is there any plan to implement this or does it need a sponsor?

alexcjohnson commented 1 year ago

@makmegs this isn't currently on our roadmap but if you're interested in sponsoring we'd be happy to discuss 😄

gvwilson commented 3 months ago

@archmoj is this one addressed by your recent work?