Missing or wrong path tiles generated beyond zoom level 5

Hi,

I,m trying to to write a backend that can generate tiles folder structure and images based on the example that We can find here

Maybe the example is little bit outdated, but essentially it just works as expected with minimal changes like new loader for my datasource, parquet files hosted in S3 buckets, that are downloaded and converted to dataframe.

The problem is the next, when I run my script and everything just seems to be normal, the folders and image tiles start to popping inside the output dir and then I’m able to run a simple python http server on this folder and connect leaflet to this XYZ source layer. Then when I go from 0 zoom level to greater zoom levels everything works fine, but I’m not be able to update my map layer beyond 5 zoom level. Leaflet is simply querying for unexistent zoom level folders, well, to be more precise, this level folders exists but seems to have different numeric names rather than expected by leaflet.

Versions:

Python 3.7.9
datashader==0.13.0
holoviews==1.14.5

Script sample:

from datashader.tiles import render_tiles
import pandas as pd
import datashader as ds
import datashader.transfer_functions as tf
from datashader.colors import viridis
import holoviews as hv

from kpi.tta.maps.config.country_bounding_boxes import country_bounding_boxes


# extent_of_area_i_want_to_tile = (-500000, -500000, 500000, 500000)  # xmin, ymin, xmax, ymax
bbox = country_bounding_boxes['MX'][1]


def load_data_func(x_range, y_range):
    df = pd.read_parquet(
        path='s3://xxx/coverage/334/202007/MX.ATT/LTE/coverage_334_202007_MX.ATT_LTE/')
    df['longitude'] = pd.to_numeric(df.longitude, errors='coerce')
    df['latitude'] = pd.to_numeric(df.latitude, errors='coerce')
    df.dropna(subset=['longitude', 'latitude'], inplace=True)
    df["longitude"], df["latitude"] = hv.Tiles.lon_lat_to_easting_northing(
        df["longitude"], df["latitude"]
    )
    df = df[['longitude', 'latitude', 'value']].rename(columns={'longitude': 'x', 'latitude': 'y'})
    # df = df.loc[df['x'].between(*x_range) & df['y'].between(*y_range)]
    return df


def rasterize_func(df, x_range, y_range, height, width):
    cvs = ds.Canvas(x_range=x_range, y_range=y_range,
                    plot_height=height, plot_width=width)
    agg = cvs.points(df, 'x', 'y')
    return agg


def shader_func(agg, span=None):
    # img = tf.shade(agg, cmap=reversed(viridis), span=span, how='log')
    img = tf.shade(agg, cmap=viridis, span=span, how='log')
    return img


def post_render_func(img, **kwargs):
    return img


if __name__ == "__main__":
    render_tiles(
        full_extent=bbox,
        levels=range(0, 16),
        output_path='example_tileset_output_directory',
        load_data_func=load_data_func,
        rasterize_func=rasterize_func,
        shader_func=shader_func,
        post_render_func=post_render_func
    )

Sample of the script output, seems normal, no error:

calculating statistics for level 0
rendering 1 supertiles for zoom level 0 with span=(0, 1767208)
calculating statistics for level 1
rendering 1 supertiles for zoom level 1 with span=(0, 861200)
calculating statistics for level 2
rendering 1 supertiles for zoom level 2 with span=(0, 736715)
calculating statistics for level 3
rendering 1 supertiles for zoom level 3 with span=(0, 473304)
calculating statistics for level 4
rendering 1 supertiles for zoom level 4 with span=(0, 223669)
calculating statistics for level 5
rendering 4 supertiles for zoom level 5 with span=(0, 96105)
calculating statistics for level 6
rendering 4 supertiles for zoom level 6 with span=(0, 3950)
calculating statistics for level 7
rendering 4 supertiles for zoom level 7 with span=(0, 6)
calculating statistics for level 8
rendering 4 supertiles for zoom level 8 with span=(0, 0)
calculating statistics for level 9
rendering 4 supertiles for zoom level 9 with span=(0, 0)
calculating statistics for level 10
rendering 4 supertiles for zoom level 10 with span=(0, 0)

Sample of tiles output dir:

example_tileset_output_directory/
β”œβ”€β”€ 0
β”‚   └── 0
β”œβ”€β”€ 1
β”‚   β”œβ”€β”€ 0
β”‚   └── 1
β”œβ”€β”€ 10
β”‚   β”œβ”€β”€ 496
β”‚   β”œβ”€β”€ 497
β”‚   β”œβ”€β”€ 498
β”‚   β”œβ”€β”€ 499
β”‚   β”œβ”€β”€ 500
β”‚   β”œβ”€β”€ 501
β”‚   β”œβ”€β”€ 502
β”‚   β”œβ”€β”€ 503
β”‚   β”œβ”€β”€ 504
β”‚   β”œβ”€β”€ 505
β”‚   β”œβ”€β”€ 506
β”‚   β”œβ”€β”€ 507
β”‚   β”œβ”€β”€ 508
β”‚   β”œβ”€β”€ 509
β”‚   β”œβ”€β”€ 510
β”‚   β”œβ”€β”€ 511
β”‚   β”œβ”€β”€ 512
β”‚   β”œβ”€β”€ 513
β”‚   β”œβ”€β”€ 514
β”‚   β”œβ”€β”€ 515
β”‚   β”œβ”€β”€ 516
β”‚   β”œβ”€β”€ 517
β”‚   β”œβ”€β”€ 518
β”‚   β”œβ”€β”€ 519
β”‚   β”œβ”€β”€ 520
β”‚   β”œβ”€β”€ 521
β”‚   β”œβ”€β”€ 522
β”‚   β”œβ”€β”€ 523
β”‚   β”œβ”€β”€ 524
β”‚   β”œβ”€β”€ 525
β”‚   β”œβ”€β”€ 526
β”‚   └── 527
β”œβ”€β”€ 11
β”‚   β”œβ”€β”€ 1000
β”‚   β”œβ”€β”€ 1001
β”‚   β”œβ”€β”€ 1002
β”‚   β”œβ”€β”€ 1003
β”‚   β”œβ”€β”€ 1004
β”‚   β”œβ”€β”€ 1005
β”‚   β”œβ”€β”€ 1006
β”‚   β”œβ”€β”€ 1007
β”‚   β”œβ”€β”€ 1008
β”‚   β”œβ”€β”€ 1009
β”‚   β”œβ”€β”€ 1010
β”‚   β”œβ”€β”€ 1011
β”‚   β”œβ”€β”€ 1012
β”‚   β”œβ”€β”€ 1013
β”‚   β”œβ”€β”€ 1014
β”‚   β”œβ”€β”€ 1015
β”‚   β”œβ”€β”€ 1016
β”‚   β”œβ”€β”€ 1017
β”‚   β”œβ”€β”€ 1018
β”‚   β”œβ”€β”€ 1019
β”‚   β”œβ”€β”€ 1020
β”‚   β”œβ”€β”€ 1021
β”‚   β”œβ”€β”€ 1022
β”‚   β”œβ”€β”€ 1023
β”‚   β”œβ”€β”€ 1024
β”‚   β”œβ”€β”€ 1025
β”‚   β”œβ”€β”€ 1026
β”‚   β”œβ”€β”€ 1027
β”‚   β”œβ”€β”€ 1028
β”‚   β”œβ”€β”€ 1029
β”‚   β”œβ”€β”€ 1030
β”‚   β”œβ”€β”€ 1031
β”‚   β”œβ”€β”€ 1032
β”‚   β”œβ”€β”€ 1033
β”‚   β”œβ”€β”€ 1034
β”‚   β”œβ”€β”€ 1035
β”‚   β”œβ”€β”€ 1036
β”‚   β”œβ”€β”€ 1037
β”‚   β”œβ”€β”€ 1038
β”‚   β”œβ”€β”€ 1039
β”‚   β”œβ”€β”€ 1040
β”‚   β”œβ”€β”€ 1041
β”‚   β”œβ”€β”€ 1042
β”‚   β”œβ”€β”€ 1043
β”‚   β”œβ”€β”€ 1044
β”‚   β”œβ”€β”€ 1045
β”‚   β”œβ”€β”€ 1046
β”‚   β”œβ”€β”€ 1047
β”‚   β”œβ”€β”€ 1048
β”‚   β”œβ”€β”€ 1049
β”‚   β”œβ”€β”€ 1050
β”‚   β”œβ”€β”€ 1051
β”‚   β”œβ”€β”€ 1052
β”‚   β”œβ”€β”€ 1053
β”‚   β”œβ”€β”€ 1054
β”‚   β”œβ”€β”€ 1055
β”‚   β”œβ”€β”€ 992
β”‚   β”œβ”€β”€ 993
β”‚   β”œβ”€β”€ 994
β”‚   β”œβ”€β”€ 995
β”‚   β”œβ”€β”€ 996
β”‚   β”œβ”€β”€ 997
β”‚   β”œβ”€β”€ 998
β”‚   └── 999
β”œβ”€β”€ 2
β”‚   β”œβ”€β”€ 0
β”‚   β”œβ”€β”€ 1
β”‚   β”œβ”€β”€ 2
β”‚   └── 3
β”œβ”€β”€ 3
β”‚   β”œβ”€β”€ 0
β”‚   β”œβ”€β”€ 1
β”‚   β”œβ”€β”€ 2
β”‚   β”œβ”€β”€ 3
β”‚   β”œβ”€β”€ 4
β”‚   β”œβ”€β”€ 5
β”‚   β”œβ”€β”€ 6
β”‚   └── 7
β”œβ”€β”€ 4
β”‚   β”œβ”€β”€ 0
β”‚   β”œβ”€β”€ 1
β”‚   β”œβ”€β”€ 10
β”‚   β”œβ”€β”€ 11
β”‚   β”œβ”€β”€ 12
β”‚   β”œβ”€β”€ 13
β”‚   β”œβ”€β”€ 14
β”‚   β”œβ”€β”€ 15
β”‚   β”œβ”€β”€ 2
β”‚   β”œβ”€β”€ 3
β”‚   β”œβ”€β”€ 4
β”‚   β”œβ”€β”€ 5
β”‚   β”œβ”€β”€ 6
β”‚   β”œβ”€β”€ 7
β”‚   β”œβ”€β”€ 8
β”‚   └── 9
β”œβ”€β”€ 5
β”‚   β”œβ”€β”€ 0
β”‚   β”œβ”€β”€ 1
β”‚   β”œβ”€β”€ 10
β”‚   β”œβ”€β”€ 11
β”‚   β”œβ”€β”€ 12
β”‚   β”œβ”€β”€ 13
β”‚   β”œβ”€β”€ 14
β”‚   β”œβ”€β”€ 15
β”‚   β”œβ”€β”€ 16
β”‚   β”œβ”€β”€ 17
β”‚   β”œβ”€β”€ 18
β”‚   β”œβ”€β”€ 19
β”‚   β”œβ”€β”€ 2
β”‚   β”œβ”€β”€ 20
β”‚   β”œβ”€β”€ 21
β”‚   β”œβ”€β”€ 22
β”‚   β”œβ”€β”€ 23
β”‚   β”œβ”€β”€ 24
β”‚   β”œβ”€β”€ 25
β”‚   β”œβ”€β”€ 26
β”‚   β”œβ”€β”€ 27
β”‚   β”œβ”€β”€ 28
β”‚   β”œβ”€β”€ 29
β”‚   β”œβ”€β”€ 3
β”‚   β”œβ”€β”€ 30
β”‚   β”œβ”€β”€ 31
β”‚   β”œβ”€β”€ 4
β”‚   β”œβ”€β”€ 5
β”‚   β”œβ”€β”€ 6
β”‚   β”œβ”€β”€ 7
β”‚   β”œβ”€β”€ 8
β”‚   └── 9
β”œβ”€β”€ 6
β”‚   β”œβ”€β”€ 16
β”‚   β”œβ”€β”€ 17
β”‚   β”œβ”€β”€ 18
β”‚   β”œβ”€β”€ 19
β”‚   β”œβ”€β”€ 20
β”‚   β”œβ”€β”€ 21
β”‚   β”œβ”€β”€ 22
β”‚   β”œβ”€β”€ 23
β”‚   β”œβ”€β”€ 24
β”‚   β”œβ”€β”€ 25
β”‚   β”œβ”€β”€ 26
β”‚   β”œβ”€β”€ 27
β”‚   β”œβ”€β”€ 28
β”‚   β”œβ”€β”€ 29
β”‚   β”œβ”€β”€ 30
β”‚   β”œβ”€β”€ 31
β”‚   β”œβ”€β”€ 32
β”‚   β”œβ”€β”€ 33
β”‚   β”œβ”€β”€ 34
β”‚   β”œβ”€β”€ 35
β”‚   β”œβ”€β”€ 36
β”‚   β”œβ”€β”€ 37
β”‚   β”œβ”€β”€ 38
β”‚   β”œβ”€β”€ 39
β”‚   β”œβ”€β”€ 40
β”‚   β”œβ”€β”€ 41
β”‚   β”œβ”€β”€ 42
β”‚   β”œβ”€β”€ 43
β”‚   β”œβ”€β”€ 44
β”‚   β”œβ”€β”€ 45
β”‚   β”œβ”€β”€ 46
β”‚   └── 47
β”œβ”€β”€ 7
β”‚   β”œβ”€β”€ 48
β”‚   β”œβ”€β”€ 49
β”‚   β”œβ”€β”€ 50
β”‚   β”œβ”€β”€ 51
β”‚   β”œβ”€β”€ 52
β”‚   β”œβ”€β”€ 53
β”‚   β”œβ”€β”€ 54
β”‚   β”œβ”€β”€ 55
β”‚   β”œβ”€β”€ 56
β”‚   β”œβ”€β”€ 57
β”‚   β”œβ”€β”€ 58
β”‚   β”œβ”€β”€ 59
β”‚   β”œβ”€β”€ 60
β”‚   β”œβ”€β”€ 61
β”‚   β”œβ”€β”€ 62
β”‚   β”œβ”€β”€ 63
β”‚   β”œβ”€β”€ 64
β”‚   β”œβ”€β”€ 65
β”‚   β”œβ”€β”€ 66
β”‚   β”œβ”€β”€ 67
β”‚   β”œβ”€β”€ 68
β”‚   β”œβ”€β”€ 69
β”‚   β”œβ”€β”€ 70
β”‚   β”œβ”€β”€ 71
β”‚   β”œβ”€β”€ 72
β”‚   β”œβ”€β”€ 73
β”‚   β”œβ”€β”€ 74
β”‚   β”œβ”€β”€ 75
β”‚   β”œβ”€β”€ 76
β”‚   β”œβ”€β”€ 77
β”‚   β”œβ”€β”€ 78
β”‚   └── 79
β”œβ”€β”€ 8
β”‚   β”œβ”€β”€ 112
β”‚   β”œβ”€β”€ 113
β”‚   β”œβ”€β”€ 114
β”‚   β”œβ”€β”€ 115
β”‚   β”œβ”€β”€ 116
β”‚   β”œβ”€β”€ 117
β”‚   β”œβ”€β”€ 118
β”‚   β”œβ”€β”€ 119
β”‚   β”œβ”€β”€ 120
β”‚   β”œβ”€β”€ 121
β”‚   β”œβ”€β”€ 122
β”‚   β”œβ”€β”€ 123
β”‚   β”œβ”€β”€ 124
β”‚   β”œβ”€β”€ 125
β”‚   β”œβ”€β”€ 126
β”‚   β”œβ”€β”€ 127
β”‚   β”œβ”€β”€ 128
β”‚   β”œβ”€β”€ 129
β”‚   β”œβ”€β”€ 130
β”‚   β”œβ”€β”€ 131
β”‚   β”œβ”€β”€ 132
β”‚   β”œβ”€β”€ 133
β”‚   β”œβ”€β”€ 134
β”‚   β”œβ”€β”€ 135
β”‚   β”œβ”€β”€ 136
β”‚   β”œβ”€β”€ 137
β”‚   β”œβ”€β”€ 138
β”‚   β”œβ”€β”€ 139
β”‚   β”œβ”€β”€ 140
β”‚   β”œβ”€β”€ 141
β”‚   β”œβ”€β”€ 142
β”‚   └── 143
└── 9
    β”œβ”€β”€ 240
    β”œβ”€β”€ 241
    β”œβ”€β”€ 242
    β”œβ”€β”€ 243
    β”œβ”€β”€ 244
    β”œβ”€β”€ 245
    β”œβ”€β”€ 246
    β”œβ”€β”€ 247
    β”œβ”€β”€ 248
    β”œβ”€β”€ 249
    β”œβ”€β”€ 250
    β”œβ”€β”€ 251
    β”œβ”€β”€ 252
    β”œβ”€β”€ 253
    β”œβ”€β”€ 254
    β”œβ”€β”€ 255
    β”œβ”€β”€ 256
    β”œβ”€β”€ 257
    β”œβ”€β”€ 258
    β”œβ”€β”€ 259
    β”œβ”€β”€ 260
    β”œβ”€β”€ 261
    β”œβ”€β”€ 262
    β”œβ”€β”€ 263
    β”œβ”€β”€ 264
    β”œβ”€β”€ 265
    β”œβ”€β”€ 266
    β”œβ”€β”€ 267
    β”œβ”€β”€ 268
    β”œβ”€β”€ 269
    β”œβ”€β”€ 270
    └── 271

