/utiles

utiles = utils & tiles w/ (rs & pyo3)

Primary LanguageRust

utiles

utiles = utils + tiles

A mostly drop-in replacement for mercantile written w/ rust, plus several other util(e)ities.

Installation

pip install utiles

Why?

I use mercantile regularly and wished it were a bit more ergonomic, had type annotations, and was faster, but overall it's a great library.

This was an excuse to learn some more rust as well as pyo3.

Do I/you REALLY need a rust-port of mercantile?

I don't know, decide for yourself. utiles is certainly faster than mercantile for some things (see benchmarks below)

Is it really a drop in replacement for mercantile?

Not quite, but it's close. utiles doesn't throw the same exceptions as mercantile, instead it throws ValueError's and TypeError's.

There might be other differences, but I have been using it instead of mercantile for a bit now and it works pretty decent, tho I am open to suggestions!

Usage

import utiles as ut

ut.bounds(1, 1, 1)
# Out: LngLatBbox(west=0, south=-85.0511287798066, east=180, north=0)

t = ut.Tile(1, 2, 3)

x, y, z = t

(x, y, z)
# Out: (1, 2, 3)

list(ut.tiles(*ut.bounds(1, 1, 1), 3)) # tiles is an ultra fast generator
# Out: [Tile(x=4, y=4, z=3), Tile(x=4, y=5, z=3), Tile(x=4, y=6, z=3), Tile(x=4, y=7, z=3), Tile(x=5, y=4, z=3), Tile(x=5, y=5, z=3), Tile(x=5, y=6, z=3), Tile(x=5, y=7, z=3), Tile(x=6, y=4, z=3), Tile(x=6, y=5, z=3), Tile(x=6, y=6, z=3), Tile(x=6, y=7, z=3), Tile(x=7, y=4, z=3), Tile(x=7, y=5, z=3), Tile(x=7, y=6, z=3), Tile(x=7, y=7, z=3)]

t
# Out: Tile(x=1, y=2, z=3)

t.parent()
# Out: Tile(x=0, y=1, z=2)

t.children()
# Out:
# [Tile(x=2, y=4, z=4),
#  Tile(x=3, y=4, z=4),
#  Tile(x=3, y=5, z=4),
#  Tile(x=2, y=5, z=4)]

t.bounds()
# Out: LngLatBbox(west=-135, south=40.97989806962013, east=-90, north=66.51326044311186)

t.ul()
# Out: LngLat(lng=-135, lat=66.51326044311186)

t.asdict()
# Out: {'x': 1, 'z': 3, 'y': 2}

t.center()
# Out: LngLat(lng=-112.5, lat=53.74657925636599)

~t  # tms flip
# Out: Tile(x=1, y=5, z=3)

t.valid()
# Out: True

ut.Tile(1000, 1231234124, 2).valid()
# Out: False

t.pmtileid()
# Out: 34

from_pmtile_id = ut.Tile.from_pmtileid(34)

ut.Tile.from_pmtileid(34)
# Out: Tile(x=1, y=2, z=3)

t.json_arr()
# Out: '[1, 2, 3]'

t.json_obj()
# Out: '{"x":1,"y":2,"z":3}'

t.fmt_zxy()
# Out: '3/1/2'

t.fmt_zxy_ext('.png')
# Out: '3/1/2..png'

t.fmt_zxy_ext('png')
# Out: '3/1/2.png'

t == (1, 2, 3)
# Out: True

t == (1, 2, 2234234)
# Out: False

t == (1, 2, 22)
# Out: False

Some benchmarks (WIP)

---------------------------------------------------------------------------------------------------- benchmark 'quadkey': 12 tests -----------------------------------------------------------------------------------------------------
Name (time in ns)                                        Min                     Max                  Mean              StdDev                Median                 IQR            Outliers  OPS (Kops/s)            Rounds  Iterations
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_quadkey_bench[utiles-(0, 0, 0)]                199.9942 (1.0)       47,100.0021 (8.78)       284.7909 (1.0)      315.1058 (6.70)       299.9950 (1.06)     100.0008 (>1000.0)  966;1164    3,511.3476 (1.0)       38911           1
test_quadkey_bench[utiles-(1, 1, 1)]                252.6316 (1.26)       5,363.1581 (1.0)        293.9171 (1.03)      47.0478 (1.0)        284.2108 (1.0)       10.5264 (>1000.0)2884;35689    3,402.3204 (0.97)     196079          19
test_quadkey_bench[utiles-(1, 0, 1)]                299.9950 (1.50)      86,300.0023 (16.09)      397.2831 (1.39)     383.5726 (8.15)       399.9958 (1.41)       0.0073 (1.0)    1451;22409    2,517.0967 (0.72)      99010           1
test_quadkey_bench[mercantile-(0, 0, 0)]            599.9973 (3.00)      28,200.0037 (5.26)       821.2744 (2.88)     301.0209 (6.40)       799.9988 (2.81)       0.0073 (1.0)     658;21559    1,217.6198 (0.35)      69445           1
test_quadkey_bench[utiles-(1, 40, 7)]               599.9973 (3.00)     136,899.9947 (25.53)      758.0325 (2.66)     676.4311 (14.38)      699.9981 (2.46)       0.0073 (1.0)     565;29079    1,319.2047 (0.38)     108696           1
test_quadkey_bench[utiles-(486, 332, 10)]           749.9999 (3.75)       8,055.0002 (1.50)       838.5705 (2.94)     137.5439 (2.92)       824.9997 (2.90)      23.7496 (>1000.0) 1445;4742    1,192.5056 (0.34)      63695          20
test_quadkey_bench[mercantile-(1, 0, 1)]            799.9988 (4.00)     104,300.0011 (19.45)    1,015.6996 (3.57)     539.0831 (11.46)    1,000.0003 (3.52)       0.0073 (1.0)    1217;51791      984.5431 (0.28)     119048           1
test_quadkey_bench[mercantile-(1, 1, 1)]            799.9988 (4.00)      75,999.9966 (14.17)    1,047.5805 (3.68)     419.8019 (8.92)     1,000.0003 (3.52)     100.0008 (>1000.0) 3366;4074      954.5806 (0.27)     166667           1
test_quadkey_bench[utiles-(486, 332, 20)]         1,299.9953 (6.50)      83,399.9948 (15.55)    1,545.1801 (5.43)     461.2615 (9.80)     1,499.9969 (5.28)     100.0008 (>1000.0)8793;17328      647.1738 (0.18)     163935           1
test_quadkey_bench[mercantile-(1, 40, 7)]         1,599.9976 (8.00)     110,599.9982 (20.62)    1,789.4247 (6.28)     711.1950 (15.12)    1,799.9992 (6.33)     100.0008 (>1000.0) 1599;2703      558.8388 (0.16)     116280           1
test_quadkey_bench[mercantile-(486, 332, 10)]     1,999.9934 (10.00)    117,000.0032 (21.82)    2,353.1110 (8.26)     768.5591 (16.34)    2,300.0030 (8.09)     200.0015 (>1000.0) 1917;2168      424.9693 (0.12)     117648           1
test_quadkey_bench[mercantile-(486, 332, 20)]     3,199.9953 (16.00)     66,100.0013 (12.32)    3,601.3369 (12.65)    567.1348 (12.05)    3,599.9983 (12.67)    100.0080 (>1000.0) 1479;4347      277.6747 (0.08)      97088           1
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------- benchmark 'tiles': 2 tests ---------------------------------------------------------------------------------------------
Name (time in us)                           Min                   Max                  Mean              StdDev                Median                 IQR            Outliers         OPS            Rounds  Iterations
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_tiles_gen_bench[utiles]           239.3000 (1.0)      1,597.3000 (1.0)        308.5684 (1.0)      130.3316 (1.0)        267.2000 (1.0)       16.5000 (1.0)       312;559  3,240.7721 (1.0)        3232           1
test_tiles_gen_bench[mercantile]     1,349.9000 (5.64)     7,159.2000 (4.48)     1,798.2186 (5.83)     779.7610 (5.98)     1,526.7000 (5.71)     149.6250 (9.07)       66;111    556.1059 (0.17)        601           1
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------- benchmark 'ul': 12 tests ------------------------------------------------------------------------------------------------------
Name (time in ns)                                   Min                     Max                  Mean                StdDev                Median                 IQR              Outliers  OPS (Kops/s)            Rounds  Iterations
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_ul_bench[utiles-(1, 1, 1)]                204.3478 (1.0)        7,160.8697 (1.0)        263.7100 (1.0)        125.3400 (1.00)       221.7392 (1.0)       26.0868 (1.30)    17101;28014    3,792.0436 (1.0)      169492          23
test_ul_bench[utiles-(1, 0, 1)]                229.9999 (1.13)      10,579.9998 (1.48)       273.2589 (1.04)       124.7846 (1.0)        250.0001 (1.13)      20.0002 (1.0)      9266;14360    3,659.5327 (0.97)     188680          20
test_ul_bench[utiles-(1, 40, 7)]               229.9999 (1.13)      42,870.0001 (5.99)       311.4689 (1.18)       188.2129 (1.51)       255.0001 (1.15)      35.0003 (1.75)    16764;39465    3,210.5932 (0.85)     200000          20
test_ul_bench[utiles-(486, 332, 20)]           229.9999 (1.13)      65,699.9997 (9.17)       318.4368 (1.21)       243.5307 (1.95)       259.9998 (1.17)      35.0003 (1.75)    11008;36596    3,140.3404 (0.83)     178572          20
test_ul_bench[utiles-(0, 0, 0)]                299.9950 (1.47)      33,899.9962 (4.73)       349.3773 (1.32)       205.0577 (1.64)       300.0023 (1.35)     100.0008 (5.00)        618;618    2,862.2349 (0.75)      70423           1
test_ul_bench[utiles-(486, 332, 10)]           299.9950 (1.47)      57,999.9978 (8.10)       403.1283 (1.53)       400.2343 (3.21)       399.9958 (1.80)     100.0008 (5.00)     2013;20449    2,480.5998 (0.65)     192308           1
test_ul_bench[mercantile-(0, 0, 0)]            999.9931 (4.89)     206,099.9977 (28.78)    1,296.5665 (4.92)     1,201.7776 (9.63)     1,200.0019 (5.41)     100.0008 (5.00)       387;2129      771.2678 (0.20)      45872           1
test_ul_bench[mercantile-(1, 0, 1)]            999.9931 (4.89)     166,500.0018 (23.25)    1,288.3700 (4.89)       712.6090 (5.71)     1,299.9953 (5.86)     100.0008 (5.00)      2119;3450      776.1746 (0.20)     147059           1
test_ul_bench[mercantile-(1, 1, 1)]          1,000.0003 (4.89)     102,799.9970 (14.36)    1,253.0401 (4.75)       570.2565 (4.57)     1,200.0019 (5.41)     100.0008 (5.00)      2957;3697      798.0590 (0.21)     144928           1
test_ul_bench[mercantile-(1, 40, 7)]         1,000.0003 (4.89)      89,599.9983 (12.51)    1,263.1955 (4.79)       586.9464 (4.70)     1,200.0019 (5.41)     100.0008 (5.00)      1775;2965      791.6431 (0.21)     166667           1
test_ul_bench[mercantile-(486, 332, 10)]     1,099.9938 (5.38)      90,200.0029 (12.60)    1,327.0801 (5.03)       536.7494 (4.30)     1,299.9953 (5.86)     100.0008 (5.00)      6813;7956      753.5340 (0.20)     135136           1
test_ul_bench[mercantile-(486, 332, 20)]     1,099.9938 (5.38)     107,300.0021 (14.98)    1,264.2361 (4.79)       594.6154 (4.77)     1,200.0019 (5.41)     100.0008 (5.00)      1522;2265      790.9915 (0.21)     123457           1
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Contributing

  • Please do! Would love some feedback!
  • Be kind!
  • I will happily accept PRs, and add you to the currently (5/26/2023) non-existent contributors list.

TODO:

  • benchmark against mercantile
  • Maybe:
    • Split library into utiles (rust lib) and utiles-python (python/pip package)?
    • [] Mbtiles support??
    • [] Reading/writing mvt files?
    • [] Re-write cli in rust with clap?

MISC

zoom info
zoom ntiles total rowcol_range max_rowcol
0 1 1 0 1
1 4 5 1 2
2 16 21 3 4
3 64 85 7 8
4 256 341 15 16
5 1_024 1_365 31 32
6 4_096 5_461 63 64
7 16_384 21_845 127 128
8 65_536 87_381 255 256
9 262_144 349_525 511 512
10 1_048_576 1_398_101 1_023 1_024
11 4_194_304 5_592_405 2_047 2_048
12 16_777_216 22_369_621 4_095 4_096
13 67_108_864 89_478_485 8_191 8_192
14 268_435_456 357_913_941 16_383 16_384
15 1_073_741_824 1_431_655_765 32_767 32_768
16 4_294_967_296 5_726_623_061 65_535 65_536
17 17_179_869_184 22_906_492_245 131_071 131_072
18 68_719_476_736 91_625_968_981 262_143 262_144
19 274_877_906_944 366_503_875_925 524_287 524_288
20 1_099_511_627_776 1_466_015_503_701 1_048_575 1_048_576
21 4_398_046_511_104 5_864_062_014_805 2_097_151 2_097_152
22 17_592_186_044_416 23_456_248_059_221 4_194_303 4_194_304
23 70_368_744_177_664 93_824_992_236_885 8_388_607 8_388_608
24 281_474_976_710_656 375_299_968_947_541 16_777_215 16_777_216
25 1_125_899_906_842_624 1_501_199_875_790_165 33_554_431 33_554_432
26 4_503_599_627_370_496 6_004_799_503_160_661 67_108_863 67_108_864
27 18_014_398_509_481_984 24_019_198_012_642_645 134_217_727 134_217_728
28 72_057_594_037_927_936 96_076_792_050_570_581 268_435_455 268_435_456
29 288_230_376_151_711_744 384_307_168_202_282_325 536_870_911 536_870_912
30 1_152_921_504_606_846_976 1_537_228_672_809_129_301 1_073_741_823 1_073_741_824
31 4_611_686_018_427_387_904 6_148_914_691_236_517_205 2_147_483_647 2_147_483_648

Zoom levels

    zoom               ntiles                total  rowcol_range  max_rowcol
0      0                    1                    1             0           1
1      1                    4                    5             1           2
2      2                   16                   21             3           4
3      3                   64                   85             7           8
4      4                  256                  341            15          16
5      5                 1024                 1365            31          32
6      6                 4096                 5461            63          64
7      7                16384                21845           127         128
8      8                65536                87381           255         256
9      9               262144               349525           511         512
10    10              1048576              1398101          1023        1024
11    11              4194304              5592405          2047        2048
12    12             16777216             22369621          4095        4096
13    13             67108864             89478485          8191        8192
14    14            268435456            357913941         16383       16384
15    15           1073741824           1431655765         32767       32768
16    16           4294967296           5726623061         65535       65536
17    17          17179869184          22906492245        131071      131072
18    18          68719476736          91625968981        262143      262144
19    19         274877906944         366503875925        524287      524288
20    20        1099511627776        1466015503701       1048575     1048576
21    21        4398046511104        5864062014805       2097151     2097152
22    22       17592186044416       23456248059221       4194303     4194304
23    23       70368744177664       93824992236885       8388607     8388608
24    24      281474976710656      375299968947541      16777215    16777216
25    25     1125899906842624     1501199875790165      33554431    33554432
26    26     4503599627370496     6004799503160661      67108863    67108864
27    27    18014398509481984    24019198012642645     134217727   134217728
28    28    72057594037927936    96076792050570581     268435455   268435456
29    29   288230376151711744   384307168202282325     536870911   536870912
30    30  1152921504606846976  1537228672809129301    1073741823  1073741824
31    31  4611686018427387904  6148914691236517205    2147483647  2147483648
json
[
  {
    "max_rowcol": 1,
    "ntiles": 1,
    "rowcol_range": 0,
    "total": 1,
    "zoom": 0
  },
  {
    "max_rowcol": 2,
    "ntiles": 4,
    "rowcol_range": 1,
    "total": 5,
    "zoom": 1
  },
  {
    "max_rowcol": 4,
    "ntiles": 16,
    "rowcol_range": 3,
    "total": 21,
    "zoom": 2
  },
  {
    "max_rowcol": 8,
    "ntiles": 64,
    "rowcol_range": 7,
    "total": 85,
    "zoom": 3
  },
  {
    "max_rowcol": 16,
    "ntiles": 256,
    "rowcol_range": 15,
    "total": 341,
    "zoom": 4
  },
  {
    "max_rowcol": 32,
    "ntiles": 1024,
    "rowcol_range": 31,
    "total": 1365,
    "zoom": 5
  },
  {
    "max_rowcol": 64,
    "ntiles": 4096,
    "rowcol_range": 63,
    "total": 5461,
    "zoom": 6
  },
  {
    "max_rowcol": 128,
    "ntiles": 16384,
    "rowcol_range": 127,
    "total": 21845,
    "zoom": 7
  },
  {
    "max_rowcol": 256,
    "ntiles": 65536,
    "rowcol_range": 255,
    "total": 87381,
    "zoom": 8
  },
  {
    "max_rowcol": 512,
    "ntiles": 262144,
    "rowcol_range": 511,
    "total": 349525,
    "zoom": 9
  },
  {
    "max_rowcol": 1024,
    "ntiles": 1048576,
    "rowcol_range": 1023,
    "total": 1398101,
    "zoom": 10
  },
  {
    "max_rowcol": 2048,
    "ntiles": 4194304,
    "rowcol_range": 2047,
    "total": 5592405,
    "zoom": 11
  },
  {
    "max_rowcol": 4096,
    "ntiles": 16777216,
    "rowcol_range": 4095,
    "total": 22369621,
    "zoom": 12
  },
  {
    "max_rowcol": 8192,
    "ntiles": 67108864,
    "rowcol_range": 8191,
    "total": 89478485,
    "zoom": 13
  },
  {
    "max_rowcol": 16384,
    "ntiles": 268435456,
    "rowcol_range": 16383,
    "total": 357913941,
    "zoom": 14
  },
  {
    "max_rowcol": 32768,
    "ntiles": 1073741824,
    "rowcol_range": 32767,
    "total": 1431655765,
    "zoom": 15
  },
  {
    "max_rowcol": 65536,
    "ntiles": 4294967296,
    "rowcol_range": 65535,
    "total": 5726623061,
    "zoom": 16
  },
  {
    "max_rowcol": 131072,
    "ntiles": 17179869184,
    "rowcol_range": 131071,
    "total": 22906492245,
    "zoom": 17
  },
  {
    "max_rowcol": 262144,
    "ntiles": 68719476736,
    "rowcol_range": 262143,
    "total": 91625968981,
    "zoom": 18
  },
  {
    "max_rowcol": 524288,
    "ntiles": 274877906944,
    "rowcol_range": 524287,
    "total": 366503875925,
    "zoom": 19
  },
  {
    "max_rowcol": 1048576,
    "ntiles": 1099511627776,
    "rowcol_range": 1048575,
    "total": 1466015503701,
    "zoom": 20
  },
  {
    "max_rowcol": 2097152,
    "ntiles": 4398046511104,
    "rowcol_range": 2097151,
    "total": 5864062014805,
    "zoom": 21
  },
  {
    "max_rowcol": 4194304,
    "ntiles": 17592186044416,
    "rowcol_range": 4194303,
    "total": 23456248059221,
    "zoom": 22
  },
  {
    "max_rowcol": 8388608,
    "ntiles": 70368744177664,
    "rowcol_range": 8388607,
    "total": 93824992236885,
    "zoom": 23
  },
  {
    "max_rowcol": 16777216,
    "ntiles": 281474976710656,
    "rowcol_range": 16777215,
    "total": 375299968947541,
    "zoom": 24
  },
  {
    "max_rowcol": 33554432,
    "ntiles": 1125899906842624,
    "rowcol_range": 33554431,
    "total": 1501199875790165,
    "zoom": 25
  },
  {
    "max_rowcol": 67108864,
    "ntiles": 4503599627370496,
    "rowcol_range": 67108863,
    "total": 6004799503160661,
    "zoom": 26
  },
  {
    "max_rowcol": 134217728,
    "ntiles": 18014398509481984,
    "rowcol_range": 134217727,
    "total": 24019198012642645,
    "zoom": 27
  },
  {
    "max_rowcol": 268435456,
    "ntiles": 72057594037927936,
    "rowcol_range": 268435455,
    "total": 96076792050570581,
    "zoom": 28
  },
  {
    "max_rowcol": 536870912,
    "ntiles": 288230376151711744,
    "rowcol_range": 536870911,
    "total": 384307168202282325,
    "zoom": 29
  },
  {
    "max_rowcol": 1073741824,
    "ntiles": 1152921504606846976,
    "rowcol_range": 1073741823,
    "total": 1537228672809129301,
    "zoom": 30
  },
  {
    "max_rowcol": 2147483648,
    "ntiles": 4611686018427387904,
    "rowcol_range": 2147483647,
    "total": 6148914691236517205,
    "zoom": 31
  }
]