Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enable options to select a layer from a provider #35

Open
mattijn opened this issue Jan 17, 2024 · 2 comments
Open

enable options to select a layer from a provider #35

mattijn opened this issue Jan 17, 2024 · 2 comments

Comments

@mattijn
Copy link
Contributor

mattijn commented Jan 17, 2024

Feature request! I'm trying to use altair_tiles within a coastal project for monitoring. I've multiple satellite images of this location that are available as wmts-links. Currently it is easy to add a single tile-layer, but could this become more dynamic so multiple layers of a provider can be selected as parameter?

An example.
The following works

import geopandas as gpd
import altair as alt
import altair_tiles as til
import xyzservices as xyz

features = [{"type": "Feature", "properties": {}, "geometry": {"type": "Polygon", "coordinates": [[[4.9794, 53.2789], [4.9794, 53.2701], [4.9717, 53.2657], [4.9717, 53.2613], [4.9485, 53.2613], [4.9563, 53.27014], [4.9794, 53.2789]]]}}]
gdf = gpd.GeoDataFrame.from_features(features)
geoshape = alt.Chart(gdf).mark_geoshape(filled=False, stroke='white', strokeWidth=3)

wmts_url = "https://tiles1.geoserve.eu/Pleiades-NEO_NRG/tileserver/20231229_110351_PNEO-03_1_62_30cm_RD_8bit_NRG_Vlieland/{z}/{x}/{y}"
sdp_provider = xyz.TileProvider(name="sdp", url=wmts_url, attribution="(C) geoserve")
chart = til.create_tiles_chart(provider=sdp_provider, zoom=17) + geoshape
chart

image

But now I like to add more options for the tile provider, like something as such:

wmts_urls = [
    "https://tiles1.geoserve.eu/Pleiades-NEO_NRG/tileserver/20231229_110351_PNEO-03_1_62_30cm_RD_8bit_NRG_Vlieland/",
    "https://tiles1.geoserve.eu/Pleiades-NEO_NRG/tileserver/20230905_105214_PNEO-03_1_9_30cm_RD_8bit_NRG_Waddenzee/",
    "https://tiles1.geoserve.eu/Pleiades-NEO_NRG/tileserver/20230815_104917_PNEO-03_1_1_30cm_RD_8bit_NRG_Vlieland/",
    "https://tiles1.geoserve.eu/Pleiades-NEO_NRG/tileserver/20230813_110015_PNEO-04_1_1_30cm_RD_8bit_NRG_Vlieland/"
]
wmts_options = alt.binding_select(options=wmts_urls)
param_wmts = alt.param(name="base_url_options", value=wmts_urls[0], bind=wmts_options)
chart = chart.add_params(param_wmts)
chart

image

This is just adding the options, but to make this actual work, something needs to modified to utilize this base_url_options param.
I was inspecting the created vega-lite specification and noticed the following, hardcoded in a transform calculate

chart.to_dict()["layer"][1]["layer"][0]["transform"][2]
{'calculate': "'https://tiles1.geoserve.eu/Pleiades-NEO_NRG/tileserver/20231229_110351_PNEO-03_1_62_30cm_RD_8bit_NRG_Vlieland/' + zoom_ceil + '/' + ((datum.a + dii_floor + max_one_side_tiles_count) % max_one_side_tiles_count) + '/' + (datum.b + djj_floor) + ''",
 'as': 'url'}

Maybe we can update altair_tiles, so this URL is referenced by a parameter, which can be easily modified to listen to the base_url_options param.
Something as such:

import re

param_base_url = alt.param(name="base_url", value="https://tiles1.geoserve.eu/Pleiades-NEO_NRG/tileserver/20231229_110351_PNEO-03_1_62_30cm_RD_8bit_NRG_Vlieland/")
chart = chart.add_params(param_base_url)

for ix, par in enumerate(chart.params):
    if par.name == 'base_url':
        chart.params[ix] = alt.param(name='base_url', expr='base_url_options').param

pattern = re.compile(r"'(https?://[^']+)'\s*\+")
tf_calculate = chart.layer[1].layer[0].transform[2].calculate
new_tf_calculate = re.sub(pattern, "base_url +", tf_calculate)
chart.layer[1].layer[0].transform[2].calculate = new_tf_calculate
chart
BQxSPJT3eO.mp4

I think this feature require a change in the code around here: https://github.com/altair-viz/altair_tiles/blob/main/altair_tiles/__init__.py#L262

(btw, I'm not sure if these wmts-URLs are accessible outside the Netherlands.)

@mattijn mattijn changed the title enable options to provide select a layer from a provider enable options to select a layer from a provider Jan 17, 2024
@binste
Copy link
Collaborator

binste commented Jan 17, 2024

Nice to see altair-tiles in action and great idea for a feature! I'd also like to make this happen but not yet sure how. Replacing the base url part with a parameter requires regex as shown in your example as a provider does not have a base_url parameter or similar, just a full url which includes all relevant parameters. I'd assume that these are similarly structured but it's probably the safest to continue to use xyzservices.Providers.build_url to create the actual URL, right?

Maybe we could pass in multiple providers and then altair_tiles builds this by itself? That might not require any regex as we can use build_url internally to pregenerate all URLs and then use a dropdown to select the proper ones.

I'll think some more about this and will play around with it. Ideas are welcome! :)

@mattijn
Copy link
Contributor Author

mattijn commented Jan 17, 2024

I'm trying to explore some more use-cases!
Ah I see, the build_url is delegated to the xyzservices build_url, which is more advanced than just formatting z, x, y. Not sure how to generalize this then. At least I found a way for now..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants