Closed itcarroll closed 5 years ago
Hum I wonder if the ./
in your string does not result in an issue... Could you please try:
import ipyleaflet
m = ipyleaflet.Map(center=(10, 36),zoom=5)
m.add_layer(ipyleaflet.LocalTileLayer(url="tileset/{z}/{x}/{y}.png"))
m
?
Thanks for the reply! Sadly, no change without ./
.
What should the path be relative to? Possibilities are the notebook's file path, the jupyter startup directory, the current working directory (set with os.chdir
).
When I look at the document elements in Chrome inspector, the tiles do not seem to be getting any src
data at all:
<div class="leaflet-tile-container leaflet-zoom-animated" style="z-index: 18; transform: translate3d(0px, 0px, 0px) scale(1);">
<img alt="" role="presentation" src="http://localhost:8888/" class="leaflet-tile" style="width: 256px; height: 256px; transform: translate3d(20px, -83px, 0px); opacity: 1;">
<img alt="" role="presentation" src="http://localhost:8888/" class="leaflet-tile" style="width: 256px; height: 256px; transform: translate3d(276px, -83px, 0px); opacity: 1;">
<img alt="" role="presentation" src="http://localhost:8888/" class="leaflet-tile" style="width: 256px; height: 256px; transform: translate3d(20px, 173px, 0px); opacity: 1;">
<img alt="" role="presentation" src="http://localhost:8888/" class="leaflet-tile" style="width: 256px; height: 256px; transform: translate3d(276px, 173px, 0px); opacity: 1;">
<img alt="" role="presentation" src="http://localhost:8888/" class="leaflet-tile" style="width: 256px; height: 256px; transform: translate3d(-236px, -83px, 0px); opacity: 1;">
<img alt="" role="presentation" src="http://localhost:8888/" class="leaflet-tile" style="width: 256px; height: 256px; transform: translate3d(532px, -83px, 0px); opacity: 1;">
<img alt="" role="presentation" src="http://localhost:8888/" class="leaflet-tile" style="width: 256px; height: 256px; transform: translate3d(-236px, 173px, 0px); opacity: 1;">
<img alt="" role="presentation" src="http://localhost:8888/" class="leaflet-tile" style="width: 256px; height: 256px; transform: translate3d(532px, 173px, 0px); opacity: 1;">
</div>
What should the path be relative to?
It should be relative to the Notebook. Could you open the browser dev console and show the 404/403 errors?
There are no console errors when I use ipyleaflet
. The console errors occure when I use Jupyter's "open in new browser tab" menu option on the file "tileset/leaflet.html" created by gdal2tile
. When I do that, I get a lot of:
GET http://localhost:8888/files/project/tileset/6/40/32.png 403 (Forbidden)
Image (async)
_loadTile @ leaflet.js:7
_addTile @ leaflet.js:7
_addTilesFromCenterOut @ leaflet.js:7
_update @ leaflet.js:7
onAdd @ leaflet.js:7
_layerAdd @ leaflet.js:6
addLayer @ leaflet.js:6
_onInputClick @ leaflet.js:9
s @ leaflet.js:8
But I'm doubting that is relevant, i think it has something to do with the jupyter /files api wanting a key that it shouldn't ask for in the same browser tab. I dunno though.
Indeed, that might be the expected behavior when using the "leaflet.html" file.
Would you mind telling me how I can reproduce your use case, so that I can debug? I'm not familiar with gdal2tile
@davidbrochart would you mind taking a look at this issue? I remember you were using the LocalTileLayer
once, do you have a working example?
I will provide an example with a .tif I can share and tested on mapbox to make sure it's not a problem with the tilesets before you diver further. Thank you!
Thanks :)
Download RGB.byte.tif.
import ipyleaflet
import gdal2tiles
gdal2tiles.generate_tiles("RGB.byte.tif", "tileset")
m = ipyleaflet.Map(center=(24.56, -77.77), zoom=8)
m.add_layer(ipyleaflet.LocalTileLayer(url="tileset/{z}/{x}/{y}.png"))
m
No tiles in notebook, but outside of jupyter it works:
$ python -m https.server -d tileset
And browse to http://localhost:8000/leaflet.html and turn on the additional layer.
@martinRenou I don't have access to a decent computer at the moment.
NP @davidbrochart :)
Thanks @itcarroll I'll try
Ok, so when doing gdal2tiles.generate_tiles("RGB.byte.tif", "tileset")
it seems like the generated tileset
directory does not contain much...
Maybe there are extra options to generate all the needed tiles for each zoom level? But the generated zoom levels are pretty empty too.. I can only count 12 tiles, which is clearly not enough for ipyleaflet to work properly.
Also, looking at the generated Leaflet.html
file I see that it actually fetches tiles from a remote url, not local tiles...
I don't know if the problems comes from your .tif
file or if it comes from the way you use gdal2tiles
... Again I'm not familiar with it.
A little further down in leaflet.html
there is
// Overlay layers (TMS)
var lyr = L.tileLayer('./{z}/{x}/{y}.png', {tms: true, opacity: 0.7, attribution: ""});
The layer control does not have this layer turned on initially, you have to turn it on when you browse to leaflet.html.
It's only a few tiles because it's a small extent, not the whole world ... more like an image overlay. If there is some reason ipyleaflet requires more than 12 tiles, I supposed that would explain the problem. It's not an issue for leaflet though.
I also figured out how to create the viz I need using geoviews
and hvplot
. So I really appreciate your looking into this functionality in ipyleaflet
, but feel free to close if not a priority.
Ok sorry, I thought you wanted enough tiles to be able to zoom-in/zoom-out and pan on the map. Now I understand more!
And I already found some weird things... First of all, the documentation is wrong, it's not
LocalTileLayer(url="tileset/{z}/{x}/{y}.png")
but
LocalTileLayer(path="tileset/{z}/{x}/{y}.png")
Also "./tileset/{z}/{x}/{y}.png"
cannot work, it must be "tileset/{z}/{x}/{y}.png"
.
I'm investigating more because it still does not work... but I feel like we are on the right path
I could make it work... There are some issues to fix in ipyleaflet for it to work. But this workaround should do the trick:
import ipyleaflet
import gdal2tiles
gdal2tiles.generate_tiles("RGB.byte.tif", "tileset")
from traitlets import Bool
from ipyleaflet import LocalTileLayer, Map
class CustomLocalLayer(LocalTileLayer):
tms = Bool(True).tag(sync=True, o=True)
m = Map(center=(24.56, -77.77), zoom=8)
layer = CustomLocalLayer(tms=True, path="tileset/{z}/{x}/{y}.png")
m.add_layer(layer)
That would only work in the classic Jupyter Notebook. If you are working on JupyterLab, you would need a path relative to your server (where you started Jupyter Lab), and you need to prefix it with "files/", for me it's something like "files/examples/tileset/{z}/{x}/{y}.png".
This workaround should work for now, and then when a new release of ipyleaflet is out you will be able to get rid of your CustomLocalLayer
class and directly use the LocalTileLayer
with the same arguments.
Can confirm it works in Jupyter Lab as you describe. Awesome!
The following shows open street map but no additional layers:
No errors or anything in the jupyter lab console log.
I created the tileset with gdal2tiles, which conveniently creates a "leaflet.html" file within "./tileset". When I use the jupter lab file browser to open that html file in a new browser window, I get a lot of 403's saying "blocking request with no referer". But I don't see anything like that in the javascript console with they ipyleaflet chunk above, so possibly not relevant.
Some version info: