GeoInterface.jl
GeoInterface.jl copied to clipboard
Add package extension on RecipesBase
This moves all the plots related code, including the macro(!) into GeoInterface. This now works:
using GeoInterface, Plots
Precompiling GeoInterface
1 dependency successfully precompiled in 1 seconds. 1 already precompiled.
[ Info: Precompiling RecipesBaseExt [b9601432-96b0-576e-9c4b-47fc12d2b5bf]
points = GeoInterface.Point.(rand(10),rand(10))
julia> plot(points)
Since we now export the macros, I think the existing GeoInterfacesRecipes continues to work, even though it's now empty.
This at least fixes #110 (for people that forget to do using GeoInterfaceRecipes).
I still have to check whether this can be used to deprecate GeoInterfaceRecipes completely, and how that would work. Essentially, as soon as a package uses RecipesBase, it would trigger this package extension, but if it triggers in an extension on RecipesBase, then the macro would not be available.
I'm also not sure about defining @enable as being only for Plots. Since RecipesBase is pretty small, (as is MakieCore), is there an issue with keeping the packages as they are, and simply using an include trick on GeoInterfaceRecipes for a package extension?
Yeah the other solution that I considered is just duplicating the code. I'm pretty unsure about include, as it's a standalone package, even though it's in a monorepo here right?
Can we just do the include("../GeoInterfaceRecipes/src/GeoInterfaceRecipes.jl") and include("../GeoInterfaceMakie/src/GoInterfaceMakie.jl") tricks in extensions GeoInterfaceRecipesExt and GeoInterfaceMakieExt?
Then we don't have the circular dep on the sub-packages but we can use the same code and not break anything.
It does end up using a bit more compilation and memory as its the same code used twice, but I think that's ok.
Edit: we may need to move code out of the modules into separate files for this to work.
GIMakieExt is circular but RecipesExt could work
Oh of course because Makie depends directly on GeoInterface.jl via GeometryOps.jl, forgot for a second.
Maybe... could we just move the GeometryBasics.jl geointerface code to an extension in GeoInterface.jl?
We need to solve this somehow
I think we tried to in a GeometryBasics PR but I ended up not wanting to do that for some reason. We can in theory just have Makie depend on GeoInterfaceMakie too...
Can we just do the
include("../GeoInterfaceRecipes/src/GeoInterfaceRecipes.jl")andinclude("../GeoInterfaceMakie/src/GoInterfaceMakie.jl")tricks in extensions GeoInterfaceRecipesExt and GeoInterfaceMakieExt?Then we don't have the circular dep on the sub-packages but we can use the same code and not break anything.
It does end up using a bit more compilation and memory as its the same code used twice, but I think that's ok.
Edit: we may need to move code out of the modules into separate files for this to work.
While it seems to work locally, I at least get cache misses for precompiling. I don't think it's intended for code to be included outside of the ext folder/file.
[ Info: Precompiling RecipesBaseExt [b9601432-96b0-576e-9c4b-47fc12d2b5bf] (cache misses: include_dependency fsize change (2))
Ok, moved all the conversion code to the extension so it doesn't slow down GeoInterface itself by default. Only the macro stubs are now left in.
GeoInterfaceRecipes is now empty, it imports RecipesBase and GeoInterface and only re-exports the enable macros. It depends on Julia 1.9 and this version of GeoInterface, so if someone loads this new version it will trigger the package extension. If you have an older version, even though the package extension will trigger, you should get the macro from GeoInterfaceRecipes itself. This effectively deprecates GeoInterfaceRecipes.
I will test this with ArchGDAL (it depends directly on GeoInterfaceRecipes).
Cool! Now we need to figure out how to do this with Makie. If we move the GeoInterface code in GeometryBasics to an extension here instead that should work too?
There will be some juggling to do to not break things in the handover
Cool! Now we need to figure out how to do this with Makie. If we move the GeoInterface code in GeometryBasics to an extension here instead that should work too?
There will be some juggling to do to not break things in the handover
It should work, although I'm not that familiar with the triangle of Makie(Core?)/GeometryBasics/GeoInterface. But thinking about it, it might clash on the @enable macro if you also load RecipesBase, since we moved the stub to the shared GeoInterface here.
Oh no the @enable macro. Can we rename it in this PR? It shouldn't be @enable in GeoInterface anyway because it unclear what that is, where GeoInterfaceRecipes.@enable was clear
Probably we need to define e.g. @enable_plots here and call the same internal code as @enable, rather than actually moving @enable here.
Oh no the
@enablemacro. Can we rename it in this PR? It shouldn't be@enablein GeoInterface anyway because it unclear what that is, whereGeoInterfaceRecipes.@enablewas clearProbably we need to define e.g.
@enable_plotshere and call the same internal code as@enable, rather than actually moving@enablehere.
We need two, or weird stuff with Module dispatch in the macro (1.10+). So I would go with
@enable_plots@enable_makie
Yeah thats what I mean @enable_plots now, and @enable_makie later
With the latest commits, this now works:
using Plots
using GeoInterface
GeoInterface.geoplot(rand(Tuple{Float64, Float64}, 100))
Using the extension, we can plot any GeoInterface compatible geometry/feature/collection. It required some more hacking of RecipesBase, mostly macroexpanding @userplot (for geoplot) and @recipe (for collections).
This should be fully backwards compatible with GeoInterfaceRecipes. I've anticipated a Makie(Core) extension, so geoplot could work with Makie in the future as well. The only problem is when both extensions are loaded, we'll need some fix for that in a future PR.
What's the motivation for geoplot? I thought plot from Plots worked fine for all featurecollections / geometries?
Yes isn't the idea that plot just works?
plot works if a package also depends on GeoInterfaceRecipes/RecipesBase and does @enable_plot. geoplot works for all GeoInterface enabled geometries.
I get the feeling that the number of geometries that are GeoInterface enabled but don't have @enable macros in extensions has got to be pretty low by now...also, shouldn't it be the solution to tell people to use @enable instead of a new function they'll have to learn? Enable is generic across all plot types so trying lines or scatter will work equally well - it just gives more options.
Now that the macros will actually be accessible it seems reasonable to do, at least to me...
I was also hoping plot would work universally, it almost does already
Ah fair enough, my two major gripes were
- forgetting to do use GeoInterfaceRecipes as user (fixed by extension in this PR)
- forgetting to depend on GeoInterfaceRecipes as producer (fixed by
geoplotin this PR)
The latter is indeed rarer, and not that important. And geoplot is a new thing indeed, so let's say that this was just a nice exercise in hacking RecipesBase.
I'll revert the geoplot thing, and then this should be good to go.
forgetting to depend on GeoInterfaceRecipes as producer
That will probably continue to be an issue AFAICT, we can document it better though.
forgetting to do use GeoInterfaceRecipes as user
My understanding is that this PR makes it so that this should not be an issue?
This (slightly outdated) PR seems relevant to the discussion in https://github.com/JuliaGeo/Shapefile.jl/issues/138. Although it still requires the package to have a weakdep, because they own the geometry types.
Closed in favor of #198