Как правильно настроить проекцию и трансформацию в картографических геоосях при построении матплотлиба - PullRequest
1 голос
/ 08 мая 2019

Я сталкиваюсь с серьезными трудностями в использовании геопанд Python, cartopy и matplotlib для совместной работы над правильным графиком данных моего шейп-файла.

Проблема заключается в трудности правильной настройки объектов Transform и Projection объектовмои данные шейп-файла.

Пример, который я здесь описываю, относится к SHP в проекции SIRGAS 2000, чей формат WKT:

GEOGCS ["SIRGAS 2000", DATUM ["D_SIRGAS_2000",SPHEROID ["GRS_1980", 6378137,298.257222101]], PRIMEM ["Гринвич", 0], UNIT ["Степень", 0.017453292519943295]]

Из WKT выше видно, что мои координаты в градусах,Глобус - это не WGS84, а GRS_1980, который похож (но не равен) на WGS84.

Этот crs еще не реализован в картопии.Таким образом, попытка использовать функции в качестве cartopy.crs.EPSG (4674) не работает, особенно потому, что это не проекция crs, а географическая crs.

Следуя вопросу прорисовки, я логически предположил, чтоследует использовать один из четырех параметров cartopy.crs для построения моих данных:

transform_option_1 = cartopy.crs.PlateCarree() # works well

transform_option_2 = cartopy.crs.PlateCarree(globe=ccrs.Globe(ellipse='GRS80')) # works well

transform_option_3 = cartopy.crs.Geodetic(globe=ccrs.Globe(ellipse='GRS80')) # doesn't work

# using wkt:

WKT = """GEOGCS["SIRGAS 2000",DATUM["D_SIRGAS_2000",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]"""

transform_option_4 = ccrs.PlateCarree(WKT) # results in an error message (see message in annex)

Однако, когда я пытаюсь использовать четыре параметра преобразования для отображения моих данных, появляется ошибка для моих параметров transform_option_3 и transform_option_4.

Первые два варианта (transform_option_1, transform_option_2), все работает хорошо.Кроме того, когда я сравниваю первые два параметра «Преобразование» на графике, они приводят к одной и той же фигуре, хотя они должны приводить к немного другим графикам (из-за объекта глобуса).Итак, вот мой первый вопрос:

Вопрос 1: почему объект ccrs.PlateCarree () приводит к одному и тому же графику для моих данных, несмотря на разные объекты Globe?

Вопрос 2: поскольку cartopy принимаетФормат строки WKT для экземпляра объекта преобразования, почему возникает ошибка?См. Сообщение об ошибке, приложенное ниже к этому сообщению (сообщение об ошибке № 1).

Вопрос 3: в чем разница между геодезической и плоской проекциями в картопы?Я не могу понять, когда я должен использовать или другой.Поскольку описание обеих проекций подразумевает координаты в градусах, их различие странно для меня.Кроме того, когда я пытаюсь использовать оба варианта для построения своего SHP с использованием картографии, работает только PlateCarree.Другие результаты приводят к черным геоосям.

Вот фрагмент кода для лучшего разъяснения моего Вопроса 3:


# importing libraries:
import geopandas as gpd
import matplotlib.pyplot as plt
import cartopy.crs as ccrs


# importing data:

SHP_path = 'Data_SHP.shp'

SHP = gpd.read_file(SHP_path)


# setting projection to PlateCarre:

projection = ccrs.PlateCarree() # projection.proj4_init


# setting SHP data transform

Transform2 = ccrs.Geodetic(globe=ccrs.Globe(ellipse='GRS80'))


# creating figure:

fig, ax = plt.subplots(1, subplot_kw={'projection':projection})


SHP.plot(ax=ax, transform=Transform2, 
         color='k', alpha=0.5)

# defining a small function to add grilines to the plot:

def custom_plot(geoaxes, projection):



    gl = geoaxes.gridlines(crs=projection)

    tick_axis_positions={'xlabels_top':False,
                     'ylabels_left':True,
                     'ylabels_right':False,
                     'xlabels_bottom':True}

    gl.xlabels_top = tick_axis_positions['xlabels_top']
    gl.ylabels_left = tick_axis_positions['ylabels_left']
    gl.ylabels_right= tick_axis_positions['ylabels_right']
    gl.xlabels_bottom = tick_axis_positions['xlabels_bottom']


    return geoaxes


# adding gridlines to the geoaxes:

ax = custom_plot(ax, projection)

fig.show()

# end of code


Вопрос 4: Почему я не могу создать экземпляр проекционного объекта с использованием картографического объекта, используямои crs (в формате WKT)?Когда я пытаюсь это сделать, появляется сообщение об ошибке (см. Сообщение об ошибке 2 в приложении).

Projection = ccrs.Projection(proj4_params=WKT, globe=ccrs.Globe(ellipse='GRS80'))

Ссылки:

1) обсуждение, касающееся создания объекта преобразования cartopy.crsиз форматов проекции системы координат WKT или proj4

2) Отображение proj4 на картопо CRS

3) Построение прямой линии в Картопи, проекция Робинсона

4) пример построения графика SHP с картопией

5) теория картопреобразования и проекции


Приложение:

Сообщение об ошибке 1)

TypeError: unsupported operand type(s) for -: 'str' and 'float'


Traceback (most recent call last):
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\backends\backend_qt5.py", line 519, in _draw_idle
    self.draw()
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\backends\backend_agg.py", line 402, in draw
    self.figure.draw(self.renderer)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\figure.py", line 1649, in draw
    renderer, self, artists, self.suppressComposite)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\image.py", line 138, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\mpl\geoaxes.py", line 385, in draw
    inframe=inframe)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\axes\_base.py", line 2628, in draw
    mimage._draw_list_compositing_images(renderer, self, artists)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\image.py", line 138, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\collections.py", line 262, in draw
    transform, transOffset, offsets, paths = self._prepare_points()
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\collections.py", line 240, in _prepare_points
    for path in paths]
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\collections.py", line 240, in <listcomp>
    for path in paths]
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\transforms.py", line 2451, in transform_path_non_affine
    return self._a.transform_path_non_affine(path)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\mpl\geoaxes.py", line 173, in transform_path_non_affine
    src_path.vertices, self.source_projection)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\crs.py", line 746, in quick_vertices_transform
    bboxes, proj_offset = self._bbox_and_offset(src_crs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\crs.py", line 709, in _bbox_and_offset
    lon_0_offset = other_lon_0 - self_lon_0
TypeError: unsupported operand type(s) for -: 'str' and 'float'
Traceback (most recent call last):
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\backends\backend_qt5.py", line 519, in _draw_idle
    self.draw()
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\backends\backend_agg.py", line 402, in draw
    self.figure.draw(self.renderer)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\figure.py", line 1649, in draw
    renderer, self, artists, self.suppressComposite)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\image.py", line 138, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\mpl\geoaxes.py", line 385, in draw
    inframe=inframe)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\axes\_base.py", line 2628, in draw
    mimage._draw_list_compositing_images(renderer, self, artists)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\image.py", line 138, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\collections.py", line 262, in draw
    transform, transOffset, offsets, paths = self._prepare_points()
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\collections.py", line 240, in _prepare_points
    for path in paths]
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\collections.py", line 240, in <listcomp>
    for path in paths]
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\transforms.py", line 2451, in transform_path_non_affine
    return self._a.transform_path_non_affine(path)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\mpl\geoaxes.py", line 173, in transform_path_non_affine
    src_path.vertices, self.source_projection)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\crs.py", line 746, in quick_vertices_transform
    bboxes, proj_offset = self._bbox_and_offset(src_crs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\crs.py", line 709, in _bbox_and_offset
    lon_0_offset = other_lon_0 - self_lon_0
TypeError: unsupported operand type(s) for -: 'str' and 'float'

Сообщение об ошибке 2)

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-165-9916b2ddcc67> in <module>
----> 1 ccrs.Projection(proj4_params=Transform_from_wkt, globe=ccrs.Globe(ellipse='GRS80'))

TypeError: Can't instantiate abstract class Projection with abstract methods boundary, threshold, x_limits, y_limits

1 Ответ

1 голос
/ 11 мая 2019
  1. PlateCarree фальсифицируется с использованием координат проекции широты / долготы.На самом деле это Equidistant Cylindrical со специальным набором глобусов по умолчанию, который позволяет широту / долготу работать.Больше в этой ошибке .Поэтому я не думаю, что передача собственного глобуса GRS80 в PlateCarree на самом деле работает для вас.Эта ошибка обрисовывает в общих чертах это, ломая все.

  2. Я не знаю, что CartoPy фактически принимает WKT где-либо.Создание проекции из строки Proj.4 или WKT Я думаю, что открытый выпуск .

  3. PlateCarree работает, принимая широту / долготу в качестве координат на плоскости, поэтому линии между точками широты и долготы являются прямыми на плоскости.Это грубое упрощение, но оно заставляет многие вещи работать, например, контурно.Geodetic правильно обрабатывает широты / долготы как координаты на сфере, поэтому линии, соединяющие широты и долготы, являются большими кругами.Это правильный способ делать вещи, но он усложняет математику и не работает для некоторых вариантов построения.См. этот пример , чтобы увидеть, как он меняется.

  4. См. (2) выше

Мне любопытно, какие проблемывы столкнулись с передачей пользовательского эллипсоида Geodetic.У меня не было проблем с этим кодом и Cartopy 0.17:

import cartopy.crs as ccrs
globe = ccrs.Globe(ellipse='GRS80')
crs = ccrs.Geodetic(globe=globe)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...