This package is in an early development stage. You should expect things to break unannounced until we release a version 1.0.0.
You can use altair_tiles to add tiles from any xyz tile provider such as OpenStreetMap to your Altair chart. It is a counterpart to the amazing contextily package which provides this functionality for matplotlib.
altair-tiles requires at least Vega version 5.26.0. If you use an IDE such as a Jupyter Notebook or VS Code, you usually don't have to worry about this.
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?
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
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:
Some functions such as _create_nonstandalone_tiles_chart have projection: alt.Projection as an argument. I think it's better to be explicit and just ask for the scale value which seems to be the only value we need. Validation of the projection type could be done only in add_tiles. For create_tiles_chart, we don't need to validate it.
Does it make sense to more directly integrate with Altair so a user could do mark_geoshape(tile=True) as proposed in vega/vega-lite#8885? Once it's implemented in Vega-Lite, I think this is a great syntax but for this package I'm not sure as it would then change the type of the Altair chart to a layered chart. As a user I'd find this transition from alt.Chart -> alt.LayerChart unexpected. Also, this way it's clearer that the functionality comes from a separate package.
Are add_tiles and create_tiles_chart good names? add_tiles is inspired from add_basemap in contextily
Is it user friendly enough to pass an alt.Projection object to create_tiles_chart or better to expand the arguments, i.e. create_tiles_chart(scale=..., translate=...)?
Instead of providing add_tiles and add_attribution functions, we could rely solely on create_..._chart functions and then the returned charts can be layered by the user themselves. For attribution, this would work and might simplify it. For add_tiles, we would always need to create the empty geoshape chart which is created in create_..._chart as else it is not a standalone working chart.
Way around this could be to introduce a new class TilesChart which only adds the geoshape layer when to_dict is called and if it is added to another chart it would loose that behavior (overwrite __add__).
TilesChart could also help with always keeping the attribution layer on top. There could be an escape hatch to convert it to a normal Altair class.
The current implementation does not work if fit is used in project, see point 4 on this page for an example. The placement of the tiles is off. This also happens if neither scale nor transpose are provided (and also not fit) as then Vega-Lite adds a fit parameter itself to prevent the chart size from exploding, this is called "autofitting" and was introduced in vega/vega-lite#4843.
fit: GeoJSON data to which the projection should attempt to automatically fit the translate and scale parameters.
size: Used in conjunction with fit, provides the width and height in pixels of the area to which the projection should be automatically fit.
As fit is very useful and it's even added in the default case of only projection type = 'mercator' without any additional settings is set, we need to support it.
Tile size will need to depend on chart size as with fit it depends on it, see signals in Vega spec above
If the chart aspect ratio is not the same as the one of the bounding box, there is some space either left and right or top and bottom and geoshape mark are centered -> Need to adjust for this (in basepoint?) and decide if white space is ok or if tiles should fill out whole chart (seems preferable to me)
Can maybe get coordinates of bounding box with geoBounds and then shift tiles by (chart width - box width) / 2 on x and similar on y
Create it using Jupyter book. Easy to use but still extensibility of Sphinx underneath it, can render Altair charts, see the Altair ally docs, and it has a nice default theme. Host with github pages.
Sections:
Intro incl. installation instructions
Tutorial
API References
Tutorial could simply be the Examples.ipynb notebook for now. Don't have to write too much as long as API is not more stable.
Add documentation link to README and github repo on the right side.
add_basemap requires an existing Altair chart with a geoshape mark. Would be nice to be able to create a standalone chart with only a basemap.
An extra feature would be if that basemap chart can be created first and then another geoshape mark chart added with the usual basemap_chart + geoshape_chart syntax.
I chose altair_basemap following the tradition of naming extensions altair_* and based on the matplotlib basemap package. But maybe there are better names? altair_tiles, altair_maptiles, altair_geotiles, ...
Could maybe subset the tile urls with a filter transform to a predetermined range based on the zoom level? Ok if calculation of these restrictions happens in Python but even better if it can be pushed to Vega Expressions.
Can maybe also use this approach to fix the issue with the grid size which currently is hard coded as data generators do not accept signals (see comments in code) -> Could make a grid which very likely is large enough for all use cases and then use transform_filter based on height and width signals to subset to only the ones which are needed. Can then remove the num_grid_* arguments to simplify function signatures.
When using (the currently only supported vl-convert) to save a chart including altair-tiles with my_chart.save('chart.png') the tiles are not shown / rendered in the resulting image.
Using the "Save as PNG" in the context menu works though (but low res).
add_tiles currently only works for altair.Chart instances. We could extend this to work for alt.LayerChart where we could iterate through all layers (recursively in case it is a layered chart again?) and find the geoshape chart. Raise an error if multiple ones? Then read projection information from that one.