Sample of leaflet requesting unexisting images in resulting tiles output:

127.0.0.1 - - [10/Sep/2021 10:23:47] "GET /6/15/26.png HTTP/1.1" 404 -
127.0.0.1 - - [10/Sep/2021 10:23:47] "GET /6/11/28.png HTTP/1.1" 404 -
127.0.0.1 - - [10/Sep/2021 10:23:47] "GET /6/11/26.png HTTP/1.1" 404 -

If you look carefully to the server log and compare that 404 to the previous output, You will realize that there is no /6/11/ structure dir and the same structure mismatch is the similar to every zoom level beyond 5.

I’ve spent some time testing with other XYZ layer client, like OpenLayers and just obtained the same result.

I’m not sure if I’m not using the tiling tool in a proper way or I’m missing some previous adjustements to data or method params to get the desired output or at least the one required by leaflet or similar XYZ web clients.

I hope that someone can help me a little bit to find the problem. Thank You.

Regards,

Javier.

FYI, I’m dumb.

The df is converted to use EPSG:3857 web mercator and the bounding boxes that I’m using for reference are in another projection system, so the problem is obvious.

When I just realized that I fixed my bounding boxes definitions and now the β€œrender_tiles” method works like a charm.

Thank You for your time.

Regards,

Javier.

2 Likes

Appreciate you reporting back @civan! Glad you fixed your issue.