Open wilkens opened 4 months ago
Thank you for reporting this issue. I tried having a look...
These cartopy transforms are weird, I have no experience working with them. Do you have an example how to even add an arrow here that would connect your desired coordinates?
Thanks for looking into this. I'm definitely no pro with cartopy myself.
Here's code that sets the labels and arrows by hand using ax.annotate
. Seems to work OK:
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.pyplot as plt
lons = [-98, -100]
lats = [40, 40]
labels = ['One', 'Two']
fig = plt.figure(figsize=(12,6))
ax = plt.axes(projection=ccrs.Robinson())
ax.set_extent([-175, 175, -60, 85], crs=ccrs.Geodetic())
# plot the points
plt.scatter(
x=lons,
y=lats,
transform=ccrs.Geodetic()
)
# add the annotations one at a time
ax.annotate(
text='One',
xy=(-98,40),
xytext=(-90,39),
xycoords=ccrs.Geodetic(),
textcoords=ccrs.Geodetic(),
va='center',
ha='left',
arrowprops={'arrowstyle':'-'}
)
ax.annotate(
text='Two',
xy=(-100,40),
xytext=(-110,41),
xycoords=ccrs.Geodetic(),
textcoords=ccrs.Geodetic(),
va='center',
ha='right',
arrowprops={'arrowstyle':'-'}
)
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.BORDERS)
fig.canvas.draw()
I don't think the annotations need both xycoords
and textcoords
. I see the same result if I supply just xycoords
. But, belt and suspenders.
You are using ax.annotate... The issue is that adjustText just changes the coordinate of the provided Text
objects, and then adds an arrow, by creating a FancyArrowPatch
and adding it to the axes. This object takes a transform
argument, however using it in this context gives an error:
AttributeError: 'Geodetic' object has no attribute 'quick_vertices_transform'
One could rewrite it using ax.annotate, but I think there were some minor issue with that solution.юю
So I am a little stumped as to how to fix this, and I suspect that without fixing this error in cartopy I can't fix this problem here in a reasonable way.
Ah, yeah, I see the problem. I can replicate the AttributeError
when I try to do the same thing by hand. I can work around the error by calling the transform directly on the positions passed to FancyArrowPatch
, but the result is the same: no arrows drawn in the output.
It does seem like the solution would be to substitute annotate
for separate calls to text
and FancyArrowPatch
. That said, if annotate
causes problems elsewhere, then I guess we're stuck, alas.
Thanks for your work on the package. It's been a great help to me on many occasions!
I think I could add an argument to change the behaviour... Not sure about the best naming. But it could simply use annotate to draw the arrow, and not touch the text. I had it like that in the past... I think the issue was aesthetic - the arrows would sometimes strike through the text for some reason. Maybe it could be solved somehow.
That would certainly be a help to me if you're up for it. In any case, I'm grateful for all your work on the package.
Oh, and happy to help test/debug ...
Can you try the latest commit? For me the arrows work, but they don't get clipped by the text, so can strike through it...
Thanks! Yes, the new version works as expected. As you note, I do see some strikethrough. I can mess about with horizontal and vertical alignment options to the text
objects, which helps a bit. In any case, it's much better than no arrows at all!
Here's my world map showing the new output. Much more legible.
You probably get a warning when running it, as it suggests you can increase the shrinkA value in arrowprops to reduce the strikethrough... But in some of them the arrow might start some distance away from the text then.
Yes, that does help. As you say, it's tricky to find the right balance between minimizing both strikethrough and the gap between texts and arrows. When the label is vertically above/below the marker, a small shrinkA
is enough. When the alignment is more horizontal (like richmond or holland or "the united states" on my map), then a very large shrinkA
is necessary.
adjust_text
works great in most situations. But I'm having a small problem using it withcartopy
for mapping. The results are as expected, but the arrows linking labels to markers are missing.A minimal example and resulting figure are below. I'm probably doing something wrong, but I notice that the cartopy example in the documentation may suffer from the same issue? Any thoughts or help are greatly appreciated. Thanks!
adjustText
version 1.1.1cartopy
version 0.23.0The issue seems to come from adding the
transform=ccrs.Geodetic()
line to theax.text
call. If I leave that out, I see proper arrows, but of course the labels and arrows are in the wrong place, since they aren't transformed to match the axes.Here's an example of the actual figure I'm trying to produce, where the missing-arrow problem is clearer: