pycoast 1.6.1__tar.gz → 1.7.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. pycoast-1.7.1/AUTHORS.md +20 -0
  2. {pycoast-1.6.1 → pycoast-1.7.1}/MANIFEST.in +1 -2
  3. pycoast-1.7.1/PKG-INFO +81 -0
  4. {pycoast-1.6.1 → pycoast-1.7.1}/docs/Makefile +1 -0
  5. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/installation.rst +1 -1
  6. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/__init__.py +1 -0
  7. pycoast-1.7.1/pycoast/conftest.py +14 -0
  8. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/cw_agg.py +5 -1
  9. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/cw_base.py +93 -69
  10. pycoast-1.7.1/pycoast/tests/coasts_and_grid.ini +13 -0
  11. pycoast-1.7.1/pycoast/tests/coasts_and_grid_agg.ini +17 -0
  12. pycoast-1.7.1/pycoast/tests/eastern_shapes_agg.png +0 -0
  13. pycoast-1.7.1/pycoast/tests/eastern_shapes_pil.png +0 -0
  14. pycoast-1.7.1/pycoast/tests/grid_europe_agg_txt.png +0 -0
  15. pycoast-1.7.1/pycoast/tests/grid_from_dict_agg.png +0 -0
  16. pycoast-1.7.1/pycoast/tests/grid_from_dict_pil.png +0 -0
  17. pycoast-1.7.1/pycoast/tests/grid_germ.png +0 -0
  18. pycoast-1.7.1/pycoast/tests/grid_nh_agg.png +0 -0
  19. pycoast-1.7.1/pycoast/tests/grid_nh_cfg_agg.png +0 -0
  20. pycoast-1.7.1/pycoast/tests/lonlat_boundary_cross.png +0 -0
  21. pycoast-1.7.1/pycoast/tests/nh_cities_agg.ini +26 -0
  22. pycoast-1.7.1/pycoast/tests/nh_cities_pil.ini +20 -0
  23. pycoast-1.7.1/pycoast/tests/nh_one_shapefile.ini +11 -0
  24. pycoast-1.7.1/pycoast/tests/nh_points_agg.ini +24 -0
  25. pycoast-1.7.1/pycoast/tests/nh_points_pil.ini +19 -0
  26. pycoast-1.7.1/pycoast/tests/no_h_scratch_agg.png +0 -0
  27. pycoast-1.7.1/pycoast/tests/no_h_scratch_pil.png +0 -0
  28. pycoast-1.7.1/pycoast/tests/no_v_scratch_agg.png +0 -0
  29. pycoast-1.7.1/pycoast/tests/no_v_scratch_pil.png +0 -0
  30. pycoast-1.7.1/pycoast/tests/test_data/DejaVuSerif.ttf +0 -0
  31. pycoast-1.7.1/pycoast/tests/test_data/gshhs/CITIES/cities.txt +20 -0
  32. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L1.dbf +0 -0
  33. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L1.prj +1 -0
  34. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L1.shp +0 -0
  35. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L1.shx +0 -0
  36. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L2.dbf +0 -0
  37. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L2.prj +1 -0
  38. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L2.shp +0 -0
  39. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L2.shx +0 -0
  40. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L3.dbf +0 -0
  41. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L3.prj +1 -0
  42. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L3.shp +0 -0
  43. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L3.shx +0 -0
  44. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L4.dbf +0 -0
  45. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L4.prj +1 -0
  46. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L4.shp +0 -0
  47. pycoast-1.7.1/pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L4.shx +0 -0
  48. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L1.dbf +0 -0
  49. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L1.prj +1 -0
  50. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L1.shp +0 -0
  51. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L1.shx +0 -0
  52. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L2.dbf +0 -0
  53. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L2.prj +1 -0
  54. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L2.shp +0 -0
  55. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L2.shx +0 -0
  56. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L3.dbf +0 -0
  57. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L3.prj +1 -0
  58. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L3.shp +0 -0
  59. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L3.shx +0 -0
  60. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L01.dbf +0 -0
  61. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L01.prj +1 -0
  62. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L01.shp +0 -0
  63. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L01.shx +0 -0
  64. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L02.dbf +0 -0
  65. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L02.prj +1 -0
  66. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L02.shp +0 -0
  67. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L02.shx +0 -0
  68. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L03.dbf +0 -0
  69. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L03.prj +1 -0
  70. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L03.shp +0 -0
  71. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L03.shx +0 -0
  72. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L04.dbf +0 -0
  73. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L04.prj +1 -0
  74. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L04.shp +0 -0
  75. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L04.shx +0 -0
  76. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L05.dbf +0 -0
  77. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L05.prj +1 -0
  78. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L05.shp +0 -0
  79. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L05.shx +0 -0
  80. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L06.dbf +0 -0
  81. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L06.prj +1 -0
  82. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L06.shp +0 -0
  83. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L06.shx +0 -0
  84. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L07.dbf +0 -0
  85. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L07.prj +1 -0
  86. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L07.shp +0 -0
  87. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L07.shx +0 -0
  88. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L08.dbf +0 -0
  89. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L08.prj +1 -0
  90. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L08.shp +0 -0
  91. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L08.shx +0 -0
  92. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L09.dbf +0 -0
  93. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L09.prj +1 -0
  94. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L09.shp +0 -0
  95. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L09.shx +0 -0
  96. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L1.dbf +0 -0
  97. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L1.shp +0 -0
  98. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L1.shx +0 -0
  99. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L10.dbf +0 -0
  100. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L10.prj +1 -0
  101. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L10.shp +0 -0
  102. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L10.shx +0 -0
  103. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L11.dbf +0 -0
  104. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L11.prj +1 -0
  105. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L11.shp +0 -0
  106. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L11.shx +0 -0
  107. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L2.dbf +0 -0
  108. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L2.shp +0 -0
  109. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L2.shx +0 -0
  110. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L3.dbf +0 -0
  111. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L3.shp +0 -0
  112. pycoast-1.7.1/pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L3.shx +0 -0
  113. pycoast-1.7.1/pycoast/tests/test_data/shapes/Metareas.dbf +0 -0
  114. pycoast-1.7.1/pycoast/tests/test_data/shapes/Metareas.mxd +0 -0
  115. pycoast-1.7.1/pycoast/tests/test_data/shapes/Metareas.prj +1 -0
  116. pycoast-1.7.1/pycoast/tests/test_data/shapes/Metareas.sbn +0 -0
  117. pycoast-1.7.1/pycoast/tests/test_data/shapes/Metareas.sbx +0 -0
  118. pycoast-1.7.1/pycoast/tests/test_data/shapes/Metareas.shp +0 -0
  119. pycoast-1.7.1/pycoast/tests/test_data/shapes/Metareas.shx +0 -0
  120. pycoast-1.7.1/pycoast/tests/test_data/shapes/README +3 -0
  121. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/BRASIL.dbf +0 -0
  122. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/BRASIL.shp +0 -0
  123. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/BRASIL.shx +0 -0
  124. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/BR_Capitais.dbf +0 -0
  125. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/BR_Capitais.shp +0 -0
  126. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/BR_Capitais.shx +0 -0
  127. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/BR_Contorno.dbf +0 -0
  128. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/BR_Contorno.shp +0 -0
  129. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/BR_Contorno.shx +0 -0
  130. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/BR_Regioes.dbf +0 -0
  131. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/BR_Regioes.shp +0 -0
  132. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/BR_Regioes.shx +0 -0
  133. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/divisao_politica.txt +40 -0
  134. pycoast-1.7.1/pycoast/tests/test_data/shapes/divisao_politica/leia.txt +9 -0
  135. pycoast-1.7.1/pycoast/tests/test_data/shapes/metarea5.gsf +0 -0
  136. pycoast-1.7.1/pycoast/tests/test_data/shapes/metarea5.tbl +21 -0
  137. pycoast-1.7.1/pycoast/tests/test_data/shapes/metarea5.tbl.info +25 -0
  138. pycoast-1.7.1/pycoast/tests/test_data/test_config.ini +12 -0
  139. pycoast-1.7.1/pycoast/tests/test_pycoast.py +2124 -0
  140. pycoast-1.7.1/pycoast/tests/western_shapes_agg.png +0 -0
  141. pycoast-1.7.1/pycoast/tests/western_shapes_pil.png +0 -0
  142. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/version.py +4 -4
  143. pycoast-1.7.1/pycoast.egg-info/PKG-INFO +81 -0
  144. pycoast-1.7.1/pycoast.egg-info/SOURCES.txt +207 -0
  145. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast.egg-info/requires.txt +7 -5
  146. {pycoast-1.6.1 → pycoast-1.7.1}/pyproject.toml +6 -0
  147. {pycoast-1.6.1 → pycoast-1.7.1}/setup.cfg +1 -1
  148. {pycoast-1.6.1 → pycoast-1.7.1}/setup.py +6 -4
  149. {pycoast-1.6.1 → pycoast-1.7.1}/versioneer.py +173 -108
  150. pycoast-1.6.1/PKG-INFO +0 -65
  151. pycoast-1.6.1/pycoast/tests/eastern_shapes_agg.png +0 -0
  152. pycoast-1.6.1/pycoast/tests/eastern_shapes_pil.png +0 -0
  153. pycoast-1.6.1/pycoast/tests/grid_europe_agg_txt.png +0 -0
  154. pycoast-1.6.1/pycoast/tests/grid_from_dict_agg.png +0 -0
  155. pycoast-1.6.1/pycoast/tests/grid_from_dict_pil.png +0 -0
  156. pycoast-1.6.1/pycoast/tests/grid_germ.png +0 -0
  157. pycoast-1.6.1/pycoast/tests/grid_nh_agg.png +0 -0
  158. pycoast-1.6.1/pycoast/tests/grid_nh_cfg_agg.png +0 -0
  159. pycoast-1.6.1/pycoast/tests/no_h_scratch_agg.png +0 -0
  160. pycoast-1.6.1/pycoast/tests/no_h_scratch_pil.png +0 -0
  161. pycoast-1.6.1/pycoast/tests/no_v_scratch_agg.png +0 -0
  162. pycoast-1.6.1/pycoast/tests/no_v_scratch_pil.png +0 -0
  163. pycoast-1.6.1/pycoast/tests/test_pycoast.py +0 -2154
  164. pycoast-1.6.1/pycoast/tests/utils.py +0 -42
  165. pycoast-1.6.1/pycoast/tests/western_shapes_agg.png +0 -0
  166. pycoast-1.6.1/pycoast/tests/western_shapes_pil.png +0 -0
  167. pycoast-1.6.1/pycoast.egg-info/PKG-INFO +0 -65
  168. pycoast-1.6.1/pycoast.egg-info/SOURCES.txt +0 -89
  169. {pycoast-1.6.1 → pycoast-1.7.1}/LICENSE.txt +0 -0
  170. {pycoast-1.6.1 → pycoast-1.7.1}/README +0 -0
  171. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/api/.gitkeep +0 -0
  172. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/conf.py +0 -0
  173. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/config.rst +0 -0
  174. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/graticule.rst +0 -0
  175. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/high_quality_contours.rst +0 -0
  176. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/BMNG_clouds_201109181715_areaT2.png +0 -0
  177. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/brazil_shapefiles_agg.png +0 -0
  178. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/euro_coast.png +0 -0
  179. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/euro_coast_agg.png +0 -0
  180. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/euro_coast_grid_agg.png +0 -0
  181. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/euro_grid.png +0 -0
  182. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/euro_grid_agg.png +0 -0
  183. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/geos_coast.png +0 -0
  184. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/geos_coast_agg.png +0 -0
  185. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/grid_geos_agg.png +0 -0
  186. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/nh_grid_coarse_agg.png +0 -0
  187. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/nh_points_agg.png +0 -0
  188. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/nh_polygons_agg.png +0 -0
  189. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/images/nh_polygons_lines_agg.png +0 -0
  190. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/index.rst +0 -0
  191. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/points.rst +0 -0
  192. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/polygons_and_lines.rst +0 -0
  193. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/shapefiles.rst +0 -0
  194. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/test.rst +0 -0
  195. {pycoast-1.6.1 → pycoast-1.7.1}/docs/source/usage.rst +0 -0
  196. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/cw_pil.py +0 -0
  197. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/__init__.py +0 -0
  198. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/brazil_shapefiles.png +0 -0
  199. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/brazil_shapefiles_agg.png +0 -0
  200. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/contours_europe.png +0 -0
  201. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/contours_europe_agg.png +0 -0
  202. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/contours_europe_alpha.png +0 -0
  203. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/contours_geos.png +0 -0
  204. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/contours_geos_agg.png +0 -0
  205. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/dateline_boundary_cross.png +0 -0
  206. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/dateline_cross.png +0 -0
  207. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/grid_europe.png +0 -0
  208. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/grid_europe_agg.png +0 -0
  209. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/grid_geos.png +0 -0
  210. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/grid_geos_agg.png +0 -0
  211. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/grid_nh.png +0 -0
  212. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/nh_cities_agg.png +0 -0
  213. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/nh_cities_from_dict_agg.png +0 -0
  214. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/nh_cities_from_dict_pil.png +0 -0
  215. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/nh_cities_pil.png +0 -0
  216. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/nh_points_agg.png +0 -0
  217. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/nh_points_cfg_pil.png +0 -0
  218. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/nh_points_pil.png +0 -0
  219. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/nh_polygons.png +0 -0
  220. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/nh_polygons_agg.png +0 -0
  221. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/one_shapefile_from_cfg_agg.png +0 -0
  222. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/one_shapefile_from_cfg_pil.png +0 -0
  223. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/two_shapefiles_agg.png +0 -0
  224. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast/tests/two_shapefiles_pil.png +0 -0
  225. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast.egg-info/dependency_links.txt +0 -0
  226. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast.egg-info/not-zip-safe +0 -0
  227. {pycoast-1.6.1 → pycoast-1.7.1}/pycoast.egg-info/top_level.txt +0 -0
@@ -0,0 +1,20 @@
1
+ # Project Contributors
2
+
3
+ The following people have made contributions to this project:
4
+
5
+ <!--- Use your GitHub account or any other personal reference URL --->
6
+ <!--- See https://gist.github.com/djhoese/52220272ec73b12eb8f4a29709be110d for auto-generating parts of this list --->
7
+
8
+ - Stefano Cerino
9
+ - [Andrew Brooks (howff)](https://github.com/howff)
10
+ - [Adam Dybbroe (adybbroe)](https://github.com/adybbroe)
11
+ - [David Hoese (djhoese)](https://github.com/djhoese)
12
+ - [Katja Hungershofer (khunger)](https://github.com/khunger)
13
+ - [Mikhail Itkin (mitkin)](https://github.com/mitkin)
14
+ - [Panu Lahtinen (pnuu)](https://github.com/pnuu)
15
+ - [Ernst Lobsiger (lobsiger)](https://github.com/lobsiger)
16
+ - [Esben S. Nielsen (storpipfugl)](https://github.com/storpipfugl)
17
+ - [Martin Raspaud (mraspaud)](https://github.com/mraspaud)
18
+ - [Hrobjartur Thorsteinsson (thorsteinssonh)](https://github.com/thorsteinssonh)
19
+ - [Antonio Valentino (avalentino)](https://github.com/avalentino)
20
+ - [Yufei Zhu (yufeizhu600)](https://github.com/yufeizhu600)
@@ -1,9 +1,8 @@
1
1
  include docs/Makefile
2
2
  recursive-include docs/source *
3
3
  include pycoast/tests/*.png
4
- include pycoast/tests/*.ttf
4
+ recursive-include pycoast/tests/ *
5
5
  include LICENSE.txt
6
- include MANIFEST.in
7
6
 
8
7
  include versioneer.py
9
8
  include pycoast/version.py
pycoast-1.7.1/PKG-INFO ADDED
@@ -0,0 +1,81 @@
1
+ Metadata-Version: 2.1
2
+ Name: pycoast
3
+ Version: 1.7.1
4
+ Summary: Writing of coastlines, borders and rivers to images in Python
5
+ Author: Esben S. Nielsen
6
+ Author-email: esn@dmi.dk
7
+ Classifier: Development Status :: 5 - Production/Stable
8
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
9
+ Classifier: Programming Language :: Python
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Topic :: Scientific/Engineering
13
+ Requires-Python: >3.9
14
+ License-File: LICENSE.txt
15
+ License-File: AUTHORS.md
16
+ Requires-Dist: aggdraw
17
+ Requires-Dist: pyshp
18
+ Requires-Dist: numpy
19
+ Requires-Dist: pyproj
20
+ Requires-Dist: pillow
21
+ Provides-Extra: docs
22
+ Requires-Dist: sphinx; extra == "docs"
23
+ Requires-Dist: pyresample; extra == "docs"
24
+ Requires-Dist: pytest; extra == "docs"
25
+ Requires-Dist: pytest-lazy-fixtures; extra == "docs"
26
+ Requires-Dist: sphinx_rtd_theme; extra == "docs"
27
+ Requires-Dist: sphinxcontrib-apidoc; extra == "docs"
28
+ Provides-Extra: tests
29
+ Requires-Dist: pyresample; extra == "tests"
30
+ Requires-Dist: pytest; extra == "tests"
31
+ Requires-Dist: pytest-cov; extra == "tests"
32
+ Requires-Dist: coverage; extra == "tests"
33
+ Requires-Dist: coveralls; extra == "tests"
34
+ Requires-Dist: pytest-lazy-fixtures; extra == "tests"
35
+
36
+ PyCoast
37
+ =======
38
+
39
+ .. image:: https://github.com/pytroll/pycoast/workflows/CI/badge.svg?branch=main
40
+ :target: https://github.com/pytroll/pycoast/actions?query=workflow%3A%22CI%22
41
+
42
+ .. image:: https://coveralls.io/repos/github/pytroll/pycoast/badge.svg?branch=main
43
+ :target: https://coveralls.io/github/pytroll/pycoast?branch=main
44
+
45
+ .. image:: https://img.shields.io/pypi/v/pycoast.svg
46
+ :target: https://pypi.python.org/pypi/pycoast
47
+
48
+ .. image:: https://results.pre-commit.ci/badge/github/pytroll/pycoast/main.svg
49
+ :target: https://results.pre-commit.ci/latest/github/pytroll/pycoast/main
50
+ :alt: pre-commit.ci status
51
+
52
+ Python package for adding coastlines, borders, rivers, lakes, cities, and other
53
+ overlays to raster images.
54
+
55
+ Installation
56
+ ------------
57
+
58
+ PyCoast can be installed from PyPI using pip::
59
+
60
+ pip install pycoast
61
+
62
+ Or with conda using the conda-forge channel::
63
+
64
+ conda install -c conda-forge pycoast
65
+
66
+ Example
67
+ -------
68
+
69
+ ::
70
+
71
+ >>> from PIL import Image
72
+ >>> from pycoast import ContourWriterAGG
73
+ >>> img = Image.open('BMNG_clouds_201109181715_areaT2.png')
74
+ >>> proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
75
+ >>> area_extent = (-3363403.31,-2291879.85,2630596.69,2203620.1)
76
+ >>> area_def = (proj4_string, area_extent)
77
+ >>> cw = ContourWriterAGG('/home/esn/data/gshhs')
78
+ >>> cw.add_coastlines(img, area_def, resolution='l', level=4)
79
+ >>> cw.add_rivers(img, area_def, level=5, outline='blue')
80
+ >>> cw.add_borders(img, area_def, outline=(255, 0, 0))
81
+ >>> img.show()
@@ -35,6 +35,7 @@ help:
35
35
 
36
36
  clean:
37
37
  -rm -rf $(BUILDDIR)/*
38
+ -rm -rf source/api/*.rst
38
39
 
39
40
  html:
40
41
  $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@@ -34,7 +34,7 @@ rivers, and lakes, shapefiles from the
34
34
  installed. Download the zipped GSHHS and WDBII shapefiles. At the time of
35
35
  writing the current zip file can be found at:
36
36
 
37
- http://www.soest.hawaii.edu/pwessel/gshhg/gshhg-shp-2.3.7.zip
37
+ https://www.soest.hawaii.edu/pwessel/gshhg/gshhg-shp-2.3.7.zip
38
38
 
39
39
  Unzip the files to a data directory (hereafter *DB_DATA_ROOT*).
40
40
  The absolute path/name of this directory is called *db_root_path*
@@ -26,5 +26,6 @@ class ContourWriter(ContourWriterPIL):
26
26
  warnings.warn(
27
27
  "'ContourWriter' has been deprecated please use " "'ContourWriterPIL' or 'ContourWriterAGG' instead",
28
28
  DeprecationWarning,
29
+ stacklevel=2,
29
30
  )
30
31
  super(ContourWriter, self).__init__(*args, **kwargs)
@@ -0,0 +1,14 @@
1
+ """The conftest file."""
2
+
3
+ from pytest import hookimpl
4
+
5
+
6
+ @hookimpl(tryfirst=True, hookwrapper=True)
7
+ def pytest_runtest_makereport(item, call):
8
+ """Add test status in the report for fixtures to use."""
9
+ # execute all other hooks to obtain the report object
10
+ outcome = yield
11
+ rep = outcome.get_result()
12
+ # store test results for each phase of a call, which can
13
+ # be "setup", "call", "teardown"
14
+ setattr(item, "rep_" + rep.when, rep)
@@ -91,7 +91,11 @@ class ContourWriterAGG(ContourWriterBase):
91
91
  ):
92
92
  """Add a text box at position (x,y)."""
93
93
  if box_outline is not None:
94
- text_size = draw.textsize(text, font)
94
+ if hasattr(draw, "textsize"):
95
+ text_size = draw.textsize(text, font)
96
+ else:
97
+ left, top, right, bottom = draw.textbbox(text_position, text, font)
98
+ text_size = right - left, top - bottom
95
99
  margin = 2
96
100
  xUL = text_position[0] - margin
97
101
  yUL = text_position[1]
@@ -26,12 +26,13 @@ import json
26
26
  import logging
27
27
  import math
28
28
  import os
29
+ from pathlib import Path
29
30
  from typing import Generator
30
31
 
31
32
  import numpy as np
32
- import pyproj
33
33
  import shapefile
34
34
  from PIL import Image
35
+ from pyproj import CRS, Proj
35
36
 
36
37
  try:
37
38
  from pyresample import AreaDefinition
@@ -45,16 +46,11 @@ def get_resolution_from_area(area_def):
45
46
  """Get the best resolution for an area definition."""
46
47
  x_size = area_def.width
47
48
  y_size = area_def.height
48
- prj = Proj(area_def.crs if hasattr(area_def, "crs") else area_def.proj_str)
49
- if prj.is_latlong():
50
- x_ll, y_ll = prj(area_def.area_extent[0], area_def.area_extent[1])
51
- x_ur, y_ur = prj(area_def.area_extent[2], area_def.area_extent[3])
52
- x_resolution = (x_ur - x_ll) / x_size
53
- y_resolution = (y_ur - y_ll) / y_size
54
- else:
55
- x_resolution = (area_def.area_extent[2] - area_def.area_extent[0]) / x_size
56
- y_resolution = (area_def.area_extent[3] - area_def.area_extent[1]) / y_size
49
+ x_resolution = abs(area_def.area_extent[2] - area_def.area_extent[0]) / x_size
50
+ y_resolution = abs(area_def.area_extent[3] - area_def.area_extent[1]) / y_size
57
51
  res = min(x_resolution, y_resolution)
52
+ if "degree" in area_def.crs.axis_info[0].unit_name:
53
+ res = _estimate_metered_resolution_from_degrees(area_def.crs, res)
58
54
 
59
55
  if res > 25000:
60
56
  return "c"
@@ -68,6 +64,12 @@ def get_resolution_from_area(area_def):
68
64
  return "f"
69
65
 
70
66
 
67
+ def _estimate_metered_resolution_from_degrees(crs: CRS, resolution_degrees: float) -> float:
68
+ major_radius = crs.datum.ellipsoid.semi_major_metre
69
+ # estimate by taking the arc length using the radius
70
+ return major_radius * math.radians(resolution_degrees)
71
+
72
+
71
73
  class _CoordConverter:
72
74
  """Convert coordinates from one space to in-bound image pixel column and row.
73
75
 
@@ -91,7 +93,8 @@ class _CoordConverter:
91
93
  raise ValueError(f"'coord_ref' must be one of {pretty_coord_refs}.")
92
94
  self._convert_method = convert_methods[coord_ref]
93
95
 
94
- def _check_area_def(self, area_def):
96
+ @staticmethod
97
+ def _check_area_def(area_def):
95
98
  if AreaDefinition is None:
96
99
  raise ImportError(
97
100
  "Missing required 'pyresample' module, please "
@@ -130,16 +133,6 @@ def hash_dict(dict_to_hash: dict) -> str:
130
133
  return dhash.hexdigest()
131
134
 
132
135
 
133
- class Proj(pyproj.Proj):
134
- """Wrapper around pyproj to add in 'is_latlong'."""
135
-
136
- def is_latlong(self):
137
- if hasattr(self, "crs"):
138
- return self.crs.is_geographic
139
- # pyproj<2.0
140
- return super(Proj, self).is_latlong()
141
-
142
-
143
136
  class ContourWriterBase(object):
144
137
  """Base class for contourwriters. Do not instantiate.
145
138
 
@@ -167,7 +160,16 @@ class ContourWriterBase(object):
167
160
 
168
161
  def _draw_text(self, draw, position, txt, font, align="cc", **kwargs):
169
162
  """Draw text with agg module."""
170
- txt_width, txt_height = draw.textsize(txt, font)
163
+ if hasattr(draw, "textsize"):
164
+ txt_width, txt_height = draw.textsize(txt, font)
165
+ else:
166
+ left, top, right, bottom = draw.textbbox(position, txt, font)
167
+ # bbox is based on "left ascender" anchor for horizontal text
168
+ # but does not include the ascender to top distance.
169
+ # In order to include that additional distance we take height from
170
+ # anchor (`position`) to the bottom of the text. See:
171
+ # https://pillow.readthedocs.io/en/stable/handbook/text-anchors.html#text-anchors
172
+ txt_width, txt_height = right - left, bottom - position[1]
171
173
  x_pos, y_pos = position
172
174
  ax, ay = align.lower()
173
175
  if ax == "r":
@@ -178,7 +180,7 @@ class ContourWriterBase(object):
178
180
  if ay == "b":
179
181
  y_pos = y_pos - txt_height
180
182
  elif ay == "c":
181
- y_pos = y_pos - txt_width / 2
183
+ y_pos = y_pos - txt_height / 2
182
184
 
183
185
  self._engine_text_draw(draw, x_pos, y_pos, txt, font, **kwargs)
184
186
 
@@ -500,16 +502,21 @@ class ContourWriterBase(object):
500
502
  return overlays
501
503
 
502
504
  def add_overlay_from_dict(self, overlays, area_def, cache_epoch=None, background=None):
503
- """Create and return a transparent image adding all the overlays contained in the `overlays` dict.
505
+ """Create and return a transparent image adding all the overlays contained in the ``overlays`` dict.
504
506
 
505
507
  Optionally caches overlay results for faster rendering of images with
506
508
  the same provided AreaDefinition and parameters. Cached results are
507
- identified by hashing the AreaDefinition and the overlays dictionary.
509
+ identified by hashing the AreaDefinition and the ``overlays`` dictionary.
510
+
511
+ Note that if ``background`` is provided and caching is not used, the
512
+ result will be the final result of applying the overlays onto the
513
+ background. This is due to an optimization step avoiding creating a
514
+ separate overlay image in memory when it isn't needed.
508
515
 
509
516
  .. warning::
510
517
 
511
518
  Font objects are ignored in parameter hashing as they can't be easily hashed.
512
- Therefore font changes will not trigger a new rendering for the cache.
519
+ Therefore, font changes will not trigger a new rendering for the cache.
513
520
 
514
521
  :Parameters:
515
522
  overlays : dict
@@ -524,24 +531,33 @@ class ContourWriterBase(object):
524
531
  provided dictionary (see below).
525
532
  background: pillow image instance
526
533
  The image on which to write the overlays on. If it's None (default),
527
- a new image is created, otherwise the provide background is
534
+ a new image is created, otherwise the provided background is
528
535
  used and changed *in place*.
529
536
 
537
+ The keys in ``overlays`` that will be taken into account are:
538
+ cache, coasts, rivers, borders, shapefiles, grid, cities, points
530
539
 
531
- The keys in `overlays` that will be taken into account are:
532
- cache, coasts, rivers, borders, shapefiles, grid, cities, points
540
+ For all of them except ``cache``, the items are the same as the
541
+ corresponding functions in pycoast, so refer to the docstrings of
542
+ these functions (add_coastlines, add_rivers, add_borders,
543
+ add_shapefile_shapes, add_grid, add_cities, add_points).
544
+ For cache, two parameters are configurable:
533
545
 
534
- For all of them except `cache`, the items are the same as the
535
- corresponding functions in pycoast, so refer to the docstrings of
536
- these functions (add_coastlines, add_rivers, add_borders,
537
- add_shapefile_shapes, add_grid, add_cities, add_points).
538
- For cache, two parameters are configurable:
546
+ - `file`:
547
+ specify the directory and the prefix
548
+ of the file to save the caches decoration to (for example
549
+ /var/run/black_coasts_red_borders)
550
+ - `regenerate`:
551
+ True or False (default) to force the overwriting
552
+ of an already cached file.
539
553
 
540
- - `file`: specify the directory and the prefix
541
- of the file to save the caches decoration to (for example
542
- /var/run/black_coasts_red_borders)
543
- - `regenerate`: True or False (default) to force the overwriting
544
- of an already cached file.
554
+ :Returns: PIL.Image.Image
555
+
556
+ Resulting overlays as an Image object. If caching was used then
557
+ the Image wraps an open file and should be closed by the caller.
558
+ If caching was not used or the cached image was recreated then
559
+ this is an in-memory Image object. Regardless, it can be closed
560
+ by calling the ``.close()`` method of the Image.
545
561
 
546
562
  """
547
563
  overlay_helper = _OverlaysFromDict(self, overlays, area_def, cache_epoch, background)
@@ -550,12 +566,22 @@ class ContourWriterBase(object):
550
566
  def add_overlay_from_config(self, config_file, area_def, background=None):
551
567
  """Create and return a transparent image adding all the overlays contained in a configuration file.
552
568
 
569
+ See :meth:`add_overlay_from_dict` for more information.
570
+
553
571
  :Parameters:
554
572
  config_file : str
555
573
  Configuration file name
556
574
  area_def : object
557
575
  Area Definition of the creating image
558
576
 
577
+ :Returns: PIL.Image.Image
578
+
579
+ Resulting overlays as an Image object. If caching was used then
580
+ the Image wraps an open file and should be closed by the caller.
581
+ If caching was not used or the cached image was recreated then
582
+ this is an in-memory Image object. Regardless, it can be closed
583
+ by calling the ``.close()`` method of the Image.
584
+
559
585
  """
560
586
  overlays = self._config_to_dict(config_file)
561
587
  return self.add_overlay_from_dict(overlays, area_def, os.path.getmtime(config_file), background)
@@ -699,8 +725,7 @@ class ContourWriterBase(object):
699
725
  # cities.red is a reduced version of the files avalable at http://download.geonames.org
700
726
  # Fields: 0=name (UTF-8), 1=asciiname, 2=longitude [°E], 3=latitude [°N], 4=countrycode
701
727
  cities_filename = os.path.join(db_root_path, os.path.join("CITIES", "cities.txt"))
702
- cities_parser = GeoNamesCitiesParser(cities_filename)
703
- for city_name, lon, lat in cities_parser.iter_cities_names_lon_lat(cities_list):
728
+ for city_name, lon, lat in iter_cities_names_lon_lat(cities_filename, cities_list):
704
729
  try:
705
730
  x, y = area_def.get_array_indices_from_lonlat(lon, lat)
706
731
  except ValueError:
@@ -1053,16 +1078,10 @@ def _get_bounding_box_lonlat_sides(area_extent, x_size, y_size, prj):
1053
1078
  x_range = np.linspace(x_ll, x_ur, num=x_size)
1054
1079
  y_range = np.linspace(y_ll, y_ur, num=y_size)
1055
1080
 
1056
- if prj.is_latlong():
1057
- lons_s1, lats_s1 = x_ll * np.ones(y_range.size), y_range
1058
- lons_s2, lats_s2 = x_range, y_ur * np.ones(x_range.size)
1059
- lons_s3, lats_s3 = x_ur * np.ones(y_range.size), y_range
1060
- lons_s4, lats_s4 = x_range, y_ll * np.ones(x_range.size)
1061
- else:
1062
- lons_s1, lats_s1 = prj(np.ones(y_range.size) * x_ll, y_range, inverse=True)
1063
- lons_s2, lats_s2 = prj(x_range, np.ones(x_range.size) * y_ur, inverse=True)
1064
- lons_s3, lats_s3 = prj(np.ones(y_range.size) * x_ur, y_range, inverse=True)
1065
- lons_s4, lats_s4 = prj(x_range, np.ones(x_range.size) * y_ll, inverse=True)
1081
+ lons_s1, lats_s1 = prj(np.ones(y_range.size) * x_ll, y_range, inverse=True)
1082
+ lons_s2, lats_s2 = prj(x_range, np.ones(x_range.size) * y_ur, inverse=True)
1083
+ lons_s3, lats_s3 = prj(np.ones(y_range.size) * x_ur, y_range, inverse=True)
1084
+ lons_s4, lats_s4 = prj(x_range, np.ones(x_range.size) * y_ll, inverse=True)
1066
1085
  return (lons_s1, lons_s2, lons_s3, lons_s4), (lats_s1, lats_s2, lats_s3, lats_s4)
1067
1086
 
1068
1087
 
@@ -1087,12 +1106,7 @@ def _get_pixel_index(shape, area_extent, x_size, y_size, prj, x_offset=0, y_offs
1087
1106
  shape_data = np.array(shape.points if hasattr(shape, "points") else shape)
1088
1107
  lons = shape_data[:, 0]
1089
1108
  lats = shape_data[:, 1]
1090
-
1091
- if prj.is_latlong():
1092
- x_ll, y_ll = prj(area_extent[0], area_extent[1])
1093
- x_ur, y_ur = prj(area_extent[2], area_extent[3])
1094
- else:
1095
- x_ll, y_ll, x_ur, y_ur = area_extent
1109
+ x_ll, y_ll, x_ur, y_ur = area_extent
1096
1110
 
1097
1111
  x, y = prj(lons, lats)
1098
1112
 
@@ -1137,14 +1151,12 @@ def _get_pixel_index(shape, area_extent, x_size, y_size, prj, x_offset=0, y_offs
1137
1151
  return index_arrays, is_reduced
1138
1152
 
1139
1153
 
1140
- class GeoNamesCitiesParser:
1141
- """Helper for parsing citiesN.txt files from GeoNames.org."""
1142
-
1143
- def __init__(self, cities_filename: str):
1144
- self._cities_file = open(cities_filename, mode="r", encoding="utf-8")
1145
-
1146
- def iter_cities_names_lon_lat(self, cities_list: list[str]) -> Generator[tuple[str, float, float], None, None]:
1147
- for city_row in self._cities_file:
1154
+ def iter_cities_names_lon_lat(
1155
+ cities_filename: str | Path, cities_list: list[str]
1156
+ ) -> Generator[tuple[str, float, float], None, None]:
1157
+ """Iterate over citiesN.txt files from GeoNames.org."""
1158
+ with open(cities_filename, mode="r", encoding="utf-8") as cities_file:
1159
+ for city_row in cities_file:
1148
1160
  city_info = city_row.split("\t")
1149
1161
  if not city_info or not (city_info[1] in cities_list or city_info[2] in cities_list):
1150
1162
  continue
@@ -1199,7 +1211,7 @@ class _OverlaysFromDict:
1199
1211
  foreground = Image.open(cache_file)
1200
1212
  logger.info("Using image in cache %s", cache_file)
1201
1213
  if background is not None:
1202
- background.paste(foreground, mask=foreground.split()[-1])
1214
+ _apply_cached_foreground_on_background(background, foreground)
1203
1215
  return foreground
1204
1216
  logger.info("Regenerating cache file.")
1205
1217
  except OSError:
@@ -1212,7 +1224,7 @@ class _OverlaysFromDict:
1212
1224
  except IOError as e:
1213
1225
  logger.error("Can't save cache: %s", str(e))
1214
1226
  if self._background is not None:
1215
- self._background.paste(self._foreground, mask=self._foreground.split()[-1])
1227
+ _apply_cached_foreground_on_background(self._background, self._foreground)
1216
1228
 
1217
1229
  def _generate_cache_filename(self, cache_prefix, area_def, overlays_dict):
1218
1230
  area_hash = hash(area_def)
@@ -1443,6 +1455,18 @@ class _OverlaysFromDict:
1443
1455
  )
1444
1456
 
1445
1457
 
1458
+ def _apply_cached_foreground_on_background(background, foreground):
1459
+ premult_foreground = foreground.convert("RGBa")
1460
+ if background.mode == "RGBA":
1461
+ # Cached foreground and background are both RGBA, no extra conversions needed
1462
+ background.paste(premult_foreground, mask=premult_foreground)
1463
+ return
1464
+ background_rgba = background.convert("RGBA")
1465
+ background_rgba.paste(premult_foreground, mask=premult_foreground)
1466
+ # overwrite background image in place
1467
+ background.paste(background_rgba)
1468
+
1469
+
1446
1470
  class _GridDrawer:
1447
1471
  """Helper for drawing graticule/grid lines."""
1448
1472
 
@@ -1514,7 +1538,7 @@ class _GridDrawer:
1514
1538
  min_lons[min_lons > 180] = min_lons[min_lons > 180] - 360
1515
1539
 
1516
1540
  # Get min_lons not in maj_lons
1517
- min_lons = np.lib.arraysetops.setdiff1d(min_lons, maj_lons)
1541
+ min_lons = np.setdiff1d(min_lons, maj_lons)
1518
1542
 
1519
1543
  # lats along major lon lines
1520
1544
  lin_lats = np.arange(
@@ -1535,7 +1559,7 @@ class _GridDrawer:
1535
1559
  min_lats = np.arange(round_lat_min + increase_min_lat, lat_max - shorten_max_lat, dlat)
1536
1560
 
1537
1561
  # Get min_lats not in maj_lats
1538
- min_lats = np.lib.arraysetops.setdiff1d(min_lats, maj_lats)
1562
+ min_lats = np.setdiff1d(min_lats, maj_lats)
1539
1563
 
1540
1564
  # lons along major lat lines (extended slightly to avoid missing the end)
1541
1565
  lin_lons = np.linspace(lon_min, lon_max + Dlon / 5.0, max(self._x_size, self._y_size) // 5)
@@ -0,0 +1,13 @@
1
+ [coasts]
2
+ level = 4
3
+ resolution = l
4
+ outline = white
5
+
6
+ [grid]
7
+ write_text = False
8
+ lon_major = 10.0
9
+ lat_major = 10.0
10
+ lon_minor = 2.0
11
+ lat_minor = 2.0
12
+ minor_outline = blue
13
+ outline = blue
@@ -0,0 +1,17 @@
1
+ [coasts]
2
+ level = 4
3
+ resolution = l
4
+ outline = white
5
+
6
+ [grid]
7
+ write_text = True
8
+ lon_major = 10.0
9
+ lat_major = 10.0
10
+ lon_minor = 2.0
11
+ lat_minor = 2.0
12
+ minor_outline = blue
13
+ outline = blue
14
+ lon_placement = tblr
15
+ lat_placement = ''
16
+ font = 'test_data/DejaVuSerif.ttf'
17
+ font_size = 10
@@ -0,0 +1,26 @@
1
+ [coasts]
2
+ level = 4
3
+ resolution = l
4
+ outline = black
5
+
6
+ [borders]
7
+ level = 1
8
+ outline = black
9
+ width = 3
10
+ resolution = c
11
+
12
+ [cities]
13
+ # Backward compatibility: Allows for *ONE* type of cities
14
+ cities_list = Zurich, Oslo, Reykjavik, Fairbanks, Toronto
15
+ font = test_data/DejaVuSerif.ttf
16
+ font_size = 20
17
+ symbol = square
18
+ ptsize = 16
19
+ outline = black
20
+ width = 1
21
+ fill = blue
22
+ fill_opacity = 128
23
+ box_outline = blue
24
+ box_linewidth = 0.5
25
+ box_fill = yellow
26
+ box_opacity = 200
@@ -0,0 +1,20 @@
1
+ [coasts]
2
+ level = 4
3
+ resolution = l
4
+ outline = black
5
+
6
+ [borders]
7
+ level = 1
8
+ outline = black
9
+ resolution = c
10
+
11
+ [cities]
12
+ # Backward compatibility: Allows for *ONE* type of cities
13
+ cities_list = Zurich, Oslo, Reykjavik, Fairbanks, Toronto
14
+ font = test_data/DejaVuSerif.ttf
15
+ font_size = 20
16
+ symbol = square
17
+ ptsize = 16
18
+ outline = black
19
+ fill = blue
20
+ box_outline = blue
@@ -0,0 +1,11 @@
1
+ [coasts]
2
+ level = 4
3
+ resolution = l
4
+ outline = yellow
5
+ width = 1.5
6
+
7
+ [shapefiles]
8
+ # For completeness: Allows for only *ONE* shapefile
9
+ filename = 'test_data/shapes/Metareas.shp'
10
+ outline = cyan
11
+ width = 3.5
@@ -0,0 +1,24 @@
1
+ [coasts]
2
+ level = 4
3
+ resolution = l
4
+ outline = black
5
+
6
+ [borders]
7
+ level = 1
8
+ outline = black
9
+ width = 3
10
+ resolution = c
11
+
12
+ [points]
13
+ points_list = ((2.3522, 48.8566), 'Paris'), ((0.1278, 51.5074), 'London')
14
+ font = 'test_data/DejaVuSerif.ttf'
15
+ symbol = circle
16
+ ptsize = 16
17
+ outline = black
18
+ width = 3
19
+ fill = red
20
+ fill_opacity = 128
21
+ box_outline = blue
22
+ box_linewidth = 0.5
23
+ box_fill = yellow
24
+ box_opacity = 200
@@ -0,0 +1,19 @@
1
+ [coasts]
2
+ level = 4
3
+ resolution = l
4
+ outline = black
5
+
6
+ [borders]
7
+ level = 1
8
+ outline = black
9
+ width = 3
10
+ resolution = c
11
+
12
+ [points]
13
+ points_list = ((13.4050, 52.5200), 'Berlin'), ((12.4964, 41.9028), 'Rome')
14
+ font = 'test_data/DejaVuSerif.ttf'
15
+ symbol = square
16
+ ptsize = 6
17
+ outline = red
18
+ fill = yellow
19
+ box_outline = black