Why did annotate work unexpectedly here in potatoes?

First code:

import cartopy.crs as ccrs import matplotlib.pyplot as plt ax = plt.axes(projection=ccrs.Mercator()) ax.set_extent([72, 135, 18, 53]) ax.annotate('hello', xy=(100, 49), xycoords='data', transform=ccrs.PlateCarree(), zorder=12) plt.show() 

The result is not expected, and I have other doubts about my approach. So my questions are:

  • If I want to build a map, it looks like a web map (e.g. google map). The area of ​​the map may be as large as China, mostly not global. After they started searching the Internet, these sites mainly use the "web mercator" projection. So I'm suppost, I have to use plt.axes(projection=ccrs.Mercator() here, am I right? Or what should I use if I am wrong?

  • The data of the coords that I want to build is 121 Β° E, 49 Β° C. w. (conversion of degrees to decimal before the start of the graph), an undesigned WGS84 coordinate system, possibly from GPS. Can I use transform=ccrs.PlateCarree() ? Or what should I use if I am wrong?

  • annotate above nothing is displayed. After the comment on the line ax.set_extent text "hello" is displayed at the zero point (0, 0). What I want is at the point (100 Β° E, 49 Β° N). How to fix this?

+6
source share
1 answer

Firstly - thanks for the code - this makes the solution much easier.

Honestly, I don’t think that annotate was used seriously with Cartopy before, so that is probably why you are faced with this problem - you make sure to look :)

It looks like the matplotlib Axes.annotate method is used Axes.annotate - it destroys the transformation going through https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/axes/_axes.py#L651 . This is mainly due to the fact that the annotate has special keywords to determine the transformation of both coordinates and text position independently (see xycoords and textcoords at http://matplotlib.org/users/annotations_intro.html#annotating-text ) .

When we dig into the Annotate class, we find that Annotate _get_xy_transform ( https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/text.py#L1446 ) can handle different (some undocumented) forms as values textcoords , including conversion instances.

Good, so good. It would seem that you can just go through the coordinate system to xycoords , and everything should be gloomy. Unfortunately, the annotation does not know how to convert the Cartopy coordinate system to the matplotlib transform, as most other matplotlib do, so we will have to do this for the annotation function up.

To create a matplotlib transform from any cartographic coordinate system, for any axis we can simply do:

 ax = plt.axes(projection=ccrs.Mercator()) crs = ccrs.PlateCarree() transform = crs._as_mpl_transform(ax) 

Now we can pass this transformation to the annotation method, and in the end we get the text and arrow in the expected place. I took a few freedoms to highlight some annotation features while I am:

 import cartopy.feature import cartopy.crs as ccrs import matplotlib.pyplot as plt ax = plt.axes(projection=ccrs.Mercator()) ax.set_extent([65, 125, 5, 40]) ax.add_feature(cartopy.feature.OCEAN) ax.add_feature(cartopy.feature.LAND) ax.add_feature(cartopy.feature.BORDERS, linestyle=':', edgecolor='gray') ax.coastlines() ax.plot(116.4, 39.95, 'ob', transform=ccrs.PlateCarree()) transform = ccrs.PlateCarree()._as_mpl_transform(ax) ax.annotate('Beijing', xy=(116.4, 39.9), xycoords=transform, ha='right', va='top') ax.annotate('Delhi', xy=(113, 40.5), xytext=(77.23, 28.61), arrowprops=dict(facecolor='gray', arrowstyle="simple", connectionstyle="arc3,rad=-0.2", alpha=0.5), xycoords=transform, ha='right', va='top') plt.show() 

Example of annotate with cartopy

Answering your other questions:

If I want to build a map, it looks like a web map (e.g. google map)

Mapopy.crs has a new constant that exactly defines Google Mercator ( cartopy.crs.GOOGLE_MERCATOR ). This is just an example of a Mercator projection with several settings to make it exactly the same as Google Mercator ( https://github.com/SciTools/cartopy/blob/master/lib/cartopy/crs.py#L889 ).

The data of the coords that I want to build are 121 Β° E, 49 Β° N. (converted to decimal before the start of the graph), undesigned, WGS84 coordinate system, possibly from GPS. So am I using conversion = ccrs.PlateCarree () correctly? Or what should I use if I am mistaken?

I would suggest that you better place a geodetic coordinate system - this coordinate system uses the WGS84 database by default, which will give you the most accurate representation of your WGS84 latitudes and longitudes. Although, on the scale that you are drawing now, I think it will be difficult for you to notice the difference (the maximum difference is about ~ 22 km in mid-latitudes).

NTN

+10
source

Source: https://habr.com/ru/post/974132/


All Articles